2016-04-25 30 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);