GCC compile and link raw output - gcc

I am trying to get the raw instruction code output for a simple C program with function calls.
I have already searched on here and Google for the answer but can only find answers that are correct for single functions (no function calls).
A trivial example:
int main(){
return addition(5, 7);
}
int addition(int a, int b){
return a + b;
}
When I use gcc -c test.c -o test.o and then objdump -d test.o on this, the JAL (jump and link) instruction shows a jump to address 0x00000000 which is obviously incorrect, however when I compile the program fully, I get an enormous amount of junk in the objdump command
I am compiling with the mips compiler (and associated mips-objdump, etc).
The programs I am compiling are self contained (no external libraries, or system include files). What I want is a dump of the instructions where the JAL and equivalent instructions point to the correct addresses for the functions they call.

While your code is not linked, the addresses may or may not be resolved (absolute addresses certainly won't be). In the latter case, you should see relocation entries if you use objdump -dr. If you link your program, those issues should be gone, and if the program is really standalone (ie. not even C libraries) then all you see should be your code. You might want to use -nostdlib switch to gcc. I don't have mips gcc available, but here is the x86 version for illustration:
080480d8 <addition>:
80480d8: 8b 44 24 08 mov 0x8(%esp),%eax
80480dc: 03 44 24 04 add 0x4(%esp),%eax
80480e0: c3 ret
080480e1 <main>:
80480e1: 83 ec 08 sub $0x8,%esp
80480e4: c7 44 24 04 07 00 00 movl $0x7,0x4(%esp)
80480eb: 00
80480ec: c7 04 24 05 00 00 00 movl $0x5,(%esp)
80480f3: e8 e0 ff ff ff call 80480d8 <addition>
80480f8: 83 c4 08 add $0x8,%esp
80480fb: c3 ret
That is all the code in the binary, and as you can see at 80480f3 the call is resolved. I expect it works similarly for mips.

Related

Calls to Addresses in the Middle of Routines

I am tracing wireshark-2.6.10 using Pin. At several points during the initialization, I can see some calls, such as this:
00000000004e9400 <__libc_csu_init##Base>:
...
4e9449: 41 ff 14 dc callq *(%r12,%rbx,8)
...
The target of this call is 0x197db0, shown here:
0000000000197cb0 <_start##Base>:
...
197db0: 55 push %rbp
197db1: 48 89 e5 mov %rsp,%rbp
197db4: 5d pop %rbp
197db5: e9 66 ff ff ff jmpq 197d20 <_start##Base+0x70>
197dba: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
...
Pin says that this is in the middle of the containing routine, i.e., _start##Base. But, when I reach this target using gdb, I see the following output:
>│0x5555556ebdb0 <frame_dummy> push %rbp
│0x5555556ebdb1 <frame_dummy+1> mov %rsp,%rbp
│0x5555556ebdb4 <frame_dummy+4> pop %rbp
│0x5555556ebdb5 <frame_dummy+5> jmpq 0x5555556ebd20 <register_tm_clones>
│0x5555556ebdba <frame_dummy+10> nopw 0x0(%rax,%rax,1)
│0x5555556ebdc0 <main_window_update()> xor %edi,%edi
Note that if I subtract the bias value, the runtime target address will be consistent with the compile time value (i.e., 0x5555556ebdb0 - 0x555555554000 = 0x197db0). It seems that there exists a pseudo-routine called frame_dummy inside _start##Base. How is that possible? How can I extract the addresses for these pseudo-routines, beforehand (i.e., before execution)?
UPDATE:
These types of calls to the middle of functions were not present in GIMP and Anjuta (which are written almost purely in C and built from source). But are present in Inkscape and Wireshark (written in C++, although I do not think that the language is the cause. These two were installed from packages.).
At first, it seemed that this situation occurs only during the initialization and before calling the main() function. But, at least in wireshark-2.6.10 this occurs at least in one place after main() starts. Here, we have wireshark-qt.cpp: Lines 522-524 (which is part of main()).
/* Get the compile-time version information string */
comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info,
get_gui_compiled_info);
This is a call to get_compiled_version_info(). In assembly, the function is called at address 0x5555556e74c2 (0x1934c2 without bias), as shown below:
>│0x5555556e74c2 <main(int, char**)+178> callq 0x5555556f5870 <get_compiled_version_info>
│0x5555556e74c7 <main(int, char**)+183> lea 0x4972(%rip),%rdi # 0x5555556ebe40 <get_wireshark_runtime_info(_GString*)>
│0x5555556e74ce <main(int, char**)+190> mov %rax,%r13
Again, the target is in the middle of another function, _ZN7QStringD1Ev##Base:
00000000001980f0 <_ZN7QStringD1Ev##Base>:
...
1a1870: 41 54 push %r12
...
This is the output of gdb (0x5555556f5870 - 0x555555554000 = 0x1a1870):
>│0x5555556f5870 <get_compiled_version_info> push %r12
│0x5555556f5872 <get_compiled_version_info+2> mov %rdi,%r12
│0x5555556f5875 <get_compiled_version_info+5> push %rbp
│0x5555556f5876 <get_compiled_version_info+6> lea 0x349445(%rip),%rdi # 0x555555a3ecc2
As can be seen, the debugger recognizes that this address is the start address of get_compiled_version_info(). This is because it has access to debug_info. In all cases that I found, the symbol for these pseudo-routines were removed from the original binary (because .symtab was removed from the binary). But the strange thing is that it is located inside _ZN7QStringD1Ev##Base. Therefore, Pin considers get_compiled_version_info() to be inside _ZN7QStringD1Ev##Base.
How is that possible?
The frame_dummy is a bona-fide C function. If Pin thinks it's in the middle of _start, it's probably because:
_start is an assembly function, and
its .st_size is set incorrectly in the symbol table.
You can confirm this by looking at readelf -Ws a.out | egrep ' (_start|frame_dummy)'.
You are probably using the binary linked with fairly old GLIBC.
GLIBC used to generate C runtime startup files (whence _start comes from) by using gcc -S to create assembly from C source, then splitting and editing the assembly with sed. Getting .size directive wrong was one problem with that approach, and it is no longer used on x86_64 as of 2012 (commit).
How can I extract the addresses for these pseudo-routines, beforehand (i.e., before execution)?
Pin doesn't magically create these pseudo-routines, they must be visible in the readelf -Ws output of the original binary.

