Skip site navigation (1)Skip section navigation (2)
Date:      26 Sep 1996 15:33:00 GMT
From:      peter@spinner.DIALix.COM (Peter Wemm)
To:        freebsd-current@freebsd.org
Subject:   Re: BLOAT in minimal programs
Message-ID:  <52e7nc$fqt$2@haywire.DIALix.COM>
References:  <324A22F6.167EB0E7@whistle.com>

next in thread | previous in thread | raw e-mail | index | archive | help
In article <199609260657.XAA00299@root.com>,
	dg@root.com (David Greenman) writes:
>>David Greenman wrote:
>>> 
>>> ...
>>> >THIS IS NOT MINIMAL!
>>> >I DID NOT WANT ALL THIS CRAP!
>>> >why oh why did I get malloc?
>>> 
>>>    Because atexit() uses it to remember exit callouts (see crt0.c).
>>so why isn't atexit in libc?
> 
>    It is.
> 
>>I certainly didn't call it..
>>of course I haven't checked.. it might well be there..
> 
>    Sorry, I meant it was called from crt0.c. Actually, if you're building your
> program static the call shouldn't be made if things are being built using
> scrt0.o like they are supposed to be (the call to atexit() is in crt0 is not
> made for the !MCRT0 && !DYNAMIC case).

That's right, it's not coming from crt0.o, it's a gcc "feature".

>>> >vfprintf?
>>> >__CurrentRuneLocale ?
>>> >hell it doesn't even contain a STRING let alone a default nationality!
>>> 
>>>    I think this is all because malloc (or something in crt0.c) calls a stdio
>>> funtion like printf either directly or indirectly via a perror() or equivilent.
>>> Of course Runes comes in because of vfprintf, etc, etc.
>>
>>
>>so do we have a way of telling cc to link with a more sensible crt0?
>>surely we can do something..
> 
>    We already do. Perhaps the calls are coming from somewhere else...
> 
> -DG

Yes, we do have a special version of crt0.o, it's /usr/lib/scrt.o and gcc
correctly links with it:

peter@spinner[11:19pm]/tmp-968> cat foo.c
main()
{
}

peter@spinner[11:19pm]/tmp-971> cc -S foo.c
peter@spinner[11:19pm]/tmp-972> more foo.s
        .file   "foo.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
        .align 2
.globl _main
        .type    _main,@function
_main:
        pushl %ebp
        movl %esp,%ebp
        call ___main
L1:
        leave
        ret
Lfe1:
        .size    _main,Lfe1-_main

peter@spinner[11:19pm]/tmp-973> cc -c foo.c
peter@spinner[11:19pm]/tmp-974> cc -v -static -o foo.exe foo.o
gcc version 2.7.2.1
 /usr/bin/ld -e start -dc -dp -Bstatic -o foo.exe /usr/lib/scrt0.o foo.o /usr/lib/libgcc.a -lc /usr/lib/libgcc.a

[add the -M flag to ld to see the map output ]

peter@spinner[11:20pm]/tmp-975> /usr/bin/ld -M -e start -dc -dp -Bstatic -o foo.exe /usr/lib/scrt0.o foo.o /usr/lib/libgcc.a -lc /usr/lib/libgcc.a | head
/usr/lib/libgcc.a(__main.o) needed due to ___main
/usr/lib/libgcc.a(_exit.o) needed due to __exit_dummy_decl
/usr/lib/libc.a(atexit.o) needed due to _atexit
/usr/lib/libc.a(malloc.o) needed due to _malloc
/usr/lib/libc.a(mmap.o) needed due to _mmap
/usr/lib/libc.a(brk.o) needed due to _brk
/usr/lib/libc.a(sbrk.o) needed due to minbrk
/usr/lib/libc.a(munmap.o) needed due to _munmap
/usr/lib/libc.a(memset.o) needed due to _memset
/usr/lib/libc.a(getenv.o) needed due to _getenv
[..LOTS MORE..]

Guess what is linked in with libgcc.c's __main(), and is called by __main():

/* Run all the global constructors on entry to the program.  */

#ifndef ON_EXIT
#define ON_EXIT(a, b)
#else
/* Make sure the exit routine is pulled in to define the globals as
   bss symbols, just in case the linker does not automatically pull
   bss definitions from the library.  */

extern int _exit_dummy_decl;
int *_exit_dummy_ref = &_exit_dummy_decl;
#endif /* ON_EXIT */

void
__do_global_ctors ()
{
  DO_GLOBAL_CTORS_BODY;
  ON_EXIT (__do_global_dtors, 0);
}
#endif /* no INIT_SECTION_ASM_OP */


So, in a nutshell if you want a small static program that doesn't use
C++ anywhere:

peter@spinner[11:27pm]/tmp-985> cat foo.c
__main() { /* dummy stub */ }

main()
{
}
peter@spinner[11:27pm]/tmp-986> cc -static -o foo.exe foo.c
peter@spinner[11:27pm]/tmp-987> nm foo.exe
00001020 F /usr/lib/scrt0.o
00001090 F /var/tmp/cc0032811.o
00002018 B ___atexit
00002014 B ___cleanup
00001090 t ___gnu_compiled_c
00001090 T ___main
00002000 D ___progname
000010f0 T __exit
00002010 D _edata
00002024 B _end
0000201c B _environ
00002020 B _errno
00001100 T _etext
000010b0 T _exit
000010f0 F _exit.o
00001098 T _main
000010b0 F exit.o
00001090 t gcc2_compiled.
00001020 T start
peter@spinner[11:27pm]/tmp-988> size foo.exe
text    data    bss     dec     hex
4096    4096    0       8192    2000

Now, you can't get smaller than that without ELF.

(I learned crude tricks like this from my Amiga days with it's "interesting"
C compilers. (ever used lattice-C 4.02?)  Sigh...)

-Peter




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?52e7nc$fqt$2>