C 如何从dwarf信息获取结构成员偏移量?

C 如何从dwarf信息获取结构成员偏移量?,c,struct,offset,objdump,dwarf,C,Struct,Offset,Objdump,Dwarf,我试图将DW_AT_data_member_location属性值从dwarf info打印到获取成员变量与结构名称的偏移量,但似乎没有任何帮助函数起作用 以下是来自objdump的dwarf_信息: <1><1bf>: Abbrev Number: 5 (DW_TAG_structure_type) <1c0> DW_AT_name : (indirect string, offset: 0xf0): class <1c4>

我试图将DW_AT_data_member_location属性值从dwarf info打印到
获取成员变量与结构名称的偏移量
,但似乎没有任何帮助函数起作用

以下是来自
objdump
的dwarf_信息:

<1><1bf>: Abbrev Number: 5 (DW_TAG_structure_type)
<1c0>   DW_AT_name        : (indirect string, offset: 0xf0): class  
<1c4>   DW_AT_byte_size   : 208 
<1c5>   DW_AT_decl_file   : 1   
<1c6>   DW_AT_decl_line   : 10  
<1c7>   DW_AT_sibling     : <0x1f8> 
<2><1cb>: Abbrev Number: 6 (DW_TAG_member)
<1cc>   DW_AT_name        : (indirect string, offset: 0xc7): schools    
<1d0>   DW_AT_decl_file   : 1   
<1d1>   DW_AT_decl_line   : 11  
<1d2>   DW_AT_type        : <0x1f8> 
<1d6>   DW_AT_data_member_location: 2 byte block: 23 0  (DW_OP_plus_uconst: 0)
<2><1d9>: Abbrev Number: 6 (DW_TAG_member)
<1da>   DW_AT_name        : (indirect string, offset: 0xd8): size   
<1de>   DW_AT_decl_file   : 1   
<1df>   DW_AT_decl_line   : 12  
<1e0>   DW_AT_type        : <0x159> 
<1e4>   DW_AT_data_member_location: 3 byte block: 23 c8 1   (DW_OP_plus_uconst: 200)
<2><1e8>: Abbrev Number: 6 (DW_TAG_member)
<1e9>   DW_AT_name        : (indirect string, offset: 0xf6): record 
<1ed>   DW_AT_decl_file   : 1   
<1ee>   DW_AT_decl_line   : 13  
<1ef>   DW_AT_type        : <0x1b8> 
<1f3>   DW_AT_data_member_location: 3 byte block: 23 cc 1   (DW_OP_plus_uconst: 204)
此变量的类型是什么? 如何获得它的价值?
哪个辅助函数在这里工作?

DWARF调试格式允许将成员的偏移量表示为简单常量或需要计算偏移量的表达式。无论出于何种原因,您试图处理的调试信息以表达式的形式表示了一个简单的常量偏移量。您需要“计算”表达式以确定偏移量。大概是这样的:

