Thanks. <div><br></div><div>I'm working on a very not-fancy implementation for Windows. When I get it done, who would be the best person to take a look at it if I put up a review?</div><div><br></div><div>Even if I'm the only person that understands the Windows-specific stuff, I think it would help to have someone familiar with these classes take a look at my implementation to make sure I've understood each of the functions correctly, and perhaps point out any gotchas that I might have fallen victim to or not be aware of.<br><br><div class="gmail_quote">On Mon Nov 17 2014 at 5:01:02 PM Greg Clayton <<a href="mailto:gclayton@apple.com" target="_blank">gclayton@apple.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> On Nov 17, 2014, at 3:59 PM, Zachary Turner <<a href="mailto:zturner@google.com" target="_blank">zturner@google.com</a>> wrote:<br>
><br>
> I'm looking into adding a new RegisterContext for windows. Virgile's patch that I was working on merging inherited from RegisterContext_POSIX, but on the surface this seems like the wrong thing to do, and I wonder if we need an entirely new one for Windows (or need to change the name of RegisterContext_POSIX to something else).<br>
><br>
> What are all the steps involved here? From what I can tell at a minimum I need to implement a RegisterContextWindows_x86 and RegisterContextWindows_x86_64, but there's also RegisterInfoInterface and a few other things I need to figure out.<br>
><br>
> A few other specific questions:<br>
> 1) Why is all this stuff for different platforms is in Plugins/Process/Utility, instead of in the individual process plugins like Plugins/Process/Linux, or Plugins/Process/FreeBSD?<br>
<br>
These were being used by multiple plug-ins. FreeBSD and Linux are closely related (they use ptrace) so they can sometimes share their register contexts.<br>
<br>
><br>
> 2) Some code seems to be dead. Like in RegisterContextPosix, there's a long list of static variables, g_contained_eax, g_invalidate_eax, etc. But none of this stuff seems to be used for anything. Am I overlooking something obvious?<br>
<br>
If they are dead then remove them. Looking at the RegisterInfo struct:<br>
<br>
typedef struct<br>
{<br>
const char *name; // Name of this register, can't be NULL<br>
const char *alt_name; // Alternate name of this register, can be NULL<br>
uint32_t byte_size; // Size in bytes of the register<br>
uint32_t byte_offset; // The byte offset in the register context data where this register's value is found<br>
lldb::Encoding encoding; // Encoding of the register bits<br>
lldb::Format format; // Default display format<br>
uint32_t kinds[lldb::kNumRegisterKinds]<u></u><u></u>; // Holds all of the various register numbers for all register kinds<br>
uint32_t *value_regs; // List of registers that must be terminated with LLDB_INVALID_REGNUM<br>
uint32_t *invalidate_regs; // List of registers that must be invalidated when this register is modified, list must be terminated with LLDB_INVALID_REGNUM<br>
} RegisterInfo;<br>
<br>
<br>
Registers can define registers that make up the value for this register (like "d0" on ARM can say it is made up from "s0" and "s1" since "d0" is a 64 bit register). Then this register is read from, it will not issue a register read for its own register number, but it will request all registers in "value_regs" be read instead.<br>
<br>
Likewise, you might want to invalidate registers when this register is modified, like "eax" (if you define one in your register context) would invalidate "rax" "ax" "al" if "eax" is modified.<br>
<br>
The static arrays seem to be left over from a copy and paste where g_contained_eax represented the register for "value_regs" or "invalidate_regs"...<br>
<br>
><br>
> 3) What is the difference between a RegisterInfoInterface and a RegisterContext?<br>
<br>
I am not sure, this class was implemented, but it isn't referenced currently.<br>
<br>
For register contexts you will just need to override all pure virtual functions in lldb_private::RegisterContext.<br>
<br>
<br>
You must define all of your registers by returning a count:<br>
<br>
virtual size_t<br>
RegisterContextWindows::<u></u>GetReg<u></u>isterCount () = 0;<br>
<br>
And supply a register info for each register. Register numbers are zero based index identifiers that must have no gaps. Each register must have a RegisterInfo struct that describes it:<br>
<br>
virtual const RegisterInfo *<br>
RegisterContextWindows::<u></u>GetReg<u></u>isterInfoAtIndex (size_t reg) = 0;<br>
<br>
<br>
You must also describe your register sets:<br>
<br>
virtual size_t<br>
GetRegisterSetCount () = 0;<br>
<br>
virtual const RegisterSet *<br>
GetRegisterSet (size_t reg_set) = 0;<br>
<br>
You must also be able to convert register numbers of various kinds into actual zero based register index IDs:<br>
<br>
virtual uint32_t<br>
ConvertRegisterKindToRegisterN<u></u><u></u>umber (lldb::RegisterKind kind, uint32_t num) = 0;<br>
<br>
<br>
And read and write the registers (see all remaining pure virtuals).<br>
<br>
The common way to define your register infos is to just have a static array in your RegisterContextWindows.cpp:<br>
<br>
static RegisterInfo g_x86_64_register_infos[] =<br>
{<br>
...<br>
}<br>
<br>
<br>
Then your RegisterContextWindows::<u></u>GetReg<u></u>isterInfoAtIndex() just returns<br>
<br>
const RegisterInfo *<br>
RegisterContextWindows::<u></u>GetReg<u></u>isterInfoAtIndex (size_t reg)<br>
{<br>
if (reg < sizeof_array(g_x86_64_<u></u>register<u></u>_infos))<br>
return g_x86_64_register_infos[reg];<br>
return NULL;<br>
}<br>
<br>
So there is nothing that special about the register context class, just implement the pure virtual and abstract it underneath so you have different classes for i386 and x86_64. The register context defines a bunch of bytes for all registers and the register info structs contain the byte_offset into the big data buffer that can contain all of your registers.<br>
<br>
Let me know if you have any questions.<br>
<br>
Greg<br>
<br>
<br>
</blockquote></div></div>