[lldb-dev] display register fields?

Greg Clayton via lldb-dev lldb-dev at lists.llvm.org
Mon Jan 29 13:11:13 PST 2018

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
> On Jan 29, 2018, at 12:08 PM, Ted Woodward via lldb-dev <lldb-dev at lists.llvm.org> wrote:
> Is there a way to define and display register fields, like gdb? Or would
> this need to be done in python?
> Example:
> (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}}
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
> Linux Foundation Collaborative Project
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20180129/31d5eeea/attachment.html>

More information about the lldb-dev mailing list