On Thu, Jul 24, 2014 at 10:15 AM, Joseph Koshy
<jko...@users.sourceforge.net> 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

------------------------------------------------------------------------------
Infragistics Professional
Build stunning WinForms apps today!
Reboot your WinForms applications with our WinForms controls. 
Build a bridge from your legacy apps to the future.
http://pubads.g.doubleclick.net/gampad/clk?id=153845071&iu=/4140/ostg.clktrk
_______________________________________________
Elftoolchain-developers mailing list
Elftoolchain-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/elftoolchain-developers

Reply via email to