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@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@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to