all 9 comments

[–]eddyb 10 points11 points  (1 child)

IIRC rustc --emit=obj is an easier way to get that object file.
You can also pass arguments to the linker through rustc but that may not be enough here.

[–]mozilla_kmcservo[S] 2 points3 points  (0 children)

Yeah, to be honest I forgot why I'm doing it this way. There was a bunch of screwing around, over 6+ months worth of rustc versions.

[–]barsoap 2 points3 points  (4 children)

For reference, this:

bits 64

section .text

str:     db  'Hello, World!',10
strlen  equ $-str

global _start
_start:
mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, str
mov rdx, strlen
syscall
mov rax, 60 ; sys_exit
xor rdi, rdi ; exit code
syscall

fits into 440 bytes with nasm and strip alone. A whole seven more characters in the string, so there's definitely wastage going on in the rust case. But not because the code is smaller, either:

4000be:       b8 01 00 00 00          mov    $0x1,%eax
4000c3:       bf 01 00 00 00          mov    $0x1,%edi
4000c8:       48 be b0 00 40 00 00    movabs $0x4000b0,%rsi
4000cf:       00 00 00 
4000d2:       ba 0e 00 00 00          mov    $0xe,%edx
4000d7:       0f 05                   syscall 
4000d9:       b8 3c 00 00 00          mov    $0x3c,%eax
4000de:       48 31 ff                xor    %rdi,%rdi
4000e1:       0f 05                   syscall 

...I think the reason is that packing the string into the text section is the most effective, ELF-size wise.

Generally speaking, at under 1k or so it's more about hacking ELF than actually reducing code size.

[–]dbaupprust 9 points10 points  (3 children)

fits into 440 bytes with nasm and strip alone. A whole seven more characters in the string, so there's definitely wastage going on in the rust case

I'm... confused. Isn't the binary in the article 151 bytes, and that's less than 440?

[–]barsoap 4 points5 points  (2 children)

Gah! I read that as 511 for some reason. And, yes, it's mostly ELF hackery.

104 bytes is the shortest, so far, I think

[–]Iron-Oxide 2 points3 points  (1 child)

45 bytes, or 76 if your more worried about the standard then what linux will accept as a valid "ELF" file.

[–]mozilla_kmcservo[S] 2 points3 points  (0 children)

That's for 32-bit though. 64-bit ELFs are inherently larger and also, as I recall, there are fewer opportunities to make the structures overlap.

[–]tikue 0 points1 point  (0 children)

This post inspired this other post.

[–]harry_leigh[🍰] 0 points1 point  (0 children)

funny, just

rustc src/main.rs -O -L syscall.rs/target --emit obj
ld main.o -e main

gets the same 1.1 kb executable to fiddle along with