flat assembler
Message board for the users of flat assembler.
Index
> Linux > Can't link 64 bit on Ubuntu |
Author |
|
Tomasz Grysztar 19 Jul 2018, 07:49
Are you sure that the object file you have is 64-bit and not a 32-bit one? What does the "format" line look like?
|
|||
19 Jul 2018, 07:49 |
|
moveax41h 19 Jul 2018, 21:26
Yes. I am trying a different file to see if I can even get anything assembled at all and I can't.. This is what happens:
Example file straight from the Linux 64-bit examples: Code: ; fasm demonstration of writing 64-bit ELF executable ; note that linux from kernel 2.6.??? needs last segment to be writeable ; else segmentation fault is generated ; compiled with fasm 1.66 ; syscall numbers: /usr/src/linux/include/asm-x86_64/unistd.h ; kernel parameters: ; r9 ; 6th param ; r8 ; 5th param ; r10 ; 4th param ; rdx ; 3rd param ; rsi ; 2nd param ; rdi ; 1st param ; eax ; syscall_number ; syscall ; ; return register: ; rax ; 1st ; rdx ; 2nd ; ; preserved accross function call: RBX RBP ESP R12 R13 R14 R15 ; ; function parameter (when linked with external libraries): ; r9 ; 6th param ; r8 ; 5th param ; rcx ; 4th param ; rdx ; 3rd param ; rsi ; 2nd param ; rdi ; 1st param ; call library format ELF64 executable at 0000000100000000h ; put image over 32-bit limit segment readable executable entry $ mov edx,msg_size ; CPU zero extends 32-bit operation to 64-bit ; we can use less bytes than in case mov rdx,... lea rsi,[msg] mov edi,1 ; STDOUT mov eax,1 ; sys_write syscall xor edi,edi ; exit code 0 mov eax,60 ; sys_exit syscall segment readable writeable msg db 'Hello 64-bit world!',0xA msg_size = $-msg What I get: Quote:
You can see that it cannot find _start. This example file has been completely untouched, however, I tried adding in a _start, using section instead of segment, and a bunch of other stuff. It just segfaults upon run. I'm very confused. _________________ -moveax41h |
|||
19 Jul 2018, 21:26 |
|
Tomasz Grysztar 19 Jul 2018, 21:42
The example you took is of creating an executable file directly. "format ELF64 executable" is like "format PE", you just run the file afterwards, no linking required.
|
|||
19 Jul 2018, 21:42 |
|
moveax41h 19 Jul 2018, 22:09
Tomasz Grysztar wrote: The example you took is of creating an executable file directly. "format ELF64 executable" is like "format PE", you just run the file afterwards, no linking required. Oh my God. Holy crap. Somebody smack me. Thank you. One of those moments for sure When you know x86 assembly, but you don't know your tools well enough cuz you're new to Linux. -_- _________________ -moveax41h |
|||
19 Jul 2018, 22:09 |
|
moveax41h 20 Jul 2018, 16:50
Ok so that wasn't entirely the issue. It appears as though I've been moving between different types of fasm files. So that example I used builds to ELF just fine, however, this one, fasm spits out an object file instead of an ELF for real:
Code: ; fasm example of using the C library in Unix systems ; compile the source with commands like: ; fasm libcdemo.asm libcdemo.o ; gcc libcdemo.o -o libcdemo ; strip libcdemo format ELF include 'ccall.inc' section '.text' executable public main extrn printf extrn getpid main: call getpid ccall printf, msg,eax ret section '.data' writeable msg db "Current process ID is %d.",0xA,0 In fact, we see that in the comments, that is what was intended. However, I cannot link this object file: Code: moveax41h@moveax41h-ThinkPad-P50:/usr/share/fasm/examples/libcdemo$ ls ccall.inc libcdemo.asm libcdemo.o moveax41h@moveax41h-ThinkPad-P50:/usr/share/fasm/examples/libcdemo$ sudo gcc libcdemo.o -o libcdemo /usr/bin/x86_64-linux-gnu-ld: i386 architecture of input file `libcdemo.o' is incompatible with i386:x86-64 output collect2: error: ld returned 1 exit status And with ld: Code: sudo ld libcdemo.o ld: i386 architecture of input file `libcdemo.o' is incompatible with i386:x86-64 output ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 libcdemo.o: In function `main': (.text+0x1): undefined reference to `getpid' (.text+0x17): undefined reference to `printf' I think this was the original problem I was having but in trying to troubleshoot it, I switched to that other one which could go directly to ELF. I'm guessing that's because the other style uses a system call instead of libc but I do want to use libc functions so I still need a hand here. Also note that this one is a 32 bit. _________________ -moveax41h |
|||
20 Jul 2018, 16:50 |
|
fasmnewbie 20 Jul 2018, 17:20
You should link with "-m32" switch for 32-bit and "-m64" switch for 64-bit.
gcc -m32 libcdemo.o -o libcdemo I think that was your original problem. If you're linking with ld, then its a different story. ld requires "_start" as default entry point not "main". or you could be missing the 32-bit libraries altogether. They're not installed by default on Ubuntu. |
|||
20 Jul 2018, 17:20 |
|
moveax41h 20 Jul 2018, 18:54
fasmnewbie you nailed it. I simply didn't have gcc-multilib installed and installing it with apt install gcc-multilib resolved this issue, along with using the -m32.
Well, I definitely learned a lot during this process, which is cool. Don't think I've ever gotten that close to the linker itself before. Was interesting to see that it looks for _start and it totally makes sense as that's typically the "actual" entrypoint, at least when I was reverse engineering Windows binaries, there was always _start followed by a bunch of boilerplate assembly followed by a jump to "main" where the actual programmer's code began. |
|||
20 Jul 2018, 18:54 |
|
fasmnewbie 21 Jul 2018, 20:34
Glad you solved it.
"main" is the entry point adhering to the C standard structure. It applies to all platforms that produce C executables. _start is more towards the loader and loading a process on Linux ("ld") into memory. _start marks a jump point in memory where RIP starts fetching the instructions from. It applies to all kind of objects that is to be loaded into memory not necessarily from C, since different languages may have different entry point requirements. But for C executable, it's main() because it may also contain the required command line arguments. |
|||
21 Jul 2018, 20:34 |
|
moveax41h 22 Jul 2018, 19:18
fasmnewbie wrote: Glad you solved it. Ahh interesting. So is _start generally the address which is present in the executable file's format header as the "code entry point?" I suppose I could check with my 010 editor, but figured I'd throw that in here. I'm assuming that _start is the point where the operating system's executable file loader transfer control to the user's program after the header has been parsed and the file mapped into memory. _________________ -moveax41h |
|||
22 Jul 2018, 19:18 |
|
Furs 22 Jul 2018, 19:42
moveax41h wrote: Ahh interesting. So is _start generally the address which is present in the executable file's format header as the "code entry point?" I suppose I could check with my 010 editor, but figured I'd throw that in here. I'm assuming that _start is the point where the operating system's executable file loader transfer control to the user's program after the header has been parsed and the file mapped into memory. glibc does some stuff there, and then usually calls __libc_start_main, which ends up calling your main. There's a lot of stuff done before C's main happens. |
|||
22 Jul 2018, 19:42 |
|
fasmnewbie 23 Jul 2018, 20:48
moveax41h wrote:
Just be careful when interpreting debugging information. Different platforms may give you different preparatory code and different loaders. Windows loaders do not use "ld" when loading C executables. All C toolchain you find on Windows are emulated. IIRC, Win64 uses BaseInitThunk as its main thread loader. Loaders are really not the concern of the CPU since it is part of Operating System kernel core services or to be exact, process scheduling. CPU concerns only what appears on its RIP for fetching the next instructions. |
|||
23 Jul 2018, 20:48 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.