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

RE: [MiNT] MiNTLib 0.51



Guido,

thanks for the explanation...

> From: owner-mint@fishpool.com [mailto:owner-mint@fishpool.com]On Behalf
> Of Guido Flohr
> Sent: Tuesday, May 18, 1999 3:01 AM
> To: MiNT mailing list
> Subject: Re: [MiNT] MiNTLib 0.51
>
>
> On Fri, May 14, 1999 at 09:38:18PM +0200, Julian Reschke wrote:
> > Who the hell is generating code like this? This would also fail
> on machines
> > where a similar parameter passing scheme is used, or where
> sizeof (long) !=
> > sizeof (void *).
>
> That "who the hell" was me. ;-)
> And all systems I know of that use the MiNTLib have 32 bit pointers and 32
> bit long ints.

Sorry, I did not intend to flame you. My (mis)understanding was that this
code was coming from some other Unix system, and I was wondering how in the
"generic" Unix world would write code that would make these assumptions.

For the Atari this is of course tolerable.

> To avoid confusion, I think I should explain the background a little: I
> needed to get the zlibc running.  The zlibc is actually a shared object
> and on systems with shared libraries it is intended that you configure
> your linker that all dynamically linked executables will get linked
> against that shared uncompress.o.  The object uncompress.o replaces most
> I/O primitives and the low-level filesystem interface routines so that
> whenever such a call fails the routines will retry to find a file of the
> same name but compressed with gzip and ".gz" appended to the name:
>
> 	int open (char* name, int flags, mode_t mode)
> 	{
> 		int retval = real_open (name, flags, mode);
> 		if (retval < 0 && errno == ENOENT)
> 		{
> 			... Try to stat NAME".gz" instead...
> 			... Iff successful
> 				retval = popen ("gzip -c name.gz", ...)
> 		}
> 	}
>
> That's the basic concept of the zlibc (and I must admit that it is a
> little suspect to me).
>
> I wanted to build a static library with the same concept.  The problem is
> that you must somehow allow the library to override the library calls but
> still be able to access the original functionality.  The easiest way to do
> this would be to
>
> 	#define real_open(name, flags, mode) (syscall (SYS_open, name,
> flags, mode))
>
> Another possibility would be to access internal library functions.
>
> Both ways didn't work with the MiNTLib and now they do (at least with gcc,
> not yet with PureC).  I have a simple text file "syscalls-list" which
> contains of entries like the following:
>
> open long int ...
>
> which translates into something like: There is a system call called
> "open", which takes one 32-bit arg, one int-arg (16 or 32 bit, depending
> on -mshort) and a va_list.  An awk-script generates various other files
> from that list, first <sys/syscall.h> which defines opcodes to use for
> syscall(), and for each system call a C source file, e.g. open.c which
> looks like:
>
> ...
> int open (long arg1, int arg2, ...)
> {
>   ... va stuff ...
>   retval = __open (arg1, arg2, variadic_args);
>   ... va end stuff ...
> }
>
> These files will only get compiled if your linker doesn't support weak
> symbols.  If weak symbols are supported, then "open" would simply be a
> weak alias for "__open()".  In the latter case (which will hopefully soon
> be the default) the whole mechanism works without any overhead.

Finally I understand what weak symbols are for. Thanks.


> Now for syscall.c.  The implementation for syscall() works like follows:
>
> struct syscall_entry
> {
>   int (*real_func) ();
>   int (*wrapper_func) (int opcode, ...);
> };
>
> struct syscall_entry entries[] =
> {
>   ...
>   { __open, wrapper_liv },
>   ...
> };
>
> The jumptable (array entries) is also generated by that awk script.  In
> the open example it means that syscall() should call the function
> WRAPPER_LIV (which returns an int and takes a 32 bit, an int arg and a
> dots arg) and return the return value from that function.
>
> The result: To open a file you can now write
>
> 	open ("/etc/passwd", O_RDONLY); or
> 	__open ("/etc/passwd", O_RDONLY); or
> 	syscall (SYS_open, "/etc/passwd", O_RDONLY);
>
> Again, normally using one of the first two methods should be equivalent.
> The syscall-method is highly deprecated but it is there if you happen to
> need it.  The main disadvantage of syscall() is that you will drag all
> modules that define the underlying functions into the link.
>
> Uhm, after doing all that stuff I finally realized that I really needed
> the "libz" (which doesn't require such ugly hacks) and not the "zlibc".
> But having a working syscall() is not so bad after all and so I would
> really like to leave that inside.  For example Perl is happy with that
> (and for Perl it is no problem that most of the library gets linked
> because it needs that anyway).
>
> Just if somebody wonders why all this stuff is necessary just to implement
> a single function:  On normal eunuchs systems (correct me if I'm wrong,
> that's how I think it works) the syscall function works much like our
> macros in <osbind.h> resp. <mintbind.h>, i. e. the function simply packs
> the arguments onto the stack and executes some trap instruction to call
> the respective kernel routine.  In other words, the function "open" is
> really an operating system call and not a library routine (and that's why
> you find the manpage for open in section 2, not section 3 of the manuals).
>
> MiNT is different.  The GEMDOS-Fopen() function is not compatible to other
> systems and the MiNTLib open() function tries its best to emulate the
> behavior of eunuchs-open both on MiNT and non-MiNT systems.
>
> If somebody can think of a smarter way to implement syscall() I'll be
> happy to hear about that. Until then: Don't use it but if you need it, you
> have it.
>
> Ciao
>
> Guido
>
> P.S.: To return to the question, the code is ugly because I wanted to
> simplify things as much as possible.  With gcc it works because gcc
> internally doesn't care if an argument or return value is really a pointer
> or a long (or unsigned long).

As Michael stated this is only true as long as nobody implements parameter
passing through registers...

> And (P.P.S.), yes, I know that the above described mechanism
> doesn't work flawlessly with variadic functions.  But I've taken care of
> that and at least with gcc it works.

Speaking of other solutions: it seems to me that all this could be avoided
if we had MagiC style shared libraries under MiNT, and if MiNT lib would be
implemented as shared library.

In which case "open()" would just be a proxy, and you would dynamically link
either mintlib.slb or a ZLIB-enabled replacement...