Reputation: 11
We have a third party Software that's picks out information from generated .elf about our global variables which are using DWARF debug info to find it. Previously we have been using IAR compiler which producing the .elf file including debugging DWARF info. With the .elf file produced from IAR there is no problem finding out location address in memory and name of variable. But when producing the .elf file with gcc "GNU Arm Embedded Toolchain 9-2020-q3-update) 9.3.1 20200408 (release)” the SW have problem locating the variables that are global variables that are declared extern in header file and definition I .c file.
So to my question, is there a way to get the DWARF info regarding external global variables to look more like the ones produced by IAR, look at example below showing an extern global variable using readelf.
Programming language: C CFLAGS: (-ggdb -ffunction-sections -O0 -gpubnames)(I've tried alot of different Compiler options regardning DWARF settings but with no luck)
The IAR produces this:
<1><2f1ab>: Abbrev Number: 3 (DW_TAG_variable)
<2f1ac> DW_AT_name : StopBtn_StopBtnActvd_flg
<2f1c5> DW_AT_type : <0x29d80>
<2f1c9> DW_AT_decl_file : 4
<2f1ca> DW_AT_decl_line : 46
<2f1cb> DW_AT_decl_column : 11
<2f1cc> Unknown AT value: 276a: 34
<2f1cd> DW_AT_external : 1
<2f1ce> DW_AT_location : 5 byte block: 3 aa 45 1 20 (DW_OP_addr: 200145aa)
<2f1d4> Unknown AT value: 2768: 1
<1><2f1d5>: Abbrev Number: 0
GCC produces this (information is divided into 2 sections when using gcc in _debug:info):
<1><46158>: Abbrev Number: 45 (DW_TAG_variable)
<46159> DW_AT_name : (indirect string, offset: 0x21a4): StopBtn_StopBtnActvd_flg
<4615d> DW_AT_decl_file : 11
<4615e> DW_AT_decl_line : 102
<4615f> DW_AT_decl_column : 17
<46160> DW_AT_type : <0x45dc1>
<46164> DW_AT_external : 1
<46164> DW_AT_declaration : 1
<1><46164>: Abbrev Number: 45 (DW_TAG_variable)
--
<1><46655>: Abbrev Number: 46 (DW_TAG_variable)
<46656> DW_AT_specification: <0x46158>
<4665a> DW_AT_decl_file : 12
<4665b> DW_AT_decl_line : 46
<4665c> DW_AT_decl_column : 11
<4665d> DW_AT_location : 5 byte block: 3 7a 4 0 20 (DW_OP_addr: 2000047a)
<1><46663>: Abbrev Number: 46 (DW_TAG_variable)
<46664> DW_AT_specification: <0x46164>
<46668> DW_AT_decl_file : 12
<46669> DW_AT_decl_line : 47
Upvotes: 1
Views: 1181
Reputation: 213375
We have a third party Software that's picks out information from generated .elf about our global variables which are using DWARF debug info to find it.
The issue appears to be that your 3rd-party software doesn't follow the DWARF
standard. In particular, it doesn't follow the DW_AT_specification
pointer to find the name of the variable located at 2000047a
.
Since DW_AT_specification
is part of DWARF2
from 1993, you can do very little other than complain the to 3rd party vendor: they had almost 30 years! to get this right.
One other thing you can possibly do to work around this is to move your global variable definitions into a file which doesn't include any headers.
Compare:
// foo.c
int var1 = 42;
with:
// bar.h
extern int var2;
// bar.c
#include "bar.h"
int var2 = 43;
When using 9.3.0-17ubuntu1~20.04
, readelf -wi foo.o
yields:
<1><1d>: Abbrev Number: 2 (DW_TAG_variable)
<1e> DW_AT_name : (indirect string, offset: 0x92): var1
<22> DW_AT_decl_file : 1
<23> DW_AT_decl_line : 1
<24> DW_AT_decl_column : 5
<25> DW_AT_type : <0x33>
<29> DW_AT_external : 1
<29> DW_AT_location : 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0)
while readelf -wi bar.o
yields:
<1><1d>: Abbrev Number: 2 (DW_TAG_variable)
<1e> DW_AT_name : (indirect string, offset: 0x93): var2
<22> DW_AT_decl_file : 1
<23> DW_AT_decl_line : 1
<24> DW_AT_decl_column : 12
<25> DW_AT_type : <0x29>
<29> DW_AT_external : 1
<29> DW_AT_declaration : 1
...
<1><30>: Abbrev Number: 4 (DW_TAG_variable)
<31> DW_AT_specification: <0x1d>
<35> DW_AT_decl_file : 2
<36> DW_AT_decl_line : 2
<37> DW_AT_decl_column : 5
<38> DW_AT_location : 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0)
Update:
But decalarion and definition in a c file of the variable makes it hard to reach for other c files, that have relations to that variable. So I guess this is no possible solution for me
You can keep the declaration in the header file, and use it everywhere except the one file which provides the definition.
Here is the workaround I am suggesting. Suppose your current code looks like this:
// foo.h
extern int var;
int foo1();
int foo2();
// foo.c
#include "foo.h"
int var = 42;
int foo1() { ...}
int foo2() { ...}
// bar.c
#include "foo.h"
int bar() { return var + foo1() + foo2(); }
Proposed workaround: move the definition of var
into a separate file, and don't #include "foo.h"
into that file:
// foo.c
#include "foo.h"
/* no longer define var here. */
int foo1() {...}
int foo2() {...}
// foo_var.c
int var = 42;
The other files would remain unchanged.
Upvotes: 1