Is qRegisterInfo required

Hello everyone,

I’m playing around with having lldb connect to a custom gdbserver (which doesn’t support the
qRegisterInfo query). I started out by writing a simple stub ABI plugin that defines the register

table for my target, but reading further through the code, I’m somewhat confused by the separation of concerns here. In particular, it seems like having the gdbserver provide qRegisterInfo is required unless runnning on ARM in which case GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters will add it using has a copy of the Register table from the ABI. I was under the impression that supporting qRegisterInfo was a good idea if registers ever change/get added but was not required and LLDB would fall back on the ABI plugin. Is that not the case? And if not, why not?

Keno

Actually after looking into Process/Utility, I’m even more confused. What’s the canonical way to declare registers for a target. Also why does it depend on operating system.
Shouldn’t the registers themselves be only CPU dependent (is it an ABI difference?)?

Hello everyone,

I'm playing around with having lldb connect to a custom gdbserver (which doesn't support the
qRegisterInfo query). I started out by writing a simple stub ABI plugin that defines the register
table for my target, but reading further through the code, I'm somewhat confused by the separation of concerns here. In particular, it seems like having the gdbserver provide qRegisterInfo is required unless runnning on ARM in which case GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters will add it using has a copy of the Register table from the ABI.

This was only for backward compatibility with older iOS devices whose debugserver didn't support the qRegisterInfo packet.

I was under the impression that supporting qRegisterInfo was a good idea if registers ever change/get added but was not required and LLDB would fall back on the ABI plugin.
Is that not the case? And if not, why not?

