2

I've compiled my project with the following flags: clang -MMD -MP -D_FORTIFY_SOURCE=2 -Weverything -Wno-poison-system-directories -O2 -fPIE -fPIC -fstack-protector -finline-functions -march=native -mtune=native src/getargv.c -o bin/getargv which has produced an executable that is 49KB (50224B) large and 96% (47799B) NULL bytes as measured by xxd -p -c 1 < bin/getargv | sort | uniq -c and ls -l bin/getargv.

llvm-size --format=darwin bin/getargv says:

Segment __PAGEZERO: 4294967296
Segment __TEXT: 16384
    Section __text: 1220
    Section __stubs: 78
    Section __stub_helper: 146
    Section __cstring: 41
    Section __unwind_info: 96
    total 1581
Segment __DATA_CONST: 16384
    Section __got: 32
    total 32
Segment __DATA: 16384
    Section __la_symbol_ptr: 104
    Section __data: 8
    Section __bss: 8
    total 120
Segment __LINKEDIT: 1072
total 4295017520

So the executable is 3*16384+1072=50224 bytes on disk (matches ls -l), but there's only 1581+32+120+1072=2805 bytes of data in the file afaict (94% empty so pretty close to the 96% above, I'm assuming some padding and null bytes in data/etc).

This seems like there must be a way to reduce the file size, but the strip command had no effect on the size.

Is there a way to reduce the segment size? Or strip the executable better?

[Edit]

$ du -h bin/getargv 
 52K    bin/getargv
sepp2k
  • 363,768
  • 54
  • 674
  • 675
Camden Narzt
  • 2,271
  • 1
  • 23
  • 42
  • 1
    run it through lz compression to see the entropy. if it shrinks to ~3k / 4k you'll be sure it's all null. If not, it's just not listed. – v.oddou Mar 30 '21 at 06:21
  • I checked with xxd, it's nulls. – Camden Narzt Mar 30 '21 at 06:21
  • Easiest way to reduce the size would be to use Linux ;) Looks like the linker does something really half-assed and doesn't interleave the segments in the file, as is standard for Gnu LD? – Antti Haapala -- Слава Україні Mar 30 '21 at 06:33
  • Unfortunately linux isn't an option for this program, it exists to expose a macOS only sysctl, to make up for the lack of `/proc//cmdline`. – Camden Narzt Mar 30 '21 at 06:36
  • Are you sure it's really taking up that much disk space? All-zero disk blocks are usually optimized away. Use `du -h bin/getargv` to see how much space it's actually using. – Barmar Mar 30 '21 at 06:41
  • Updated question with `du` output. – Camden Narzt Mar 30 '21 at 06:46
  • 2
    Don’t Mach-O segments require page alignment (16k on this system)? If so, I don’t think you’ll be able to win without dropping a segment… That GOT in __DATA_CONST must be tempting to target, how wedded are you to PIC/PIE? – James Greenhalgh Mar 30 '21 at 06:54
  • What makes you sure that there are bigger blocks of zeroes? Did youtake a look into the binary? There can be all sorts of more-than-8-bit-values that have single zeroes in them, additionally to opcodes that contain zeroes. – the busybee Mar 30 '21 at 09:01
  • @thebusybee yeah I looked at the hex output there are huge runs of just 00 bytes. – Camden Narzt Mar 30 '21 at 15:51
  • 1
    @JamesGreenhalgh that's interesting, I'd have thought that the segments would just be loaded into RAM at appropriate alignment, not stored on disk that way. – Camden Narzt Mar 30 '21 at 16:00
  • Does this answer your question? [Why aren't padding bytes in executables optimized?](https://stackoverflow.com/questions/65521176/why-arent-padding-bytes-in-executables-optimized) – Siguza Mar 30 '21 at 18:50
  • 1
    Maybe also see this: https://stackoverflow.com/a/65449833 – Siguza Mar 30 '21 at 18:52
  • @Siguza I think the second one is it. – the busybee Mar 30 '21 at 18:53
  • the busybee and Siguza yes those links explain it well, and even give me a flag to reduce the executable size a bit. You can flag this as a dup or whatever if you like. – Camden Narzt Mar 30 '21 at 21:26

0 Answers0