Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DWARF info seem to be wrong for DW_AT_high_pc with gcc 4.8.2

Tags:

c

gcc

objdump

dwarf

As a newbie to DWARF, I tried the code presented in this page (code is here) but when I launch it I get:

$> ./dwarf_get_func_addr tracedprog
DW_TAG_subprogram: 'do_stuff'
abort() in libdwarf. No error argument, no handler.
zsh: abort (core dumped)  ./dwarf_get_func_addr tracedprog

After a debugging session, the problem appears to come from line 78:

    else if (attrcode == DW_AT_high_pc)
        dwarf_formaddr(attrs[i], &highpc, 0);

The problem is, the form of attrs[i] shows attrs[i] is not an address (it is set to 7 instead of 1). Exploring tracedprog with objdump it gives, for do_stuff function:

<1><73>: Numéro d'abréviation: 4 (DW_TAG_subprogram)
    <74>   DW_AT_external    : 1
    <74>   DW_AT_name        : (chaîne indirecte, décalage: 0x55): do_stuff
    <78>   DW_AT_decl_file   : 1
    <79>   DW_AT_decl_line   : 4
    <7a>   DW_AT_prototyped  : 1
    <7a>   DW_AT_low_pc      : 0x400500
    <82>   DW_AT_high_pc     : 0x3f
    <8a>   DW_AT_frame_base  : 1 bloc d'octets: 9c      (DW_OP_call_frame_cfa)
    <8c>   DW_AT_GNU_all_tail_call_sites: 1
    <8c>   DW_AT_sibling     : <0xb9>

In this output, DW_AT_high_pc doesn't seem correct to me as it is only two octets long.

For your reference, I compiled tracedprog with:

$> gcc -g tracedprog2.c -o tracedprog

Edit it seems to be a gcc issue as there is no issue on another machine. I am using gcc 4.8.2.

like image 975
Vincent Avatar asked Feb 14 '23 15:02

Vincent


2 Answers

To use DW_AT_high_pc with libdwarf on a binary compiled by gcc >= 4.8 without overriding the default DWARF version one has to check the form of the attribute before extracting the value.

Depending on the version of the DWARF information, the DW_AT_high_pc attribute can be either a DW_FORM_addr form or a DW_FORM_data8 form. Each form has its own extracting function.

Here is an example of how to check the form of the an attribute:

void print_attribute(Dwarf_Attribute a)
{
    Dwarf_Half form;
    Dwarf_Error err;
    Dwarf_Half attrcode;
    unsigned int offset = 0;
    Dwarf_Addr addr;

    dwarf_whatform(a, &form, &err);

    switch(form)
    {
    case DW_FORM_addr:
        dwarf_formaddr(a, &addr, &err);
        printf("DW_FORM_addr: 0x%08llx\n", addr);
        break;
    case DW_FORM_data8:
        dwarf_formudata(a, &offset , &err);
        printf("DW_FORM_data8: 0x%08llx\n", offset);
        break;
    default:
        break;
    }
}          
like image 56
fdeslaur Avatar answered Apr 27 '23 00:04

fdeslaur


I found the issue. Starting from gcc 4.8, default DWARF version is 4. To make my program work, I had to compile tracedprog with -gdwarf-2 flag.

like image 25
Vincent Avatar answered Apr 27 '23 00:04

Vincent