How could the ABI tell you what registers are available through the interface? For example, on ARM, which registers will be available? R0-15, CPSR? Most probably. R8_fiq-R15_fiq? Only if you are debugging something that supports protected mode debugging like JTAG drivers. R13_sys and R14_sys and cpsr_sys? Again only if you have something that supports protected mode debugging. What order would those registers come in? R0 - R15 followed by CPSR? Maybe. Maybe CPSR, then R0-R15. Does R8_fiq-R15_fiq come next or does R13_sys and R14_sys and cpsr_sys? There is no way to tell. Each OS and interface always represents the registers contexts that are pushed differently. If you connect to newer ARM cores you might have BVR/BCR debug registers (JTAG), you might not (user space debugging sometimes doesn't expose these at a thread level because the OS doesn't support them in their thread contexts. So the ABI is absolutely no help is telling you how a OS or emulator will stores its registers contexts.

The old state of things was: custom build a GDB for your architecture with hard coded register contexts. Do the same for your GDB-remote binary which has the same hard coded notion of register. If the two do not match, you are hosed. The other problem is that as you were developing support for your binary, you compiler might change and use different register numbers for DWARF, EH frame and more. Allowing dynamic register info gets us out of all these issues. If your compiler numbers changes, you would need to go and change GDB and GDB-server and recompile and make sure to use the right copies of the binaries.

The new state of things is: the GDB remote server should tell you what registers it can provide dynamically so we don't run into the above case. There is one section of hard coded registers that for ARM on iOS due to us not being able to ever change the debugserver for older iOS releases. Other than that you have two options:

1 - add support for the qRegisterInfo and dynamically tell LLDB about your registers
2 - make a target definition file that defines the registers your GDB remote binary supports and set the settings:

See example target definition python files by doing:

% svn cat http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/x86_64_linux_target_definition.py
% svn cat http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/x86_64_qemu_target_definition.py
% svn cat http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/x86_64_target_definition.py

Then set your target definition file:

(lldb) settings set plugin.process.gdb-remote.target-definition-file /tmp/my_target_definition.py

Then attach and debug. If your GDB remote binary supports qRegisterInfo it will still use that, but if it doesn't, it will fall back to using the target-definition-file you specify in the setting.

Let me know if you have more questions.

Greg Clayton

See my other email and let me know if you still have questions.

Greg

Hi Greg,

thank you so much for your detailed explanation, much appreciated. That makes a lot of sense.
I’m still confused why the register definitions are duplicated in so many places though (in the non gdb-remote case, I guess).
The ABI has a copy, the Process has a copy and even in Process/Utility there seems to be some confusion about how things are organized (some platforms have a RegisterInfoInterface, some just fold that into the RegisterContext). Is this just historical? If so what’s the preferred way to do these things now. Second, in the gdb-remote case, wouldn’t it make sense to give the GDBRemoteRegisterContext an optional RegisterInfoInterface that it could use if the dynamic info is not available. Given that we have to do this for the old iOS case anyway, wouldn’t that be a cleaner abstraction?

Thanks,
Keno

Hi Greg,

thank you so much for your detailed explanation, much appreciated. That makes a lot of sense.
I'm still confused why the register definitions are duplicated in so many places though (in the non gdb-remote case, I guess).
The ABI has a copy, the Process has a copy and even in Process/Utility there seems to be some confusion about how things are organized (some platforms have a RegisterInfoInterface, some just fold that into the RegisterContext). Is this just historical?

There are many register numbers. One kind is DWARF register numbers for when a variable says "my value is in register 12". Each ABI usually specifies what the DWARF register numbers are for each registers. So the ABI can in fact answer "what is the DWARF register number for 'rax'". It just can't answer what order the registers are in and in what groupings they come in (GPR, FPU, Exception?, or all registers in one big buffer).

If so what's the preferred way to do these things now.

I would still like to have things specified manually. This way you could ship a compiler + lldb that all works together. Then you modify the compiler and it changes the DWARF register numbers, but when you ship the tools they all go together. We could have a way to specify that the DWARF register number is "ABI", and we could then lookup the ABI register number by checking with the "ABI" plug-in. The main issue I see with that is when we connect to a remote GDB server, we often stop for the first time, then we run the qRegisterInfo packets. We might not have an ABI plug-in yet because we haven't been able to load the dynamic loader plug-in or run any other qHostInfo, qProcessInfo packets to tell us what we are debugging so we might not know.

Second, in the gdb-remote case, wouldn't it make sense to give the GDBRemoteRegisterContext an optional RegisterInfoInterface that it could use if the dynamic info is not available. Given that we have to do this for the old iOS case anyway, wouldn't that be a cleaner abstraction?

Not really. We have dealt with changing ARM registers over the years with iOS and by far the best thing we did was have the "debugserver" binary on the device tell us what registers are available since it makes things really simple. If not, we have to get the CPUID from the chip and try to figure out which generation it was and then figure out what registers were available with kernel version 1.2.3. So we let the low level software that runs on a device figure it out as it often has access to sysctl() and many other local functions that help it to determine what registers are available. Otherwise you must allow the code on the remote side of this (LLDB) figure it out by calling down through the GDB remote interface and possibly having to add packets to return the results of a sysctl() call, or call any other system functions. It just makes more sense to determine this on the device in the GDB server since it it always on the device in question.

Greg Clayton

Hi Greg,

thank you so much for your detailed explanation, much appreciated. That makes a lot of sense.
I'm still confused why the register definitions are duplicated in so many places though (in the non gdb-remote case, I guess).
The ABI has a copy, the Process has a copy and even in Process/Utility there seems to be some confusion about how things are organized (some platforms have a RegisterInfoInterface, some just fold that into the RegisterContext). Is this just historical?

There are many register numbers. One kind is DWARF register numbers for when a variable says "my value is in register 12". Each ABI usually specifies what the DWARF register numbers are for each registers. So the ABI can in fact answer "what is the DWARF register number for 'rax'". It just can't answer what order the registers are in and in what groupings they come in (GPR, FPU, Exception?, or all registers in one big buffer).

If so what's the preferred way to do these things now.

I would still like to have things specified manually.

What I meant here is have the GDB server specify things so LLDB can dynamically get the info from the GBD server.

Let me second what Greg said here. The Hexagon simulator supports many
different core versions, with different register sets. Having the simulator
implement qRegisterInfo lets LLDB not care which core version it's talking
to. I could look at the target binary, but we can legally run a v4 binary on
a v5 core, so that doesn't work.

I fully expect to be able to use today's LLDB to talk to a hypothetical new
Hexagon core 5 years from now. It won't care about the registers because the
simulator/target stub will tell it what they are.

Ok, having registers vary between different core versions is an
understandable concern and I think the solution is good - I guess I'm lucky
in that my targets all have one set of registers that I'm interested in ;).
I guess my confusion stemmed from the fact that it seems like adding a new
target requires so many things that the register table seemed minor (I
understand now that it is not). Would it make sense to edit the
lldb-for-gdb-remote.txt, which currently says

//----------------------------------------------------------------------
// "qRegisterInfo<hex-reg-id>"
//
// BRIEF
// Discover register information from the remote GDB server.
//
// PRIORITY TO IMPLEMENT
// High. Any target that can self describe its registers, should do so.
// This means if new registers are ever added to a remote target, they
// will get picked up automatically, and allows registers to change
// depending on the actual CPU type that is used.
//----------------------------------------------------------------------

to indicate that this is indeed required in order for LLDB to do any
debugging with this target?

Also, I still think that some of this stuff is more duplicated than it
needs to be. For example, grepping for gcc_dwarf_ymm in the current tree
gives three different locations where this is declared, shouldn't that be
somehow factored out?

We could have a way to specify that the DWARF register number is "ABI",

and we could then lookup the ABI register number

by checking with the "ABI" plug-in. The main issue I see with that is

when we connect to a remote GDB server, we often stop

for the first time, then we run the qRegisterInfo packets. We might not

have an ABI plug-in yet because we haven't been able

to load the dynamic loader plug-in or run any other qHostInfo,

qProcessInfo packets to tell us what we are debugging so we

might not know.

Sorry, I didn't understand this suggestion. What exactly does the ABI
register number define? Is it the one used by the compiler for e.g.
eh_frame? Are you suggesting, the ABI plugin specify a mapping from the
dwarf to the compiler register numbers but not the full register info table?

Ok, having registers vary between different core versions is an understandable concern and I think the solution is good - I guess I'm lucky in that my targets all have one set of registers that I'm interested in ;). I guess my confusion stemmed from the fact that it seems like adding a new target requires so many things that the register table seemed minor (I understand now that it is not). Would it make sense to edit the lldb-for-gdb-remote.txt, which currently says

