This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

mapping shared libraries at fixed address...


So as to be able to mmap BIG data files on i386, I would like to get
the shared libraries out of the way. With no userspace specification,
ld.so and libc.so are mmap()ed by the kernel at one third of the
address space (starting at 0x55555000), which means that I can't mmap
contiguously a file larger than 1.6GB approximately (less than I
need), at opposed to a maximum of 2.9GB or so if I could get the
libraries loaded near the bottom of the memory.

There are three problems:
(1) ld.so itself is defined as a shared library with no load address
specification, and the kernel loads it at TASK_UNMAPPED_BASE. I don't
understand how I need to edit the ld script so that it would do
otherwise -- my attempts so far get me segfaults and/or link errors.
(2) ld.so itself must load things at a lower address. I could somehow
try to define __elf_preferred_address for i386 or to intercept
__mmap() with code that tries to load from some address in low memory.
(3) the libc itself might use mmap(0,...) at which point I could have
it use a custom __mmap() defined with LD_PRELOAD. This would not be
required if I get a chance to mmap() my own stuff soon enough for the
address space to not be clobbered yet.

I'm at loss how to solve problem (1), and that's where I'm requesting
help. Between what the kernel wants, how to achieve it with ld, and
how to fulfill the runtime expectations of ld.so while doing it, I
don't know what to do.

For (2) I think I could implement __elf_preferred_address if I tried,
but I'm not sure it would spare me the need to intercept mmap, and if
not, then it's redundant anyway.

For (2) and/or (3), I think I understand how to intercept mmap(); I'm
concerned however about how to do it right. I must maintain a
userspace mirror of enough of the kernel vma structures so as to
emulate mmap with a smaller TASK_UNMAPPED_BASE. (a) this raises the
question of ensuring that all calls to mmap are properly intercepted
by the same copy of the code. (b) this also raises the question of
what libc calls I may use to initialize the map: typically, I suppose
I could try to read from /proc/self/maps though this requires at least
strtol to be present if not sscanf, and/or I could suppose that the
only thing mapped into memory initially is ld.so, at its known address
and size.

Ideally, I should be able to backport those changes to older version
of ld.so (2.2.5), but I could live with shipping around the set of a
binary and all its dependent dynamic libraries.

Workarounds:
* One "easy" workaround would be to recompile the kernel with a small
TASK_UNMAPPED_BASE, but I can't change the kernel on all the targetted
machines.
* Another workaround would be to compile my binaries statically, but
the whole environment crucially depends on dynamic libraries at the
time being, and it would be quite some engineering to make it not so.

PS: I suppose that such features could be useful to other people than
me, especially if no mmap() interception is required in ld.so -- at
which time it could usefully be made a runtime option controlled by
some LD_PREFERRED_ADDRESS environment variable or some such.

[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
When everything seems to be going against you, remember that the airplane takes
off against the wind, not with it. -- Henry Ford


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]