2016-04-25 2 views
0

Comment puis-je obtenir l'adresse de ma variable par référence à DWARF?Comment déréférencer une référence dans DWARF

Par exemple, nous avons les structures suivantes:

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) {} 
} 

Après que nous initialize cette structure dans l'environnement mondial:

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

Dans la pratique test_inst.as_ref devrait se référer à la structure test_sub. Et je veux obtenir l'emplacement de la variable qui est stockée dans as_ref référence.

Si je lis fichier nain de code compilé, alors je vais chercher mes structures créées:

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 

Comme vous pouvez le voir test_inst est situé à 0x1fff6e50 adresse. Et test_sub est situé à 0x1fff6e48. C'est correct. Si nous vérifions la mémoire, puis:

  • test_sub.a est situé à 0x1fff6e48
  • test_sub.b est situé à 0x1fff6e4c
  • test_inst.as_ref devrait être situé à 0x1fff6e50
  • test_inst.c est situé à 0x1fff6e54
  • test_inst.d est situé à 0x1fff6e58

Je veux savoir comment trouver manuellement 0x1fff6e48 adresse, si je référer uniquement dans as_ref.

Information Nain pour main_struct est la suivante:

<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 type est référence à ceci:

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

qui sera rereference à ceci:

<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 

Répondre

1

TLDR: pointeur et refe les clôtures sont la même chose sous l'hameçon. as_ref contient l'adresse du sub_struct référencé.

Cela vous dit que as_ref est situé à l'offset 0 (ainsi 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) 

Il est le type est donné par:

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

qui signifie qu'il est une référence à un autre type. Les références et les pointeurs sont sous le même cap: ils contiennent l'adresse d'une autre variable.

A l'intérieur du processus:

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); 

D'un autre processus:

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);