//----------------------------------------------------------------------
// "qRegisterInfo<hex-reg-id>"
//
// BRIEF
// Discover register information from the remote GDB server.
//
// PRIORITY TO IMPLEMENT
// High. Any target that can self describe its registers, should do so.
// This means if new registers are ever added to a remote target, they
// will get picked up automatically, and allows registers to change
// depending on the actual CPU type that is used.
//----------------------------------------------------------------------

to indicate that this is indeed required in order for LLDB to do any debugging with this target?

Yes, other one must reply to the qRegisterInfo packets, or they must create a target definition python file and specify it using the "settings set".

Also, I still think that some of this stuff is more duplicated than it needs to be. For example, grepping for gcc_dwarf_ymm in the current tree gives three different locations where this is declared, shouldn't that be somehow factored out?

Depends if they are all the same or not. They might differ for some targets. If they are the same, we can centralize them into a single file.

>We could have a way to specify that the DWARF register number is "ABI", and we could then lookup the ABI register number
> by checking with the "ABI" plug-in. The main issue I see with that is when we connect to a remote GDB server, we often stop
> for the first time, then we run the qRegisterInfo packets. We might not have an ABI plug-in yet because we haven't been able
> to load the dynamic loader plug-in or run any other qHostInfo, qProcessInfo packets to tell us what we are debugging so we
> might not know.

Sorry, I didn't understand this suggestion. What exactly does the ABI register number define?

Your ABI specifies for your target what registers numbers will be used by the compiler for the DWARF register numbers and also the compiler register numbers (which might differ). We have "ABI" plug-ins that help us to determine things like calling conventions when calling functions with multiple arguments (where to put arg1, arg2, arg3, etc), where return values will be (in which registers and if too large for registers where on the stack), and many other aspects of general calling conventions. In order to get an ABI plug-in that could answer the question of "what is the DWARF register number for 'rax'", we need to first find an ABI plug-in using a target triple "x86_64-apple-macosx". When we first connect to a target via GDB remote, we might not know this right away, so we have a chicken/egg problem: "I can't find out about my registers unless you can give me a target triple", or "I can't get my target triple unless I can check if register 'version' is available".

Is it the one used by the compiler for e.g. eh_frame? Are you suggesting, the ABI plugin specify a mapping from the dwarf to the compiler register numbers but not the full register info table?

DWARF register numbers can differ from EH frame registers numbers. An ABI plug-in for a given triple can usually answer the DWARF and compiler registers numbers, but again, if you hardcode this in the ABI, and if you change your ABI as you are developing it, you would not be able to change things around to test a new compiler with new register numbers without modifying the debugger itself. That sounds like a bad idea to me.

So this all leads to: lets discover the registers dynamically because you don't want to change the debugger if you can avoid it.

Greg

Thanks again Greg, really appreciate you taking the time to answer my questions.

I’ll commit some clarification to lldb-for-gdb-remote.txt later.

To play devil’s advocate, one last question. Why does the ABI plugin have to have register information at all? If we agree hardcoding this is a bad idea, shouldn’t it always ask the process for this information?

It does IMHO because the ARM ABI documentation specifies the DWARF register information in their ABI PDF docs.