[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] MiNT lib 55



Hi,

On Wed, May 24, 2000 at 03:56:41PM +0200, Konrad M. Kokoszkiewicz wrote:
> > > 2) Where the macro S_IFBLK is defined (in PL 49 it was)?
> > 
> > See reply to Q-Funk.  Add -D_BSD_SOURCE to your CFLAGS and then read
> > NOTES. ;-)
> 
> Sorry, my mistake: I meant S_IFSOCK... and also sys/types.h seems to

S_IFSOCK was introduced only this month, it didn't vanish, it's new
altogether.  Anyway, the same cure helps, use -D_BSD_SOURCE.

BTW: There is an annoying typo in the new sys/stat.h, a couple of lines
below:

	#define S_ISSOCK		((m & S_IFMT) == S_IFSOCK)

should read

	#define S_ISSOCK(m)		((m & S_IFMT) == S_IFSOCK)

> define ushort and ulong, but doesn't define uchar, which is a bit

ushort and ulong are only in sys/types.h for backwards compatibility.  Is
there any sys/types.h that also defines uchar?  Why don't you simply use
"unsigned char"?  

> annoying. And mintbind.h doesn't define Slbopen()/Slbclose().

Because I didn't know that they were missing until now. ;-)
Frank, can you patch in the bindings?

But for compatibility you should provide your own macros anyway, like

#include <mintbind.h>
#ifndef Slbopen
# define Slbopen(foo, bar, baz) trap_such_and_such(opcode, ...)
#endif

> > > 	#include <mintbind.h> 
> > >  
> > > 	int
> > > 	main()
> > > 	{
> > > 		Cconws("Dupa blada\r\n"); 
> > > 		return 0;
> > > 	} 
> > 
> > Become an ld wizard! ;-)
> > I can link that into a file of less than 400 bytes.  It would be less
> > than 20 Bytes without the header and the relocation info.
> 
> I think i would be satisfied with 400 bytes. Okay, nice to know that it is
> possible :)

Kind of, see below.

> > >    which does not contain a single library reference, has exactly 39 
> > 
> > Sure it contains library references: _start, __main, _environ, ...
> 
> Nope, it doesn't. I am explaining: i didn't use any library function, so
> it does not have rights to contain any single library reference.

Ask Frank, I fought for your case even in advance. ;-)
I've eliminated all references to printf from at least libgcc (by default
libgcc.a references printf and it is quite hard to get along without
libgcc).

Apart from that: Yep, it does! See below.

> 
> > The reason for that annoying size problem is simple to find and hard to
> > solve.  The startup code contains a lot of library references and drags a
> > lot of seemingly unused modules into the link.  In "normal" applications
> 
> Well, I can't imagine why the startup code, which basically has to shrink
> the mem and parse the commandline, and this is rather simple task, has to
> use a lot of library references and finally become 40k in size.

You forgot a lot of things like establishing a new stack, repairing
ill-designed command lines, checking for being called as an accessory,
fixing up the environment, ...  Theses tasks are all very Atari specific.

The startup code is roughly organized as follows (profiling left aside):

	crt0.S: Are we an accessory?
	crtinit.c: Do Atari stuff namely parse the command line, fix the
		   environment (temporarily polluted with ARGV), establish
		   a new stack, shrink, init signal handlers (I think for
		   the TOS emulation) and finally call _main() which is
		   currently a weak alias for __libc_main().
	main.c: Initialize a lot of stuff, like Ssystem checking,
		preparing for clock() emulation, evaluating $UNIXMODE,
		setting up the standard streams stdin, stdout and stderr,
		fix DOSish environments, and finally call main().

Nothing is unnecessary there.  And if you "nm main.o | grep ' U '" you
will see how many library functions are needed to perform these tasks.
Omitting something from the above list will prevent some library functions
to work.

If you are not content with it, you have a lot of options to change
that.  If you want to bypass the libc and crt0.o altogether, either start
linking with another undefined reference than _start (which is resolved in
crt0.o) and don't link against crt0.o (provide your own startup
module).

