Mike Copeland <
mrc...@cox.net> writes:
> I have a fair amount of code to search for matches on constants and
>assign "offset values" of the constants' position in an array. The code
>is tedious and slow, and making changes to add new constants is
>difficult.
> In some other languages I've used there there's a way to assign an
>"address value" that's coded in a table, so that a loop can be used to
>scan for matches and assign a value to an associated variable whose
>address is in the table. Something like:
>
> {"NO.", &BNoffset, "BIB", &BNoffset, "PLACE", &OPoffset, etc. }
>
> Is such a thing available in C++? If so, how is it coded and used?
If you can do it in C, you can do it in C++, the same way. Consider
a class as a struct and use offset_of to store the offset of the
class/struct data member in the array.
# define OFFSET_OF(struct, member) \
((size_t)(&(reinterpret_cast<struct*>(__alignof__(struct*)))->member) - \
__alignof__(struct*))
/**
* Describe the "location" of each of the registers named above in the
* current guest. The entries in this table should be ordered
* consistent with the register enumeration and regnames tables.
*/
static struct _reglist guestregs[] = {
{ OFFSET_OF(user_regs_t, rax), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rbx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rcx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rdx), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rsp), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rbp), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rsi), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, rdi), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r8 ), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r9 ), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r10), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r11), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r12), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r13), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r14), sizeof(uint64), BASE_URP },
{ OFFSET_OF(user_regs_t, r15), sizeof(uint64), BASE_URP },
{ OFFSET_OF(vmcb_t, rip), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, rflags), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, ss.selector), sizeof(uint16), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cs.selector), sizeof(uint16), BASE_VMCB },
{ OFFSET_OF(vmcb_t, exit_code)+4, sizeof(uint32), BASE_VMCB },
{ OFFSET_OF(vmcb_t, exit_info1)+4, sizeof(uint32), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr0), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr2), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr3), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, cr4), sizeof(uint64), BASE_VMCB },
{ 0, sizeof(uint64), BASE_DR },
{ 1, sizeof(uint64), BASE_DR },
{ 2, sizeof(uint64), BASE_DR },
{ 3, sizeof(uint64), BASE_DR },
{ 4, sizeof(uint64), BASE_DR },
{ 5, sizeof(uint64), BASE_DR },
{ OFFSET_OF(vmcb_t, dr6), sizeof(uint64), BASE_VMCB },
{ OFFSET_OF(vmcb_t, dr7), sizeof(uint64), BASE_VMCB },
};
switch (rp->r_base) {
case BASE_URP:
base = urp;
break;
case BASE_VMCB:
base = vp;
break;
...
}
switch (rp->r_len) {
case sizeof(uint64_t):
contents = getu64((uint64)base + rp->r_offset);
break;
case sizeof(uint32_t):
contents = getu32((uint64)base + rp->r_offset);
break;
case sizeof(uint16_t):
contents = getu16((uint64)base + rp->r_offset);
break;
case sizeof(uint8_t):
contents = getu8((uint64)base + rp->r_offset);
break;
}
/**
* Return an unsigned 16-bit quantity from the designed address.
* Returns the value zero if the address couldn't be validated.
*
* @param addr The address from which to fetch the word
* @returns the word value at address, or zero if address isn't valid
*/
inline uint16_t
c_debugger::getu16(uint64_t addr)
{
if (check(addr, sizeof(uint16_t))) return *(uint16_t *)addr;
return 0;
}
(This code is from a bare-metal hypervisor written in C++)