[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Re: exporting symbols (was Re: The goodness of goodness)
From:       Rik Hemsley <rik () kde ! org>
Date:       2001-05-30 17:38:22
[Download RAW message or body]

#if Dirk A . Mueller
> Moin Matthias!
> 
> > http://www.BitWagon.com/elfvector.html
> > 
> > on freshmeat, and it talks about reducing KDE's startup time by using a 
> > different mechanism for dynamic relocations. Might this be relevant for this 
> > discussion?
> 
> Yes, extremely :)
> 
> Looks interesting. 

John Reiser (the author of elfvector) posted to dot.kde.org in the
discussion page of the article about Waldo's paper.

In case you missed both of his postings, here they are:

-----------------------------------------------------------------------

Here's how to get rid of nearly all relocations, by assigning fixed
virtual addresses to shared libraries. You can run it and measure its
performance today. Assign the addresses from the space below 0x08048000;
leave a gap between adjacent libraries for expansion, etc.

# demo: main() calls foo(); foo() printf()s a message
gcc -c main.c foo.c # compile only

# Create a "shared library" at a fixed address using foo.o
# elf_i386.x is a copy of /usr/lib/ldscripts/elf_i386.x,
# EXCEPT that `0x08048000' has been changed, such as to `0x07ff0000'.
gcc -Wl,-E -nostartfiles -o foo.so -T elf_i386.x foo.o

cat >dyn4exec.c <<EOF
#include <elf.h>
#include <sys/mman.h>
#include <fcntl.h>

main(int argc, char const *const *const argv)
{
  int const fd = open(argv[1], O_RDWR, 0);
  Elf32_Ehdr *const ehdr = (Elf32_Ehdr *)mmap(0, 4096,
    PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (ehdr->e_type!=ET_EXEC) {
    return 1;
  }
  ehdr->e_type = ET_DYN;
  return 0;
}
EOF

gcc -o dyn4exec dyn4exec.c
/dyn4exec foo.so # sets Elf32_Ehdr.e_type = ET_DYN

gcc -o main main.o foo.so # link main() to new shared lib

export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
/main # test run

-----------------------------------------------------------------------

My project http://www.BitWagon.com/elfvector.html speeds up application
start by providing transfer vectors. PLT relocation goes from 1 per
symbol to 1 per library. The symbols covered cannot be overridden, but
it is easy to exclude an arbitrary list (such as
  malloc,calloc,realloc,free,memalign) by regular expression matching on
the symbol name. You can even retrofit elfvector into existing shared
libraries and existing apps; no recompilation and no relinking are
required. What is required is maintenance: the ordered list of symbols
is now very important, and it must be versioned, etc.

The instructions generated for calling a virtual function could be
changed to delay relocation of the vtable until the first call through
it, by adding one more level of indirection. After the first call, the
ongoing cost would be 2 cycles per call.

More generally, a shared library linked as an ET_EXEC file loaded at a
fixed address could be handled by _dl_map_object_from_fd() in
glibc-2.2/elf/dl-load.c. Currently anything that is not ET_DYN is
rejected, but there is essentially no difference in file format between
ET_EXEC and ET_DYN. The only real problem is detecting address conflicts
at runtime, in order to diagnose errors. The runtime linker could use a
bitmap of 1 bit per page (32-bit address space with pages of 4KB
requries 128KBytes). To handle conflicts between dynamic linking and
malloc(), it would be nice to have a binary interface to
/proc/self/maps, perhaps implemented via ioctl(). sbrk() should be
deprecated in favor of a user-space page manager which provides services
to both malloc, mmap, dlopen, etc.

And while we're here, there is a missing piece in <link.h>, namely
ElfW(Ehdr) *l_elfehdr;
in the "public protocol" section of struct link_map:
-----
struct link_map
{
  /* These first few members are part of the protocol with the debugger.
     This is the same format used in SVR4. */

  ElfW(Addr) l_addr; /* Base address shared object is loaded at. */
  char *l_name; /* Absolute file name object was found in. */
  ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
  struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
  ElfW(Ehdr) *l_elfhdr; /* Public, so everyone can find it */
  -----

Yes, this partially duplicates
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
ElfW(Half) l_phnum; /* Number of program header entries. */
later in the structure, but these are "private" to the implementation.

-----------------------------------------------------------------------

I don't understand this stuff :)

Rik

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic