How to link assembly functions without a linker? - windows

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.

Related

Why Windows changes a .text section of a 32-bit EXE file when it loaded into RAM?

I have a 32-bit windows executable file. A .text section of this file starts with these bytes:
68 50 a0 d0 00 e8 3c 68 84 00 59 c3 cc cc cc cc ..
Disassembled:
push 0xd0a050
call 0x846846
pop ecx
ret
int3
int3
int3
int3
..
But when I run the executable, the .text section in RAM becomes like this:
68 50 a0 1b 01 e8 3c 68 84 00 59 c3 cc cc cc cc ..
Disassembled:
push 0x11ba050
call 0x846846
pop ecx
ret
int3
int3
int3
int3
..
As you can see, the address at the push line is changed. How to explain it?
Note that if I build and run the 64-bit version of the executable, I get absolutely identical .text section in file and in RAM.
Software: Win10 x64, MSVC 2019 x86.

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

GCC compile and link raw output

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.

Determine if a compiled ELF object is 32-bit or 64-bit

I want to verify if an object has been compiled in 32-bit or 64-bit:
% readelf -h my_obj
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
...
Since ELF32 is displayed, does this guarantee that the object is in 32-bit mode?
Fat binaries aren't common or standard for ELF, so the class does reliably indicate 32 vs 64 bit. But to figure out whether you're looking at 32-bit x86, ARM, MIPS, or whatever, you have to also inspect the Machine field right below the Type field.

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