Fix the ELF base calculation

Find the effective ELF load address in dl_iterate_phdr by computing the
difference between the in-memory phdr and its p_vaddr specified in the
ELF file.

This makes the dl_iterate_phdr test pass and restores the stack traces.
master
LemonBoy 2020-11-23 14:58:08 +01:00
parent 0a84f85945
commit 3e22077d46
3 changed files with 15 additions and 8 deletions

View File

@ -4340,7 +4340,7 @@ pub fn dl_iterate_phdr(
const elf_base = std.process.getBaseAddress();
const ehdr = @intToPtr(*elf.Ehdr, elf_base);
// Make sure the base address points to an ELF image
// Make sure the base address points to an ELF image.
assert(mem.eql(u8, ehdr.e_ident[0..4], "\x7fELF"));
const n_phdr = ehdr.e_phnum;
const phdrs = (@intToPtr([*]elf.Phdr, elf_base + ehdr.e_phoff))[0..n_phdr];
@ -4348,10 +4348,21 @@ pub fn dl_iterate_phdr(
var it = dl.linkmap_iterator(phdrs) catch unreachable;
// The executable has no dynamic link segment, create a single entry for
// the whole ELF image
// the whole ELF image.
if (it.end()) {
// Find the base address for the ELF image, if this is a PIE the value
// is non-zero.
const base_address = for (phdrs) |*phdr| {
if (phdr.p_type == elf.PT_PHDR) {
break @ptrToInt(phdrs.ptr) - phdr.p_vaddr;
// We could try computing the difference between _DYNAMIC and
// the p_vaddr of the PT_DYNAMIC section, but using the phdr is
// good enough (Is it?).
}
} else unreachable;
var info = dl_phdr_info{
.dlpi_addr = 0,
.dlpi_addr = base_address,
.dlpi_name = "/proc/self/exe",
.dlpi_phdr = phdrs.ptr,
.dlpi_phnum = ehdr.e_phnum,
@ -4360,7 +4371,7 @@ pub fn dl_iterate_phdr(
return callback(&info, @sizeOf(dl_phdr_info), context);
}
// Last return value from the callback function
// Last return value from the callback function.
while (it.next()) |entry| {
var dlpi_phdr: [*]elf.Phdr = undefined;
var dlpi_phnum: u16 = undefined;

View File

@ -386,8 +386,6 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
test "dl_iterate_phdr" {
if (builtin.os.tag == .windows or builtin.os.tag == .wasi or builtin.os.tag == .macos)
return error.SkipZigTest;
if (builtin.position_independent_executable)
return error.SkipZigTest;
var counter: usize = 0;
try os.dl_iterate_phdr(&counter, IterFnError, iter_fn);

View File

@ -686,8 +686,6 @@ pub fn getBaseAddress() usize {
if (base != 0) {
return base;
}
// XXX: Wrong for PIE executables, it should look at the difference
// between _DYNAMIC and the PT_DYNAMIC phdr instead.
const phdr = os.system.getauxval(std.elf.AT_PHDR);
return phdr - @sizeOf(std.elf.Ehdr);
},