display register fields?

Is there a way to define and display register fields, like gdb? Or would
this need to be done in python?

(gdb) p/x $vac0
$3 = {value = 0xedcba111, fields = {LENGTH = 0x111, SRC4_BANK = 0xa,
SRC3_BANK = 0xb,
      SRC2_BANK = 0xc, SRC1_BANK = 0xd, DEST1_BANK = 0xe}}

There isn't a built-in way to do this.

It would be nice to have "register {format, summary, synthetic children} add <REGNAME> {provider}" in parallel with the "type {format/summary/synthetic} add".

The registers come to us as value objects so it would be straightforward to hook them up, and the various ways of providing the formats should be exactly the same.


Two way you can do this, the easy way, and the hard way.

The easy way is to allow a register to define a summary string that can be attached to itself, just like “type summary add …”, but there is no typename to associate here, you just give the summary a unique name. Type summaries allow you to access bits of an integer using the “” operator. So if you have a variable that is an integer, then you can do have a summary string of “bit zero = ${var[0]}”. This will show bit zero of the ${var} which in this case is your register. Since we hand out register values in lldb_private::ValueObject objects, and lldb::SBValue through the API, it would be easy to just give the lldb_private::ValueObject a summary when a RegisterInfo has one. If you want to access more that one bit, you can use “low nibble = ${var[0-3]}”. So this would easily allow you to add a summary to any register. “type summary add” also has a “–name” option that allows you to name the summary. So if you uniquely name your register summary string with something like:

(lldb) type summary add --summary-string “N=${var[31]} Z=${var[30]} C=${var[29]} V=${var[28]}” --name register.arm.cpsr

Then you can always just give your register’s value object the summary by name just like:

(lldb) frame variable --summary register.arm.cpsr argc
(int) argc = 1 N=0 Z=0 C=0 V=0

The drawback of the summary approach is you can to something like:
(lldb) expr $cpsr.N

The hard way would be to actually define a CompilerType for the register and somehow attach it to the value object for the register when you hand them out. The benefit of this is the expression above would work and the fields could be accessed. This means your register context would need to create a CompilerType from scratch and register it with the Target’s type system for a specific language. This could be made easier by having a register value just write a blurb or C code like:

const char *CPSRType_code = “struct CPSRType { uint32_t N:1, Z:1, C:1, V:1; };”

Then we ask the target to create a type from code:

CompilerType reg_type = target.CreateTypeFromCode(CPSRType_code, “CPSRType”, eLanguageC);

This would use the code in “CPSRType_code” and compile it and grab the type from the compiled code named “CPSRType” and it would compile it in C so the resulting CompilerType would be clang based.

The benefit of this is your code could contain enum values and multiple types. Think of the real definition for a complete CPSR for ARM:

const char *CPSRType_code = "
namespace arm {
enum Mode { User = 0x10, FIQ = 0x11, IRQ = 0x12, SVC = 0x13, Abort = 0x17, Undefined = 0x1b, System = 0x1f };

struct CPSRType {
uint32_t N:1, Z:1, C:1, V:1;
Mode mode;

This would allow us to define “arm::Mode” as an enum and have that enum in a struct named “arm::CPSRType” and then put them all together:

CompilerType t = target.CreateTypeFromCode(CPSRType_code, “arm::CPSRType”, eLanguageC);

Then attach the type “t” to your lldb_private::ValueObject for your register.

Greg Clayton