llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.83k stars 11.91k forks source link

No DWARF information for external global variable in shared object #102143

Open GwenTheKween opened 2 months ago

GwenTheKween commented 2 months ago

Hello. I am compiling the following code:

extern int gdb_dlmopen_glob;

__attribute__((visibility ("default")))
int
inc (int n)
{
  int amount = gdb_dlmopen_glob;
  return n + amount;  /* bp.inc.  */
}

With the following command line calls to clang:

clang -fdiagnostics-color=never -Wno-unknown-warning-option -fpic -c -g -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.base/dlmopen-lib-dep.c
clang /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so -fdiagnostics-color=never -Wno-unknown-warning-option -shared -g -Wl,-soname,dlmopen-lib.1.so -Wl,-rpath,$ORIGIN -ldl -lm -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so

Looking at the debug information in the resulting shared object, there is no references to gdb_dlmopen_glob. I believe there should be a declaration of the external variable in the resulting output, which is in line with the debug information generated by GCC.

For convenience, here's a compiler explorer page that is setup to compile the code and compare the debug info from gcc and clang: https://godbolt.org/z/7x3r8TPEv

llvmbot commented 2 months ago

@llvm/issue-subscribers-debuginfo

Author: Guinevere Larsen (GwenTheKween)

Hello. I am compiling the following code: ``` extern int gdb_dlmopen_glob; __attribute__((visibility ("default"))) int inc (int n) { int amount = gdb_dlmopen_glob; return n + amount; /* bp.inc. */ } ``` With the following command line calls to clang: ``` clang -fdiagnostics-color=never -Wno-unknown-warning-option -fpic -c -g -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.base/dlmopen-lib-dep.c clang /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so -fdiagnostics-color=never -Wno-unknown-warning-option -shared -g -Wl,-soname,dlmopen-lib.1.so -Wl,-rpath,$ORIGIN -ldl -lm -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so ``` Looking at the debug information in the resulting shared object, there is no references to gdb_dlmopen_glob. I believe there should be a declaration of the external variable in the resulting output, which is in line with the debug information generated by GCC. For convenience, here's a compiler explorer page that is setup to compile the code and compare the debug info from gcc and clang: https://godbolt.org/z/7x3r8TPEv
dwblaikie commented 2 months ago

As with calls to external functions, clang doesn't produce debug info for external entities (well, if we're producing call_site info we will produce function declarations, but not otherwise). This is an intentional choice to reduce debug info size.

It's probably not the most expensive debug info to emit, but generally clang assumes the whole program is built with debug info (as GCC and Clang both do in other ways, though arguably when clang is passed -fstandalone-debug it could produce global variable declarations in the resulting DWARF)

llvmbot commented 2 months ago

@llvm/issue-subscribers-clang-codegen

Author: Guinevere Larsen (GwenTheKween)

Hello. I am compiling the following code: ``` extern int gdb_dlmopen_glob; __attribute__((visibility ("default"))) int inc (int n) { int amount = gdb_dlmopen_glob; return n + amount; /* bp.inc. */ } ``` With the following command line calls to clang: ``` clang -fdiagnostics-color=never -Wno-unknown-warning-option -fpic -c -g -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/../../../binutils-gdb/gdb/testsuite/gdb.base/dlmopen-lib-dep.c clang /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.c.o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib-dep.so -fdiagnostics-color=never -Wno-unknown-warning-option -shared -g -Wl,-soname,dlmopen-lib.1.so -Wl,-rpath,$ORIGIN -ldl -lm -o /home/gwenthekween/Documents/upstream-build/gdb/testsuite/outputs/gdb.base/dlmopen/dlmopen-lib.1.so ``` Looking at the debug information in the resulting shared object, there is no references to gdb_dlmopen_glob. I believe there should be a declaration of the external variable in the resulting output, which is in line with the debug information generated by GCC. For convenience, here's a compiler explorer page that is setup to compile the code and compare the debug info from gcc and clang: https://godbolt.org/z/7x3r8TPEv
jebradbury39 commented 1 month ago

Here's another example of this issue (slightly different, as it involves header files):

https://godbolt.org/z/5PdExcPKG

main.c


#include <stdio.h>
#include "test.h"

int main (int argc, char** argv) { printf("foo = %d\n", g_foo); return 0; }


> lib.c

include "test.h"

int g_foo = 15;


> test.h

extern int g_foo;


The primary difference in functionality is that gcc always records the declarations (for each compilation unit):

> main.c

0x00000077: DW_TAG_variable DW_AT_name ("g_foo") DW_AT_decl_file ("/app/test.h") DW_AT_decl_line (1) DW_AT_decl_column (12) DW_AT_type (0x00000058 "int") DW_AT_external (true) DW_AT_declaration (true)


> lib.c

0x00000101: DW_TAG_variable DW_AT_name ("g_foo") DW_AT_decl_file ("/app/test.h") DW_AT_decl_line (1) DW_AT_decl_column (12) DW_AT_type (0x0000010d "int") DW_AT_external (true) DW_AT_declaration (true)

0x00000114: DW_TAG_variable DW_AT_specification (0x00000101 "g_foo") DW_AT_decl_file ("/app/lib.c") DW_AT_decl_line (3) DW_AT_decl_column (5) DW_AT_location (DW_OP_addr 0x404018)


Whereas clang only records the definitions (only for the compilation unit where the definition resides):

0x00000094: DW_TAG_variable DW_AT_name ("g_foo") DW_AT_type (0x0000009f "int") DW_AT_external (true) DW_AT_decl_file ("/app/lib.c") DW_AT_decl_line (3) DW_AT_location (DW_OP_addrx 0x0)



Note that I did try out `-fstandalone-debug` as well (however, this did not produce the declaration info).

Having access to the declarations via the DWARF is rather handy for some debug scenarios (for example, it allows a more precise addr2line implementation which can show you both the definition and declaration point for a given address), so it would be nice to have this working in clang (even if it is something you have to enable via a flag, rather than being turned on by default).