I'm trying to get the content of the dynamic symbol table of compiled c file
#include<stdio.h>
int main(){
printf("Hello, World!");
return 0;
}
as portable executable (PE) on Linux with
i686-w64-mingw32-gcc hello_world.c -o hello32
x86_64-w64-mingw32-gcc hello_world.c -o hello64
I'm using objdump:
objdump --dynamic-syms hello32
and get the output:
hello32: file format pei-i386
objdump: hello32: not a dynamic object
DYNAMIC SYMBOL TABLE:
no symbols
I would expect to have functions like printf in the table. It works with gcc and ELF binaries.
Does anyone know how to compile the file correctly to have a dynamic symbol table with content?
The concept of dynamic symbols seems to be a bit lost in PE-targetting binutils. Use objdump -p <file> or objdump -x <file> and look for import tables in the output. I haven't found a better solution with binutils yet. There's llvm-readobj --coff-imports <file> from LLVM. If you want to see where the symbols will come from at runtime, ntldd is a good tool.
Related
I write NASM (netwide assembler) program and for some reasons I needed to use some functions written in C. So, I tried to link compiled C object files with compiled Assembly objects using ld link editor. I did it by this way :
ld -m elf_x86_64 -lc --dynamic-linker=/lib64/ld-linux-x86-64.so.2 object_files -o program.
And it didn't want to link and work long enough until I picked up the necessary parameters. Now this works as expected with this parameter set. But I don't understand the meaning of -lc and --dynamic-linker=/lib64/ld-linux-x86-64.so.2. What do they do ?
-lc - link c standard library
--dynamic-linker=/lib64/ld-linux-x86-64.so.2. - set the program loader. Linux ELF binaries have a field for this.
Afaik the latter is needed even for static binaries, anything other will confuse the loader, and it won't execute.
man ld lists its parameters.
I'm using gcc -save-temps to generate assembly and I added -fverbose-asm but that option does NOT generate what I want; it's some weird debug-ish comments.
To get the assembly + inline source, I'm doing gcc -g followed by objdump -S.
Since -save-temps generates the assembly anyway, is there a way to configure it to output the inline source that objdump -S produces?
The GNU C compiler (gcc) produces assembly output if you specify the option -S during compilation. Note that this output is not like the output of objdump -S in the source code is not interspersed with the assembly. To get such output, there is currently no way around creating an object file and then disassembling it. Consider filing a bug report if you would like to have such a feature.
Let's have a look to this basic c program:
#include <stdio.h>
int myadd(int a, int b);
int myadd(int a, int b)
{
return a+b;
}
int main(int argc, char *argv[])
{
int res = myadd(argc,3);
printf("%d\n",res);
return 0;
}
What i want is to understand how debug symbol files work.
If i compile this way:
gcc test.c
I can see debug symbols in gdb:
gdb ./a.out
(gdb) disassemble myadd
Dump of assembler code for function myadd:
0x00000000000006b0 <+0>: push %rbp
That's fine !
Now, if i run:
gcc -s test.c
Here what i get in gdb:
(gdb) disassemble myadd
No symbol table is loaded. Use the "file" command.
That's fine too, because i have stripped symbols with -s gcc option.
Now, i want to "split" my elf executable in 2 files:
- A stripped elf executable
- an external debug symbol files.
Here what i read in some tutorials:
gcc test.c
objcopy --only-keep-debug a.out a.dbg
strip ./a.out
But, now, if i want to run gdb, i say to gdb to look inside ./a.dbg for debug symbols
gdb -s ./a.dbg a.out
And gdb cannot resolve myadd function:
(gdb) disassemble myadd
No symbol table is loaded. Use the "file" command.
And this is what i do not understand: Why gdb does not resolv myadd function?
Thanks
If i compile this way: gcc test.c I can see debug symbols in gdb
You do not see debug symbols here, only the symbol table (which is distinct from debug symbols).
To see debug symbols, compile with gcc -g test.c.
gdb -s a.dbg a.out
The problem here is that when GDB sees "unadorned" a.out, it throws away previously specified symbol file (a.dbg) and replaces it with (fully stripped) a.out. You want:
gdb -s a.dbg -e a.out
Update:
What does mean a "stripped" file: Does it mean this is a file without symbol table or without debuging informations?
On ELF platforms, the state of the file with respect to "strip"-ness is not binary: you can remove individual sections of the file, and depending on exactly what you stripped, your debugging experience will be affected to varying degree.
This command: strip -g a.out removes all .debug_* sections, leaving you without instruction address to source file and line mapping, and without stack address to local variables mapping. However, the symbol table remains in the binary, and can be used to provide instruction address to function name mapping.
This command: strip a.out removes all .debug_* sections, as well as .symtab and .strtab (which together form the symbol table). Such binary is often called "fully stripped".
One could also use obcopy to remove individual sections. It is possible to remove source file/line info (.debug_line section) without removing variable info, and vice versa.
I have tried eu-unstrip ./a.out ./a.dbg but ./a.out result file does not contains debug informations.
You may be hitting a bug in eu-unstrip, perhaps this one.
I would like to create a symbol definition table to be used in a separate application during linking. ARM's armlink linker has the following flag but I'm using arm-eabi:
--symdefs=filename
The GNU objcopy utility has an option --extract-symbol that may do what you want. It generates an object file with only symbol data - no actual code or data.
It is specifically intended to generate a .sym file for use in the VxWorks RTOS which has a command shell and dynamic linker/loader that uses this information. It is also used by the VxWorks host shell and source-level debugger.
The binutils nm utility on the other hand generates output very similar to armlink's --symdefs which you might easily post-process into exactly the form you need.
-Wl,-Map -Wl,mapfile -Wl,--cref
added to the final gcc (link) command line should do the trick.
This the correct answer from arm gnu launchpad:
Do you intend to load the symdef file with the GNU toolchain or with armcc one? If the former I think using nm on the object file and then linking with -R <filename> would work. So you would do arm-none-eabi-nm -D ./prog > ./prog.defsym after linking prog and then arm-none-eabi-gcc -Wl,-R,./prog.defsym when you want to use this.
When I try to build the following program:
#include <stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
On OS X 10.6.4, with the following flags:
gcc -static -o blah blah.c
It returns this:
ld: library not found for -lcrt0.o
collect2: ld returned 1 exit status
Has anyone else encountered this, or is it something that noone else has been affected with yet? Any fixes?
Thanks
This won’t work. From the man page for gcc:
This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.
Per Nate's answer, a completely static application is apparently not possible - see also man ld:
-static Produces a mach-o file that does not use the dyld. Only used building the kernel.
The problem in linking with static libraries is that, if both a static and a dynamic version of a library are found in the same directory, the dynamic version will be taken in preference. Three ways of avoiding this are:
Do not attempt to find them via the -L and -l options; instead, specify the full paths, to the libraries you want to use, on the compiler or linker command line.
$ g++ -Wall -Werror -o hi /usr/local/lib/libboost_unit_test_framework.a hi.cpp
Create a separate directory, containing symbolic links to the static libraries, use the -L option to have this directory searched first, and use the -l option to specify the libraries you want to use.
$ g++ -Wall -Werror -L ./staticBoostLib -l boost_unit_test_framework -o hi hi.cpp
Instead of creating a link of the same name in a different directory, create a link of a different name in the same directory, and specify that name in a -l argument.
$ g++ -Wall -Werror -l boost_unit_test_framework_static -o hi hi.cpp
You may also try LLVM LLD linker - I did prebuilt version for my two major OSes - https://github.com/VerKnowSys/Sofin-llds
This one allows me to link for exmple: "Qemu" properly - which is impossible with ld preinstalled by Apple.
And last one is - to build GCC yourself with libstdc++ (don't).