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

Re: shared libraries for MiNT



  A Proposal for Implementing Shared Libraries
  
  I think I've finally figured out a "good" way to implement shared
  libraries (i.e. low overhead, doesn't need VM, requires few changes
  to existing applications). Here's my proposal; please let me know what
  you think. (In case it isn't obvious, this is *very* far from being
  cast in stone :-). I do think we need to do shared libraries soon,
  though.)
  
  A shared library will be implemented as a DRI format object file, with
  the GST long name symbol table. A program linked with shared libraries
  will have the same format, but with an additional header prepended
  which gives the names and version numbers of the shared libraries it
  requires.

I really think we need to have an object format that includes separate
segments for blockdata, blockbss, and maybe even blocktext for constant
arrays & structures. That's the only way to insure enough breathing space
while using 16 bit offsets.
  
  Both the libraries and the programs will be compiled to use
  register A5 as a base register (e.g. when compiled with gcc they will
  be compiled with -mbaserel). They need not be position independent;
  the libraries will appear at the same virtual address (determined at
  load time) in every process, and programs will be relocated at load
  time by the kernel.

Just a minor note, a5 is unusable for this purpose because it is zeroed
by Supexec. The current baserel stuff uses a4.
  
  The data and bss segments of a given shared library will always be
  located at the same (relative) offset in the data/bss area of
  a program using that library. (Note that I'm going to call the
  "data/bss area" just the "data segment" from here on in, because the
  bss is just a special part of the data segment from the kernel's point
  of view.)

I don't understand how this can be enforced without collisions. Is the load
address & size of the data section stored in the respective library? What
happens if the library is revised and the data section changes in size? Also,
it seems that trying to deal with gaps from unused libraries will be messy...
Finally, what about library code referencing data symbols that are external
to the library? (I think e.g. curses references some of termcap's variables...)
Is this scheme going to only support Atari-generated libraries, or will anyone
be able to write a shared library?
  
  Does this make sense? The key thing is that since everyone is using
  register A5 as a base register, the libraries can always find their
  data (at the particular fixed offset into the data segment assigned to
  them).
  
It certainly has that advantage. My previous scheme involved resetting the
base register on a per-library basis, but I couldn't figure out how to cope
with libraries that called each other, or called back into user code (like
bsearch or qsort, for example...).

  The disadvantage of this scheme is that once more than 64K of data is
  filled up, libraries and/or programs that use 16 bit offsets will be
  in trouble. There are ways around this, of course.
  
  Another disadvantage is that program load times will be longer, since
  the kernel is going to have to do the relocation and symbol resolving.

Meaning that executables must never be stripped, as well, right? And, just
to clarify, this is not an attempt at providing dynamic loading and linking
as well, is it? (Oh, I see, you can strip any resolved symbols, of course,
and only leave the unresolved ones in a program file...)
  
  An alternative would be to use something like Sun's global offset table.
  That scheme is slower, though, since it adds another layer of indirection
  to variable references.
  
  Please let me know your thoughts on this matter.

Perhaps if we ate up yet another address register for a per-library base
register. Allow the data segment to be sized and located dynamically, with
the location stored in the main program's data region, and passed into (say)
a3 before entering a library routine. This pretty much requires stub routines
to be linked into every program, as well as any library that calls another
library. The stub will pull the correct base pointer to use from the main
program's a4 base, and restore the old register before returning. The easiest
way to deal with this is to assign fixed offsets from the program's base
pointer for each library's private base pointer. Still can't get away from
assigning some kind of fixed resource to each library, I guess.

Something else to establish that could help this discussion - is gnulib.a
treated as a single library, or does it get broken up into smaller functional
groups?
  -- Howard