aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Target.zig6
-rw-r--r--lib/std/builtin.zig15
-rw-r--r--lib/std/dynamic_library.zig13
-rw-r--r--lib/std/pie.zig343
-rw-r--r--lib/std/start.zig12
-rw-r--r--lib/std/zig/llvm/Builder.zig12
6 files changed, 218 insertions, 183 deletions
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index 084344535e..347b3357f5 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -2581,12 +2581,16 @@ pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
}
pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
+ return ptrBitWidth_arch_abi(cpu.arch, abi);
+}
+
+pub fn ptrBitWidth_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) u16 {
switch (abi) {
.gnux32, .muslx32, .gnuabin32, .muslabin32, .ilp32 => return 32,
.gnuabi64, .muslabi64 => return 64,
else => {},
}
- return switch (cpu.arch) {
+ return switch (cpu_arch) {
.avr,
.msp430,
=> 16,
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 1683cc500b..88e2304332 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -61,7 +61,7 @@ pub const StackTrace = struct {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
-pub const GlobalLinkage = enum {
+pub const GlobalLinkage = enum(u2) {
internal,
strong,
weak,
@@ -70,7 +70,7 @@ pub const GlobalLinkage = enum {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
-pub const SymbolVisibility = enum {
+pub const SymbolVisibility = enum(u2) {
default,
hidden,
protected,
@@ -1030,8 +1030,19 @@ pub const ExternOptions = struct {
name: []const u8,
library_name: ?[]const u8 = null,
linkage: GlobalLinkage = .strong,
+ visibility: SymbolVisibility = .default,
+ /// Setting this to `true` makes the `@extern` a runtime value.
is_thread_local: bool = false,
is_dll_import: bool = false,
+ relocation: Relocation = .any,
+
+ pub const Relocation = enum(u1) {
+ /// Any type of relocation is allowed.
+ any,
+ /// A program-counter-relative relocation is required.
+ /// Using this value makes the `@extern` a runtime value.
+ pcrel,
+ };
};
/// This data structure is used by the Zig language code generation and
diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig
index 4b1faa87ba..bac31f5760 100644
--- a/lib/std/dynamic_library.zig
+++ b/lib/std/dynamic_library.zig
@@ -83,13 +83,16 @@ const RDebug = extern struct {
r_ldbase: usize,
};
-/// TODO make it possible to reference this same external symbol 2x so we don't need this
-/// helper function.
-pub fn get_DYNAMIC() ?[*]elf.Dyn {
- return @extern([*]elf.Dyn, .{ .name = "_DYNAMIC", .linkage = .weak });
+/// TODO fix comparisons of extern symbol pointers so we don't need this helper function.
+pub fn get_DYNAMIC() ?[*]const elf.Dyn {
+ return @extern([*]const elf.Dyn, .{
+ .name = "_DYNAMIC",
+ .linkage = .weak,
+ .visibility = .hidden,
+ });
}
-pub fn linkmap_iterator(phdrs: []elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
+pub fn linkmap_iterator(phdrs: []const elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
_ = phdrs;
const _DYNAMIC = get_DYNAMIC() orelse {
// No PT_DYNAMIC means this is either a statically-linked program or a
diff --git a/lib/std/pie.zig b/lib/std/pie.zig
index 572f3ddf96..0f4b4ff4b3 100644
--- a/lib/std/pie.zig
+++ b/lib/std/pie.zig
@@ -39,167 +39,175 @@ const R_RELATIVE = switch (builtin.cpu.arch) {
// Obtain a pointer to the _DYNAMIC array.
// We have to compute its address as a PC-relative quantity not to require a
// relocation that, at this point, is not yet applied.
-inline fn getDynamicSymbol() [*]elf.Dyn {
- return switch (builtin.cpu.arch) {
- .x86 => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ call 1f
- \\ 1: pop %[ret]
- \\ lea _DYNAMIC-1b(%[ret]), %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- .x86_64 => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ lea _DYNAMIC(%%rip), %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- .arc => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ add %[ret], pcl, _DYNAMIC@pcl
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- // Work around the limited offset range of `ldr`
- .arm, .armeb, .thumb, .thumbeb => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ ldr %[ret], 1f
- \\ add %[ret], pc
- \\ b 2f
- \\ 1: .word _DYNAMIC-1b
- \\ 2:
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- // A simple `adr` is not enough as it has a limited offset range
- .aarch64, .aarch64_be => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ adrp %[ret], _DYNAMIC
- \\ add %[ret], %[ret], #:lo12:_DYNAMIC
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first
- // entry in the GOT is defined to hold the address of _DYNAMIC.
- .csky => asm volatile (
- \\ mov %[ret], gb
- \\ ldw %[ret], %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- .hexagon => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ jump 1f
- \\ .word _DYNAMIC - .
- \\ 1:
- \\ r1 = pc
- \\ r1 = add(r1, #-4)
- \\ %[ret] = memw(r1)
- \\ %[ret] = add(r1, %[ret])
- : [ret] "=r" (-> [*]elf.Dyn),
- :
- : "r1"
- ),
- .loongarch32, .loongarch64 => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ la.local %[ret], _DYNAMIC
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- // Note that the - 8 is needed because pc in the second lea instruction points into the
- // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.)
- .m68k => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ lea _DYNAMIC - . - 8, %[ret]
- \\ lea (%[ret], %%pc), %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- .mips, .mipsel => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ bal 1f
- \\ .gpword _DYNAMIC
- \\ 1:
- \\ lw %[ret], 0($ra)
- \\ addu %[ret], %[ret], $gp
- : [ret] "=r" (-> [*]elf.Dyn),
- :
- : "lr"
- ),
- .mips64, .mips64el => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ .balign 8
- \\ bal 1f
- \\ .gpdword _DYNAMIC
- \\ 1:
- \\ ld %[ret], 0($ra)
- \\ daddu %[ret], %[ret], $gp
- : [ret] "=r" (-> [*]elf.Dyn),
- :
- : "lr"
- ),
- .powerpc, .powerpcle => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ bl 1f
- \\ .long _DYNAMIC - .
- \\ 1:
- \\ mflr %[ret]
- \\ lwz 4, 0(%[ret])
- \\ add %[ret], 4, %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- :
- : "lr", "r4"
- ),
- .powerpc64, .powerpc64le => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ bl 1f
- \\ .quad _DYNAMIC - .
- \\ 1:
- \\ mflr %[ret]
- \\ ld 4, 0(%[ret])
- \\ add %[ret], 4, %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- :
- : "lr", "r4"
- ),
- .riscv32, .riscv64 => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ lla %[ret], _DYNAMIC
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- .s390x => asm volatile (
- \\ .weak _DYNAMIC
- \\ .hidden _DYNAMIC
- \\ larl %[ret], 1f
- \\ ag %[ret], 0(%[ret])
- \\ jg 2f
- \\ 1: .quad _DYNAMIC - .
- \\ 2:
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- // The compiler does not necessarily have any obligation to load the `l7` register (pointing
- // to the GOT), so do it ourselves just in case.
- .sparc, .sparc64 => asm volatile (
- \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7
- \\ call 1f
- \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7
- \\ 1:
- \\ add %%l7, %%o7, %[ret]
- : [ret] "=r" (-> [*]elf.Dyn),
- ),
- else => {
- @compileError("PIE startup is not yet supported for this target!");
+inline fn getDynamicSymbol() [*]const elf.Dyn {
+ return switch (builtin.zig_backend) {
+ else => switch (builtin.cpu.arch) {
+ .x86 => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ call 1f
+ \\ 1: pop %[ret]
+ \\ lea _DYNAMIC-1b(%[ret]), %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ .x86_64 => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ lea _DYNAMIC(%%rip), %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ .arc => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ add %[ret], pcl, _DYNAMIC@pcl
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ // Work around the limited offset range of `ldr`
+ .arm, .armeb, .thumb, .thumbeb => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ ldr %[ret], 1f
+ \\ add %[ret], pc
+ \\ b 2f
+ \\ 1: .word _DYNAMIC-1b
+ \\ 2:
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ // A simple `adr` is not enough as it has a limited offset range
+ .aarch64, .aarch64_be => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ adrp %[ret], _DYNAMIC
+ \\ add %[ret], %[ret], #:lo12:_DYNAMIC
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ // The CSKY ABI requires the gb register to point to the GOT. Additionally, the first
+ // entry in the GOT is defined to hold the address of _DYNAMIC.
+ .csky => asm volatile (
+ \\ mov %[ret], gb
+ \\ ldw %[ret], %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ .hexagon => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ jump 1f
+ \\ .word _DYNAMIC - .
+ \\ 1:
+ \\ r1 = pc
+ \\ r1 = add(r1, #-4)
+ \\ %[ret] = memw(r1)
+ \\ %[ret] = add(r1, %[ret])
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ :
+ : "r1"
+ ),
+ .loongarch32, .loongarch64 => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ la.local %[ret], _DYNAMIC
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ // Note that the - 8 is needed because pc in the second lea instruction points into the
+ // middle of that instruction. (The first lea is 6 bytes, the second is 4 bytes.)
+ .m68k => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ lea _DYNAMIC - . - 8, %[ret]
+ \\ lea (%[ret], %%pc), %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ .mips, .mipsel => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ bal 1f
+ \\ .gpword _DYNAMIC
+ \\ 1:
+ \\ lw %[ret], 0($ra)
+ \\ addu %[ret], %[ret], $gp
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ :
+ : "lr"
+ ),
+ .mips64, .mips64el => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ .balign 8
+ \\ bal 1f
+ \\ .gpdword _DYNAMIC
+ \\ 1:
+ \\ ld %[ret], 0($ra)
+ \\ daddu %[ret], %[ret], $gp
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ :
+ : "lr"
+ ),
+ .powerpc, .powerpcle => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ bl 1f
+ \\ .long _DYNAMIC - .
+ \\ 1:
+ \\ mflr %[ret]
+ \\ lwz 4, 0(%[ret])
+ \\ add %[ret], 4, %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ :
+ : "lr", "r4"
+ ),
+ .powerpc64, .powerpc64le => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ bl 1f
+ \\ .quad _DYNAMIC - .
+ \\ 1:
+ \\ mflr %[ret]
+ \\ ld 4, 0(%[ret])
+ \\ add %[ret], 4, %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ :
+ : "lr", "r4"
+ ),
+ .riscv32, .riscv64 => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ lla %[ret], _DYNAMIC
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ .s390x => asm volatile (
+ \\ .weak _DYNAMIC
+ \\ .hidden _DYNAMIC
+ \\ larl %[ret], 1f
+ \\ ag %[ret], 0(%[ret])
+ \\ jg 2f
+ \\ 1: .quad _DYNAMIC - .
+ \\ 2:
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ // The compiler does not necessarily have any obligation to load the `l7` register (pointing
+ // to the GOT), so do it ourselves just in case.
+ .sparc, .sparc64 => asm volatile (
+ \\ sethi %%hi(_GLOBAL_OFFSET_TABLE_ - 4), %%l7
+ \\ call 1f
+ \\ add %%l7, %%lo(_GLOBAL_OFFSET_TABLE_ + 4), %%l7
+ \\ 1:
+ \\ add %%l7, %%o7, %[ret]
+ : [ret] "=r" (-> [*]const elf.Dyn),
+ ),
+ else => {
+ @compileError("PIE startup is not yet supported for this target!");
+ },
},
+ .stage2_x86_64 => @extern([*]const elf.Dyn, .{
+ .name = "_DYNAMIC",
+ .linkage = .weak,
+ .visibility = .hidden,
+ .relocation = .pcrel,
+ }).?,
};
}
-pub fn relocate(phdrs: []elf.Phdr) void {
+pub fn relocate(phdrs: []const elf.Phdr) void {
@setRuntimeSafety(false);
@disableInstrumentation();
@@ -256,10 +264,9 @@ pub fn relocate(phdrs: []elf.Phdr) void {
const rel = sorted_dynv[elf.DT_REL];
if (rel != 0) {
- const rels = @call(.always_inline, std.mem.bytesAsSlice, .{
- elf.Rel,
- @as([*]u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]],
- });
+ const rels: []const elf.Rel = @alignCast(@ptrCast(
+ @as([*]align(@alignOf(elf.Rel)) const u8, @ptrFromInt(base_addr + rel))[0..sorted_dynv[elf.DT_RELSZ]],
+ ));
for (rels) |r| {
if (r.r_type() != R_RELATIVE) continue;
@as(*usize, @ptrFromInt(base_addr + r.r_offset)).* += base_addr;
@@ -268,10 +275,9 @@ pub fn relocate(phdrs: []elf.Phdr) void {
const rela = sorted_dynv[elf.DT_RELA];
if (rela != 0) {
- const relas = @call(.always_inline, std.mem.bytesAsSlice, .{
- elf.Rela,
- @as([*]u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]],
- });
+ const relas: []const elf.Rela = @alignCast(@ptrCast(
+ @as([*]align(@alignOf(elf.Rela)) const u8, @ptrFromInt(base_addr + rela))[0..sorted_dynv[elf.DT_RELASZ]],
+ ));
for (relas) |r| {
if (r.r_type() != R_RELATIVE) continue;
@as(*usize, @ptrFromInt(base_addr + r.r_offset)).* = base_addr + @as(usize, @bitCast(r.r_addend));
@@ -280,10 +286,9 @@ pub fn relocate(phdrs: []elf.Phdr) void {
const relr = sorted_dynv[elf.DT_RELR];
if (relr != 0) {
- const relrs = @call(.always_inline, std.mem.bytesAsSlice, .{
- elf.Relr,
- @as([*]u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]],
- });
+ const relrs: []const elf.Relr = @ptrCast(
+ @as([*]align(@alignOf(elf.Relr)) const u8, @ptrFromInt(base_addr + relr))[0..sorted_dynv[elf.DT_RELRSZ]],
+ );
var current: [*]usize = undefined;
for (relrs) |r| {
if ((r & 1) == 0) {
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 2280bea9e7..9b4897260e 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -163,7 +163,7 @@ fn exit2(code: usize) noreturn {
// exits(0)
.plan9 => std.os.plan9.exits(null),
.windows => {
- std.os.windows.ntdll.RtlExitUserProcess(@as(u32, @truncate(code)));
+ std.os.windows.ntdll.RtlExitUserProcess(@truncate(code));
},
else => @compileError("TODO"),
}
@@ -511,7 +511,7 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
// Code coverage instrumentation might try to use thread local variables.
@disableInstrumentation();
const argc = argc_argv_ptr[0];
- const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
+ const argv: [*][*:0]u8 = @ptrCast(argc_argv_ptr + 1);
const envp_optional: [*:null]?[*:0]u8 = @ptrCast(@alignCast(argv + argc + 1));
var envp_count: usize = 0;
@@ -573,11 +573,11 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn {
expandStackSize(phdrs);
}
- const opt_init_array_start = @extern([*]*const fn () callconv(.c) void, .{
+ const opt_init_array_start = @extern([*]const *const fn () callconv(.c) void, .{
.name = "__init_array_start",
.linkage = .weak,
});
- const opt_init_array_end = @extern([*]*const fn () callconv(.c) void, .{
+ const opt_init_array_end = @extern([*]const *const fn () callconv(.c) void, .{
.name = "__init_array_end",
.linkage = .weak,
});
@@ -651,7 +651,7 @@ fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) cal
}
fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int {
- std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@as(usize, @intCast(c_argc))];
+ std.os.argv = @as([*][*:0]u8, @ptrCast(c_argv))[0..@intCast(c_argc)];
return callMain();
}
@@ -701,7 +701,7 @@ pub inline fn callMain() u8 {
pub fn call_wWinMain() std.os.windows.INT {
const peb = std.os.windows.peb();
const MAIN_HINSTANCE = @typeInfo(@TypeOf(root.wWinMain)).@"fn".params[0].type.?;
- const hInstance = @as(MAIN_HINSTANCE, @ptrCast(peb.ImageBaseAddress));
+ const hInstance: MAIN_HINSTANCE = @ptrCast(peb.ImageBaseAddress);
const lpCmdLine: [*:0]u16 = @ptrCast(peb.ProcessParameters.CommandLine.Buffer);
// There are various types used for the 'show window' variable through the Win32 APIs:
diff --git a/lib/std/zig/llvm/Builder.zig b/lib/std/zig/llvm/Builder.zig
index d8d5ff19c7..865e1efa6d 100644
--- a/lib/std/zig/llvm/Builder.zig
+++ b/lib/std/zig/llvm/Builder.zig
@@ -1823,6 +1823,14 @@ pub const Visibility = enum(u2) {
hidden = 1,
protected = 2,
+ pub fn fromSymbolVisibility(sv: std.builtin.SymbolVisibility) Visibility {
+ return switch (sv) {
+ .default => .default,
+ .hidden => .hidden,
+ .protected => .protected,
+ };
+ }
+
pub fn format(
self: Visibility,
comptime _: []const u8,
@@ -2555,6 +2563,10 @@ pub const Variable = struct {
return self.ptrConst(builder).global.setLinkage(linkage, builder);
}
+ pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void {
+ return self.ptrConst(builder).global.setVisibility(visibility, builder);
+ }
+
pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void {
return self.ptrConst(builder).global.setDllStorageClass(class, builder);
}