What is the difference between Early inliner and IPA inliner in GCC?

Reading through GCC code comments and online documentation, it seems there are two types of inliners - Early inliner and the IPA inliner.
For example, in gcc/ipa-fnsummary.c
/* When optimizing and analyzing for IPA inliner, initialize loop
optimizer so we can produce proper inline hints.
When optimizing and analyzing for early inliner, initialize node
params so we can produce correct BB predicates. */
What are these two kinds of inliners ? And What is the difference between the two ?
Simply put:
The early inliner operates on the single source file level, when compiling a single file. It will inline functions in the scope of the compiled source file and its included header files only (the scope of a single compilation unit).
The IPA inliner operates on link time, during whole program optimization. It takes place when activating the -flto option, standing for Link Time
Optimization.
When -flto is specified, gcc embeds the intermediate program representation, called a GIMPLE tree, into specialized sections in each object file. Later on, the link time optimizer (GCC's lto1 executable) reads this information, and executes different optimization passes, including the IPA inliner, to produce the final optimized executable.
The impact of the two inliners could be illustrated with a simple example:
// foo.h
void foo() {}
// goo.h
int goo();
// goo.cpp
#include "goo.h"
int goo() { return 0x123; }
// foo.cpp
#include "foo.h"
#include "goo.h"
int main()
{
foo();
return goo();
}
First, usual -O3 compilation:
g++ -O3 foo.cpp goo.cpp
By disassembling a.out (objdump a.out -d) we get the following code for main:
00000000000004f0 <main>:
4f0: e9 0b 01 00 00 jmpq 600 <_Z3goov>
4f5: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4fc: 00 00 00
4ff: 90 nop
The call to foo() is gone - this is the work of the early inliner. The function goo(), however, is not visible to the compiler during compilation of foo.cpp, so it is not able to optimize it.
Now, repeating compilation with -flto:
g++ -O3 -flto foo.cpp goo.cpp
We would get the following disassembly:
00000000000004f0 <main>:
4f0: b8 23 01 00 00 mov $0x123,%eax
4f5: c3 retq
4f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4fd: 00 00 00
This time, the call to goo was inlined and replaced with its result, 0x123 - this is the work of the IPA inliner.
According to the internal documentation in the ipa-inline.c early inline is a simple local inlining pass that inline callees in the current function based on local properties only. The main strength of this pass is its ability to remove the abstraction penalty present in most C++ code and prepare the code for the more advanced inter-procedural analysis (IPA).
The IPA inliner is a more advanced inliner based on the information collected during IPA. Since it has more information it can make a better estimate on which callees are most beneficial to inline. It will also prune the call-graph and remove functions where all the call sites have been inlined.
For more information refer to the internal documentation of ipa-inline.c

How to link assembly functions without a linker?

I'm using NASM for some projects in Windows. I'd like to call C's printf function, but I don't want GCC with all it's burocracy, making my small project (assembly is actually 30 lines) in disassembled 24000 lines. How can I make linking ( get a function be called within system definitions, like MessageBox ) without a linker?
Edit:
I made it using a disassembler. It's funny to see that almost everything is add and nop.
0000000000402b90 <MessageBoxA>:
402b90: ff 25 2a 58 00 00 jmpq *0x582a(%rip) # 4083c0 <__imp_MessageBoxA>
402b96: 90 nop
402b97: 90 nop
402b98: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
402b9f: 00
and __imp_MessageBoxA:
00000000004083c0 <__imp_MessageBoxA>:
4083c0: 14 87 adc $0x87,%al
4083c2: 00 00 add %al,(%rax)
4083c4: 00 00 add %al,(%rax)
What does it actually do?
You can do C library linking manually. use following command on your object file produced with NASM:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 objectfile -lc
Above command tested on 64bit linux so if you want to use it on windows you must change /lib64/ld-linux-x86-64.so.2 into your dynamic linker library usually find on C:/cygwin/lib/.. if you are using cygwin and on C:/MingW/msys/1.0/lib64/ld-linux-x86-64.so.2 if you using MinGW.

assignment of addresses in shared library

I am trying to understand the shared libraries. From what I know, shared libraries have their base addresses as zero so they can be loaded at any address during runtime and so the variables are correctly relocated either during runtime or load time. So before the loading of the library, all the symbols are given some offsets from the base of the library. Hence, I tried to investigate some existing libraries and also created one library. But I found some differences. For libc.so, what I found is this :
$ objdump -D /lib64/libc.so.6
/lib64/libc.so.6: file format elf64-x86-64
Disassembly of section .note.gnu.build-id:
0000003b47a00270 <.note.gnu.build-id>:
3b47a00270: 04 00 add $0x0,%al
3b47a00272: 00 00 add %al,(%rax)
3b47a00274: 14 00 adc $0x0,%al
3b47a00276: 00 00 add %al,(%rax)
3b47a00278: 03 00 add (%rax),%eax
[More contents...]
From what I know, is that the elf headers take some space. But even if it does, it won't take up the addresses from 0 to 0x3b47a00270.
So, I created my own library (using -fPIC and -shared flags) and I saw this :
$ objdump -D ./libvector.so
./libvector.so: file format elf64-x86-64
Disassembly of section .note.gnu.build-id:
00000000000001c8 <.note.gnu.build-id>:
1c8: 04 00 add $0x0,%al
1ca: 00 00 add %al,(%rax)
1cc: 14 00 adc $0x0,%al
1ce: 00 00 add %al,(%rax)
1d0: 03 00 add (%rax),%eax
[More contents...]
This one seems more reasonable in terms of addresses. .note.gnu.build-id here starts at 0x1c8. So, guys any idea, why in case of libc or the other existing libraries like libpthread, the case is different? I am using fedora 18 x86_64. I think that this may be a case of prelinking but I am not sure and even if it is how to find that it is prelinked?
Thanks a lot in advance...
objdump -D /lib64/libc.so.6
You are disassembling sections which do not contain code. Since you don't (yet) understand what you are doing, stick to objdump -d -- it will confuse you less.
From what I know, shared libraries have their base addresses as zero
The above statement is incorrect: shared libraries may have their base address as zero, but they don't have to.
why in case of libc or the other existing libraries like libpthread, the case is different
Because these libraries have been prelinked. See "man prelink", e.g. here.
You can see this clearer with readelf -l. You want to look at the VirtAddr for the first LOAD segment.
In case of non-prelinked library, that address would be 0. In case of your prelinked libc.so.6, it will be 0x3b47a00000. Also note that RedHat systems are often set up to re-run prelink every two weeks, and so the address your libc.so.6 is prelinked at may change with time.

How do I get full assembler output in gcc?

I know I can get the assembler source code generated by the compiler by using:
gcc -S ...
even though that annoyingly doesn't give me an object file as part of the process.
But how can I get everything about the compiled code? I mean addresses, the bytes generated and so forth.
The instructions output by gcc -S do not tell me anything about instruction lengths or encodings, which is what I want to see.
I like objdump for this, but the most useful options are non-obvious - especially if you're using it on an object file which contains relocations, rather than a final binary.
objdump -d some_binary does a reasonable job.
objdump -d some_object.o is less useful because calls to external functions don't get disassembled helpfully:
...
00000005 <foo>:
5: 55 push %ebp
6: 89 e5 mov %esp,%ebp
8: 53 push %ebx
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
30: e8 fc ff ff ff call 31 <foo+0x2c>
35: 89 d8 mov %ebx,%eax
...
The call is actually to printf()... adding the -r flag helps with that; it marks relocations. objdump -dr some_object.o gives:
...
29: c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
30: e8 fc ff ff ff call 31 <foo+0x2c>
31: R_386_PC32 printf
...
Then, I find it useful to see each line annotated as <symbol+offset>. objdump has a handy option for that, but it has the annoying side effect of turning off the dump of the actual bytes - objdump --prefix-addresses -dr some_object.o gives:
...
00000005 <foo> push %ebp
00000006 <foo+0x1> mov %esp,%ebp
00000008 <foo+0x3> push %ebx
...
But it turns out that you can undo that by providing another obscure option, finally arriving at my favourite objdump incantation:
objdump --prefix-addresses --show-raw-insn -dr file.o
which gives output like this:
...
00000005 <foo> 55 push %ebp
00000006 <foo+0x1> 89 e5 mov %esp,%ebp
00000008 <foo+0x3> 53 push %ebx
...
00000029 <foo+0x24> c7 04 24 00 00 00 00 movl $0x0,(%esp)
2c: R_386_32 .rodata.str1.1
00000030 <foo+0x2b> e8 fc ff ff ff call 00000031 <foo+0x2c>
31: R_386_PC32 printf
00000035 <foo+0x30> 89 d8 mov %ebx,%eax
...
And if you've built with debugging symbols (i.e. compiled with -g), and you replace the -dr with -Srl, it will attempt to annotate the output with the corresponding source lines.
The easiest way to get a quick listing is to use the -a option to the assembler, which you can do by putting -Wa,-a on the gcc command line. You can use various modifiers to the a option to affect exactly what comes out -- see the as(1) man page.
It sounds to me like you want a disassembler. objdump is pretty much the standard (otool on Mac OS X); in concert with whatever map file information your linker gives you, the disassembly of your object file should give you everything you want.
gcc will produce an assembly language source file. You can then use as -a yourfile.S to produce a listing that includes offsets and encoded bytes for each instruction. -a also has some sub-options to control what shows up in the listing file (as --help will give a list of them along with the other available options).
nasm -f elf xx.asm -l x.lst
gcc xx.c xx.o -o xx
generates a 'list' file x.lst which is only for xx.asm
for xx.c along with xx.asm you can compile them both and then use 'gdb' - gnu debugger

Resources