Skip to content
Advertisement

Cannot load custom ELF executable in GDB

I am currently writing a compiler (http://curly-lang.org if you’re curious), and have been encountering a strange bug when trying to run the generated ELF binaries on the latest Linux kernel. The same binaries run fine on older kernels (I’ve tried on several Ubuntu boxes, uname 4.4.0-1049-aws), but on my updated Arch box (uname 4.17.11-arch1), I can’t even open them under GDB.

The error message given by GDB is During startup program terminated with signal SIGSEGV, Segmentation fault, which as I understand is indicative of a failure to load the program segments before the first instruction is ever run.

I compiled a minimal ELF executable with GCC/NASM to try and reproduce the problem, but the GCC-produced executable loads without a hitch, whereas my programs definitely do not.

Here are the printouts of readelf -a for both executables, for reference. The first is the program generated by my compiler :

JavaScript

And for the GCC-generated program :

JavaScript

As you can see, I’ve tried to mirror GCC’s segment placement (~0x400000 for the code, and ~0x800000 for the data), and the two ELF headers are strictly identical. The only meaningful difference I can think of is that my custom binaries have two LOAD segments (one for the initialization code, one for the rest) that share the same page, whereas GCC only produces a single code LOAD segment. That shouldn’t pose a problem, though, since they both share the same permissions and don’t overlap.

Other than that, I do not see what could possibly keep the first program from loading correctly. If anyone well-versed in the arcanes of the Linux ELF loader could enlighten me, that would be greatly appreciated.

Thank you for your attention,

Advertisement

Answer

Nevermind everyone, it was the page-sharing segments that were causing the problem all along.

Thinking the problem was probably in the kernel loader, I should have thought about running dmesg much earlier, where I would have noticed the following message, clear as day :

JavaScript

Apparently, some benevolent mastermind decided 3 months ago that it would be good to actually catch double-mapping errors instead of just letting them go silently as we always did in the ELF loader.

It’s not that my binaries used to be correct, it’s that the error they were causing wasn’t caught before. I don’t know if I should be proud or ashamed for my bugs to have eluded detection all this time.

Anyway, I leave this answer to warn anyone foolish enough to map multiple segments on a single page in an ELF binary : do not. There is no try.

PS: @rodrigo: Thanks for your answer, I didn’t even notice the PhysAddr before you pointed them out. The manual says that they’re used “on systems where physical addressing is relevant”, which doesn’t seem to be the case here, but I’ll remember to keep a lookout for them next time.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement