Re: [PATCH] Handle loading improper core files gracefully in the mips backend.

Maciej W. Rozycki
2016-02-05T14:10:01Z

On Fri, 5 Feb 2016, Luis Machado wrote:

> > 1. There's no executable and we want to connect to a live target for
> > minimal binary-only/disasembly-level debugging. We need to set the
> > endianness, ABI, ISA, etc. to match the target then (although arguably
> > at least the endianness should be supplied by the debug stub somehow;
> > we just don't have a way defined right now).
> >
>
> While trying reproducers out, i noticed this use case doesn't seem to work
> properly under some conditions anymore. Whenever GDB doesn't find a binary and
> sysroot is set to empty, it will not attempt to continue with the remote
> session. It seems to just give up.
>
> Sending packet: $qXfer:exec-file:read:6394:0,fff#60...Packet received:
> lgdb.base/break
> <- remote->to_xfer_partial (0xcb3a80, 27, 6394, 0xe38cc0, 0x0, 0x0, 0xfff,
> 0x98) = 1
> remote:target_xfer_partial (27, 6394, 0xe38cc0, 0x0, 0x0, 4095) = 1, 152,
> bytes =
> 2f 6e 65 74 2f 62 75 69 6c 64 32 2d 6c 75 63 69 ...
> -> remote->to_check_pending_interrupt (...)
> <- remote->to_check_pending_interrupt (0xcb3a80)
> -> remote->to_xfer_partial (...)
> <- remote->to_xfer_partial (0xcb3a80, 27, 6394, 0xe38d58, 0x0, 0x98, 0xf67,
> 0x0) = 0
> remote:target_xfer_partial (27, 6394, 0xe38d58, 0x0, 0x98, 3943) = 0, 0
> <- remote->to_pid_to_exec_file (0xcb3a80, 25492) = gdb.base/break
> target_close ()
> gdb.base/break: No such file or directory.
> (gdb) i r
> The program has no registers now.
> (gdb) kill
> The program is not being run.
>
> Otherwise gdbserver will transfer the file over from the remote end. But i
> digress.

Thanks for letting me know, I'll have a look -- this might be an issue
with gdbserver rather than GDB proper.

Actually I have never tried this scenario with gdbserver, my usual case
was running through board firmware over JTAG and a third-party debug stub
talking to it. Or, in the very old days, the MDI target I posted a while
ago (<https://sourceware.org/ml/gdb-patches/2008-02/msg00439.html>).

> I can easily reproduce the internal error by simply loading a 32-bit MIPS
> binary and flipping the abi to any of the 64-bit variants.

I think I can see where this can happen. We have this condition in
`mips_gdbarch_init' to catch this situation:

/* If we have only 32-bit registers, then we can't debug a 64-bit
ABI. */
if (info.target_desc
&& tdesc_property (info.target_desc, PROPERTY_GP32) != NULL
&& mips_abi != MIPS_ABI_EABI32
&& mips_abi != MIPS_ABI_O32)

-- however it works in positive logic, that is only if we have a valid
target description and that description is wrong, and doing nothing if we
don't. However `mips_isa_regsize' also has fallback logic, specifically:

/* Fall back to the previous behavior. */
return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
/ gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);

So I think in `mips_gdbarch_init' we need to incorporate a corresponding
check and reject any BFD arch which implies an incompatible register size;
I think irrespectively of whether we have a target description or not.
We have the necessary bits readily available here AFAICT.

> This doesn't seem to be terribly important as people interested in playing
> with these setting will most likely know what they're doing.
>
> The testcase causing an internal error seems to be even less important and
> very unlikely to occur, but it always runs as part of the testsuite and it is
> a bit of an annoyance.
>
> GDB should not give an internal error or crash, obviously.

Oh absolutely, no argument about this as far as I'm concerned. I'd even
say stronger that it must not!

> > TBH I'm not convinced whether the auxiliary variable buys us anything
> > here -- it doesn't serve as documentation as we have an explanatory
> > comment here already, which BTW needs to be updated accordingly if the
> > condition is extended to cover an ISA incompatibility.
>
> The naming could've been better. I went that route in the hopes that future
> checks would just flip that boolean while keeping the conditional block
> separate, otherwise we would have a bigger conditional block that may not be
> as straightforward to parse.

Fair enough -- right now we only have this single `if' statement, but if
we have a separate knob to be driven, as you're proposing, then it'll make
it easier, and therefore might encourage people to keep it clean if it
tunrs out the control needs to be more complex, e.g. by using a `switch'
statement if needed. So OK, I'm not opposing it -- let's just make it
separate from the fix to the original issue.

> > As to which, and more importantly -- there is no actual architectural
> > incompatibility between the n64 (or n32) ABI and the MIPS16 instruction
> > set; there are 64-bit MIPS processors in existence which implement the
> > MIPS16 ISA as well, e.g. the NEC VR4111, and the ISA itself includes
> > 64-bit instructions on such a processor. So the MIPS16 ISA is really
> > agnostic to the ABI, just as is the regular MIPS ISA or the microMIPS ISA.
> > Therefore any such fix needs to go elsewhere I'm afraid -- we probably do
> > something outright silly for the ISA_MIPS16 setting.
>
> Fair enough. Do you have a suggestion on where that fix should go to?

None offhand, I'll see if I can have a look soon. With my observation
above about `mips_gdbarch_init' vs `mips_isa_regsize' I think this is a
separate bug though, probably in BFD.

> The culprit seems to be the mix of an arch selection that gives us 64-bit
> cooked registers (due to mips_abi_regsize) and an ISA that gives us 32-bit
> registers (due to mips_isa_regsize). With that combination,
> mips_pseudo_register_read will fail in a fatal way, as well as
> mips_pseudo_register_write if we ever manage to go past the reading step.

Correct, however setting the MIPS16 ISA (or microMIPS, for that matter,
as this is analogous) shouldn't affect `mips_isa_regsize'. That just
seems plain wrong to me. I suspect this might be just some historical
baggage, needing cleaning up.

Maciej