Hi Sasha,
On Sat, 2020-06-06 at 00:30 +0000, Sasha Da Rocha Pinheiro wrote:
> As you can see the following variables have distinct locations:
> [ 81] variable abbrev: 5
> name (string) "a"
> decl_file (data1) sasha.c (1)
> decl_line (data1) 12
> type (ref4) [ cd]
> location (sec_offset) location list
> [ 0]
> [ 9f] variable abbrev: 5
> name (string) "g"
> decl_file (data1) sasha.c (1)
> decl_line (data1) 15
> type (ref4) [ cd]
> location (sec_offset) location list
> [ 4a]
> [ bd] variable abbrev: 5
> name (string) "z"
> decl_file (data1) sasha.c (1)
> decl_line (data1) 16
> type (ref4) [ cd]
> location (sec_offset) location list
> [ 6e]
>
> But when I use the code I sent before to list the three variables, I
> always get:
>
> [main01.cpp:73] - Variable and location found (a), size(1).
> [main01.cpp:78] - interval: (0x0,0x5)
> [main01.cpp:78] - interval: (0x5,0xa)
> [main01.cpp:78] - interval: (0x16,0x24)
> [main01.cpp:73] - Variable and location found (g), size(1).
> [main01.cpp:78] - interval: (0x0,0x5)
> [main01.cpp:78] - interval: (0x5,0xa)
> [main01.cpp:78] - interval: (0x16,0x24)
> [main01.cpp:73] - Variable and location found (z), size(1).
> [main01.cpp:78] - interval: (0x0,0x5)
> [main01.cpp:78] - interval: (0x5,0xa)
> [main01.cpp:78] - interval: (0x16,0x24)
>
>
> No matter the locationAttribute the code always get the first
> location descriptors in .debug_loc:
>
> DWARF section [ 7] '.debug_loc' at offset 0x1c6:
>
> CU [ b] base: .text+000000000000000000 <main>
> [ 0] range 0, 5
> .text+000000000000000000 <main>..
> .text+0x0000000000000004 <main+0x4>
> [ 0] lit0
> [ 1] stack_value
> range 5, a
> .text+0x0000000000000005 <main+0x5>..
> .text+0x0000000000000009 <main+0x9>
> [ 0] reg1
> range 16, 24
> .text+0x0000000000000016 <main+0x16>..
> .text+0x0000000000000023 <main+0x23>
> [ 0] reg1
> [ 4a] range 0, 5
> .text+000000000000000000 <main>..
> .text+0x0000000000000004 <main+0x4>
> [ 0] lit0
> [ 1] stack_value
> [ 6e] range 5, a
> .text+0x0000000000000005 <main+0x5>..
> .text+0x0000000000000009 <main+0x9>
> [ 0] lit0
> [ 1] stack_value
> range a, e
> .text+0x000000000000000a <main+0xa>..
> .text+0x000000000000000d <main+0xd>
> [ 0] const4u 65537
> [ 5] breg0 0
> [ 7] minus
> [ 8] stack_value
I think I see what is happening. The fact that <main> is at
.text+000000000000000000 suggests that this is actually an ET_REL file
(not linked object file). The libdw dwarf_xxx calls don't do
relocations. But eu-readelf does. So while eu-readelf shows some
offsets as their relocated values, your program just using dwarf_xxx
calls does not. Specifically the DW_AT_location list attributes will
all point to zero. Which explains why every location list seems to be
the same.
We don't have a public function to just apply all relocations to an
object file, but opening the file through dwfl_begin () will do it.
Something like the attached.
Hope that helps,
Mark
/* Print all locations in the whole DIE tree of a single file using
dwfl to handle ET_REL files (which need the .debug sections to be
relocated) and to automatically get separate debuginfo.
gcc -Wall -Wextra -g -O2 -o dwfl_dwarf dwfl_dwarf.c -ldw
*/
/* We want the sane basename function. */
#define _GNU_SOURCE
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <inttypes.h>
#include <dwarf.h>
#include <elfutils/libdw.h>
#include <elfutils/libdwfl.h>
void
handle_die (Dwarf_Die *die)
{
do
{
Dwarf_Attribute attr;
if ((dwarf_attr (die, DW_AT_location, &attr) != NULL))
{
printf ("[%" PRIx64 "]", dwarf_dieoffset (die));
ptrdiff_t off = 0;
Dwarf_Addr base, start, end;
do
{
Dwarf_Op *expr;
size_t exprlen;
off = dwarf_getlocations(&attr, off, &base, &start, &end,
&expr, &exprlen);
if (off > 0)
printf ("(%" PRIx64 ",%" PRIx64 ")[%zd] ",
start, end, exprlen);
}
while (off > 0);
printf ("\n");
}
Dwarf_Die child;
if (dwarf_child (die, &child) == 0)
handle_die (&child);
}
while (dwarf_siblingof (die, die) == 0);
}
static const Dwfl_Callbacks dwfl_callbacks =
{
.find_debuginfo = dwfl_standard_find_debuginfo,
.section_address = dwfl_offline_section_address,
.find_elf = dwfl_build_id_find_elf,
};
int main (int argc, char **argv)
{
if (argc == 2)
{
const char *file = argv[1];
const char *base = basename (file);
/* Create a one elf module file Dwfl. */
Dwfl *dwfl = dwfl_begin (&dwfl_callbacks);
dwfl_report_begin (dwfl);
Dwfl_Module *mod = dwfl_report_elf (dwfl, base, file, -1, 0, true);
dwfl_report_end (dwfl, NULL, NULL);
Dwarf_Addr bias;
Dwarf *dbg = dwfl_module_getdwarf(mod, &bias);
if (dbg != NULL)
{
/* Should be zero with one module. */
printf ("bias: %" PRIx64 "\n", bias);
Dwarf_CU *cu = NULL;
Dwarf_Half version;
Dwarf_Die cudie, subdie;
uint8_t unit_type;
while (dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
&cudie, &subdie) == 0)
handle_die (&cudie);
}
dwfl_end (dwfl);
}
}