2016-04-25 60 views
0

如何从DWARF引用我的变量地址?如何在DWARF中对引用进行解引用

例如,我们有下一个结构:

struct sub_struct 
{ 
    int a, b; 
    sub_struct(int a, int b) : a(a), b(b) {} 
} 

struct main_struct 
{ 
    sub_struct & as_ref; 
    int c, d; 
    main_struct(sub_struct & ss) : as_ref(ss), c(0x100), d(0x101) {} 
} 

之后,我们初始化这个结构,全球环境:

sub_struct test_sub(0x10, 0x11); 
main_struct test_inst(sub_struct); 

在实践test_inst.as_ref应该有参考结构test_sub。我想获取存储在as_ref参考中的变量的位置。

如果我读的编译代码矮文件,然后我会得到我的创建结构:

Compilation Unit @ offset 0x1a80bf: 
    Length:  0x11e (32-bit) 
    Version:  3 
    Abbrev Offset: 0xd3e6 
    Pointer Size: 4 
<0><1a80ca>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    <1a814d> DW_AT_stmt_list : 0x8e02a 
    <1a8151> DW_AT_macro_info : 0xc6fb 
<1><1a819b>: Abbrev Number: 3 (DW_TAG_variable) 
    <1a819c> DW_AT_name  : test_inst 
    <1a81ad> DW_AT_type  : <0x1a7643> 
    <1a81b6> DW_AT_location : 5 byte block: 3 50 6e ff 1f (DW_OP_addr: 1fff6e50) 
    <1a81bc> Unknown AT value: 2768: 1 
<1><1a81e0>: Abbrev Number: 0 

    Compilation Unit @ offset 0x1a829e: 
    Length:  0xb8 (32-bit) 
    Version:  3 
    Abbrev Offset: 0xd3e6 
    Pointer Size: 4 
<0><1a82a9>: Abbrev Number: 1 (DW_TAG_compile_unit) 
    <1a832c> DW_AT_stmt_list : 0x8e02a 
    <1a8330> DW_AT_macro_info : 0xc6fb 
<1><1a8334>: Abbrev Number: 3 (DW_TAG_variable) 
    <1a8335> DW_AT_name  : test_sub 
    <1a834a> DW_AT_type  : <0x1a761a> 
    <1a8352> DW_AT_location : 5 byte block: 3 48 7d ff 1f (DW_OP_addr: 1fff7d48) 
    <1a8358> Unknown AT value: 2768: 1 
<1><1a8359>: Abbrev Number: 0 

正如你可以看到test_inst位于0x1fff6e50地址。而test_sub位于0x1fff6e48。这是对的。如果我们将检查内存,然后:

  • test_sub.a位于0x1fff6e48
  • test_sub.b位于0x1fff6e4c
  • test_inst.as_ref应位于0x1fff6e50
  • test_inst.c位于在0x1fff6e54
  • test_inst.d位于0x1fff6e58

我想知道如何手动查找0x1fff6e48地址,如果我只参考ence as_ref

main_struct矮信息是这样的:

<1><1a7643>: Abbrev Number: 40 (DW_TAG_structure_type) 
    <1a7644> DW_AT_sibling  : <0x1a76cf> 
    <1a7648> DW_AT_name  : test_struct 
    <1a7654> DW_AT_byte_size : 44 
<2><1a7655>: Abbrev Number: 44 (DW_TAG_member) 
    <1a7656> DW_AT_type  : <0x1a683a> 
    <1a7658> DW_AT_accessibility: 1 (public) 
    <1a7659> DW_AT_name  : as_ref 
    <1a7660> DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) 
<2><1a7663>: Abbrev Number: 44 (DW_TAG_member) 
    <1a7664> DW_AT_type  : <0x1a6833> 
    <1a7666> DW_AT_accessibility: 1 (public) 
    <1a7667> DW_AT_name  : c 
    <1a7669> DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4) 
<2><1a766c>: Abbrev Number: 44 (DW_TAG_member) 
    <1a766d> DW_AT_type  : <0x1a6833> 
    <1a766f> DW_AT_accessibility: 1 (public) 
    <1a7670> DW_AT_name  : d 
    <1a7672> DW_AT_data_member_location: 2 byte block: 23 8 (DW_OP_plus_uconst: 8) 
<2><1a76ce>: Abbrev Number: 0 

as_ref类型是参照这样的:

<1><1a683a>: Abbrev Number: 5 (DW_TAG_reference_type) 
<1a683b> DW_AT_type  : <0x1a761a> 

这将是rereference这样:

<1><1a761a>: Abbrev Number: 40 (DW_TAG_structure_type) 
    <1a761b> DW_AT_sibling  : <0x1a7643> 
    <1a761f> DW_AT_name  : sub_struct 
    <1a762f> DW_AT_byte_size : 8 
<2><1a7630>: Abbrev Number: 44 (DW_TAG_member) 
    <1a7631> DW_AT_type  : <0x1a6833> 
    <1a7633> DW_AT_accessibility: 1 (public) 
    <1a7634> DW_AT_name  : a 
    <1a7636> DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) 
<2><1a7639>: Abbrev Number: 44 (DW_TAG_member) 
    <1a763a> DW_AT_type  : <0x1a6833> 
    <1a763c> DW_AT_accessibility: 1 (public) 
    <1a763d> DW_AT_name  : b 
    <1a763f> DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4) 
<2><1a7642>: Abbrev Number: 0 

回答

1

TLDR:指针和参考rences在hookd下是同样的东西。 as_ref包含引用的sub_struct的地址。

这告诉您as_ref位于偏移0(因此0x1fff6e50):

<2><1a7655>: Abbrev Number: 44 (DW_TAG_member) 
    <1a7656> DW_AT_type  : <0x1a683a> 
    <1a7658> DW_AT_accessibility: 1 (public) 
    <1a7659> DW_AT_name  : as_ref 
    <1a7660> DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) 

它的类型由下式给出:

<1><1a683a>: Abbrev Number: 5 (DW_TAG_reference_type) 
    <1a683b> DW_AT_type  : <0x1a761a> 

这意味着它是另一种类型的引用。引用和指针都是同样的东西:它们包含另一个变量的地址。

过程里面:

void* main_struct_addr = 0x1fff6e50; // from DWARF 
std::uint64_t as_ref_offset = 0;  // from DWARF 
void* main_as_ref_addr = (char*) main_struct_addr + as_ref_offset; 
void as_addr = *(void**) main_a_ref_addr; 
assert(as_adddr == (void*) 0x1fff6e48); 

从另一个过程:

std::uint64_t main_struct_addr = 0x1fff6e50; // from DWARF 
std::uint64_t as_ref_offset = 0;    // from DWARF 
std::uint64_t main_as_ref_addr = main_struct_addr + as_ref_offset; 
errno = 0; 
void* as_addr = (void*) ptrace(PTRACE_PEEKDATA, pid, (void*) main_as_ref_addr, NULL); 
if (errno) { ... } 
assert(as_adddr == (void*) 0x1fff6e48);