I'm messing around with writing my own dynamic linker for Linux (replacement for ld-linux.so). Yes, I'm a maniac.
I discovered what I consider a kernel bug, but I'm sure the kernel people would disagree. It's a simple bug really: the kernel honors the load addresses inside the program interpreter.
Here's what I was seeing. I created a small test program which uses my new dynamic linker as its program interpreter (PT_INTERP). My test program has 8 PHDR entries.
When I launch the program and breakpoint inside my dynamic linker, I can see the aux vector, and it indeed indicates that there are 8 PHDR entries, and gives a pointer to their location: 0x08048034.
But when my linker goes to examine the entries at this address, it finds... 3 PHDRs?! Everything after the third looks like garbage.
Okay, here's what happened. Most Linux programs are linked with a base load address of 0x08048000. Since my dynamic linker itself is not linked in any particularly special way, it too is given a load address of 0x08048000.
So what does the kernel do? It doesn't whine at all! It happily maps my dynamic linker RIGHT OVER THE TOP OF the program being dynamically linked! STUPID! So what I was seeing was the linker's own PHDRs, not the PHDRs of the program. Thanks for warning me, Mr. Kernel!
I fixed my problem by deliberately re-basing the dynamic linker using a link script. Now it loads at address 0x00000000, which I didn't actually think was possible but apparently it is. One of the things my linker must do is remap itself higher in memory, since residing on the NULL code page is a big stupid no-no.
Weird stuff.