> On Nov 17, 2014, at 3:59 PM, Zachary Turner <ztur...@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



_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to