if (attrcode == DW_AT_data_member_location) {
    Dwarf_Half form;
    dwarf_whatform(attrs[i], &form, &error);
    if (form == DW_FORM_data1 || form == DW_FORM_data2
        form == DW_FORM_data2 || form == DW_FORM_data4
        form == DW_FORM_data8 || form == DW_FORM_udata) {
        dwarf_formudata(attrs[i], &offset, 0);
    } else if (form == DW_FORM_sdata) {
        Dwarf_Signed soffset;
        dwarf_formsdata(attrs[i], &soffset, 0);
        if (soffset < 0) {
             printf("unsupported negative offset\n");
             /* FAIL */
        }
        offset = (Dwarf_Unsigned) soffset;
    } else {
        Dwarf_Locdesc **locdescs;
        Dwarf_Signed len;
        if (dwarf_loclist_n(attrs[i], &locdescs, &len,  &error) == DW_DLV_ERROR) {
             printf("unsupported member offset\n");
             /* FAIL */
        }
        if (len != 1
            || locdescs[0]->ld_cents != 1
            || (locdescs[0]->ld_s[0]).lr_atom != DW_OP_plus_uconst) {
             printf("unsupported location expression\n");
             /* FAIL */
        }
        offset = (locdescs[0]->ld_s[0]).lr_number;
    }
}
if(attrcode==DW\u在数据成员位置){
矮化半形式;
dwarf_whatform(attrs[i],&form,&error);
if(form==DW_form_data1 | | form==DW_form_data2
形式==DW|U形式|U数据2 |形式==DW|U形式|U数据4
形式==DW_形式_数据8||形式==DW_形式_数据){
dwarf_formudata(attrs[i],&offset,0);
}否则如果(形式==DW\U形式\U数据){
矮人符号soffset;
dwarf_formsdata(attrs[i],&soffset,0);
if(soffset<0){
printf(“不支持的负偏移量\n”);
/*失败*/
}
偏移量=(无符号)soffset;
}否则{
矮人_Locdesc**locdescs;
小矮人;
if(dwarf\u loclist\n(attrs[i]、&locdescs、&len、&error)==DW\u DLV\u error){
printf(“不支持的成员偏移量\n”);
/*失败*/
}
如果(len!=1
||locdescs[0]->ld_cents!=1
||(locdescs[0]->ld_s[0]).lr_原子!=DW_OP_plus_uconst){
printf(“不支持的位置表达式\n”);
/*失败*/
}
偏移量=(locdescs[0]->ld_s[0])。lr_编号;
}
}

如果您喜欢使用JVM,我编写了一个简单的示例,创建了一个基于EMF的模型。下面是打印结构成员位置的示例代码:

def someFunction() {
  var elf = new Elf32Context(buffer)
  var dwarf = new Dwarf32Context(elf)
  var model = DwarfModelFactory::createModel(dwarf)
  model.eAllContents.filter(StructureType).forEach[it.dumpStruct]
}


def dumpStruct(CompositeType struct) '''
  «switch(struct) {StructureType:'struct' UnionType:'union' default:'composite?'}» «struct.typedef?.name» {
    «FOR m : struct.members»
        «m.type.dumpType» «m.name»  @«m.dataMemberLocation»
    «ENDFOR»
  }
'''

我希望您展示的代码片段只是伪代码,因为否则,变量与文本字符串的比较是非常可疑的。事实上,如果这是真实的代码,那么条件永远不会是真的。此外,如果这是真实的代码,那么上面的
printf
调用也是可疑的。@JoachimPileborg感谢您的指出。。我已经编辑了代码,非常感谢。我现在明白了。我对你的代码做了一些编辑。可能是您没有运行代码,因此错误地将某些(指向struct的指针)假定为(struct)本身。再次感谢:-)我根本没有测试它,因为我不得不写一堆其他的代码来达到这个代码可以工作的地方。谢谢你用正确的代码更新了答案。你能评论一下我如何获得变量的位置(地址)吗?代码示例在最后一个分支中有内存泄漏。以下释放将释放libdwarf分配的内存:dwarf_dealloc(debug,locdescs[0]>ld_s,DW_DLA_LOC_BLOCK);dwarf_dealoc(调试,locdescs[0],DW_DLA_LOCDESC);dwarf_dealloc(调试、locdescs、DW_DLA_列表);或者将最后一个分支替换为:if(form==DW\u form\u block1){Dwarf\u Block*Block;int rv=Dwarf\u formblock(DW\u属性,&Block,NULL);assert(rv==DW\u DLV\u OK);if(DW\u OP\u加上uconst==(uint8\u t)Block->bl\u data){uint8\u t*leb128=Block->bl\u data+sizeof(uint8\t);int i,shift=0;offset=0;for(i=1;ibl_len;++i){offset |=(*leb128++&(1
def someFunction() {
  var elf = new Elf32Context(buffer)
  var dwarf = new Dwarf32Context(elf)
  var model = DwarfModelFactory::createModel(dwarf)
  model.eAllContents.filter(StructureType).forEach[it.dumpStruct]
}


def dumpStruct(CompositeType struct) '''
  «switch(struct) {StructureType:'struct' UnionType:'union' default:'composite?'}» «struct.typedef?.name» {
    «FOR m : struct.members»
        «m.type.dumpType» «m.name»  @«m.dataMemberLocation»
    «ENDFOR»
  }
'''