diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 07bb43a4fa2997a61ea5b2286132de2c427ce648..f5e5943848ce1fbb1177114583b5e603cce76c61 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -42,7 +42,7 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { // Deal with some special cases first. if (native_arch.isArc() and native_os == .linux) { var native: Native = .{ - .r = [_]u32{ uc.mcontext.r31, uc.mcontext.r30, 0, uc.mcontext.r28 } ++ + .r = [_]Arc.Gpr{ uc.mcontext.r31, uc.mcontext.r30, 0, uc.mcontext.r28 } ++ uc.mcontext.r27_26 ++ uc.mcontext.r25_13 ++ uc.mcontext.r12_0, @@ -100,15 +100,29 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { .i = frame.i, .pc = uc.mcontext.pc, }; + } else if (native_arch.isSparc() and native_os == .netbsd) { + // The kernel flushes all user windows before delivering a signal. + const save: *const [16]usize = @ptrFromInt(uc.mcontext.o[6] +% if (native_arch == .sparc64) 2047 else 0); + + return .{ + .g = [_]Sparc.Gpr{0} ++ uc.mcontext.g1_7, + .o = uc.mcontext.o, + .l = save[0..8].*, + .i = save[8..16].*, + .pc = uc.mcontext.pc, + }; + } else if (native_arch == .sparc64 and native_os == .openbsd) { + // https://codeberg.org/ziglang/zig/issues/30958 + return null; } // Only unified conversions from here. return switch (native_arch) { .arm, .armeb, .thumb, .thumbeb => .{ - .r = uc.mcontext.r ++ [_]u32{uc.mcontext.pc}, + .r = uc.mcontext.r ++ [_]Arm.Gpr{uc.mcontext.pc}, }, .aarch64, .aarch64_be => .{ - .x = uc.mcontext.x ++ [_]u64{uc.mcontext.lr}, + .x = uc.mcontext.x ++ [_]Aarch64.Gpr{uc.mcontext.lr}, .sp = uc.mcontext.sp, .pc = uc.mcontext.pc, }, @@ -118,9 +132,9 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { }, .csky => .{ .r = uc.mcontext.r0_13 ++ - [_]u32{ uc.mcontext.r14, uc.mcontext.r15 } ++ + [_]Csky.Gpr{ uc.mcontext.r14, uc.mcontext.r15 } ++ uc.mcontext.r16_30 ++ - [_]u32{uc.mcontext.r31}, + [_]Csky.Gpr{uc.mcontext.r31}, .pc = uc.mcontext.pc, }, .hexagon, .loongarch32, .loongarch64, .mips, .mipsel, .mips64, .mips64el, .or1k => .{ @@ -2557,7 +2571,17 @@ const signal_ucontext_t = switch (native_os) { }, }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sparc64/include/signal.h - .sparc64 => @compileError("sparc64-openbsd ucontext_t missing"), + .sparc64 => extern struct { + _cookie: i64, + mcontext: extern struct { + sp: u64, + pc: u64, + _npc: i64, + _tstate: i64, + g1: u64, + o0: u64, + }, + }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sh/include/signal.h .sh => extern struct { pc: u32, @@ -2694,8 +2718,22 @@ const signal_ucontext_t = switch (native_os) { pc: usize, }, // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sparc/include/mcontext.h - .sparc => @compileError("sparc-netbsd mcontext_t missing"), - .sparc64 => @compileError("sparc64-netbsd mcontext_t missing"), + .sparc => extern struct { + _psr: i32 align(8), + pc: u32, + _npc: i32, + _y: i32, + g1_7: [7]u32, + o: [8]u32, + }, + .sparc64 => extern struct { + _ccr: i64 align(16), + pc: u64, + _npc: i64, + _y: i64, + g1_7: [7]u64, + o: [8]u64, + }, // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sh3/include/mcontext.h .sh, .sheb => extern struct { _gbr: i32, diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig index b94a2099056b1a997b4fda6dc28f892c4c490b90..17db6a50a8170e70bf26f011950126de927859b5 100644 --- a/src/link/Elf2.zig +++ b/src/link/Elf2.zig @@ -1356,6 +1356,7 @@ const SymbolReloc = struct { @"32[10:0]", @"32[11:0]", @"32[12:0]", + @"32[18:0]", @"32[21:0]", @"32[21:10]", @"32[24:5]", @@ -1399,6 +1400,7 @@ const SymbolReloc = struct { @"12", @"22", @"32", + @"42", @"52", }, @@ -1418,6 +1420,7 @@ const SymbolReloc = struct { .@"12" => .{ 12, false }, .@"22" => .{ 22, false }, .@"32" => .{ 32, false }, + .@"42" => .{ 42, false }, .@"52" => .{ 52, false }, }; @@ -1438,6 +1441,7 @@ const SymbolReloc = struct { .@"32[10:0]" => .{ 32, 10, 0 }, .@"32[11:0]" => .{ 32, 11, 0 }, .@"32[12:0]" => .{ 32, 12, 0 }, + .@"32[18:0]" => .{ 32, 18, 0 }, .@"32[21:0]" => .{ 32, 21, 0 }, .@"32[21:10]" => .{ 32, 21, 10 }, .@"32[24:5]" => .{ 32, 24, 5 }, @@ -1500,7 +1504,10 @@ const SymbolReloc = struct { larch_b26, larch_call36, + sparc_hix22, sparc_le_hix22, + sparc_wdisp10, + sparc_wdisp16, fn applyInner( s: Special, @@ -1598,6 +1605,17 @@ const SymbolReloc = struct { else => unreachable, } }, + + .sparc_hix22 => { + const dest_ptr: *align(1) packed struct(u32) { + imm22: u22, + b22_31: u10, + } = @ptrCast(dest_slice); + elf.targetStore(dest_ptr, .{ + .imm22 = @truncate(~(target.value(elf) +% addend) >> 10), + .b22_31 = elf.targetLoad(dest_ptr).b22_31, + }); + }, .sparc_le_hix22 => { const tls_phndx = elf.getNode(elf.ni.tls.unwrap().?).segment; const tls_size: u64 = switch (elf.phdrSlice()) { @@ -1615,6 +1633,57 @@ const SymbolReloc = struct { .b22_31 = elf.targetLoad(dest_ptr).b22_31, }); }, + .sparc_wdisp16, .sparc_wdisp10 => { + const target_vaddr: u64 = elf.pltEntryTargetAddr(target) orelse target.value(elf); + const jump_offset: i64 = @bitCast(target_vaddr +% addend -% dest_vaddr); + if ((jump_offset >> 2) << 2 != jump_offset) { + return error.RelocationMisaligned; + } + const shifted_jump_offset: i64 = @shrExact(jump_offset, 2); + switch (s) { + .sparc_wdisp10 => { + if ((shifted_jump_offset << (64 - 10)) >> (64 - 10) != shifted_jump_offset) { + return error.RelocationOverflow; + } + const truncated: i10 = @intCast(shifted_jump_offset); + const parts: packed struct { lo8: u8, hi2: u2 } = @bitCast(truncated); + const inst: *align(1) packed struct(u32) { + b0_4: u5, + disp10: u8, + b13_18: u6, + d2: u2, + b21_31: u11, + } = @ptrCast(dest_slice[0..4]); + elf.targetStore(inst, .{ + .b0_4 = elf.targetLoad(inst).b0_4, + .disp10 = parts.lo8, + .b13_18 = elf.targetLoad(inst).b13_18, + .d2 = parts.hi2, + .b21_31 = elf.targetLoad(inst).b21_31, + }); + }, + .sparc_wdisp16 => { + if ((shifted_jump_offset << (64 - 16)) >> (64 - 16) != shifted_jump_offset) { + return error.RelocationOverflow; + } + const truncated: i16 = @intCast(shifted_jump_offset); + const parts: packed struct { lo14: u14, hi2: u2 } = @bitCast(truncated); + const inst: *align(1) packed struct(u32) { + disp14: u14, + b14_19: u6, + d2: u2, + b22_31: u10, + } = @ptrCast(dest_slice[0..4]); + elf.targetStore(inst, .{ + .disp14 = parts.lo14, + .b14_19 = elf.targetLoad(inst).b14_19, + .d2 = parts.hi2, + .b22_31 = elf.targetLoad(inst).b22_31, + }); + }, + else => unreachable, + } + }, } } }; @@ -1649,6 +1718,10 @@ const SymbolReloc = struct { .larch_b21, .larch_b26, .larch_call36, + + .sparc_hix22, + .sparc_wdisp10, + .sparc_wdisp16, => false, }, }, @@ -9000,38 +9073,31 @@ fn addRelocAssumeCapacity( .JMP_SLOT, .RELATIVE, .IRELATIVE, + .TLS_DTPMOD32, + .TLS_DTPMOD64, + .TLS_TPOFF32, + .TLS_TPOFF64, => return error.NonStaticRelocation, - .WDISP22, - .HI22, - .LO10, + // Nobody seems to support these. .HIPLT22, .LOPLT10, .PCPLT22, .PCPLT10, - .OLO10, - .HH22, - .HM10, - .LM22, - .PC_HH22, - .PC_HM10, - .PC_LM22, - .WDISP16, - .WDISP19, - .HIX22, - .LOX10, - .REGISTER, - .TLS_IE_HI22, - .TLS_IE_LO10, - .TLS_DTPMOD32, - .TLS_DTPMOD64, - .H34, - .WDISP10, => return error.UnimplementedRelocation, + // Needs to use the second addend in `ELF64_R_TYPE_DATA(reloc.r_info)` which we currently can't model. + .OLO10 => return error.UnimplementedRelocation, + + // Does not patch any bytes. Together with `STT_SPARC_REGISTER`, this is used to indicate that an object + // file owns a global register and what value it should be initialized to. I don't think this sees any + // real-world use. + .REGISTER => return error.UnimplementedRelocation, + // These need similar handling to `R_X86_64_GOTOFF64`. No compiler seems to emit them though. - .GOTDATA_HIX22 => return error.UnimplementedRelocation, - .GOTDATA_LOX10 => return error.UnimplementedRelocation, + .GOTDATA_HIX22, + .GOTDATA_LOX10, + => return error.UnimplementedRelocation, // These relocations signal that certain relaxations are legal, but this linker does // not yet implement relaxation, so these are ignored. @@ -9063,15 +9129,26 @@ fn addRelocAssumeCapacity( .DISP32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), .DISP64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), - .SIZE32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.size, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), - .SIZE64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.size, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), + .SIZE32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.size, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), + .SIZE64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.size, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), .PCPLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), .PLT32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), .PLT64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltabs, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), + .WDISP10 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_wdisp10)), + .WDISP16 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_wdisp16)), + .WDISP19 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32[18:0]", .cast = .signed, .shift = .@"2_exact" })), + .WDISP22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32[21:0]", .cast = .signed, .shift = .@"2_exact" })), .WDISP30, .WPLT30 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.pltrel, .{ .dest = .@"32[29:0]", .cast = .signed, .shift = .@"2_exact" })), .PC22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"10" })), + .PC_LM22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), + .PC_HH22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"42" })), + .HI22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"10" })), + .LM22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), + .HH22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"42" })), + .HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_hix22)), + .H34 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"12" })), .H44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[21:0]", .cast = .unsigned, .shift = .@"22" })), .M44 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"12" })), @@ -9079,8 +9156,6 @@ fn addRelocAssumeCapacity( .TLS_LE_HIX22 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .special(.sparc_le_hix22)), .TLS_DTPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"32", .cast = .unsigned, .shift = .@"0" })), .TLS_DTPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.dtpoff, .{ .dest = .@"64", .cast = .unsigned, .shift = .@"0" })), - .TLS_TPOFF32 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"32", .cast = .signed, .shift = .@"0" })), - .TLS_TPOFF64 => try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.tpoff, .{ .dest = .@"64", .cast = .signed, .shift = .@"0" })), .GOT13 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32[12:0]", .cast = .unsigned, .shift = .@"0" })), .GOT22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), @@ -9088,6 +9163,7 @@ fn addRelocAssumeCapacity( .GOTDATA_OP_HIX22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .symbol = target }, addend, .special(.sparc_op_hix22)), .TLS_GD_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .tlsgd0 = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), .TLS_LDM_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), + .TLS_IE_HI22 => elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .simple(.offset, .{ .dest = .@"32[21:0]", .cast = .trunc, .shift = .@"10" })), // zig fmt: on .TLS_GD_CALL, .TLS_LDM_CALL => { @@ -9109,6 +9185,22 @@ fn addRelocAssumeCapacity( try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); }, + .PC_HM10 => { + try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); + try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.rel, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"32" })); + }, + .LO10 => { + try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); + try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); + }, + .HM10 => { + try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); + try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"32" })); + }, + .LOX10 => { + try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b111" }); + try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); + }, .L44 => { try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:12] = 0b0" }); try elf.addSymbolRelocAssumeCapacity(node, offset, target, addend, .simple(.abs, .{ .dest = .@"32[11:0]", .cast = .trunc, .shift = .@"0" })); @@ -9133,6 +9225,10 @@ fn addRelocAssumeCapacity( try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); elf.addGotRelocAssumeCapacity(node, offset, .tlsld0, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); }, + .TLS_IE_LO10 => { + try elf.one_shot_fixups.append(elf.base.comp.gpa, .{ .node = node, .offset = offset, .action = .@"32[12:10] = 0b000" }); + elf.addGotRelocAssumeCapacity(node, offset, .{ .tpoff = target }, addend, .simple(.offset, .{ .dest = .@"32[9:0]", .cast = .trunc, .shift = .@"0" })); + }, }, .X86_64 => rel_type: switch (@"type".X86_64) { .NONE => {}, @@ -9256,12 +9352,17 @@ fn addSymbolRelocAssumeCapacity( .larch_pcala_hi20, .larch_pcala64_lo20, .larch_pcala64_hi12, + + .sparc_hix22, => true, .larch_b21, .larch_b26, .larch_call36, + .sparc_le_hix22, + .sparc_wdisp10, + .sparc_wdisp16, => false, }, }; diff --git a/test/tests.zig b/test/tests.zig index 989d4482571365a13c165422f94f84ccb6b4c13c..fc060c1519b6c1a8b53786beebc9a97ff4d790f6 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1566,6 +1566,15 @@ const module_test_targets = blk: { .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .sparc64, + .os_tag = .openbsd, + .abi = .none, + }, + .link_libc = true, + }, + .{ .target = .{ .cpu_arch = .x86,