|
From: Julian S. <js...@ac...> - 2007-01-01 21:49:45
|
On Sunday 31 December 2006 22:50, John Reiser wrote:
> Julian Seward wrote:
> > I've been testing the 3.2 branch on OpenSUSE 10.2 (kernel 2.6.18.2,
> > glibc-2.5) and mostly it works pretty well. However, it can't run bash:
>
> ...
>
> > sys_mmap ( 0xFFFDE000, 69636, 5, 2050, 3, 0 ) --> [pre-fail] Failure(0x=
C)
> > sys_mmap ( 0xFFFD9000, 90236, 5, 2050, 3, 0 ) --> [pre-fail] Failure(0x=
C)
> > sys_mmap ( 0xFFFA1000, 319664, 5, 2050, 3, 0 ) --> [pre-fail]
> > Failure(0xC)
> >
> > This strikes me as strange because the addresses (0xFFFDE000 etc) are
> > almost at the end of 4G. It's also strange because other programs,
> > including large ones, run just fine, and these .so's are mapped quite
> > low, as is normal.
On further investigation I am more mystified. I have established that this
is not a regression, as 3.2.1 fails similarly on ppc32, and also that it is=
=20
not caused by the 64k page stuff added to 3.2.2.
I cannot afford to spend any more time on this, so maybe some Linux-on-PPC
person can chase it more if required.
Here's what else I discovered:
The bogus mmap addresses are produced by __elf_preferred_address in
glibc-2.5/sysdeps/powerpc/powerpc32/dl-machine.c (I assume). They are
handed off to the failing mmap in _dl_map_object_from_fd in dl-load.c:
/* This is a position-independent shared object. We can let the
kernel map it anywhere it likes, but we must have space for all
the segments in their specified positions relative to the first.
So we map the first segment without MAP_FIXED, but with its
extent increased to cover all the segments. Then we remove
access from excess portion, and there is known sufficient space
there to remap from the later segments.
As a refinement, sometimes we have an address that we would
prefer to map such objects at; but this is only a preference,
the OS can do whatever it likes. */
ElfW(Addr) mappref;
mappref =3D (ELF_PREFERRED_ADDRESS (loader, maplength,
c->mapstart
& GLRO(dl_use_load_bias))
- MAP_BASE_ADDR (l));
/* Remember which part of the address space this object uses. */
l->l_map_start =3D (ElfW(Addr)) __mmap ((void *) mappref, maplength,
c->prot,
MAP_COPY|MAP_FILE,
fd, c->mapoff);
if (__builtin_expect ((void *) l->l_map_start =3D=3D MAP_FAILED, 0))
{
map_error:
errstring =3D N_("failed to map segment from shared object");
goto call_lose_errno;
}
=46rom comparing against strace results, I see the failing mmap addresses a=
re
exactly of 0x80000000 greater than the corresponding values from strace.
This made me wonder if there is some sign-extend bug in the 32-bit virtual
ppc CPU code, but I could not find any such, and besides that code has been
extensively tested and hammered on this past year.
I also discovered the same mmap-fail problem occurs in various other
situations:
kernel in 32-bit mode, openSUSE 10.2, running bash
kernel in 32-bit mode, openSUSE 10.2, running ssh
kernel in 32-bit mode, openSUSE 10.1, running ssh (but bash is OK)
=46or a kernel in 64-bit mode (on ppc970), openSUSE 10.1, both bash and
ssh run fine, even though they are still 32-bit executables.
I notice that 32-bit mode kernels appear to have 2G+2G userspace split,
whereas a 64-bit kernel running a 32-bit executable can offer that exe
a full 4G of its own.
Anyway, this is all just for the record. Am not chasing it further.
J
|