问题
I'm reading this page https://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
This is one of the example
; tiny.asm
BITS 32
GLOBAL _start
SECTION .text
_start:
mov eax, 1
mov ebx, 42
int 0x80
Here we go:
$ nasm -f elf tiny.asm
$ gcc -Wall -s -nostdlib tiny.o
$ ./a.out ; echo $?
42
Ta-da! And the size?
$ wc -c a.out
372 a.out
However I don't get the same results. I tried nasm -f elf64
and then tried -m32
on gcc (then again on clang). No matter what I try I can not get it to be the tiny size. I'm on arch linux
$ cat tiny.asm
; tiny.asm
BITS 32
GLOBAL _start
SECTION .text
_start:
mov eax, 1
mov ebx, 42
int 0x80
[eric@eric test]$ gcc -Wall -s -nostdlib -m32 tiny.o
[eric@eric test]$ stat ./a.out
File: ./a.out
Size: 12780 Blocks: 32 IO Block: 4096 regular file
Device: 2eh/46d Inode: 1279 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 1000/ eric) Gid: ( 1000/ eric)
Access: 2020-12-26 17:19:19.216294869 -0500
Modify: 2020-12-26 17:19:19.216294869 -0500
Change: 2020-12-26 17:19:19.216294869 -0500
Birth: -
回答1:
-static
is not the default even with -nostdlib
when GCC is configured to make PIEs by default. Use gcc -m32 -static -nostdlib
to get the historical behaviour. (-static
implies -no-pie
). See What's the difference between "statically linked" and "not a dynamic executable" from Linux ldd? for more.
Also, you may need to disable alignment of other sections with gcc -Wl,--nmagic
or using a custom linker script, and maybe disable extra sections of metadata that GCC adds. Minimal executable size now 10x larger after linking than 2 years ago, for tiny programs?
You probably don't have a .eh_frame
section if you're not linking any compiler-generated (from C) .o
files. But if you were, you can disable that with gcc -fno-asynchronous-unwind-tables
. (See also How to remove "noise" from GCC/clang assembly output? for general tips aimed at looking at the compiler's asm text output, moreso than executable size.)
See also GCC + LD + NDISASM = huge amount of assembler instructions (ndisasm doesn't handle metadata at all, only flat binary, so it "disassembles" metadata. So the answer there includes info on how to avoid other sections.)
GCC -Wl,--build-id=none
will avoid including a .note.gnu.build-id
section in the executable.
$ nasm -felf32 foo.asm
$ gcc -m32 -static -nostdlib -Wl,--build-id=none -Wl,--nmagic foo.o
$ ll a.out
-rwxr-xr-x 1 peter peter 488 Dec 26 18:47 a.out
$ strip a.out
$ ll a.out
-rwxr-xr-x 1 peter peter 248 Dec 26 18:47 a.out
(Tested on x86-64 Arch GNU/Linux, NASM 2.15.05, gcc 10.2, ld
from GNU Binutils 2.35.1.)
You can check on the sections in your executable with readelf -a a.out
(or use a more specific option to only get part of readelf
's large output.) e.g. before stripping,
$ readelf -S unstripped_a.out
...
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 08048060 000060 00000c 00 AX 0 0 16
[ 2] .symtab SYMTAB 00000000 00006c 000070 10 3 3 4
[ 3] .strtab STRTAB 00000000 0000dc 000021 00 0 0 1
[ 4] .shstrtab STRTAB 00000000 0000fd 000021 00 0 0 1
And BTW, you definitely do not want to use nasm -felf64
on a file that uses BITS 32
, unless you're writing a kernel or something that switches from 64-bit long mode to 32-bit compat mode. Putting 32-bit machine code in a 64-bit object file is not helpful. Only ever use BITS
when you want raw binary mode to work (later in that tiny-ELF tutorial). When you're making a .o
to link, it only makes it possible to shoot yourself in the foot; don't do it. (Although it's not harmful if you do properly use nasm -felf32
that matches your BITS directive.)
来源:https://stackoverflow.com/questions/65461235/why-do-my-results-different-following-along-the-tiny-asm-example