mirror of
https://github.com/ziglang/zig.git
synced 2025-12-12 17:23:09 +00:00
Initial support for static PIE executables
This commit is contained in:
parent
4d54e9a4fb
commit
333eec557f
@ -24,7 +24,7 @@ pub const DynLib = switch (builtin.os) {
|
|||||||
// fashion.
|
// fashion.
|
||||||
const LinkMap = extern struct {
|
const LinkMap = extern struct {
|
||||||
l_addr: usize,
|
l_addr: usize,
|
||||||
l_name: [*]const u8,
|
l_name: [*:0]const u8,
|
||||||
l_ld: ?*elf.Dyn,
|
l_ld: ?*elf.Dyn,
|
||||||
l_next: ?*LinkMap,
|
l_next: ?*LinkMap,
|
||||||
l_prev: ?*LinkMap,
|
l_prev: ?*LinkMap,
|
||||||
@ -53,48 +53,48 @@ const RDebug = extern struct {
|
|||||||
r_ldbase: usize,
|
r_ldbase: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn elf_get_va_offset(phdrs: []elf.Phdr) !usize {
|
// XXX: This should be weak (#1917)
|
||||||
for (phdrs) |*phdr| {
|
extern var _DYNAMIC: [128]elf.Dyn;
|
||||||
if (phdr.p_type == elf.PT_LOAD) {
|
|
||||||
return @ptrToInt(phdr) - phdr.p_vaddr;
|
comptime {
|
||||||
|
if (builtin.os == .linux) {
|
||||||
|
asm (
|
||||||
|
\\ .weak _DYNAMIC
|
||||||
|
\\ .hidden _DYNAMIC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error.InvalidExe;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
|
pub fn linkmap_iterator(phdrs: []elf.Phdr) !LinkMap.Iterator {
|
||||||
const va_offset = try elf_get_va_offset(phdrs);
|
if (@ptrToInt(&_DYNAMIC[0]) == 0) {
|
||||||
|
|
||||||
const dyn_table = init: {
|
|
||||||
for (phdrs) |*phdr| {
|
|
||||||
if (phdr.p_type == elf.PT_DYNAMIC) {
|
|
||||||
const ptr = @intToPtr([*]elf.Dyn, va_offset + phdr.p_vaddr);
|
|
||||||
break :init ptr[0 .. phdr.p_memsz / @sizeOf(elf.Dyn)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No PT_DYNAMIC means this is either a statically-linked program or a
|
// No PT_DYNAMIC means this is either a statically-linked program or a
|
||||||
// badly corrupted one
|
// badly corrupted one
|
||||||
return LinkMap.Iterator{ .current = null };
|
return LinkMap.Iterator{ .current = null };
|
||||||
};
|
}
|
||||||
|
|
||||||
const link_map_ptr = init: {
|
const link_map_ptr = init: {
|
||||||
for (dyn_table) |*dyn| {
|
var i: usize = 0;
|
||||||
switch (dyn.d_tag) {
|
while (_DYNAMIC[i].d_tag != elf.DT_NULL) : (i += 1) {
|
||||||
|
switch (_DYNAMIC[i].d_tag) {
|
||||||
elf.DT_DEBUG => {
|
elf.DT_DEBUG => {
|
||||||
const r_debug = @intToPtr(*RDebug, dyn.d_un.d_ptr);
|
const ptr = @intToPtr(?*RDebug, _DYNAMIC[i].d_un.d_ptr);
|
||||||
|
if (ptr) |r_debug| {
|
||||||
if (r_debug.r_version != 1) return error.InvalidExe;
|
if (r_debug.r_version != 1) return error.InvalidExe;
|
||||||
break :init r_debug.r_map;
|
break :init r_debug.r_map;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
elf.DT_PLTGOT => {
|
elf.DT_PLTGOT => {
|
||||||
const got_table = @intToPtr([*]usize, dyn.d_un.d_ptr);
|
const ptr = @intToPtr(?[*]usize, _DYNAMIC[i].d_un.d_ptr);
|
||||||
// The address to the link_map structure is stored in the
|
if (ptr) |got_table| {
|
||||||
// second slot
|
// The address to the link_map structure is stored in
|
||||||
|
// the second slot
|
||||||
break :init @intToPtr(?*LinkMap, got_table[1]);
|
break :init @intToPtr(?*LinkMap, got_table[1]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error.InvalidExe;
|
return LinkMap.Iterator{ .current = null };
|
||||||
};
|
};
|
||||||
|
|
||||||
return LinkMap.Iterator{ .current = link_map_ptr };
|
return LinkMap.Iterator{ .current = link_map_ptr };
|
||||||
|
|||||||
@ -640,20 +640,48 @@ pub const Elf64_Syminfo = extern struct {
|
|||||||
pub const Elf32_Rel = extern struct {
|
pub const Elf32_Rel = extern struct {
|
||||||
r_offset: Elf32_Addr,
|
r_offset: Elf32_Addr,
|
||||||
r_info: Elf32_Word,
|
r_info: Elf32_Word,
|
||||||
|
|
||||||
|
pub inline fn r_sym(self: @This()) u24 {
|
||||||
|
return @truncate(u24, self.r_info >> 8);
|
||||||
|
}
|
||||||
|
pub inline fn r_type(self: @This()) u8 {
|
||||||
|
return @truncate(u8, self.r_info & 0xff);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pub const Elf64_Rel = extern struct {
|
pub const Elf64_Rel = extern struct {
|
||||||
r_offset: Elf64_Addr,
|
r_offset: Elf64_Addr,
|
||||||
r_info: Elf64_Xword,
|
r_info: Elf64_Xword,
|
||||||
|
|
||||||
|
pub inline fn r_sym(self: @This()) u32 {
|
||||||
|
return @truncate(u32, self.r_info >> 32);
|
||||||
|
}
|
||||||
|
pub inline fn r_type(self: @This()) u32 {
|
||||||
|
return @truncate(u32, self.r_info & 0xffffffff);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pub const Elf32_Rela = extern struct {
|
pub const Elf32_Rela = extern struct {
|
||||||
r_offset: Elf32_Addr,
|
r_offset: Elf32_Addr,
|
||||||
r_info: Elf32_Word,
|
r_info: Elf32_Word,
|
||||||
r_addend: Elf32_Sword,
|
r_addend: Elf32_Sword,
|
||||||
|
|
||||||
|
pub inline fn r_sym(self: @This()) u24 {
|
||||||
|
return @truncate(u24, self.r_info >> 8);
|
||||||
|
}
|
||||||
|
pub inline fn r_type(self: @This()) u8 {
|
||||||
|
return @truncate(u8, self.r_info & 0xff);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pub const Elf64_Rela = extern struct {
|
pub const Elf64_Rela = extern struct {
|
||||||
r_offset: Elf64_Addr,
|
r_offset: Elf64_Addr,
|
||||||
r_info: Elf64_Xword,
|
r_info: Elf64_Xword,
|
||||||
r_addend: Elf64_Sxword,
|
r_addend: Elf64_Sxword,
|
||||||
|
|
||||||
|
pub inline fn r_sym(self: @This()) u32 {
|
||||||
|
return @truncate(u32, self.r_info >> 32);
|
||||||
|
}
|
||||||
|
pub inline fn r_type(self: @This()) u32 {
|
||||||
|
return @truncate(u32, self.r_info & 0xffffffff);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
pub const Elf32_Phdr = extern struct {
|
pub const Elf32_Phdr = extern struct {
|
||||||
p_type: Elf32_Word,
|
p_type: Elf32_Word,
|
||||||
@ -853,6 +881,16 @@ pub const Dyn = switch (@sizeOf(usize)) {
|
|||||||
8 => Elf64_Dyn,
|
8 => Elf64_Dyn,
|
||||||
else => @compileError("expected pointer size of 32 or 64"),
|
else => @compileError("expected pointer size of 32 or 64"),
|
||||||
};
|
};
|
||||||
|
pub const Rel = switch (@sizeOf(usize)) {
|
||||||
|
4 => Elf32_Rel,
|
||||||
|
8 => Elf64_Rel,
|
||||||
|
else => @compileError("expected pointer size of 32 or 64"),
|
||||||
|
};
|
||||||
|
pub const Rela = switch (@sizeOf(usize)) {
|
||||||
|
4 => Elf32_Rela,
|
||||||
|
8 => Elf64_Rela,
|
||||||
|
else => @compileError("expected pointer size of 32 or 64"),
|
||||||
|
};
|
||||||
pub const Shdr = switch (@sizeOf(usize)) {
|
pub const Shdr = switch (@sizeOf(usize)) {
|
||||||
4 => Elf32_Shdr,
|
4 => Elf32_Shdr,
|
||||||
8 => Elf64_Shdr,
|
8 => Elf64_Shdr,
|
||||||
|
|||||||
@ -996,7 +996,7 @@ pub const dirent64 = extern struct {
|
|||||||
|
|
||||||
pub const dl_phdr_info = extern struct {
|
pub const dl_phdr_info = extern struct {
|
||||||
dlpi_addr: usize,
|
dlpi_addr: usize,
|
||||||
dlpi_name: ?[*]const u8,
|
dlpi_name: ?[*:0]const u8,
|
||||||
dlpi_phdr: [*]std.elf.Phdr,
|
dlpi_phdr: [*]std.elf.Phdr,
|
||||||
dlpi_phnum: u16,
|
dlpi_phnum: u16,
|
||||||
};
|
};
|
||||||
|
|||||||
138
lib/std/os/linux/start_pie.zig
Normal file
138
lib/std/os/linux/start_pie.zig
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -205,6 +205,8 @@ export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 {
|
|||||||
test "dl_iterate_phdr" {
|
test "dl_iterate_phdr" {
|
||||||
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)
|
||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
|
if (builtin.position_independent_executable)
|
||||||
|
return error.SkipZigTest;
|
||||||
|
|
||||||
var counter: usize = 0;
|
var counter: usize = 0;
|
||||||
expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
|
expect(os.dl_iterate_phdr(usize, iter_fn, &counter) != 0);
|
||||||
|
|||||||
@ -155,6 +155,12 @@ fn posixCallMainAndExit() noreturn {
|
|||||||
// Find the beginning of the auxiliary vector
|
// Find the beginning of the auxiliary vector
|
||||||
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
|
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
|
||||||
std.os.linux.elf_aux_maybe = auxv;
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the TLS area
|
// Initialize the TLS area
|
||||||
const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
|
const gnu_stack_phdr = std.os.linux.tls.initTLS() orelse @panic("ELF missing stack size");
|
||||||
|
|
||||||
|
|||||||
@ -1922,6 +1922,12 @@ enum WantPIC {
|
|||||||
WantPICEnabled,
|
WantPICEnabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum WantPIE {
|
||||||
|
WantPIEAuto,
|
||||||
|
WantPIEDisabled,
|
||||||
|
WantPIEEnabled,
|
||||||
|
};
|
||||||
|
|
||||||
enum WantStackCheck {
|
enum WantStackCheck {
|
||||||
WantStackCheckAuto,
|
WantStackCheckAuto,
|
||||||
WantStackCheckDisabled,
|
WantStackCheckDisabled,
|
||||||
@ -2101,6 +2107,7 @@ struct CodeGen {
|
|||||||
Stage2ProgressNode *sub_progress_node;
|
Stage2ProgressNode *sub_progress_node;
|
||||||
|
|
||||||
WantPIC want_pic;
|
WantPIC want_pic;
|
||||||
|
WantPIE want_pie;
|
||||||
WantStackCheck want_stack_check;
|
WantStackCheck want_stack_check;
|
||||||
WantCSanitize want_sanitize_c;
|
WantCSanitize want_sanitize_c;
|
||||||
CacheHash cache_hash;
|
CacheHash cache_hash;
|
||||||
@ -2175,6 +2182,7 @@ struct CodeGen {
|
|||||||
bool disable_gen_h;
|
bool disable_gen_h;
|
||||||
bool bundle_compiler_rt;
|
bool bundle_compiler_rt;
|
||||||
bool have_pic;
|
bool have_pic;
|
||||||
|
bool have_pie;
|
||||||
bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
|
bool have_dynamic_link; // this is whether the final thing will be dynamically linked. see also is_dynamic
|
||||||
bool have_stack_probing;
|
bool have_stack_probing;
|
||||||
bool have_sanitize_c;
|
bool have_sanitize_c;
|
||||||
|
|||||||
@ -8233,18 +8233,39 @@ static bool detect_dynamic_link(CodeGen *g) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool detect_pic(CodeGen *g) {
|
static void detect_pic_pie(CodeGen *g) {
|
||||||
if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr))
|
const bool requires_pic = target_requires_pic(g->zig_target, g->libc_link_lib != nullptr);
|
||||||
return true;
|
const bool requires_pie = target_requires_pie(g->zig_target);
|
||||||
|
|
||||||
|
bool have_pic = false;
|
||||||
|
bool have_pie = false;
|
||||||
|
|
||||||
|
switch (g->want_pie) {
|
||||||
|
case WantPIEDisabled:
|
||||||
|
have_pie = false;
|
||||||
|
break;
|
||||||
|
case WantPIEEnabled:
|
||||||
|
have_pie = true;
|
||||||
|
break;
|
||||||
|
case WantPIEAuto:
|
||||||
|
have_pie = requires_pie;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (g->want_pic) {
|
switch (g->want_pic) {
|
||||||
case WantPICDisabled:
|
case WantPICDisabled:
|
||||||
return false;
|
have_pic = false;
|
||||||
|
break;
|
||||||
case WantPICEnabled:
|
case WantPICEnabled:
|
||||||
return true;
|
have_pic = true;
|
||||||
|
break;
|
||||||
case WantPICAuto:
|
case WantPICAuto:
|
||||||
return g->have_dynamic_link;
|
have_pic = have_pie || g->have_dynamic_link || requires_pic;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
|
||||||
|
g->have_pic = have_pic;
|
||||||
|
g->have_pie = have_pie;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool detect_stack_probing(CodeGen *g) {
|
static bool detect_stack_probing(CodeGen *g) {
|
||||||
@ -8309,7 +8330,7 @@ static bool detect_err_ret_tracing(CodeGen *g) {
|
|||||||
|
|
||||||
Buf *codegen_generate_builtin_source(CodeGen *g) {
|
Buf *codegen_generate_builtin_source(CodeGen *g) {
|
||||||
g->have_dynamic_link = detect_dynamic_link(g);
|
g->have_dynamic_link = detect_dynamic_link(g);
|
||||||
g->have_pic = detect_pic(g);
|
detect_pic_pie(g);
|
||||||
g->have_stack_probing = detect_stack_probing(g);
|
g->have_stack_probing = detect_stack_probing(g);
|
||||||
g->have_sanitize_c = detect_sanitize_c(g);
|
g->have_sanitize_c = detect_sanitize_c(g);
|
||||||
g->is_single_threaded = detect_single_threaded(g);
|
g->is_single_threaded = detect_single_threaded(g);
|
||||||
@ -8465,6 +8486,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
|||||||
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
|
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
|
||||||
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
|
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
|
||||||
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
|
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
|
||||||
|
buf_appendf(contents, "pub const position_independent_executable = %s;\n", bool_to_str(g->have_pie));
|
||||||
buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
|
buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -8526,6 +8548,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
|||||||
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
|
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
|
||||||
cache_bool(&cache_hash, g->valgrind_support);
|
cache_bool(&cache_hash, g->valgrind_support);
|
||||||
cache_int(&cache_hash, detect_subsystem(g));
|
cache_int(&cache_hash, detect_subsystem(g));
|
||||||
|
cache_bool(&cache_hash, g->have_pic);
|
||||||
|
cache_bool(&cache_hash, g->have_pie);
|
||||||
|
|
||||||
Buf digest = BUF_INIT;
|
Buf digest = BUF_INIT;
|
||||||
buf_resize(&digest, 0);
|
buf_resize(&digest, 0);
|
||||||
@ -8595,7 +8619,7 @@ static void init(CodeGen *g) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
g->have_dynamic_link = detect_dynamic_link(g);
|
g->have_dynamic_link = detect_dynamic_link(g);
|
||||||
g->have_pic = detect_pic(g);
|
detect_pic_pie(g);
|
||||||
g->have_stack_probing = detect_stack_probing(g);
|
g->have_stack_probing = detect_stack_probing(g);
|
||||||
g->have_sanitize_c = detect_sanitize_c(g);
|
g->have_sanitize_c = detect_sanitize_c(g);
|
||||||
g->is_single_threaded = detect_single_threaded(g);
|
g->is_single_threaded = detect_single_threaded(g);
|
||||||
@ -8640,6 +8664,14 @@ static void init(CodeGen *g) {
|
|||||||
reloc_mode = LLVMRelocStatic;
|
reloc_mode = LLVMRelocStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g->have_pic) {
|
||||||
|
ZigLLVMSetModulePICLevel(g->module);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g->have_pie) {
|
||||||
|
ZigLLVMSetModulePIELevel(g->module);
|
||||||
|
}
|
||||||
|
|
||||||
const char *target_specific_cpu_args;
|
const char *target_specific_cpu_args;
|
||||||
const char *target_specific_features;
|
const char *target_specific_features;
|
||||||
if (g->zig_target->is_native) {
|
if (g->zig_target->is_native) {
|
||||||
@ -9327,6 +9359,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
|
|||||||
cache_bool(cache_hash, g->strip_debug_symbols);
|
cache_bool(cache_hash, g->strip_debug_symbols);
|
||||||
cache_int(cache_hash, g->build_mode);
|
cache_int(cache_hash, g->build_mode);
|
||||||
cache_bool(cache_hash, g->have_pic);
|
cache_bool(cache_hash, g->have_pic);
|
||||||
|
cache_bool(cache_hash, g->have_pie);
|
||||||
cache_bool(cache_hash, g->have_sanitize_c);
|
cache_bool(cache_hash, g->have_sanitize_c);
|
||||||
cache_bool(cache_hash, want_valgrind_support(g));
|
cache_bool(cache_hash, want_valgrind_support(g));
|
||||||
cache_bool(cache_hash, g->function_sections);
|
cache_bool(cache_hash, g->function_sections);
|
||||||
@ -10104,6 +10137,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
|||||||
cache_bool(ch, g->bundle_compiler_rt);
|
cache_bool(ch, g->bundle_compiler_rt);
|
||||||
cache_bool(ch, want_valgrind_support(g));
|
cache_bool(ch, want_valgrind_support(g));
|
||||||
cache_bool(ch, g->have_pic);
|
cache_bool(ch, g->have_pic);
|
||||||
|
cache_bool(ch, g->have_pie);
|
||||||
cache_bool(ch, g->have_dynamic_link);
|
cache_bool(ch, g->have_dynamic_link);
|
||||||
cache_bool(ch, g->have_stack_probing);
|
cache_bool(ch, g->have_stack_probing);
|
||||||
cache_bool(ch, g->have_sanitize_c);
|
cache_bool(ch, g->have_sanitize_c);
|
||||||
@ -10224,7 +10258,7 @@ void codegen_build_and_link(CodeGen *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
g->have_dynamic_link = detect_dynamic_link(g);
|
g->have_dynamic_link = detect_dynamic_link(g);
|
||||||
g->have_pic = detect_pic(g);
|
detect_pic_pie(g);
|
||||||
g->is_single_threaded = detect_single_threaded(g);
|
g->is_single_threaded = detect_single_threaded(g);
|
||||||
g->have_err_ret_tracing = detect_err_ret_tracing(g);
|
g->have_err_ret_tracing = detect_err_ret_tracing(g);
|
||||||
g->have_sanitize_c = detect_sanitize_c(g);
|
g->have_sanitize_c = detect_sanitize_c(g);
|
||||||
@ -10429,6 +10463,7 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
|
|||||||
|
|
||||||
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
|
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
|
||||||
child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;
|
child_gen->want_pic = parent_gen->have_pic ? WantPICEnabled : WantPICDisabled;
|
||||||
|
child_gen->want_pie = parent_gen->have_pie ? WantPIEEnabled : WantPIEDisabled;
|
||||||
child_gen->valgrind_support = ValgrindSupportDisabled;
|
child_gen->valgrind_support = ValgrindSupportDisabled;
|
||||||
|
|
||||||
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
|
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
|
||||||
|
|||||||
19
src/link.cpp
19
src/link.cpp
@ -1469,6 +1469,14 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||||||
c_file->args.append("-fno-stack-protector");
|
c_file->args.append("-fno-stack-protector");
|
||||||
c_file->args.append("-DCRT");
|
c_file->args.append("-DCRT");
|
||||||
return build_libc_object(parent, "crt1", c_file, progress_node);
|
return build_libc_object(parent, "crt1", c_file, progress_node);
|
||||||
|
} else if (strcmp(file, "rcrt1.o") == 0) {
|
||||||
|
CFile *c_file = allocate<CFile>(1);
|
||||||
|
c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "rcrt1.c");
|
||||||
|
musl_add_cc_args(parent, c_file, false);
|
||||||
|
c_file->args.append("-fno-stack-protector");
|
||||||
|
c_file->args.append("-DCRT");
|
||||||
|
c_file->args.append("-fPIC");
|
||||||
|
return build_libc_object(parent, "rcrt1", c_file, progress_node);
|
||||||
} else if (strcmp(file, "Scrt1.o") == 0) {
|
} else if (strcmp(file, "Scrt1.o") == 0) {
|
||||||
CFile *c_file = allocate<CFile>(1);
|
CFile *c_file = allocate<CFile>(1);
|
||||||
c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c");
|
c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c");
|
||||||
@ -1661,6 +1669,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
|||||||
} else {
|
} else {
|
||||||
lj->args.append("-static");
|
lj->args.append("-static");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g->out_type == OutTypeExe && g->have_pie) {
|
||||||
|
lj->args.append("-pie");
|
||||||
|
lj->args.append("--no-dynamic-linker");
|
||||||
|
}
|
||||||
} else if (is_dyn_lib) {
|
} else if (is_dyn_lib) {
|
||||||
lj->args.append("-shared");
|
lj->args.append("-shared");
|
||||||
|
|
||||||
@ -1668,10 +1681,6 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
|||||||
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
|
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) {
|
|
||||||
lj->args.append("-pie");
|
|
||||||
}
|
|
||||||
|
|
||||||
lj->args.append("-o");
|
lj->args.append("-o");
|
||||||
lj->args.append(buf_ptr(&g->output_file_path));
|
lj->args.append(buf_ptr(&g->output_file_path));
|
||||||
|
|
||||||
@ -1686,7 +1695,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
|||||||
crt1o = "crtbegin_static.o";
|
crt1o = "crtbegin_static.o";
|
||||||
}
|
}
|
||||||
} else if (!g->have_dynamic_link) {
|
} else if (!g->have_dynamic_link) {
|
||||||
crt1o = "crt1.o";
|
crt1o = g->have_pie ? "rcrt1.o" : "crt1.o";
|
||||||
} else {
|
} else {
|
||||||
crt1o = "Scrt1.o";
|
crt1o = "Scrt1.o";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -525,6 +525,7 @@ int main(int argc, char **argv) {
|
|||||||
Buf *main_pkg_path = nullptr;
|
Buf *main_pkg_path = nullptr;
|
||||||
ValgrindSupport valgrind_support = ValgrindSupportAuto;
|
ValgrindSupport valgrind_support = ValgrindSupportAuto;
|
||||||
WantPIC want_pic = WantPICAuto;
|
WantPIC want_pic = WantPICAuto;
|
||||||
|
WantPIE want_pie = WantPIEAuto;
|
||||||
WantStackCheck want_stack_check = WantStackCheckAuto;
|
WantStackCheck want_stack_check = WantStackCheckAuto;
|
||||||
WantCSanitize want_sanitize_c = WantCSanitizeAuto;
|
WantCSanitize want_sanitize_c = WantCSanitizeAuto;
|
||||||
bool function_sections = false;
|
bool function_sections = false;
|
||||||
@ -721,6 +722,10 @@ int main(int argc, char **argv) {
|
|||||||
want_pic = WantPICEnabled;
|
want_pic = WantPICEnabled;
|
||||||
} else if (strcmp(arg, "-fno-PIC") == 0) {
|
} else if (strcmp(arg, "-fno-PIC") == 0) {
|
||||||
want_pic = WantPICDisabled;
|
want_pic = WantPICDisabled;
|
||||||
|
} else if (strcmp(arg, "-fPIE") == 0) {
|
||||||
|
want_pie = WantPIEEnabled;
|
||||||
|
} else if (strcmp(arg, "-fno-PIE") == 0) {
|
||||||
|
want_pie = WantPIEDisabled;
|
||||||
} else if (strcmp(arg, "-fstack-check") == 0) {
|
} else if (strcmp(arg, "-fstack-check") == 0) {
|
||||||
want_stack_check = WantStackCheckEnabled;
|
want_stack_check = WantStackCheckEnabled;
|
||||||
} else if (strcmp(arg, "-fno-stack-check") == 0) {
|
} else if (strcmp(arg, "-fno-stack-check") == 0) {
|
||||||
@ -1099,6 +1104,7 @@ int main(int argc, char **argv) {
|
|||||||
g->subsystem = subsystem;
|
g->subsystem = subsystem;
|
||||||
g->valgrind_support = valgrind_support;
|
g->valgrind_support = valgrind_support;
|
||||||
g->want_pic = want_pic;
|
g->want_pic = want_pic;
|
||||||
|
g->want_pie = want_pie;
|
||||||
g->want_stack_check = want_stack_check;
|
g->want_stack_check = want_stack_check;
|
||||||
g->want_sanitize_c = want_sanitize_c;
|
g->want_sanitize_c = want_sanitize_c;
|
||||||
g->want_single_threaded = want_single_threaded;
|
g->want_single_threaded = want_single_threaded;
|
||||||
@ -1199,6 +1205,7 @@ int main(int argc, char **argv) {
|
|||||||
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
|
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
|
||||||
g->valgrind_support = valgrind_support;
|
g->valgrind_support = valgrind_support;
|
||||||
g->want_pic = want_pic;
|
g->want_pic = want_pic;
|
||||||
|
g->want_pie = want_pie;
|
||||||
g->want_stack_check = want_stack_check;
|
g->want_stack_check = want_stack_check;
|
||||||
g->want_sanitize_c = want_sanitize_c;
|
g->want_sanitize_c = want_sanitize_c;
|
||||||
g->subsystem = subsystem;
|
g->subsystem = subsystem;
|
||||||
|
|||||||
@ -877,6 +877,14 @@ void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {
|
|||||||
unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1);
|
unwrap(module)->addModuleFlag(Module::Warning, "CodeView", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ZigLLVMSetModulePICLevel(LLVMModuleRef module) {
|
||||||
|
unwrap(module)->setPICLevel(PICLevel::Level::BigPIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZigLLVMSetModulePIELevel(LLVMModuleRef module) {
|
||||||
|
unwrap(module)->setPIELevel(PIELevel::Level::Large);
|
||||||
|
}
|
||||||
|
|
||||||
static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
|
static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
|
||||||
switch (Ordering) {
|
switch (Ordering) {
|
||||||
case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic;
|
case LLVMAtomicOrderingNotAtomic: return AtomicOrdering::NotAtomic;
|
||||||
|
|||||||
@ -158,6 +158,8 @@ ZIG_EXTERN_C struct ZigLLVMDIBuilder *ZigLLVMCreateDIBuilder(LLVMModuleRef modul
|
|||||||
ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder);
|
ZIG_EXTERN_C void ZigLLVMDisposeDIBuilder(struct ZigLLVMDIBuilder *dbuilder);
|
||||||
ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
|
ZIG_EXTERN_C void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module);
|
||||||
ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
|
ZIG_EXTERN_C void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module);
|
||||||
|
ZIG_EXTERN_C void ZigLLVMSetModulePICLevel(LLVMModuleRef module);
|
||||||
|
ZIG_EXTERN_C void ZigLLVMSetModulePIELevel(LLVMModuleRef module);
|
||||||
|
|
||||||
ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column,
|
ZIG_EXTERN_C void ZigLLVMSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column,
|
||||||
struct ZigLLVMDIScope *scope);
|
struct ZigLLVMDIScope *scope);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user