[lldb-dev] Adding a new RegisterContext for Windows

Zachary Turner zturner at google.com
Tue Nov 18 16:13:56 PST 2014


Thanks.

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?

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.

On Mon Nov 17 2014 at 5:01:02 PM Greg Clayton <gclayton at apple.com> wrote:

>
> > On Nov 17, 2014, at 3:59 PM, Zachary Turner <zturner at google.com> wrote:
> >
> > 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).
> >
> > 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.
> >
> > A few other specific questions:
> > 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?
>
> 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.
>
> >
> > 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?
>
> If they are dead then remove them. Looking at the RegisterInfo struct:
>
>     typedef struct
>     {
>         const char *name;        // Name of this register, can't be NULL
>         const char *alt_name;    // Alternate name of this register, can
> be NULL
>         uint32_t byte_size;      // Size in bytes of the register
>         uint32_t byte_offset;    // The byte offset in the register
> context data where this register's value is found
>         lldb::Encoding encoding; // Encoding of the register bits
>         lldb::Format format;     // Default display format
>         uint32_t kinds[lldb::kNumRegisterKinds]; // Holds all of the
> various register numbers for all register kinds
>         uint32_t *value_regs;    // List of registers that must be
> terminated with LLDB_INVALID_REGNUM
>         uint32_t *invalidate_regs; // List of registers that must be
> invalidated when this register is modified, list must be terminated with
> LLDB_INVALID_REGNUM
>     } RegisterInfo;
>
>
> 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.
>
> 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.
>
> 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"...
>
> >
> > 3) What is the difference between a RegisterInfoInterface and a
> RegisterContext?
>
> I am not sure, this class was implemented, but it isn't referenced
> currently.
>
> For register contexts you will just need to override all pure virtual
> functions in lldb_private::RegisterContext.
>
>
> You must define all of your registers by returning a count:
>
>     virtual size_t
>     RegisterContextWindows::GetRegisterCount () = 0;
>
> 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:
>
>     virtual const RegisterInfo *
>     RegisterContextWindows::GetRegisterInfoAtIndex (size_t reg) = 0;
>
>
> You must also describe your register sets:
>
>     virtual size_t
>     GetRegisterSetCount () = 0;
>
>     virtual const RegisterSet *
>     GetRegisterSet (size_t reg_set) = 0;
>
> You must also be able to convert register numbers of various kinds into
> actual zero based register index IDs:
>
>     virtual uint32_t
>     ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind,
> uint32_t num) = 0;
>
>
> And read and write the registers (see all remaining pure virtuals).
>
> The common way to define your register infos is to just have a static
> array in your RegisterContextWindows.cpp:
>
> static RegisterInfo g_x86_64_register_infos[] =
> {
>         ...
> }
>
>
> Then your RegisterContextWindows::GetRegisterInfoAtIndex() just returns
>
> const RegisterInfo *
> RegisterContextWindows::GetRegisterInfoAtIndex (size_t reg)
> {
>         if (reg < sizeof_array(g_x86_64_register_infos))
>             return g_x86_64_register_infos[reg];
>         return NULL;
> }
>
> 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.
>
> Let me know if you have any questions.
>
> Greg
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20141119/790b6aef/attachment.html>


More information about the lldb-dev mailing list