But crt0.o is really harmless regarding size.  The first candidate to omit
would be crtinit.o.  To do this, you have to provide your own function
_crtinit().  But crtinit.o is also relatively cheap.  To gain something
you will have to provide your own version of _main() thus preventing
main.o being dragged into the link.  But you have to be very careful with
that.  A tiny little mistake can prevent things from working.  If you are
lucky you will have only link-time errors to fix (possibly unresolved
references) but most of the time your software will simply not work
because the library hasn't been properly initialized (happy debugging).

Compile hello.c with "gcc -static" under recent Linux versions.  The
unstripped binary has 960305 bytes (105964 bytes on MiNT).  After
stripping you still have 209172 bytes (87302 bytes on MiNT).  The
super-minimal hello.c:

	int main (int argc, char* argv[]) { return 0; }

is only 4k smaller under Linux (because you still have printf
referenced).  MiNT/MiNTLib is much more modest here, the stripped binary
has "only" 41611 Bytes (less than 50 % of the normal hello.c).  This is
not arbitrary but the result of my efforts to avoid printf like the plague
in everything that is referenced by the startup code.

Building under MiNT with "gcc -o hello hello.o -liio" (talking about a
printf-hello.c again) results in a binary of 64315 bytes, i. e. you save
about 20 k by linking against -liio.

A couple of weeks I have made similar tests with HP-UX (both with the crap
compiler and gcc) with results in the same dimensions as with Linux.  In
other words: The MiNTLib startup code is really modest compared to other
system libraries.  If this is still inacceptable for certain applications
then the application programmer has to leave the path of virtue and tune
by overriding libc definitions but that implies a risk that grows
dramatically with increasing insights in the libc internals.

> > this is not such a big problem because you will reference most of it from
> > your application code as well but in pathological cases like your
> > three-liner it is a nuisance, that's right.
> 
> I disagree. Even a complex program can be written without many references
> to the library. I actually have one such program, which has four modules
> of less than 2k each (after compiling downto *.o files) and is basically

You can use "size *.o" to get the relevant sizes.  That does only take the
text, data and bss size into account, not the symbol and string table.

> using strcpy(), strstr(), strlwr(), strcat() and printf(). Even
> considering the printf() may be large, I still don't understand why the
> final binary has over 100k. I suppose 70k of this just wastes disk and
> memory space.

I don't think so.  I would rather say that it is my sweat magnetized into
your hard disk. ;-)

> 
> > I have already given a lot of reasons for the larger binaries in a
> > previous thread.  In brief: Old MiNTLib versions had countless bugs which
> > turned up when I added the test suite to the MiNTLib.  The most common
> > reason for the bugs was that the old code was too simple, ignoring a lot
> > of special cases or tolerating bugs.  I have tried to overcome that either
> > by adding code for special cases or by updating the sources to newer
> > versions from other sources which had fewer bugs, more features and which
> > are mostly bigger.
> 
> I don't deny the fact that a better library is larger. I am trying to
> point out, that nothing (or very little) of that should be linked to a
> program that DOES NOT WANT TO USE THE LIBRARY. Writing a program in C I am
> expecting, that the linker will produce something executable, and
> particularly I don't want it to present me gifts in a form of linked stuff
> which I don't use, don't want to use and don't want to see in the
> executable.

A program that DOES NOT WANT TO USE THE LIBRARY should not USE the
library.  But the startup code (including the separated crt0.o) is an
integral part of the libc and it is both legal and common to reference
arbitrary library functions from the startup code.  If you are very
concerned about the program sizes you have to build them with
-nostartfiles and -nostdlib. If you are not concerned about arbitrary bugs
you can do the same.

Believe me, I already did a lot to reduce the size of MiNTLib linked
binaries.  But I think it is rather pointless to try to optimize the bare
code (i. e. the algorithms used).  I rather tried to avoid unresolved
references from one module to another, potentially large one wherever that
seemed appropriate (somebody using wordexp() or regex is obviously not
concerned about size).  If you think that the actual code in a library
module can be optimized for size, then go ahead and optimize it but make
sure that you have read the manpage for the function in question first.  
I am concerned about your issue and I already try to keep the binaries
small.  Thus, general complaints are not very useful; I need something
like "line 123 in foobar.c is overhead".

