-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Initial support for static PIE executables #3960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
const std = @import("std"); | ||
const elf = std.elf; | ||
const builtin = @import("builtin"); | ||
const assert = std.debug.assert; | ||
|
||
const R_AMD64_RELATIVE = 8; | ||
const R_386_RELATIVE = 8; | ||
const R_ARM_RELATIVE = 23; | ||
const R_AARCH64_RELATIVE = 1027; | ||
const R_RISCV_RELATIVE = 3; | ||
|
||
const ARCH_RELATIVE_RELOC = switch (builtin.arch) { | ||
.i386 => R_386_RELATIVE, | ||
.x86_64 => R_AMD64_RELATIVE, | ||
.arm => R_ARM_RELATIVE, | ||
.aarch64 => R_AARCH64_RELATIVE, | ||
.riscv64 => R_RISCV_RELATIVE, | ||
else => @compileError("unsupported architecture"), | ||
}; | ||
|
||
// Just a convoluted (but necessary) way to obtain the address of the _DYNAMIC[] | ||
// vector as PC-relative so that we can use it before any relocation is applied | ||
fn getDynamicSymbol() [*]elf.Dyn { | ||
const addr = switch (builtin.arch) { | ||
.i386 => asm volatile ( | ||
\\ .weak _DYNAMIC | ||
\\ .hidden _DYNAMIC | ||
\\ call 1f | ||
\\ 1: pop %[ret] | ||
\\ lea _DYNAMIC-1b(%[ret]), %[ret] | ||
: [ret] "=r" (-> usize) | ||
), | ||
.x86_64 => asm volatile ( | ||
\\ .weak _DYNAMIC | ||
\\ .hidden _DYNAMIC | ||
\\ lea _DYNAMIC(%%rip), %[ret] | ||
: [ret] "=r" (-> usize) | ||
), | ||
// Work around the limited offset range of `ldr` | ||
.arm => asm volatile ( | ||
\\ .weak _DYNAMIC | ||
\\ .hidden _DYNAMIC | ||
\\ ldr %[ret], 1f | ||
\\ add %[ret], pc | ||
\\ b 2f | ||
\\ 1: .word _DYNAMIC-1b | ||
\\ 2: | ||
: [ret] "=r" (-> usize) | ||
), | ||
// A simple `adr` is not enough as it has a limited offset range | ||
.aarch64 => asm volatile ( | ||
\\ .weak _DYNAMIC | ||
\\ .hidden _DYNAMIC | ||
\\ adrp %[ret], _DYNAMIC | ||
\\ add %[ret], %[ret], #:lo12:_DYNAMIC | ||
: [ret] "=r" (-> usize) | ||
), | ||
.riscv64 => asm volatile ( | ||
\\ lla %[ret], _DYNAMIC | ||
: [ret] "=r" (-> usize) | ||
), | ||
else => @compileError("???"), | ||
}; | ||
if (addr == 0) unreachable; | ||
return @intToPtr([*]elf.Dyn, addr); | ||
} | ||
|
||
pub fn apply_relocations() void { | ||
@setRuntimeSafety(false); | ||
|
||
const dynv = getDynamicSymbol(); | ||
const auxv = std.os.linux.elf_aux_maybe.?; | ||
var at_phent: usize = undefined; | ||
var at_phnum: usize = undefined; | ||
var at_phdr: usize = undefined; | ||
var at_hwcap: usize = undefined; | ||
|
||
{ | ||
var i: usize = 0; | ||
while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) { | ||
switch (auxv[i].a_type) { | ||
elf.AT_PHENT => at_phent = auxv[i].a_un.a_val, | ||
elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val, | ||
elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val, | ||
else => continue, | ||
} | ||
} | ||
} | ||
|
||
// Sanity check | ||
assert(at_phent == @sizeOf(elf.Phdr)); | ||
|
||
// Search the TLS section | ||
const phdrs = (@intToPtr([*]elf.Phdr, at_phdr))[0..at_phnum]; | ||
|
||
const base_addr = blk: { | ||
for (phdrs) |*phdr| { | ||
if (phdr.p_type == elf.PT_DYNAMIC) { | ||
break :blk @ptrToInt(&dynv[0]) - phdr.p_vaddr; | ||
} | ||
} | ||
unreachable; | ||
}; | ||
|
||
var rel_addr: usize = 0; | ||
var rela_addr: usize = 0; | ||
var rel_size: usize = 0; | ||
var rela_size: usize = 0; | ||
|
||
{ | ||
var i: usize = 0; | ||
while (dynv[i].d_tag != elf.DT_NULL) : (i += 1) { | ||
switch (dynv[i].d_tag) { | ||
elf.DT_REL => rel_addr = base_addr + dynv[i].d_un.d_ptr, | ||
elf.DT_RELA => rela_addr = base_addr + dynv[i].d_un.d_ptr, | ||
elf.DT_RELSZ => rel_size = dynv[i].d_un.d_val, | ||
elf.DT_RELASZ => rela_size = dynv[i].d_un.d_val, | ||
else => {}, | ||
} | ||
} | ||
} | ||
|
||
// Perform the relocations | ||
if (rel_addr != 0) { | ||
const rel = @bytesToSlice(elf.Rel, @intToPtr([*]u8, rel_addr)[0..rel_size]); | ||
for (rel) |r| { | ||
if (r.r_type() != ARCH_RELATIVE_RELOC) continue; | ||
@intToPtr(*usize, base_addr + r.r_offset).* += base_addr; | ||
} | ||
} | ||
if (rela_addr != 0) { | ||
const rela = @bytesToSlice(elf.Rela, @intToPtr([*]u8, rela_addr)[0..rela_size]); | ||
for (rela) |r| { | ||
if (r.r_type() != ARCH_RELATIVE_RELOC) continue; | ||
@intToPtr(*usize, base_addr + r.r_offset).* += base_addr + @bitCast(usize, r.r_addend); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -155,6 +155,12 @@ fn posixCallMainAndExit() noreturn { | |
// Find the beginning of the auxiliary vector | ||
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1); | ||
std.os.linux.elf_aux_maybe = auxv; | ||
|
||
// Do this as early as possible, the aux vector is needed | ||
if (builtin.position_independent_executable) { | ||
@import("os/linux/start_pie.zig").apply_relocations(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to pass in auxv instead of using it indirectly via the global? |
||
} | ||
|
||
// Initialize the TLS area | ||
const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size"); | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case-styling? Or is this a traditional name from somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not used to camelCase all the identifiers, will change it later :)