Hai all,

I've done some looking around in the code and made a little diagram of
the auxv and phdr structures.  I decided having some reference to look
for is a good idea, see if we can agree on the cause of the crash and
attack the bug together.

In src/libexec/ld.elf_so/map_object.c,  line 257 we see the offending
mmap.  It runs as
SYSCALL[13347,1](197) old_mmap ( 0x4D96000, 0, 3, 4114, -1, 0 )
  --> [pre-fail] Failure(0x16)
The size of 0 is what causes the failure.

When we look at the actual code, the second param is
base_vlimit - data_vlimit

Where does it get these from?  base_vlimit and data_vlimit are initialized
on lines 202 and 207, respectively.  They're initialized as
        base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz);            
and
        data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz);           

When we go a few lines back, we can see that segs[0] and segs[1]
correspond the the two PT_LOAD sections in the auxv PHDR.
(around line 163)

I wrote down the entire AUXV struct and PHDR structs.  I'm not going to
copy them by hand.  In any case, the PHDR pointer (AT_PHDR) is simply
a pointer to the info->phdr struct in m_main.c.  You can inspect these.

The two phdr structs of interest are:
gdb> print ((Elf32_Phdr *)info->phdr)[2]
$1 = {p_type = 0x1, p_offset = 0x0, p_vaddr = 0x8048000,
      p_paddr = 0x8048000, p_filesz = 0x851, p_memsz = 0x851,
      p_flags = 0x5, p_align = 0x1000}
and
gdb> print ((Elf32_Phdr *)info->phdr)[3]
$2 = {p_type = 0x1, p_offset = 0x854, p_vaddr = 0x8049854,
      p_paddr = 0x8049854, p_filesz = 0x120, p_memsz = 0x140,
      p_flags = 0x6, p_align = 0x1000}

The first represents the text segment (segs[0] in map_object.c),
the second represents the data segment (segs[1] in map_object.c).

Look at src/libexec/ld.elf_so/rtld.h for a moment.
#define round_down(x)   ((x) & ~(_rtld_pagesz - 1))                             
#define round_up(x)     round_down((x) + _rtld_pagesz - 1)                      

_rtld_pagesz is set to the AT_PAGESZ value in rtld.c, line 317.
This is 0x1000 in vg4nbsd.

So, the round_up lines are equivalent to:
        base_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_memsz)
                    = round_up(0x8049854 + 0x140)
                    = round_up(0x80499a8)
                    = round_down(0x80499a8 + 0xfff)
                    = round_down(0x804a9a7)
                    = (0x804a9a7 & ~0xfff)
                    = (0x804a9a7 & 0xfffff000)
        base_vlimit = 0x804a000
and
        data_vlimit = round_up(segs[1]->p_vaddr + segs[1]->p_filesz)
                    = round_up(0x8049854 + 0x120)
                    = ....
        data_vlimit = 0x804a000

Obviously, when ld.elf_so tries to subtract these from eachother this
is 0 difference because they are in the same segment.

What we need to figure out, consequently, is if this calculation is
correct, and if filesz should differ at least one page from memsz.
And if the page size is correct.

Kailash, you have a L00nix/i386 box at your disposal, right?  Can you have
a look at these PHDR values on that machine?  I'd love to know what the
correct value ought to be.

I hope we can finally squash this motherfucking bug!

Peter
-- 
http://sjamaan.ath.cx
--
"The process of preparing programs for a digital computer
 is especially attractive, not only because it can be economically
 and scientifically rewarding, but also because it can be an aesthetic
 experience much like composing poetry or music."
                                                        -- Donald Knuth

Attachment: pgpqsVSCR8QR9.pgp
Description: PGP signature

_______________________________________________
Vg4nbsd-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/vg4nbsd-devel

Reply via email to