I'm trying to use dladdr. It correctly locates the library, but it does not find the function name. I can call objdump, do a little math, and get the address of the function that I pass dladdr. If objdump can see it, why can't dladdr?
Here is my function:
const char *FuncName(const void *pFunc)
{
Dl_info DlInfo;
int nRet;
// Lookup the name of the function given the function pointer
if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
return DlInfo.dli_sname;
return NULL;
}
Here is a gdb transcript showing what I get.
Program received signal SIGINT, Interrupt.
[Switching to Thread 0xf7f4c6c0 (LWP 28365)]
0xffffe410 in __kernel_vsyscall ()
(gdb) p MatchRec8Cmp
$2 = {void (TCmp *, TWork *, TThread *)} 0xf1b62e73 <MatchRec8Cmp>
(gdb) call FuncName(MatchRec8Cmp)
$3 = 0x0
(gdb) call FuncName(0xf1b62e73)
$4 = 0x0
(gdb) b FuncName
Breakpoint 1 at 0xf44bdddb: file threads.c, line 3420.
(gdb) call FuncName(MatchRec8Cmp)
Breakpoint 1, FuncName (pFunc=0xf1b62e73) at threads.c:3420
3420 {
The program being debugged stopped while in a function called from GDB.
When the function (FuncName) is done executing, GDB will silently
stop (instead of continuing to evaluate the expression containing
the function call).
(gdb) s
3426 if ((nRet = dladdr(pFunc, &DlInfo)) != 0)
(gdb)
3427 return DlInfo.dli_sname;
(gdb) p DlInfo
$5 = {dli_fname = 0x8302e08 "/xxx/libdata.so", dli_fbase = 0xf1a43000, dli_sname = 0x0, dli_saddr = 0x0}
(gdb) p nRet
$6 = 1
(gdb) p MatchRec8Cmp - 0xf1a43000
$7 = (void (*)(TCmp *, TWork *, TThread *)) 0x11fe73
(gdb) q
The program is running. Exit anyway? (y or n) y
Here is what I get from objdmp
$ objdump --syms /xxx/libdata.so | grep MatchRec8Cmp
0011fe73 l F .text 00000a98 MatchRec8Cmp
Sure enough, 0011fe73 = MatchRec8Cmp - 0xf1a43000. Anyone know why dladdr can't return dli_sname = "MatchRec8Cmp" ???
I'm running Red Hat Enterprise Linux Server release 5.4 (Tikanga). I have seen this work before. Maybe it's my compile switches:
CFLAGS = -m32 -march=i686 -msse3 -ggdb3 -pipe -fno-common -fomit-frame-pointer \
-Ispio -fms-extensions -Wmissing-declarations -Wstrict-prototypes -Wunused -Wall \
-Wno-multichar -Wdisabled-optimization -Wmissing-prototypes -Wnested-externs \
-Wpointer-arith -Wextra -Wno-sign-compare -Wno-sequence-point \
-I../../../include -I/usr/local/include -fPIC \
-D$(Uname) -D_REENTRANT -D_GNU_SOURCE
I have tried it with -g instead of -ggdb3 although I don't think debugging symbols have anything to do with elf.
If objdump can see it, why can't dladdr
dladdr can only see functions exported in the dynamic symbol table. Most likely
nm -D /xxx/libdata.so | grep MatchRec8Cmp
shows nothing. Indeed your objdump shows that the symbol is local, which proves that this is the cause.
The symbol is local either because it has a hidden visibility, is static, or because you hide it in some other way (e.g. with a linker script).
Update:
Those marked with the 'U' work with dladdr. They get "exported" automatically somehow.
They work because they are exported from some other shared library. The U stands for unresolved, i.e. defined elsewhere.
I added -rdynamic to my LDFLAGS.
man gcc says:
-rdynamic
Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the
dynamic symbol table. This option is needed for some uses of "dlopen" or to allow obtaining backtraces from within a program.
Adding the gcc option "-export-dynamic" solved this for me.
hinesmr solution worked for me. The exact option I passed gcc was "-Wl,--export-dynamic" and all the functions became visible to dladdr
Related
Here is the source file fragment:
#define TEST 34
#define PRINT_CONCAT(a, b) \
printf("%d\n", a##b)
Compiling with GCC and linking this source file into a binary with flags -ggdb3 -O3 and running the app with gdb shows up the following behavior:
(gdb) p TEST
$3 = 34
(gdb) p PRINT_CONCAT
No symbol "PRINT_CONCAT" in current context.
Is there a way to make gdb expand function macros in any way?
It turned to be as easy as macro expand
(gdb) macro expand PRINT_CONCAT(2, 4)
expands to: printf("%d\n", 24)
-ggdb3 is not even required, -g3 is enough. -g2 does not seem to include the desired information.
I know that on ELF platforms, __attribute__((constructor)) uses the .ctors ELF section. Now I realized that the function attribute works with GCC on MinGW as well and I'm wondering how it is implemented.
For MinGW targets (and other COFF targets, like Cygwin) compiler just emits each constructor function address in .ctors COFF section:
$ cat c1.c
void c1() {
}
$ x86_64-w64-mingw32-gcc -c c1.c
$ objdump -x c1.o | grep ctors
# nothing
$ cat c1.c
__attribute__((constructor)) void c1() {
}
$ x86_64-w64-mingw32-gcc -c c1.c
$ objdump -x c1.o | grep ctors
5 .ctors 00000008 0000000000000000 0000000000000000 00000150 2**3
GNU ld linker (for MinGW targets) is then configured (via its default linker script) to combine these sections into regular .text section with __CTOR_LIST__ symbol pointing to the first item, and having the last item terminated with zero. (Probably .rdata section would be clearer since these are just addresses of functions, not CPU instructions, but for some reason .text is used. In fact LLVM LLD linker targeting MinGW places them in .rdata.)
LD linker:
$ x86_64-w64-mingw32-ld --verbose
...
.text ... {
...
__CTOR_LIST__ = .;
LONG (-1); LONG (-1);
KEEP (*(.ctors));
KEEP (*(.ctor));
KEEP (*(SORT_BY_NAME(.ctors.*)));
LONG (0); LONG (0);
...
...
}
Then it is up to C runtime library to run these constructors during initialization, by using this __CTOR_LIST__ symbol.
From mingw-w64 C runtime:
extern func_ptr __CTOR_LIST__[];
void __do_global_ctors (void)
{
// finds the last (zero terminated) item
...
// then runs from last to first:
for (i = nptrs; i >= 1; i--)
{
__CTOR_LIST__[i] ();
}
...
}
(also, it is very similar in Cygwin runtime)
This can be also seen in the debugger:
$ echo $MSYSTEM
MINGW64
$ cat c11.c
#include <stdio.h>
__attribute__((constructor))
void i1() {
puts("i 1");
}
int main() {
puts("main");
return 0;
}
$ gcc c11.c -o c11
$ gdb ./c11.exe
(gdb) b i1
(gdb) r
(gdb) bt
#0 0x00007ff603591548 in i1 ()
#1 0x00007ff6035915f2 in __do_global_ctors () at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:44
#2 0x00007ff60359164f in __main () at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:58
#3 0x00007ff60359139b in __tmainCRTStartup () at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:313
#4 0x00007ff6035914f6 in mainCRTStartup () at C:/_/M/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:202
(gdb)
Note that in some environments (not MinGW and not Linux) it is instead the responsibility of GCC (its compiler runtime libgcc, more specifically its static part called crtbegin.o and crtend.o) and not C runtime to run these constructors.
Also, for comparison, on ELF targets (like Linux) GCC compiler used similar mechanism like the one described above for MinGW (it used ELF .ctors sections, although the rest was a bit different), but since GCC 4.7 (released in 2012) it uses slightly different mechanism (ELF .init_array section).
I have a function in my C code that is being called implicitly, and getting dumped by the linker. how can I prevent this phenomena?
I'm compiling using gcc and the linker flag -gc-sections, and I don't want to exclude the whole file from the flag. I tried using attributes: "used" and "externally_visible" and neither has worked.
void __attribute__((section(".mySec"), nomicromips, used)) func(){
...
}
on map file I can see that the function has compiled but didn't linked. am I using it wrong? is there any other way to do it?
You are misunderstanding the used attribute
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced...
i.e the compiler must emit the function definition even the function appears
to be unreferenced. The compiler will never conclude that a function is unreferenced
if it has external linkage. So in this program:
main1.c
static void foo(void){}
int main(void)
{
return 0;
}
compiled with:
$ gcc -c -O1 main1.c
No definition of foo is emitted at all:
$ nm main1.o
0000000000000000 T main
because foo is not referenced in the translation unit, is not external,
and so may be optimised out.
But in this program:
main2.c
static void __attribute__((used)) foo(void){}
int main(void)
{
return 0;
}
__attribute__((used)) compels the compiler to emit the local definition:
$ gcc -c -O1 main2.c
$ nm main2.o
0000000000000000 t foo
0000000000000001 T main
But this does nothing to inhibit the linker from discarding a section
in which foo is defined, in the presence of -gc-sections, even if foo is external, if that section is unused:
main3.c
void foo(void){}
int main(void)
{
return 0;
}
Compile with function-sections:
$ gcc -c -ffunction-sections -O1 main3.c
The global definition of foo is in the object file:
$ nm main3.o
0000000000000000 T foo
0000000000000000 T main
But after linking:
$ gcc -Wl,-gc-sections,-Map=mapfile main3.o
foo is not defined in the program:
$ nm a.out | grep foo; echo Done
Done
And the function-section defining foo was discarded:
mapfile
...
...
Discarded input sections
...
...
.text.foo 0x0000000000000000 0x1 main3.o
...
...
As per Eric Postpischil's comment, to force the linker to retain
an apparently unused function-section you must tell it to assume that the program
references the unused function, with linker option {-u|--undefined} foo:
main4.c
void __attribute__((section(".mySec"))) foo(void){}
int main(void)
{
return 0;
}
If you don't tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections main4.o
$ nm a.out | grep foo; echo Done
Done
foo is not defined in the program. If you do tell it that:
$ gcc -c main4.c
$ gcc -Wl,-gc-sections,--undefined=foo main4.o
$ nm a.out | grep foo; echo Done
0000000000001191 T foo
Done
it is defined. There's no use for attribute used.
Apart from -u already mentioned here are two other ways to keep the symbol using GCC.
Create a reference to it without calling it
This approach does not require messing with linker scripts, which means it will work for hosted programs and libraries using the operating system's default linker script.
However it varies with compiler optimization settings and may not be very portable.
For example, in GCC 7.3.1 with LD 2.31.1, you can keep a function without actually calling it, by calling another function on its address, or branching on a pointer to its address.
bool function_exists(void *address) {
return (address != NULL);
}
// Somewhere reachable from main
assert(function_exists(foo));
assert(foo != NULL); // Won't work, GCC optimises out the constant expression
assert(&foo != NULL); // works on GCC 7.3.1 but not GCC 10.2.1
Another way is to create a struct containing function pointers, then you can group them all together and just check the address of the struct. I use this a lot for interrupt handlers.
Modify the linker script to keep the section
If you are developing a hosted program or a library, then it's pretty tricky to change the linker script.
Even if you do, its not very portable, for example gcc on OSX does not actually use the GNU linker since OSX uses the Mach-O format instead of ELF.
Your code already shows a custom section though, so it's possible you are working on an embedded system and can easily modify the linker script.
SECTIONS {
// ...
.mySec {
KEEP(*(.mySec));
}
}
const int hello= 0x1111;
int main(){
}
I build a really simple code, and compile it with
gcc t.c -g -o t.out
Can I use objdump or nm or any tools to make sure the const variable value?
I always find address of variable "hello", but cannot find value
Anyone can help me, thanks a lot
The example code
const int hello = 0xdeadbeef;
int main()
{
return 0;
}
compile with
gcc-4.9 -W -Wall -Wextra -pedantic -std=c11 fortests.c -o fortests
dump the content with
objdump -xDSs fortests | less
(dumped a bit too much, but costs nothing, so ... meh ...) and search for hello
0000000000400594 g O .rodata 0000000000000004 hello
That means it is in the section .rodata. We explicitly asked objdump to list the contents of all sections, so here we have it, the value 0xdeadbeef.
Contents of section .rodata:
400590 01000200 efbeadde ........
^^^^^^^^
here ||||||||
And it should be clear by now, why you had trouble to find it.
I am compiling the below code with "-nostdlib". My understanding was that arm-none-eabi-gcc will not use the _start in "crt0.o" but it will use the user defined _start. For this I was expecting to create a start.S file and put the _start symbol.
But if I compile the below shown code without the _start symbol defined from my side, I am not getting any warning. I was expecting "warning: cannot find entry symbol _start;"
Questions:
1) Why am I not getting the warning ? From where did GCC get the _start symbol ?
2) If gcc got the _start symbol from a file from somewhere, could you let me know how to ask GCC to use the _start from my start.S file ?
$ cat test.c
int main()
{
volatile int i=0;
i = i+1;
return 0;
}
$ cat linker.ld
MEMORY
{
ram : ORIGIN = 0x8000, LENGTH = 20K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.bss*) } > ram
}
$ arm-none-eabi-gcc -Wall -Werror -O2 -mfpu=neon-vfpv4 -mfloat-abi=hard -march=armv7-a -mtune=cortex-a7 -nostdlib -T linker.ld test.c -o test.o
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.9.3 20150529 >(release) [ARM/embedded-4_9-branch revision 224288]
Compile and link with arm-none-eabi-gcc -v -Wall -Werror -O2.... to understand what the compiler is doing (and which crt0 it is using; that crt0 probably has a _start calling your main, also _start might be the default entry point for your linker)
Notice that -nostdlib is related to the (lack of) C standard library; perhaps you want to compile in a freestanding environment (see this), then use -ffreestanding (and in that case main has no particular meaning, you need to define your starting function[s], and no standard C functions like malloc or printf are available except perhaps setjmp).
Read the C99 standard n1256 draft. It explains what freestanding means in ยง5.1.2.1