From: Daniel W. <dan...@gm...> - 2014-07-29 20:23:18
|
On Thu, Jul 24, 2014 at 10:15 AM, Joseph Koshy <jk...@us...> wrote: > dw> Libelf and Libdwarf are APIs to nowhere: they are full of functions > dw> that tell you how to get a foo from a bar, but do not tell you how to > dw> get a bar in the first place or what you can do with a foo once you > dw> have one. jk> As for DWARF(3), we have an open ticket (#23) to write a tutorial jk> for the DWARF(3) API. Please feel free to submit a patch; notes jk> on some possible contents for the tutorial are here: jk> jk> http://sourceforge.net/p/elftoolchain/wiki/LibDwarfTutorial/ For some DWARF attribute forms I have been unable to get a meaningful value no matter how long I read your documentation or grep through your source. (Note that below I omit error checking for readability.) >From a Dwarf_Die const die, I can get an attribute list: Dwarf_Attribute *attrbuf; Dwarf_Signed attrcount; Dwarf_Error dwarf_error; dwarf_attrlist(die, &attrbuf, &attrcount, &dwarf_error); Iterating over the list I can get Dwarf_Attributes: Dwarf_Attribute const at = attrbuf[i]; >From each attribute I can get the code: Dwarf_Half at_code; dwarf_whatattr(at, &at_code, &dwarf_error); I can get the attribute's name: char const *at_name; dwarf_get_AT_name(at_code, &at_name); I can get the attribute's form: Dwarf_Half at_form; dwarf_whatform(at, &at_form, &dwarf_error); And for many forms, I can get some sort of sensible value. (Sometimes there are even multiple APIs to do so: dwaf_attrval_flag() / dward_formflag().) switch (at_form) { case DW_FORM_flag: case DW_FORM_flag_present: { Dwarf_Bool flag; // fix: dwarf_attrval_flag() seems redundant with // dwarf_formflag(); there are other such examples dwarf_attrval_flag(die, at_code, &flag, &dwarf_error); out << (flag ? "T" : "F") << std::endl; break; } case DW_FORM_string: case DW_FORM_strp: { char const *string; dwarf_attrval_string(die, at_code, &string, &dwarf_error); out << "'" << string << "'" << std::endl; break; } case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_sdata: { Dwarf_Signed signed_int; dwarf_attrval_signed(die, at_code, &signed_int, &dwarf_error); out << (signed_int >= 0 ? "+" : "") << signed_int << std::endl; break; } case DW_FORM_udata: { Dwarf_Unsigned unsigned_int; dwarf_attrval_unsigned(die, at_code, &unsigned_int, &dwarf_error) out << unsigned_int << std::endl; break; } case DW_FORM_addr: { // from libdwarf.h: // typedef uint64_t Dwarf_Addr; Dwarf_Addr dwarf_addr; dwarf_formaddr(at, &dwarf_addr, &dwarf_error); out << dwarf_addr << std::endl; break; } This one is quite tricky, as due to the DWARF DIE tree encoding: when you recurse you have to remember to not look for the siblings of the root as they are non-sensical when referred to in this context (the symptom is that traversing the DIE tree leads to an infinite loop; fun!): case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: { Dwarf_Off ref_offset; dwarf_formref(at, &ref_offset, &dwarf_error); Dwarf_Die ref_die; dwarf_offdie(dwarf_debug, ref_offset, &ref_die, &dwarf_error); // NOTE: don't look for siblings here: dwarf nodes linked in // this way seem to exhibit phantom siblings due to the // dwarf encoding traversal.traverse(ref_die, depth+1, false/*look_for_siblings*/); break; } But for some forms, even if I have an API to give me something, I have no idea how to process the result in a meaningful way: case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: { // from libdwarf.h: // typedef struct { // Dwarf_Unsigned bl_len; // Dwarf_Ptr bl_data; // } Dwarf_Block; // typedef uint64_t Dwarf_Unsigned; // typedef void *Dwarf_Ptr; Dwarf_Block *block; dwarf_formblock(at, &block, &dwarf_error); // FIX: then what? break; } case DW_FORM_exprloc: { // from libdwarf.h: // typedef uint64_t Dwarf_Unsigned; // typedef void *Dwarf_Ptr; Dwarf_Unsigned exprloc_len; Dwarf_Ptr exprloc; dwarf_formexprloc(at, &exprloc_len, &exprloc, &dwarf_error); // FIX: then what? break; } Note that the technique of case DW_FORM_ref1 above does not work here: case DW_FORM_ref_addr: case DW_FORM_sec_offset: { // from libdwarf.h: // typedef off_t Dwarf_Off; Dwarf_Off ref_offset; dwarf_global_formref(at, &ref_offset, &dwarf_error); // FIX: then what? break; } Daniel |