flat assembler
Message board for the users of flat assembler.
Index
> Linux > Linking object files: do you use ld or gcc? Goto page 1, 2 Next |
Author |
|
vid 16 Mar 2009, 00:45
Quote: So my question to all of you is: do you use either ld or gcc on your fasm-generated object files, and why that one and not the other? What, if anything, do you assume about eg the stack (or anything else) upon program entry? Insight is that control freaks usually use 'format ELF executable', eg. they use FASM to produce directly executable file, not object that needs to linked. Does this mean that ld adds some extra initialization code, which you didn't want there? I haven't used it with asm programs for quite some time, so I don't remember how exactly I linked my all-asm apps. |
|||
16 Mar 2009, 00:45 |
|
revolution 16 Mar 2009, 01:20
vid wrote: Insight is that control freaks usually use 'format ELF executable', eg. they use FASM to produce directly executable file, not object that needs to linked. |
|||
16 Mar 2009, 01:20 |
|
buzzkill 16 Mar 2009, 01:21
When you use 'format ELF executable', fasm generates an executable without sections, so none of the standard gnu/linux tools can deal with it
Here's what happens after you assemble the hello.asm (from examples/elfexe/ directory) with "fasm hello.asm" : Code: $ objdump -d ./hello ./hello: file format elf32-i386 -> So no disassembly... Code: $ readelf -a ./hello ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Intel 80386 Version: 0x1 Entry point address: 0x8048074 Start of program headers: 52 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 2 Size of section headers: 40 (bytes) Number of section headers: 0 Section header string table index: 0 There are no sections in this file. There are no sections in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000074 0x08048074 0x08048074 0x0001f 0x0001f R E 0x1000 LOAD 0x000093 0x08049093 0x08049093 0x0000d 0x0000d RW 0x1000 There is no dynamic section in this file. There are no relocations in this file. There are no unwind sections in this file. No version information found in this file. -> Note the "There are no sections in this file.", also no symbols... Code: $ agdb ./hello GNU gdb 6.3 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-linux-gnu"...(no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (gdb) disas start No symbol table is loaded. Use the "file" command. (gdb) disas 0x8048074 No function contains specified address. (gdb) q -> Note how we can't disassemble here either, not by using the symbolic entry point from the program (start), and not by using the entry point address either (see "Entry point address:" line in readelf output). So it appears that the way fasm generates its executables is not very compatible with the way things are normally done in linux, and all your linux tools don't work (well) with fasm-generated executables That's the reason I define the needed sections myself and use fasm to generate an object file, which I then link with ld, the linux linker, to produce a "normal" executable (no offense ) For the record, this is what a hello.asm looks like when I do it: Code: ; assemble/link: ; $ fasm hello2.asm hello2.o ; $ ld hello2.o -o hello2 format ELF section '.text' executable public _start _start: mov eax, 4 mov ebx, 1 mov ecx, msg mov edx, msg.len int 80h mov eax, 1 mov ebx, 0 int 80h section '.data' writeable msg db "It works!", 0Ah .len = $-msg This defines two standard sections and a standard entry point and is usable in gdb and all other linux tools. I have to say, I'm surprised that other linux asm coders don't do it this way. Can I ask you what tools you use for debugging etc your fasm programs? |
|||
16 Mar 2009, 01:21 |
|
buzzkill 16 Mar 2009, 01:26
vid wrote:
Forgot to answer that one No, I mean the opposite, linking with gcc adds (a lot of) stuff I don't want or need, and linking with ld doesn't. The fact that in a gcc-generated executable the stack seems "off" to me, is precisely because of the fact that gcc adds startup code. |
|||
16 Mar 2009, 01:26 |
|
buzzkill 16 Mar 2009, 01:30
revolution wrote: And real control freaks use format binary. Yep, that'll take care of all that unwanted fluff in your binaries It's just that getting your OS to load your programs gets to be such a hassle |
|||
16 Mar 2009, 01:30 |
|
revolution 16 Mar 2009, 01:35
And hyper control-freaks write their own OS (with format binary of course) so loading is not a problem.
|
|||
16 Mar 2009, 01:35 |
|
vid 16 Mar 2009, 11:55
buzzkill: you can create executables with sections, just as you create objects with sections.
Code:
format ELF executable
entry start
segment executable
start:
...
segment readable writeable
|
|||
16 Mar 2009, 11:55 |
|
vid 16 Mar 2009, 11:57
You should read TFM more carefully next time:
Quote: To create executable file, follow the format choice directive with the executable keyword. It allows to use entry directive followed by the value to set as entry point of program. On the other hand it makes extrn and public directives unavailable, and instead of section there should be the segment directive used, followed only by one or more segment permission flags. The origin of segment is aligned to page (4096 bytes), and available flags for are: readable, writeable and executable. |
|||
16 Mar 2009, 11:57 |
|
Tomasz Grysztar 16 Mar 2009, 12:32
vid: The ELF segments are a different entity than sections. See ELF specification, section "Program Loading".
|
|||
16 Mar 2009, 12:32 |
|
vid 16 Mar 2009, 13:17
Hmm, I never noticed this. So, since buzzkill says standard linux tools expect executables to have sections, obvious question pops out: how do segments and sections mix up in ELF executables?
|
|||
16 Mar 2009, 13:17 |
|
Tomasz Grysztar 16 Mar 2009, 13:35
vid wrote: obvious question pops out: how do segments and sections mix up in ELF executables? ELF specification wrote: Sections hold the bulk of object file information for the linking view (...). Files used during linking must have a section header table; other object files may or may not have one. And, as you can see in the attached figure, the run-time segments usually are "larger unit" than sections, they group the sections of the same attributes (like writeable).
|
||||||||||
16 Mar 2009, 13:35 |
|
vid 16 Mar 2009, 13:59
I see. Soooo, why doesn't FASM then support 'section' in ELF executable? Internal problem?
|
|||
16 Mar 2009, 13:59 |
|
Tomasz Grysztar 16 Mar 2009, 14:04
vid wrote: I see. Soooo, why doesn't FASM then support 'section' in ELF executable? Internal problem? Just lack of necessity. The Unix/Linux systems are generally equipped with linker, so it was object format that was my main concern here. The executable variant is just a toy for generating really simple executables, maximally stripped (that is, containing only the obligatory parts). |
|||
16 Mar 2009, 14:04 |
|
Tomasz Grysztar 16 Mar 2009, 14:42
buzzkill wrote:
Note that the very similar thing will happen with your ld-generated executable, when you run "strip" (which is "standard" tool) on in first. So it's not that these files are "unstandard", they are just not so suitable for the debugging purposes, etc. |
|||
16 Mar 2009, 14:42 |
|
buzzkill 16 Mar 2009, 15:46
Tomasz, first of all let me say thank you for creating fasm, it's a great assembler. And it's nice to see that you yourself get involved in these forums too.
Quote: Note that the very similar thing will happen with your ld-generated executable, when you run "strip" (which is "standard" tool) on in first. Yes, that's correct, but you would only run strip on an executable that's ready "to go out into the world", ie while developing/debugging/etc you wouldn't strip your binaries. (BTW, even "strip --strip-all" leaves some sections intact ) This is like when programming C, you would always put debugging info into your executable while developing, and only when you're ready to ship the program, you'd leave debugging info out. Quote: Thus the section table is only used for linking, and the program loader just ignores it. So this would mean that a fasm-generated executable can't be linked to anything else? For a noob (such as myself) this can be a real hassle, because something like a printf() is really useful when you don't have your own library of output functions yet. I've seen tutorials where they just have you use printf() to communicate with the outside world. Anyway, I'm not trying to tell you how to do your job ofcourse, but maybe some explanation of this in the manual, and maybe an included example program linking to libc would make things a little clearer for newbies? BTW Tomasz, would you have a look at my first question (in my original post)? I'd like to know why you assume what you do about the stack at program startup. Do you expect your users to use gcc to generate the executables? What, according to you, should be at [esp] (before argc) at startup? Because even though you use the "section way" instead of the "format ELF executable" way in listing.asm (hope that makes sense to you ), it will segfault for users who use ld to generate the listing executable. (Maybe a few words in the readme.txt about what we should do to your src to create an executable might help?) |
|||
16 Mar 2009, 15:46 |
|
Endre 16 Mar 2009, 16:10
On linux you may give a chance to the gnu assembler. With intel syntax it's no longer so terrible although its syntax differs a bit from that of fasm. Recently I use it rather than fasm. You can debug your code with gdb, and in addition you can reduce its final size with elfkickers (sstrip). I appreciate that fasm's macro capabilities are far better but I practically never use them. On the other hand with gnu assembler you can apply cpp (the c preprocessor) to get those C-constants defined in any of the header files. With fasm it is almost impossible. Here the hello world application. The header inclusions are between .if/.endif because the assembler cannot process C-headers, and with this you can avoid compiler errors. The preprocessor however works fine thus your C-constants will be changed to the appropriate values.
Code: /** * For debugging compile with * gcc -g -nostdlib hello_gcc.S -o hello_gcc * * or for releasing with * * gcc -s -nostdlib hello_gcc.S -o hello_gcc * sstrip ./hello_gcc */ .if 0 #include <asm/unistd.h> #include <unistd.h> .endif .line __LINE__ .intel_syntax noprefix .globl _start .text _start: nop mov rax, __NR_write mov rdi, STDOUT_FILENO mov rsi, offset msg mov rdx, offset msg_size syscall xor rdi, rdi mov rax, __NR_exit syscall msg: .ascii "Hello 64-bit world!\n" msg_size = . - msg The nop at _start is there because gdb cannot stop at the first instruction so you have to set your break point at the second instruction. Here my gdb session: Code: GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-pc-linux-gnu"... (gdb) b 22 Breakpoint 1 at 0x4000b1: file hello_gcc.S, line 22. (gdb) set radix 16 Input and output radices now set to decimal 16, hex 10, octal 20. (gdb) r Starting program: /home/kozmae/projects/asm/termios/hello_gcc Breakpoint 1, _start () at hello_gcc.S:22 22 mov rax, __NR_write Current language: auto; currently asm (gdb) disp $rax 1: $rax = 0x0 (gdb) disp $rdi 2: $rdi = 0x0 (gdb) disp $rsi 3: $rsi = 0x0 (gdb) disp $rdx 4: $rdx = 0x0 (gdb) s 23 mov rdi, STDOUT_FILENO 4: $rdx = 0x0 3: $rsi = 0x0 2: $rdi = 0x0 1: $rax = 0x1 (gdb) 24 mov rsi, offset msg 4: $rdx = 0x0 3: $rsi = 0x0 2: $rdi = 0x1 1: $rax = 0x1 (gdb) |
|||
16 Mar 2009, 16:10 |
|
Endre 16 Mar 2009, 16:19
Oh sorry, now I see that you're using 32bit, so
Code: /** * For debugging compile with * gcc -g -m32 -nostdlib hello_gcc.S -o hello_gcc * * or for releasing with * * gcc -s -m32 -nostdlib hello_gcc.S -o hello_gcc * sstrip32 ./hello_gcc */ .if 0 #include <asm/unistd.h> #include <unistd.h> .endif .line __LINE__ .intel_syntax noprefix .globl _start .text _start: nop mov eax, __NR_write mov ebx, STDOUT_FILENO mov ecx, offset msg mov edx, offset msg_size int 0x80 xor ebx, ebx mov eax, __NR_exit int 0x80 msg: .ascii "Hello 32-bit world!\n" msg_size = . - msg |
|||
16 Mar 2009, 16:19 |
|
Tomasz Grysztar 16 Mar 2009, 16:37
buzzkill wrote: So this would mean that a fasm-generated executable can't be linked to anything else? Yes, and that's why you should use object output for any serious project. As I said above, the executable output is just for the case, when you want to create a very simple, completely stripped executable containing just a bare code. Right, I should make it more clear in manual, that this format option is just a toy, really. buzzkill wrote: BTW Tomasz, would you have a look at my first question (in my original post)? I'd like to know why you assume what you do about the stack at program startup. Do you expect your users to use gcc to generate the executables? What, according to you, should be at [esp] (before argc) at startup? Because even though you use the "section way" instead of the "format ELF executable" way in listing.asm (hope that makes sense to you ), it will segfault for users who use ld to generate the listing executable. (Maybe a few words in the readme.txt about what we should do to your src to create an executable might help?) With libc package comes the README.TXT file... readme from libc package wrote: The fasm.o is an object file in ELF format. To get the final executable for And listing.asm doesn't use "format ELF executable" - it uses object format, and should be linked in the same way, as fasm.o (I perhaps need to add this info to tools readme). Note that all those program declare function "main", which implies that it should be linked just as a C program would be. This is done to ensure maximum portability. |
|||
16 Mar 2009, 16:37 |
|
buzzkill 16 Mar 2009, 16:55
Endre,
I have used gas (a little) before, Programming From The Ground Up uses it too. I've also used nasm before, but now that I'm once again starting to dabble with assembly, I thought I'd give fasm a try . I'm planning to have a look at fasm's macro capabilities, because I usually find that sort of stuff handy to "abstract away" some things like function entry/exit, locals and arguments on the stack etc, I used those with nasm too. As for using constants from std include files, for nasm I just created a .inc myself with some handy constants I used often, and I'm sure somebody who's good with eg Perl could whip up a script to convert the include files to something fasm understands. I haven't looked into all that with fasm, though. In principle you can use any assembler with any OS ofcourse, and a lot of things (eg macros vs preprocessor) are down to personal preference I think. But gas is the de facto assembler on linux ofcourse because it's the backend for gcc (incidentally, people used to say that gas wasn't that suitable as a standalone assembler for precisely that reason). Totally off-topic: I see you use int 80h syscalls. Any reason you don't use the more 'modern' sysenter way (through VDSO)? |
|||
16 Mar 2009, 16:55 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.