> Frank told me, that dropping the code, that emulates stuff on poor systems
> would make the library dramatically smaller. So, the library is big,
> because it emulates MiNT features on TOS and MagiC. My question is, why a

The effect is probably not that dramatical but still significant and of
course a nuisance.  I follow two strategies in parallel here: I try to
concentrate the critical stuff and I (will) try to embed emulations for
old systems into "#ifndef FOR_MINT_ONLY" or some other preprocessor macro.  
You will not find that in the current version, right now I rather try to
organize the code in a way that makes it easy to do that in the future.

> MiNT only program, which does not have a chance to work under TOS or Magix
> (ssh for example, or pine, or syslogd, or init, or whatever needs
> mintnet) has to carry all this stuff inside? This is not a stupid
> question, because the current situation is that MiNTlib is used as libc
> for gcc, so it is mainly used to compile programs which run under MinT,
> then again, non-Minters don't use MiNT Library, because it is a) too big,
> b) current versiosns of gcc don't work under anything but MiNT.... So the
> presence of the code that emulates MiNT functions seems like a serious
> paranoia.

I personally don't care whether MiNTLib linked binaries run under Magic or
not.  But there are a lot of people out there that will stone me as soon
as I drop TOS/Magic compatibility as a main goal of the MiNTLib.

> And even if tossers and magicers would use mint library for something, I
> still don't uderstand why my init (which is resident in the memory all the
> time the system is up) has to contain code that emulates
> e.g. vfork() under TOS...

Patch your init daemon to use a modified version of vfork() that does not
emulate the call.  Or convince TOS/Magic users that they shouldn't cry
when their binaries crash or exit when Pvfork() is not available (there
are also other programs that use vfork).

> > You will agree that an extra 30 or 40 kBytes wouldn't count at all if the
> > MiNTLib was a shared library.  But the MiNTLib won't become a shared
> > library in just a day and in the meantime you either have to live with the
> > larger code or you have to stick with an older version.  Don't ask for a
> > bugfix-only version.  Bugfixes generally result in bigger code; that's
> > what I am trying to explain.
> 
> This wasn;t the question. The question was, why a lot is linked when
> nothing was used...

Why, either it is used although it is not obvious or it is only used in
certain cases.  It is a dilemma, right, but show me a real way out of it.

Really, Konrad, I understand you and I try my best to avoid the nuisances
you complain about.  But the MiNTLib (like every libc) is really complex
and I may overlook things and sometimes you simply have to surrender when
you have to decide between small but buggy and huge but correct
code.  Sure, the old printf was somewhat smaller than the new one.  Same
for stdio in general.  But a lot of stuff either didn't work at all
because of that or it worked unreliably or uncorrectly.  What should I
do in these cases? Accept the bugs and ignore bug reports?

> > Profiling worked here after some changes in the code and some changes in
> > libgcc (not tested with the latest kernel).  I will re-check that.   If
> > profiled programs crash again, I'm sorry.  I really spent a lot of time to
> > make it run again.
> 
> I believe the profiling worked, but the question is why it links the
> GEMDOS timer, because if it is intended to do so, it will never work on
> systems with memory protection enabled (because GEMDOS timer vector cannot
> point to programs private text segment; yet bios.c should kill such a
> program, but it doesn't which means that the gcrt.o or whatever touches
> the GEMDOS timer, does not do it cleanly, i.e. via Setexc()).

You will remember that the GEMDOS timers are not my closest friends. ;-)
Could you provide a patch?  This is really not my area of expertise and I
prefer not to touch code that I don't understand completely.

Just to make sure that we talk about the same problem:  Here, profiling
generally works.  I only get a memory violation if I link the profiled
code against -lc_p, in other words profiling the libc itself with memory
protection does not work, whereas profiling the application code does
work, with or without mp.

Anyway, a patch would be very helpful.  A problem description is probably
not enough due to my limited knowledge of that GEMDOS vector stuff, sorry.

Ciao

Guido
-- 
http://www.stud.uni-saarland.de/
Send your spam to president@whitehouse.gov and your replies to
mailto:guido at freemint dot de