| author | |
| committer | |
| log | f289b82d0efda77b72ccf9c826023e904f9ffcab |
| tree | eb0bbade490e385b46942628016d34dd32515c86 |
| parent | 26d4fd5276eaaa939cf21a516265101c551b62f2 |
17 files changed, 1202 insertions(+), 274 deletions(-)
lib/std/leb128.zig+1-1| ... | @@ -125,7 +125,7 @@ pub const readILEB128 = readIleb128; | ... | @@ -125,7 +125,7 @@ pub const readILEB128 = readIleb128; |
| 125 | pub fn writeIleb128(writer: anytype, arg: anytype) !void { | 125 | pub fn writeIleb128(writer: anytype, arg: anytype) !void { |
| 126 | const Arg = @TypeOf(arg); | 126 | const Arg = @TypeOf(arg); |
| 127 | const Int = switch (Arg) { | 127 | const Int = switch (Arg) { |
| 128 | comptime_int => std.math.IntFittingRange(-arg - 1, arg), | 128 | comptime_int => std.math.IntFittingRange(-@abs(arg), @abs(arg)), |
| 129 | else => Arg, | 129 | else => Arg, |
| 130 | }; | 130 | }; |
| 131 | const Signed = if (@typeInfo(Int).Int.bits < 8) i8 else Int; | 131 | const Signed = if (@typeInfo(Int).Int.bits < 8) i8 else Int; |
lib/std/os/linux/x86_64.zig+3-2| ... | @@ -114,14 +114,15 @@ pub fn clone() callconv(.Naked) usize { | ... | @@ -114,14 +114,15 @@ pub fn clone() callconv(.Naked) usize { |
| 114 | \\ movq %%rcx,(%%rsi) | 114 | \\ movq %%rcx,(%%rsi) |
| 115 | \\ syscall | 115 | \\ syscall |
| 116 | \\ testq %%rax,%%rax | 116 | \\ testq %%rax,%%rax |
| 117 | \\ jnz 1f | 117 | \\ jz 1f |
| 118 | \\ retq | ||
| 119 | \\1: .cfi_undefined %%rip | ||
| 118 | \\ xorl %%ebp,%%ebp | 120 | \\ xorl %%ebp,%%ebp |
| 119 | \\ popq %%rdi | 121 | \\ popq %%rdi |
| 120 | \\ callq *%%r9 | 122 | \\ callq *%%r9 |
| 121 | \\ movl %%eax,%%edi | 123 | \\ movl %%eax,%%edi |
| 122 | \\ movl $60,%%eax // SYS_exit | 124 | \\ movl $60,%%eax // SYS_exit |
| 123 | \\ syscall | 125 | \\ syscall |
| 124 | \\1: ret | ||
| 125 | \\ | 126 | \\ |
| 126 | ); | 127 | ); |
| 127 | } | 128 | } |
lib/std/start.zig+1| ... | @@ -249,6 +249,7 @@ fn _start() callconv(.Naked) noreturn { | ... | @@ -249,6 +249,7 @@ fn _start() callconv(.Naked) noreturn { |
| 249 | // linker explicitly. | 249 | // linker explicitly. |
| 250 | asm volatile (switch (native_arch) { | 250 | asm volatile (switch (native_arch) { |
| 251 | .x86_64 => | 251 | .x86_64 => |
| 252 | \\ .cfi_undefined %%rip | ||
| 252 | \\ xorl %%ebp, %%ebp | 253 | \\ xorl %%ebp, %%ebp |
| 253 | \\ movq %%rsp, %%rdi | 254 | \\ movq %%rsp, %%rdi |
| 254 | \\ andq $-16, %%rsp | 255 | \\ andq $-16, %%rsp |
src/arch/x86_64/CodeGen.zig+112-13| ... | @@ -1491,6 +1491,46 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void { | ... | @@ -1491,6 +1491,46 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void { |
| 1491 | }); | 1491 | }); |
| 1492 | } | 1492 | } |
| 1493 | 1493 | ||
| 1494 | fn asmPseudoRegister(self: *Self, ops: Mir.Inst.Ops, reg: Register) !void { | ||
| 1495 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and | ||
| 1496 | std.mem.endsWith(u8, @tagName(ops), "_r")); | ||
| 1497 | _ = try self.addInst(.{ | ||
| 1498 | .tag = .pseudo, | ||
| 1499 | .ops = ops, | ||
| 1500 | .data = .{ .r = .{ .r1 = reg } }, | ||
| 1501 | }); | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | fn asmPseudoImmediate(self: *Self, ops: Mir.Inst.Ops, imm: Immediate) !void { | ||
| 1505 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and | ||
| 1506 | std.mem.endsWith(u8, @tagName(ops), "_i_s")); | ||
| 1507 | _ = try self.addInst(.{ | ||
| 1508 | .tag = .pseudo, | ||
| 1509 | .ops = ops, | ||
| 1510 | .data = .{ .i = .{ .i = @bitCast(imm.signed) } }, | ||
| 1511 | }); | ||
| 1512 | } | ||
| 1513 | |||
| 1514 | fn asmPseudoRegisterRegister(self: *Self, ops: Mir.Inst.Ops, reg1: Register, reg2: Register) !void { | ||
| 1515 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and | ||
| 1516 | std.mem.endsWith(u8, @tagName(ops), "_rr")); | ||
| 1517 | _ = try self.addInst(.{ | ||
| 1518 | .tag = .pseudo, | ||
| 1519 | .ops = ops, | ||
| 1520 | .data = .{ .rr = .{ .r1 = reg1, .r2 = reg2 } }, | ||
| 1521 | }); | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | fn asmPseudoRegisterImmediate(self: *Self, ops: Mir.Inst.Ops, reg: Register, imm: Immediate) !void { | ||
| 1525 | assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and | ||
| 1526 | std.mem.endsWith(u8, @tagName(ops), "_ri_s")); | ||
| 1527 | _ = try self.addInst(.{ | ||
| 1528 | .tag = .pseudo, | ||
| 1529 | .ops = ops, | ||
| 1530 | .data = .{ .ri = .{ .r1 = reg, .i = @bitCast(imm.signed) } }, | ||
| 1531 | }); | ||
| 1532 | } | ||
| 1533 | |||
| 1494 | fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void { | 1534 | fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void { |
| 1495 | _ = try self.addInst(.{ | 1535 | _ = try self.addInst(.{ |
| 1496 | .tag = tag[1], | 1536 | .tag = tag[1], |
| ... | @@ -1877,7 +1917,10 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -1877,7 +1917,10 @@ fn gen(self: *Self) InnerError!void { |
| 1877 | const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); | 1917 | const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*); |
| 1878 | if (cc != .Naked) { | 1918 | if (cc != .Naked) { |
| 1879 | try self.asmRegister(.{ ._, .push }, .rbp); | 1919 | try self.asmRegister(.{ ._, .push }, .rbp); |
| 1920 | try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8)); | ||
| 1921 | try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0)); | ||
| 1880 | try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp); | 1922 | try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp); |
| 1923 | try self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, .rbp); | ||
| 1881 | const backpatch_push_callee_preserved_regs = try self.asmPlaceholder(); | 1924 | const backpatch_push_callee_preserved_regs = try self.asmPlaceholder(); |
| 1882 | const backpatch_frame_align = try self.asmPlaceholder(); | 1925 | const backpatch_frame_align = try self.asmPlaceholder(); |
| 1883 | const backpatch_frame_align_extra = try self.asmPlaceholder(); | 1926 | const backpatch_frame_align_extra = try self.asmPlaceholder(); |
| ... | @@ -1962,6 +2005,7 @@ fn gen(self: *Self) InnerError!void { | ... | @@ -1962,6 +2005,7 @@ fn gen(self: *Self) InnerError!void { |
| 1962 | const backpatch_stack_dealloc = try self.asmPlaceholder(); | 2005 | const backpatch_stack_dealloc = try self.asmPlaceholder(); |
| 1963 | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); | 2006 | const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder(); |
| 1964 | try self.asmRegister(.{ ._, .pop }, .rbp); | 2007 | try self.asmRegister(.{ ._, .pop }, .rbp); |
| 2008 | try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, Immediate.s(8)); | ||
| 1965 | try self.asmOpOnly(.{ ._, .ret }); | 2009 | try self.asmOpOnly(.{ ._, .ret }); |
| 1966 | 2010 | ||
| 1967 | const frame_layout = try self.computeFrameLayout(cc); | 2011 | const frame_layout = try self.computeFrameLayout(cc); |
| ... | @@ -14038,7 +14082,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14038,7 +14082,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14038 | var mnem_it = mem.tokenizeAny(u8, line, " \t"); | 14082 | var mnem_it = mem.tokenizeAny(u8, line, " \t"); |
| 14039 | var prefix: Instruction.Prefix = .none; | 14083 | var prefix: Instruction.Prefix = .none; |
| 14040 | const mnem_str = while (mnem_it.next()) |mnem_str| { | 14084 | const mnem_str = while (mnem_it.next()) |mnem_str| { |
| 14041 | if (mem.startsWith(u8, mnem_str, "#")) continue :next_line; | 14085 | if (mnem_str[0] == '#') continue :next_line; |
| 14042 | if (mem.startsWith(u8, mnem_str, "//")) continue :next_line; | 14086 | if (mem.startsWith(u8, mnem_str, "//")) continue :next_line; |
| 14043 | if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| { | 14087 | if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| { |
| 14044 | if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str}); | 14088 | if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str}); |
| ... | @@ -14063,8 +14107,14 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14063,8 +14107,14 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14063 | } | 14107 | } |
| 14064 | label_gop.value_ptr.target = @intCast(self.mir_instructions.len); | 14108 | label_gop.value_ptr.target = @intCast(self.mir_instructions.len); |
| 14065 | } else continue; | 14109 | } else continue; |
| 14110 | if (mnem_str[0] == '.') { | ||
| 14111 | if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{ @tagName(prefix), mnem_str }); | ||
| 14112 | prefix = .directive; | ||
| 14113 | } | ||
| 14066 | 14114 | ||
| 14067 | var mnem_size: ?Memory.Size = if (mem.endsWith(u8, mnem_str, "b")) | 14115 | var mnem_size: ?Memory.Size = if (prefix == .directive) |
| 14116 | null | ||
| 14117 | else if (mem.endsWith(u8, mnem_str, "b")) | ||
| 14068 | .byte | 14118 | .byte |
| 14069 | else if (mem.endsWith(u8, mnem_str, "w")) | 14119 | else if (mem.endsWith(u8, mnem_str, "w")) |
| 14070 | .word | 14120 | .word |
| ... | @@ -14095,7 +14145,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14095,7 +14145,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14095 | mnem_size = fixed_mnem_size; | 14145 | mnem_size = fixed_mnem_size; |
| 14096 | } | 14146 | } |
| 14097 | const mnem_name = @tagName(mnem_tag); | 14147 | const mnem_name = @tagName(mnem_tag); |
| 14098 | const mnem_fixed_tag: Mir.Inst.FixedTag = for (std.enums.values(Mir.Inst.Fixes)) |fixes| { | 14148 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) |
| 14149 | .{ ._, .pseudo } | ||
| 14150 | else for (std.enums.values(Mir.Inst.Fixes)) |fixes| { | ||
| 14099 | const fixes_name = @tagName(fixes); | 14151 | const fixes_name = @tagName(fixes); |
| 14100 | const space_i = mem.indexOfScalar(u8, fixes_name, ' '); | 14152 | const space_i = mem.indexOfScalar(u8, fixes_name, ' '); |
| 14101 | const fixes_prefix = if (space_i) |i| | 14153 | const fixes_prefix = if (space_i) |i| |
| ... | @@ -14116,7 +14168,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14116,7 +14168,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14116 | } else { | 14168 | } else { |
| 14117 | assert(prefix != .none); // no combination of fixes produced a known mnemonic | 14169 | assert(prefix != .none); // no combination of fixes produced a known mnemonic |
| 14118 | return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{ | 14170 | return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{ |
| 14119 | @tagName(prefix), mnem_str, | 14171 | @tagName(prefix), mnem_name, |
| 14120 | }); | 14172 | }); |
| 14121 | }; | 14173 | }; |
| 14122 | 14174 | ||
| ... | @@ -14324,7 +14376,62 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14324,7 +14376,62 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 14324 | } else return self.fail("invalid operand: '{s}'", .{op_str}); | 14376 | } else return self.fail("invalid operand: '{s}'", .{op_str}); |
| 14325 | } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str}); | 14377 | } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str}); |
| 14326 | 14378 | ||
| 14327 | (switch (ops[0]) { | 14379 | (if (prefix == .directive) switch (mnem_tag) { |
| 14380 | .@".cfi_def_cfa" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none) | ||
| 14381 | self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, ops[0].reg, ops[1].imm) | ||
| 14382 | else | ||
| 14383 | error.InvalidInstruction, | ||
| 14384 | .@".cfi_def_cfa_register" => if (ops[0] == .reg and ops[1] == .none) | ||
| 14385 | self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, ops[0].reg) | ||
| 14386 | else | ||
| 14387 | error.InvalidInstruction, | ||
| 14388 | .@".cfi_def_cfa_offset" => if (ops[0] == .imm and ops[1] == .none) | ||
| 14389 | self.asmPseudoImmediate(.pseudo_cfi_def_cfa_offset_i_s, ops[0].imm) | ||
| 14390 | else | ||
| 14391 | error.InvalidInstruction, | ||
| 14392 | .@".cfi_adjust_cfa_offset" => if (ops[0] == .imm and ops[1] == .none) | ||
| 14393 | self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, ops[0].imm) | ||
| 14394 | else | ||
| 14395 | error.InvalidInstruction, | ||
| 14396 | .@".cfi_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none) | ||
| 14397 | self.asmPseudoRegisterImmediate(.pseudo_cfi_offset_ri_s, ops[0].reg, ops[1].imm) | ||
| 14398 | else | ||
| 14399 | error.InvalidInstruction, | ||
| 14400 | .@".cfi_val_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none) | ||
| 14401 | self.asmPseudoRegisterImmediate(.pseudo_cfi_val_offset_ri_s, ops[0].reg, ops[1].imm) | ||
| 14402 | else | ||
| 14403 | error.InvalidInstruction, | ||
| 14404 | .@".cfi_rel_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none) | ||
| 14405 | self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, ops[0].reg, ops[1].imm) | ||
| 14406 | else | ||
| 14407 | error.InvalidInstruction, | ||
| 14408 | .@".cfi_register" => if (ops[0] == .reg and ops[1] == .reg and ops[2] == .none) | ||
| 14409 | self.asmPseudoRegisterRegister(.pseudo_cfi_register_rr, ops[0].reg, ops[1].reg) | ||
| 14410 | else | ||
| 14411 | error.InvalidInstruction, | ||
| 14412 | .@".cfi_restore" => if (ops[0] == .reg and ops[1] == .none) | ||
| 14413 | self.asmPseudoRegister(.pseudo_cfi_restore_r, ops[0].reg) | ||
| 14414 | else | ||
| 14415 | error.InvalidInstruction, | ||
| 14416 | .@".cfi_undefined" => if (ops[0] == .reg and ops[1] == .none) | ||
| 14417 | self.asmPseudoRegister(.pseudo_cfi_undefined_r, ops[0].reg) | ||
| 14418 | else | ||
| 14419 | error.InvalidInstruction, | ||
| 14420 | .@".cfi_same_value" => if (ops[0] == .reg and ops[1] == .none) | ||
| 14421 | self.asmPseudoRegister(.pseudo_cfi_same_value_r, ops[0].reg) | ||
| 14422 | else | ||
| 14423 | error.InvalidInstruction, | ||
| 14424 | .@".cfi_remember_state" => if (ops[0] == .none) | ||
| 14425 | self.asmPseudo(.pseudo_cfi_remember_state_none) | ||
| 14426 | else | ||
| 14427 | error.InvalidInstruction, | ||
| 14428 | .@".cfi_restore_state" => if (ops[0] == .none) | ||
| 14429 | self.asmPseudo(.pseudo_cfi_restore_state_none) | ||
| 14430 | else | ||
| 14431 | error.InvalidInstruction, | ||
| 14432 | .@".cfi_escape" => error.InvalidInstruction, | ||
| 14433 | else => unreachable, | ||
| 14434 | } else switch (ops[0]) { | ||
| 14328 | .none => self.asmOpOnly(mnem_fixed_tag), | 14435 | .none => self.asmOpOnly(mnem_fixed_tag), |
| 14329 | .reg => |reg0| switch (ops[1]) { | 14436 | .reg => |reg0| switch (ops[1]) { |
| 14330 | .none => self.asmRegister(mnem_fixed_tag, reg0), | 14437 | .none => self.asmRegister(mnem_fixed_tag, reg0), |
| ... | @@ -19210,14 +19317,6 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { | ... | @@ -19210,14 +19317,6 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError { |
| 19210 | return error.CodegenFail; | 19317 | return error.CodegenFail; |
| 19211 | } | 19318 | } |
| 19212 | 19319 | ||
| 19213 | fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError { | ||
| 19214 | @branchHint(.cold); | ||
| 19215 | assert(self.err_msg == null); | ||
| 19216 | const gpa = self.gpa; | ||
| 19217 | self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args); | ||
| 19218 | return error.CodegenFail; | ||
| 19219 | } | ||
| 19220 | |||
| 19221 | fn parseRegName(name: []const u8) ?Register { | 19320 | fn parseRegName(name: []const u8) ?Register { |
| 19222 | if (@hasDecl(Register, "parseRegName")) { | 19321 | if (@hasDecl(Register, "parseRegName")) { |
| 19223 | return Register.parseRegName(name); | 19322 | return Register.parseRegName(name); |
src/arch/x86_64/Emit.zig+53| ... | @@ -30,6 +30,59 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -30,6 +30,59 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 30 | var lowered_relocs = lowered.relocs; | 30 | var lowered_relocs = lowered.relocs; |
| 31 | for (lowered.insts, 0..) |lowered_inst, lowered_index| { | 31 | for (lowered.insts, 0..) |lowered_inst, lowered_index| { |
| 32 | const start_offset: u32 = @intCast(emit.code.items.len); | 32 | const start_offset: u32 = @intCast(emit.code.items.len); |
| 33 | if (lowered_inst.prefix == .directive) { | ||
| 34 | switch (emit.debug_output) { | ||
| 35 | .dwarf => |dwarf| switch (lowered_inst.encoding.mnemonic) { | ||
| 36 | .@".cfi_def_cfa" => try dwarf.genDebugFrame(start_offset, .{ .def_cfa = .{ | ||
| 37 | .reg = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 38 | .off = lowered_inst.ops[1].imm.signed, | ||
| 39 | } }), | ||
| 40 | .@".cfi_def_cfa_register" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 41 | .def_cfa_register = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 42 | }), | ||
| 43 | .@".cfi_def_cfa_offset" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 44 | .def_cfa_offset = lowered_inst.ops[0].imm.signed, | ||
| 45 | }), | ||
| 46 | .@".cfi_adjust_cfa_offset" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 47 | .adjust_cfa_offset = lowered_inst.ops[0].imm.signed, | ||
| 48 | }), | ||
| 49 | .@".cfi_offset" => try dwarf.genDebugFrame(start_offset, .{ .offset = .{ | ||
| 50 | .reg = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 51 | .off = lowered_inst.ops[1].imm.signed, | ||
| 52 | } }), | ||
| 53 | .@".cfi_val_offset" => try dwarf.genDebugFrame(start_offset, .{ .val_offset = .{ | ||
| 54 | .reg = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 55 | .off = lowered_inst.ops[1].imm.signed, | ||
| 56 | } }), | ||
| 57 | .@".cfi_rel_offset" => try dwarf.genDebugFrame(start_offset, .{ .rel_offset = .{ | ||
| 58 | .reg = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 59 | .off = lowered_inst.ops[1].imm.signed, | ||
| 60 | } }), | ||
| 61 | .@".cfi_register" => try dwarf.genDebugFrame(start_offset, .{ .register = .{ | ||
| 62 | lowered_inst.ops[0].reg.dwarfNum(), | ||
| 63 | lowered_inst.ops[1].reg.dwarfNum(), | ||
| 64 | } }), | ||
| 65 | .@".cfi_restore" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 66 | .restore = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 67 | }), | ||
| 68 | .@".cfi_undefined" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 69 | .undefined = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 70 | }), | ||
| 71 | .@".cfi_same_value" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 72 | .same_value = lowered_inst.ops[0].reg.dwarfNum(), | ||
| 73 | }), | ||
| 74 | .@".cfi_remember_state" => try dwarf.genDebugFrame(start_offset, .remember_state), | ||
| 75 | .@".cfi_restore_state" => try dwarf.genDebugFrame(start_offset, .restore_state), | ||
| 76 | .@".cfi_escape" => try dwarf.genDebugFrame(start_offset, .{ | ||
| 77 | .escape = lowered_inst.ops[0].bytes, | ||
| 78 | }), | ||
| 79 | else => unreachable, | ||
| 80 | }, | ||
| 81 | .plan9 => {}, | ||
| 82 | .none => {}, | ||
| 83 | } | ||
| 84 | continue; | ||
| 85 | } | ||
| 33 | try lowered_inst.encode(emit.code.writer(), .{}); | 86 | try lowered_inst.encode(emit.code.writer(), .{}); |
| 34 | const end_offset: u32 = @intCast(emit.code.items.len); | 87 | const end_offset: u32 = @intCast(emit.code.items.len); |
| 35 | while (lowered_relocs.len > 0 and | 88 | while (lowered_relocs.len > 0 and |
src/arch/x86_64/Encoding.zig+32-7| ... | @@ -220,6 +220,21 @@ pub fn format( | ... | @@ -220,6 +220,21 @@ pub fn format( |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | pub const Mnemonic = enum { | 222 | pub const Mnemonic = enum { |
| 223 | // Directives | ||
| 224 | @".cfi_def_cfa", | ||
| 225 | @".cfi_def_cfa_register", | ||
| 226 | @".cfi_def_cfa_offset", | ||
| 227 | @".cfi_adjust_cfa_offset", | ||
| 228 | @".cfi_offset", | ||
| 229 | @".cfi_val_offset", | ||
| 230 | @".cfi_rel_offset", | ||
| 231 | @".cfi_register", | ||
| 232 | @".cfi_restore", | ||
| 233 | @".cfi_undefined", | ||
| 234 | @".cfi_same_value", | ||
| 235 | @".cfi_remember_state", | ||
| 236 | @".cfi_restore_state", | ||
| 237 | @".cfi_escape", | ||
| 223 | // zig fmt: off | 238 | // zig fmt: off |
| 224 | // General-purpose | 239 | // General-purpose |
| 225 | adc, add, @"and", | 240 | adc, add, @"and", |
| ... | @@ -442,6 +457,7 @@ pub const Op = enum { | ... | @@ -442,6 +457,7 @@ pub const Op = enum { |
| 442 | imm8s, imm16s, imm32s, | 457 | imm8s, imm16s, imm32s, |
| 443 | al, ax, eax, rax, | 458 | al, ax, eax, rax, |
| 444 | cl, | 459 | cl, |
| 460 | rip, eip, ip, | ||
| 445 | r8, r16, r32, r64, | 461 | r8, r16, r32, r64, |
| 446 | rm8, rm16, rm32, rm64, | 462 | rm8, rm16, rm32, rm64, |
| 447 | r32_m8, r32_m16, r64_m16, | 463 | r32_m8, r32_m16, r64_m16, |
| ... | @@ -487,7 +503,12 @@ pub const Op = enum { | ... | @@ -487,7 +503,12 @@ pub const Op = enum { |
| 487 | 256 => .ymm, | 503 | 256 => .ymm, |
| 488 | else => unreachable, | 504 | else => unreachable, |
| 489 | }, | 505 | }, |
| 490 | .ip => unreachable, | 506 | .ip => switch (reg) { |
| 507 | .rip => .rip, | ||
| 508 | .eip => .eip, | ||
| 509 | .ip => .ip, | ||
| 510 | else => unreachable, | ||
| 511 | }, | ||
| 491 | }, | 512 | }, |
| 492 | 513 | ||
| 493 | .mem => |mem| switch (mem) { | 514 | .mem => |mem| switch (mem) { |
| ... | @@ -531,13 +552,15 @@ pub const Op = enum { | ... | @@ -531,13 +552,15 @@ pub const Op = enum { |
| 531 | else | 552 | else |
| 532 | .imm64, | 553 | .imm64, |
| 533 | }, | 554 | }, |
| 555 | |||
| 556 | .bytes => unreachable, | ||
| 534 | }; | 557 | }; |
| 535 | } | 558 | } |
| 536 | 559 | ||
| 537 | pub fn immBitSize(op: Op) u64 { | 560 | pub fn immBitSize(op: Op) u64 { |
| 538 | return switch (op) { | 561 | return switch (op) { |
| 539 | .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable, | 562 | .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable, |
| 540 | .al, .cl, .r8, .rm8, .r32_m8 => unreachable, | 563 | .al, .cl, .rip, .eip, .ip, .r8, .rm8, .r32_m8 => unreachable, |
| 541 | .ax, .r16, .rm16 => unreachable, | 564 | .ax, .r16, .rm16 => unreachable, |
| 542 | .eax, .r32, .rm32, .r32_m16 => unreachable, | 565 | .eax, .r32, .rm32, .r32_m16 => unreachable, |
| 543 | .rax, .r64, .rm64, .r64_m16 => unreachable, | 566 | .rax, .r64, .rm64, .r64_m16 => unreachable, |
| ... | @@ -560,9 +583,9 @@ pub const Op = enum { | ... | @@ -560,9 +583,9 @@ pub const Op = enum { |
| 560 | .rel8, .rel16, .rel32 => unreachable, | 583 | .rel8, .rel16, .rel32 => unreachable, |
| 561 | .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable, | 584 | .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable, |
| 562 | .al, .cl, .r8, .rm8 => 8, | 585 | .al, .cl, .r8, .rm8 => 8, |
| 563 | .ax, .r16, .rm16 => 16, | 586 | .ax, .ip, .r16, .rm16 => 16, |
| 564 | .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32, | 587 | .eax, .eip, .r32, .rm32, .r32_m8, .r32_m16 => 32, |
| 565 | .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64, | 588 | .rax, .rip, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64, |
| 566 | .st => 80, | 589 | .st => 80, |
| 567 | .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => 128, | 590 | .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => 128, |
| 568 | .ymm, .ymm_m256 => 256, | 591 | .ymm, .ymm_m256 => 256, |
| ... | @@ -574,7 +597,7 @@ pub const Op = enum { | ... | @@ -574,7 +597,7 @@ pub const Op = enum { |
| 574 | .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable, | 597 | .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable, |
| 575 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, | 598 | .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable, |
| 576 | .rel8, .rel16, .rel32 => unreachable, | 599 | .rel8, .rel16, .rel32 => unreachable, |
| 577 | .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64 => unreachable, | 600 | .al, .cl, .r8, .ax, .ip, .r16, .eax, .eip, .r32, .rax, .rip, .r64 => unreachable, |
| 578 | .st, .mm, .xmm0, .xmm, .ymm => unreachable, | 601 | .st, .mm, .xmm0, .xmm, .ymm => unreachable, |
| 579 | .m8, .rm8, .r32_m8, .xmm_m8 => 8, | 602 | .m8, .rm8, .r32_m8, .xmm_m8 => 8, |
| 580 | .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16, | 603 | .m16, .rm16, .r32_m16, .r64_m16, .xmm_m16 => 16, |
| ... | @@ -602,8 +625,9 @@ pub const Op = enum { | ... | @@ -602,8 +625,9 @@ pub const Op = enum { |
| 602 | pub fn isRegister(op: Op) bool { | 625 | pub fn isRegister(op: Op) bool { |
| 603 | // zig fmt: off | 626 | // zig fmt: off |
| 604 | return switch (op) { | 627 | return switch (op) { |
| 605 | .cl, | ||
| 606 | .al, .ax, .eax, .rax, | 628 | .al, .ax, .eax, .rax, |
| 629 | .cl, | ||
| 630 | .ip, .eip, .rip, | ||
| 607 | .r8, .r16, .r32, .r64, | 631 | .r8, .r16, .r32, .r64, |
| 608 | .rm8, .rm16, .rm32, .rm64, | 632 | .rm8, .rm16, .rm32, .rm64, |
| 609 | .r32_m8, .r32_m16, .r64_m16, | 633 | .r32_m8, .r32_m16, .r64_m16, |
| ... | @@ -664,6 +688,7 @@ pub const Op = enum { | ... | @@ -664,6 +688,7 @@ pub const Op = enum { |
| 664 | .mm, .mm_m64 => .mmx, | 688 | .mm, .mm_m64 => .mmx, |
| 665 | .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => .sse, | 689 | .xmm0, .xmm, .xmm_m8, .xmm_m16, .xmm_m32, .xmm_m64, .xmm_m128 => .sse, |
| 666 | .ymm, .ymm_m256 => .sse, | 690 | .ymm, .ymm_m256 => .sse, |
| 691 | .rip, .eip, .ip => .ip, | ||
| 667 | }; | 692 | }; |
| 668 | } | 693 | } |
| 669 | 694 |
src/arch/x86_64/Lower.zig+87-11| ... | @@ -12,7 +12,7 @@ src_loc: Zcu.LazySrcLoc, | ... | @@ -12,7 +12,7 @@ src_loc: Zcu.LazySrcLoc, |
| 12 | result_insts_len: u8 = undefined, | 12 | result_insts_len: u8 = undefined, |
| 13 | result_relocs_len: u8 = undefined, | 13 | result_relocs_len: u8 = undefined, |
| 14 | result_insts: [ | 14 | result_insts: [ |
| 15 | std.mem.max(usize, &.{ | 15 | @max( |
| 16 | 1, // non-pseudo instructions | 16 | 1, // non-pseudo instructions |
| 17 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode | 17 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode |
| 18 | 2, // cmovcc: cmovcc \ cmovcc | 18 | 2, // cmovcc: cmovcc \ cmovcc |
| ... | @@ -22,18 +22,18 @@ result_insts: [ | ... | @@ -22,18 +22,18 @@ result_insts: [ |
| 22 | pseudo_probe_adjust_unrolled_max_insts, | 22 | pseudo_probe_adjust_unrolled_max_insts, |
| 23 | pseudo_probe_adjust_setup_insts, | 23 | pseudo_probe_adjust_setup_insts, |
| 24 | pseudo_probe_adjust_loop_insts, | 24 | pseudo_probe_adjust_loop_insts, |
| 25 | abi.Win64.callee_preserved_regs.len, // push_regs/pop_regs | 25 | abi.Win64.callee_preserved_regs.len * 2, // push_regs/pop_regs |
| 26 | abi.SysV.callee_preserved_regs.len, // push_regs/pop_regs | 26 | abi.SysV.callee_preserved_regs.len * 2, // push_regs/pop_regs |
| 27 | }) | 27 | ) |
| 28 | ]Instruction = undefined, | 28 | ]Instruction = undefined, |
| 29 | result_relocs: [ | 29 | result_relocs: [ |
| 30 | std.mem.max(usize, &.{ | 30 | @max( |
| 31 | 1, // jmp/jcc/call/mov/lea: jmp/jcc/call/mov/lea | 31 | 1, // jmp/jcc/call/mov/lea: jmp/jcc/call/mov/lea |
| 32 | 2, // jcc: jcc \ jcc | 32 | 2, // jcc: jcc \ jcc |
| 33 | 2, // test \ jcc \ probe \ sub \ jmp | 33 | 2, // test \ jcc \ probe \ sub \ jmp |
| 34 | 1, // probe \ sub \ jcc | 34 | 1, // probe \ sub \ jcc |
| 35 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode | 35 | 3, // (ELF only) TLS local dynamic (LD) sequence in PIC mode |
| 36 | }) | 36 | ) |
| 37 | ]Reloc = undefined, | 37 | ]Reloc = undefined, |
| 38 | 38 | ||
| 39 | pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp | 39 | pub const pseudo_probe_align_insts = 5; // test \ jcc \ probe \ sub \ jmp |
| ... | @@ -265,6 +265,50 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -265,6 +265,50 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 265 | .pseudo_push_reg_list => try lower.pushPopRegList(.push, inst), | 265 | .pseudo_push_reg_list => try lower.pushPopRegList(.push, inst), |
| 266 | .pseudo_pop_reg_list => try lower.pushPopRegList(.pop, inst), | 266 | .pseudo_pop_reg_list => try lower.pushPopRegList(.pop, inst), |
| 267 | 267 | ||
| 268 | .pseudo_cfi_def_cfa_ri_s => try lower.emit(.directive, .@".cfi_def_cfa", &.{ | ||
| 269 | .{ .reg = inst.data.ri.r1 }, | ||
| 270 | .{ .imm = lower.imm(.ri_s, inst.data.ri.i) }, | ||
| 271 | }), | ||
| 272 | .pseudo_cfi_def_cfa_register_r => try lower.emit(.directive, .@".cfi_def_cfa_register", &.{ | ||
| 273 | .{ .reg = inst.data.r.r1 }, | ||
| 274 | }), | ||
| 275 | .pseudo_cfi_def_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_def_cfa_offset", &.{ | ||
| 276 | .{ .imm = lower.imm(.i_s, inst.data.i.i) }, | ||
| 277 | }), | ||
| 278 | .pseudo_cfi_adjust_cfa_offset_i_s => try lower.emit(.directive, .@".cfi_adjust_cfa_offset", &.{ | ||
| 279 | .{ .imm = lower.imm(.i_s, inst.data.i.i) }, | ||
| 280 | }), | ||
| 281 | .pseudo_cfi_offset_ri_s => try lower.emit(.directive, .@".cfi_offset", &.{ | ||
| 282 | .{ .reg = inst.data.ri.r1 }, | ||
| 283 | .{ .imm = lower.imm(.ri_s, inst.data.ri.i) }, | ||
| 284 | }), | ||
| 285 | .pseudo_cfi_val_offset_ri_s => try lower.emit(.directive, .@".cfi_val_offset", &.{ | ||
| 286 | .{ .reg = inst.data.ri.r1 }, | ||
| 287 | .{ .imm = lower.imm(.ri_s, inst.data.ri.i) }, | ||
| 288 | }), | ||
| 289 | .pseudo_cfi_rel_offset_ri_s => try lower.emit(.directive, .@".cfi_rel_offset", &.{ | ||
| 290 | .{ .reg = inst.data.ri.r1 }, | ||
| 291 | .{ .imm = lower.imm(.ri_s, inst.data.ri.i) }, | ||
| 292 | }), | ||
| 293 | .pseudo_cfi_register_rr => try lower.emit(.directive, .@".cfi_register", &.{ | ||
| 294 | .{ .reg = inst.data.rr.r1 }, | ||
| 295 | .{ .reg = inst.data.rr.r2 }, | ||
| 296 | }), | ||
| 297 | .pseudo_cfi_restore_r => try lower.emit(.directive, .@".cfi_restore", &.{ | ||
| 298 | .{ .reg = inst.data.r.r1 }, | ||
| 299 | }), | ||
| 300 | .pseudo_cfi_undefined_r => try lower.emit(.directive, .@".cfi_undefined", &.{ | ||
| 301 | .{ .reg = inst.data.r.r1 }, | ||
| 302 | }), | ||
| 303 | .pseudo_cfi_same_value_r => try lower.emit(.directive, .@".cfi_same_value", &.{ | ||
| 304 | .{ .reg = inst.data.r.r1 }, | ||
| 305 | }), | ||
| 306 | .pseudo_cfi_remember_state_none => try lower.emit(.directive, .@".cfi_remember_state", &.{}), | ||
| 307 | .pseudo_cfi_restore_state_none => try lower.emit(.directive, .@".cfi_restore_state", &.{}), | ||
| 308 | .pseudo_cfi_escape_bytes => try lower.emit(.directive, .@".cfi_escape", &.{ | ||
| 309 | .{ .bytes = inst.data.bytes.get(lower.mir) }, | ||
| 310 | }), | ||
| 311 | |||
| 268 | .pseudo_dbg_prologue_end_none, | 312 | .pseudo_dbg_prologue_end_none, |
| 269 | .pseudo_dbg_line_line_column, | 313 | .pseudo_dbg_line_line_column, |
| 270 | .pseudo_dbg_epilogue_begin_none, | 314 | .pseudo_dbg_epilogue_begin_none, |
| ... | @@ -280,6 +324,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -280,6 +324,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 280 | .pseudo_dbg_local_af, | 324 | .pseudo_dbg_local_af, |
| 281 | .pseudo_dbg_local_am, | 325 | .pseudo_dbg_local_am, |
| 282 | .pseudo_dbg_var_args_none, | 326 | .pseudo_dbg_var_args_none, |
| 327 | |||
| 283 | .pseudo_dead_none, | 328 | .pseudo_dead_none, |
| 284 | => {}, | 329 | => {}, |
| 285 | else => unreachable, | 330 | else => unreachable, |
| ... | @@ -665,12 +710,43 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { | ... | @@ -665,12 +710,43 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 665 | 710 | ||
| 666 | fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Error!void { | 711 | fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Error!void { |
| 667 | const callee_preserved_regs = abi.getCalleePreservedRegs(lower.cc); | 712 | const callee_preserved_regs = abi.getCalleePreservedRegs(lower.cc); |
| 668 | var it = inst.data.reg_list.iterator(.{ .direction = switch (mnemonic) { | 713 | var off: i32 = switch (mnemonic) { |
| 669 | .push => .reverse, | 714 | .push => 0, |
| 670 | .pop => .forward, | 715 | .pop => undefined, |
| 671 | else => unreachable, | 716 | else => unreachable, |
| 672 | } }); | 717 | }; |
| 673 | while (it.next()) |i| try lower.emit(.none, mnemonic, &.{.{ .reg = callee_preserved_regs[i] }}); | 718 | { |
| 719 | var it = inst.data.reg_list.iterator(.{ .direction = switch (mnemonic) { | ||
| 720 | .push => .reverse, | ||
| 721 | .pop => .forward, | ||
| 722 | else => unreachable, | ||
| 723 | } }); | ||
| 724 | while (it.next()) |i| { | ||
| 725 | try lower.emit(.none, mnemonic, &.{.{ | ||
| 726 | .reg = callee_preserved_regs[i], | ||
| 727 | }}); | ||
| 728 | switch (mnemonic) { | ||
| 729 | .push => off -= 8, | ||
| 730 | .pop => {}, | ||
| 731 | else => unreachable, | ||
| 732 | } | ||
| 733 | } | ||
| 734 | } | ||
| 735 | switch (mnemonic) { | ||
| 736 | .push => { | ||
| 737 | var it = inst.data.reg_list.iterator(.{}); | ||
| 738 | while (it.next()) |i| { | ||
| 739 | try lower.emit(.directive, .@".cfi_rel_offset", &.{ | ||
| 740 | .{ .reg = callee_preserved_regs[i] }, | ||
| 741 | .{ .imm = Immediate.s(off) }, | ||
| 742 | }); | ||
| 743 | off += 8; | ||
| 744 | } | ||
| 745 | assert(off == 0); | ||
| 746 | }, | ||
| 747 | .pop => {}, | ||
| 748 | else => unreachable, | ||
| 749 | } | ||
| 674 | } | 750 | } |
| 675 | 751 | ||
| 676 | const page_size: i32 = 1 << 12; | 752 | const page_size: i32 = 1 << 12; |
src/arch/x86_64/Mir.zig+48-1| ... | @@ -879,6 +879,7 @@ pub const Inst = struct { | ... | @@ -879,6 +879,7 @@ pub const Inst = struct { |
| 879 | /// Probe adjust loop | 879 | /// Probe adjust loop |
| 880 | /// Uses `rr` payload. | 880 | /// Uses `rr` payload. |
| 881 | pseudo_probe_adjust_loop_rr, | 881 | pseudo_probe_adjust_loop_rr, |
| 882 | |||
| 882 | /// Push registers | 883 | /// Push registers |
| 883 | /// Uses `reg_list` payload. | 884 | /// Uses `reg_list` payload. |
| 884 | pseudo_push_reg_list, | 885 | pseudo_push_reg_list, |
| ... | @@ -886,6 +887,47 @@ pub const Inst = struct { | ... | @@ -886,6 +887,47 @@ pub const Inst = struct { |
| 886 | /// Uses `reg_list` payload. | 887 | /// Uses `reg_list` payload. |
| 887 | pseudo_pop_reg_list, | 888 | pseudo_pop_reg_list, |
| 888 | 889 | ||
| 890 | /// Define cfa rule as offset from register. | ||
| 891 | /// Uses `ri` payload. | ||
| 892 | pseudo_cfi_def_cfa_ri_s, | ||
| 893 | /// Modify cfa rule register. | ||
| 894 | /// Uses `r` payload. | ||
| 895 | pseudo_cfi_def_cfa_register_r, | ||
| 896 | /// Modify cfa rule offset. | ||
| 897 | /// Uses `i` payload. | ||
| 898 | pseudo_cfi_def_cfa_offset_i_s, | ||
| 899 | /// Offset cfa rule offset. | ||
| 900 | /// Uses `i` payload. | ||
| 901 | pseudo_cfi_adjust_cfa_offset_i_s, | ||
| 902 | /// Define register rule as stored at offset from cfa. | ||
| 903 | /// Uses `ri` payload. | ||
| 904 | pseudo_cfi_offset_ri_s, | ||
| 905 | /// Define register rule as offset from cfa. | ||
| 906 | /// Uses `ri` payload. | ||
| 907 | pseudo_cfi_val_offset_ri_s, | ||
| 908 | /// Define register rule as stored at offset from cfa rule register. | ||
| 909 | /// Uses `ri` payload. | ||
| 910 | pseudo_cfi_rel_offset_ri_s, | ||
| 911 | /// Define register rule as register. | ||
| 912 | /// Uses `rr` payload. | ||
| 913 | pseudo_cfi_register_rr, | ||
| 914 | /// Define register rule from initial. | ||
| 915 | /// Uses `r` payload. | ||
| 916 | pseudo_cfi_restore_r, | ||
| 917 | /// Define register rule as undefined. | ||
| 918 | /// Uses `r` payload. | ||
| 919 | pseudo_cfi_undefined_r, | ||
| 920 | /// Define register rule as itself. | ||
| 921 | /// Uses `r` payload. | ||
| 922 | pseudo_cfi_same_value_r, | ||
| 923 | /// Push cfi state. | ||
| 924 | pseudo_cfi_remember_state_none, | ||
| 925 | /// Pop cfi state. | ||
| 926 | pseudo_cfi_restore_state_none, | ||
| 927 | /// Raw cfi bytes. | ||
| 928 | /// Uses `bytes` payload. | ||
| 929 | pseudo_cfi_escape_bytes, | ||
| 930 | |||
| 889 | /// End of prologue | 931 | /// End of prologue |
| 890 | pseudo_dbg_prologue_end_none, | 932 | pseudo_dbg_prologue_end_none, |
| 891 | /// Update debug line | 933 | /// Update debug line |
| ... | @@ -1028,8 +1070,13 @@ pub const Inst = struct { | ... | @@ -1028,8 +1070,13 @@ pub const Inst = struct { |
| 1028 | fixes: Fixes = ._, | 1070 | fixes: Fixes = ._, |
| 1029 | payload: u32, | 1071 | payload: u32, |
| 1030 | }, | 1072 | }, |
| 1031 | ix: struct { | 1073 | bytes: struct { |
| 1032 | payload: u32, | 1074 | payload: u32, |
| 1075 | len: u32, | ||
| 1076 | |||
| 1077 | pub fn get(bytes: @This(), mir: Mir) []const u8 { | ||
| 1078 | return std.mem.sliceAsBytes(mir.extra[bytes.payload..])[0..bytes.len]; | ||
| 1079 | } | ||
| 1033 | }, | 1080 | }, |
| 1034 | a: struct { | 1081 | a: struct { |
| 1035 | air_inst: Air.Inst.Index, | 1082 | air_inst: Air.Inst.Index, |
src/arch/x86_64/bits.zig+1-1| ... | @@ -371,7 +371,7 @@ pub const Register = enum(u7) { | ... | @@ -371,7 +371,7 @@ pub const Register = enum(u7) { |
| 371 | .x87 => 33 + @as(u6, reg.enc()), | 371 | .x87 => 33 + @as(u6, reg.enc()), |
| 372 | .mmx => 41 + @as(u6, reg.enc()), | 372 | .mmx => 41 + @as(u6, reg.enc()), |
| 373 | .segment => 50 + @as(u6, reg.enc()), | 373 | .segment => 50 + @as(u6, reg.enc()), |
| 374 | .ip => unreachable, | 374 | .ip => 16, |
| 375 | }; | 375 | }; |
| 376 | } | 376 | } |
| 377 | }; | 377 | }; |
src/arch/x86_64/encoder.zig+43-12| ... | @@ -25,6 +25,7 @@ pub const Instruction = struct { | ... | @@ -25,6 +25,7 @@ pub const Instruction = struct { |
| 25 | repz, | 25 | repz, |
| 26 | repne, | 26 | repne, |
| 27 | repnz, | 27 | repnz, |
| 28 | directive, | ||
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| 30 | pub const Immediate = union(enum) { | 31 | pub const Immediate = union(enum) { |
| ... | @@ -180,6 +181,7 @@ pub const Instruction = struct { | ... | @@ -180,6 +181,7 @@ pub const Instruction = struct { |
| 180 | reg: Register, | 181 | reg: Register, |
| 181 | mem: Memory, | 182 | mem: Memory, |
| 182 | imm: Immediate, | 183 | imm: Immediate, |
| 184 | bytes: []const u8, | ||
| 183 | 185 | ||
| 184 | /// Returns the bitsize of the operand. | 186 | /// Returns the bitsize of the operand. |
| 185 | pub fn bitSize(op: Operand) u64 { | 187 | pub fn bitSize(op: Operand) u64 { |
| ... | @@ -188,6 +190,7 @@ pub const Instruction = struct { | ... | @@ -188,6 +190,7 @@ pub const Instruction = struct { |
| 188 | .reg => |reg| reg.bitSize(), | 190 | .reg => |reg| reg.bitSize(), |
| 189 | .mem => |mem| mem.bitSize(), | 191 | .mem => |mem| mem.bitSize(), |
| 190 | .imm => unreachable, | 192 | .imm => unreachable, |
| 193 | .bytes => unreachable, | ||
| 191 | }; | 194 | }; |
| 192 | } | 195 | } |
| 193 | 196 | ||
| ... | @@ -199,6 +202,7 @@ pub const Instruction = struct { | ... | @@ -199,6 +202,7 @@ pub const Instruction = struct { |
| 199 | .reg => |reg| reg.class() == .segment, | 202 | .reg => |reg| reg.class() == .segment, |
| 200 | .mem => |mem| mem.isSegmentRegister(), | 203 | .mem => |mem| mem.isSegmentRegister(), |
| 201 | .imm => unreachable, | 204 | .imm => unreachable, |
| 205 | .bytes => unreachable, | ||
| 202 | }; | 206 | }; |
| 203 | } | 207 | } |
| 204 | 208 | ||
| ... | @@ -207,6 +211,7 @@ pub const Instruction = struct { | ... | @@ -207,6 +211,7 @@ pub const Instruction = struct { |
| 207 | .none, .imm => false, | 211 | .none, .imm => false, |
| 208 | .reg => |reg| reg.isExtended(), | 212 | .reg => |reg| reg.isExtended(), |
| 209 | .mem => |mem| mem.base().isExtended(), | 213 | .mem => |mem| mem.base().isExtended(), |
| 214 | .bytes => unreachable, | ||
| 210 | }; | 215 | }; |
| 211 | } | 216 | } |
| 212 | 217 | ||
| ... | @@ -214,6 +219,7 @@ pub const Instruction = struct { | ... | @@ -214,6 +219,7 @@ pub const Instruction = struct { |
| 214 | return switch (op) { | 219 | return switch (op) { |
| 215 | .none, .reg, .imm => false, | 220 | .none, .reg, .imm => false, |
| 216 | .mem => |mem| if (mem.scaleIndex()) |si| si.index.isExtended() else false, | 221 | .mem => |mem| if (mem.scaleIndex()) |si| si.index.isExtended() else false, |
| 222 | .bytes => unreachable, | ||
| 217 | }; | 223 | }; |
| 218 | } | 224 | } |
| 219 | 225 | ||
| ... | @@ -299,6 +305,7 @@ pub const Instruction = struct { | ... | @@ -299,6 +305,7 @@ pub const Instruction = struct { |
| 299 | if (imms < 0) try writer.writeByte('-'); | 305 | if (imms < 0) try writer.writeByte('-'); |
| 300 | try writer.print("0x{x}", .{@abs(imms)}); | 306 | try writer.print("0x{x}", .{@abs(imms)}); |
| 301 | } else try writer.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}), | 307 | } else try writer.print("0x{x}", .{imm.asUnsigned(enc_op.immBitSize())}), |
| 308 | .bytes => unreachable, | ||
| 302 | } | 309 | } |
| 303 | } | 310 | } |
| 304 | 311 | ||
| ... | @@ -308,20 +315,39 @@ pub const Instruction = struct { | ... | @@ -308,20 +315,39 @@ pub const Instruction = struct { |
| 308 | }; | 315 | }; |
| 309 | 316 | ||
| 310 | pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction { | 317 | pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction { |
| 311 | const encoding = (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse { | 318 | const encoding: Encoding = switch (prefix) { |
| 312 | log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{ | 319 | else => (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse { |
| 313 | @tagName(prefix), | 320 | log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{ |
| 314 | @tagName(mnemonic), | 321 | @tagName(prefix), |
| 315 | @tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none), | 322 | @tagName(mnemonic), |
| 316 | @tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none), | 323 | @tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none), |
| 317 | @tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none), | 324 | @tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none), |
| 318 | @tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none), | 325 | @tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none), |
| 319 | }); | 326 | @tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none), |
| 320 | return error.InvalidInstruction; | 327 | }); |
| 328 | return error.InvalidInstruction; | ||
| 329 | }, | ||
| 330 | .directive => .{ | ||
| 331 | .mnemonic = mnemonic, | ||
| 332 | .data = .{ | ||
| 333 | .op_en = .zo, | ||
| 334 | .ops = .{ | ||
| 335 | if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none, | ||
| 336 | if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none, | ||
| 337 | if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none, | ||
| 338 | if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none, | ||
| 339 | }, | ||
| 340 | .opc_len = 0, | ||
| 341 | .opc = undefined, | ||
| 342 | .modrm_ext = 0, | ||
| 343 | .mode = .none, | ||
| 344 | .feature = .none, | ||
| 345 | }, | ||
| 346 | }, | ||
| 321 | }; | 347 | }; |
| 322 | log.debug("selected encoding: {}", .{encoding}); | 348 | log.debug("selected encoding: {}", .{encoding}); |
| 323 | 349 | ||
| 324 | var inst = Instruction{ | 350 | var inst: Instruction = .{ |
| 325 | .prefix = prefix, | 351 | .prefix = prefix, |
| 326 | .encoding = encoding, | 352 | .encoding = encoding, |
| 327 | .ops = [1]Operand{.none} ** 4, | 353 | .ops = [1]Operand{.none} ** 4, |
| ... | @@ -338,7 +364,10 @@ pub const Instruction = struct { | ... | @@ -338,7 +364,10 @@ pub const Instruction = struct { |
| 338 | ) @TypeOf(writer).Error!void { | 364 | ) @TypeOf(writer).Error!void { |
| 339 | _ = unused_format_string; | 365 | _ = unused_format_string; |
| 340 | _ = options; | 366 | _ = options; |
| 341 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); | 367 | switch (inst.prefix) { |
| 368 | .none, .directive => {}, | ||
| 369 | else => try writer.print("{s} ", .{@tagName(inst.prefix)}), | ||
| 370 | } | ||
| 342 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); | 371 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); |
| 343 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { | 372 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { |
| 344 | if (op == .none) break; | 373 | if (op == .none) break; |
| ... | @@ -349,6 +378,7 @@ pub const Instruction = struct { | ... | @@ -349,6 +378,7 @@ pub const Instruction = struct { |
| 349 | } | 378 | } |
| 350 | 379 | ||
| 351 | pub fn encode(inst: Instruction, writer: anytype, comptime opts: Options) !void { | 380 | pub fn encode(inst: Instruction, writer: anytype, comptime opts: Options) !void { |
| 381 | assert(inst.prefix != .directive); | ||
| 352 | const encoder = Encoder(@TypeOf(writer), opts){ .writer = writer }; | 382 | const encoder = Encoder(@TypeOf(writer), opts){ .writer = writer }; |
| 353 | const enc = inst.encoding; | 383 | const enc = inst.encoding; |
| 354 | const data = enc.data; | 384 | const data = enc.data; |
| ... | @@ -435,6 +465,7 @@ pub const Instruction = struct { | ... | @@ -435,6 +465,7 @@ pub const Instruction = struct { |
| 435 | .lock => legacy.prefix_f0 = true, | 465 | .lock => legacy.prefix_f0 = true, |
| 436 | .repne, .repnz => legacy.prefix_f2 = true, | 466 | .repne, .repnz => legacy.prefix_f2 = true, |
| 437 | .rep, .repe, .repz => legacy.prefix_f3 = true, | 467 | .rep, .repe, .repz => legacy.prefix_f3 = true, |
| 468 | .directive => unreachable, | ||
| 438 | } | 469 | } |
| 439 | 470 | ||
| 440 | switch (data.mode) { | 471 | switch (data.mode) { |
src/link/Dwarf.zig+646-130| ... | @@ -10,6 +10,7 @@ navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), | ... | @@ -10,6 +10,7 @@ navs: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Entry.Index), |
| 10 | 10 | ||
| 11 | debug_abbrev: DebugAbbrev, | 11 | debug_abbrev: DebugAbbrev, |
| 12 | debug_aranges: DebugAranges, | 12 | debug_aranges: DebugAranges, |
| 13 | debug_frame: DebugFrame, | ||
| 13 | debug_info: DebugInfo, | 14 | debug_info: DebugInfo, |
| 14 | debug_line: DebugLine, | 15 | debug_line: DebugLine, |
| 15 | debug_line_str: StringSection, | 16 | debug_line_str: StringSection, |
| ... | @@ -73,11 +74,7 @@ const DebugAranges = struct { | ... | @@ -73,11 +74,7 @@ const DebugAranges = struct { |
| 73 | section: Section, | 74 | section: Section, |
| 74 | 75 | ||
| 75 | fn headerBytes(dwarf: *Dwarf) u32 { | 76 | fn headerBytes(dwarf: *Dwarf) u32 { |
| 76 | return std.mem.alignForwardAnyAlign( | 77 | return dwarf.unitLengthBytes() + 2 + dwarf.sectionOffsetBytes() + 1 + 1; |
| 77 | u32, | ||
| 78 | dwarf.unitLengthBytes() + 2 + dwarf.sectionOffsetBytes() + 1 + 1, | ||
| 79 | @intFromEnum(dwarf.address_size) * 2, | ||
| 80 | ); | ||
| 81 | } | 78 | } |
| 82 | 79 | ||
| 83 | fn trailerBytes(dwarf: *Dwarf) u32 { | 80 | fn trailerBytes(dwarf: *Dwarf) u32 { |
| ... | @@ -85,6 +82,47 @@ const DebugAranges = struct { | ... | @@ -85,6 +82,47 @@ const DebugAranges = struct { |
| 85 | } | 82 | } |
| 86 | }; | 83 | }; |
| 87 | 84 | ||
| 85 | const DebugFrame = struct { | ||
| 86 | header: Header, | ||
| 87 | section: Section, | ||
| 88 | |||
| 89 | const Format = enum { none, debug_frame, eh_frame }; | ||
| 90 | const Header = struct { | ||
| 91 | format: Format, | ||
| 92 | code_alignment_factor: u32, | ||
| 93 | data_alignment_factor: i32, | ||
| 94 | return_address_register: u32, | ||
| 95 | initial_instructions: []const Cfa, | ||
| 96 | }; | ||
| 97 | |||
| 98 | fn headerBytes(dwarf: *Dwarf) u32 { | ||
| 99 | const target = dwarf.bin_file.comp.root_mod.resolved_target.result; | ||
| 100 | return @intCast(switch (dwarf.debug_frame.header.format) { | ||
| 101 | .none => return 0, | ||
| 102 | .debug_frame => dwarf.unitLengthBytes() + dwarf.sectionOffsetBytes() + 1 + "\x00".len + 1 + 1, | ||
| 103 | .eh_frame => dwarf.unitLengthBytes() + 4 + 1 + "zR\x00".len + | ||
| 104 | uleb128Bytes(1) + 1, | ||
| 105 | } + switch (target.cpu.arch) { | ||
| 106 | .x86_64 => len: { | ||
| 107 | dev.check(.x86_64_backend); | ||
| 108 | const Register = @import("../arch/x86_64/bits.zig").Register; | ||
| 109 | break :len uleb128Bytes(1) + sleb128Bytes(-8) + uleb128Bytes(Register.rip.dwarfNum()) + | ||
| 110 | 1 + uleb128Bytes(Register.rsp.dwarfNum()) + sleb128Bytes(-1) + | ||
| 111 | 1 + uleb128Bytes(1); | ||
| 112 | }, | ||
| 113 | else => unreachable, | ||
| 114 | }); | ||
| 115 | } | ||
| 116 | |||
| 117 | fn trailerBytes(dwarf: *Dwarf) u32 { | ||
| 118 | return @intCast(switch (dwarf.debug_frame.header.format) { | ||
| 119 | .none => 0, | ||
| 120 | .debug_frame => dwarf.unitLengthBytes() + dwarf.sectionOffsetBytes() + 1 + "\x00".len + 1 + 1 + uleb128Bytes(1) + sleb128Bytes(1) + uleb128Bytes(0), | ||
| 121 | .eh_frame => dwarf.unitLengthBytes() + 4 + 1 + "\x00".len + uleb128Bytes(1) + sleb128Bytes(1) + uleb128Bytes(0), | ||
| 122 | }); | ||
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 88 | const DebugInfo = struct { | 126 | const DebugInfo = struct { |
| 89 | section: Section, | 127 | section: Section, |
| 90 | 128 | ||
| ... | @@ -227,8 +265,10 @@ pub const Section = struct { | ... | @@ -227,8 +265,10 @@ pub const Section = struct { |
| 227 | len: u64, | 265 | len: u64, |
| 228 | units: std.ArrayListUnmanaged(Unit), | 266 | units: std.ArrayListUnmanaged(Unit), |
| 229 | 267 | ||
| 230 | const Index = enum { | 268 | pub const Index = enum { |
| 231 | debug_abbrev, | 269 | debug_abbrev, |
| 270 | debug_aranges, | ||
| 271 | debug_frame, | ||
| 232 | debug_info, | 272 | debug_info, |
| 233 | debug_line, | 273 | debug_line, |
| 234 | debug_line_str, | 274 | debug_line_str, |
| ... | @@ -259,15 +299,17 @@ pub const Section = struct { | ... | @@ -259,15 +299,17 @@ pub const Section = struct { |
| 259 | const unit: Unit.Index = @enumFromInt(sec.units.items.len); | 299 | const unit: Unit.Index = @enumFromInt(sec.units.items.len); |
| 260 | const unit_ptr = try sec.units.addOne(dwarf.gpa); | 300 | const unit_ptr = try sec.units.addOne(dwarf.gpa); |
| 261 | errdefer sec.popUnit(dwarf.gpa); | 301 | errdefer sec.popUnit(dwarf.gpa); |
| 302 | const aligned_header_len: u32 = @intCast(sec.alignment.forward(header_len)); | ||
| 303 | const aligned_trailer_len: u32 = @intCast(sec.alignment.forward(trailer_len)); | ||
| 262 | unit_ptr.* = .{ | 304 | unit_ptr.* = .{ |
| 263 | .prev = sec.last, | 305 | .prev = sec.last, |
| 264 | .next = .none, | 306 | .next = .none, |
| 265 | .first = .none, | 307 | .first = .none, |
| 266 | .last = .none, | 308 | .last = .none, |
| 267 | .off = 0, | 309 | .off = 0, |
| 268 | .header_len = header_len, | 310 | .header_len = aligned_header_len, |
| 269 | .trailer_len = trailer_len, | 311 | .trailer_len = aligned_trailer_len, |
| 270 | .len = header_len + trailer_len, | 312 | .len = aligned_header_len + aligned_trailer_len, |
| 271 | .entries = .{}, | 313 | .entries = .{}, |
| 272 | .cross_unit_relocs = .{}, | 314 | .cross_unit_relocs = .{}, |
| 273 | .cross_section_relocs = .{}, | 315 | .cross_section_relocs = .{}, |
| ... | @@ -288,8 +330,8 @@ pub const Section = struct { | ... | @@ -288,8 +330,8 @@ pub const Section = struct { |
| 288 | const unit_ptr = sec.getUnit(unit); | 330 | const unit_ptr = sec.getUnit(unit); |
| 289 | if (unit_ptr.prev.unwrap()) |prev_unit| sec.getUnit(prev_unit).next = unit_ptr.next; | 331 | if (unit_ptr.prev.unwrap()) |prev_unit| sec.getUnit(prev_unit).next = unit_ptr.next; |
| 290 | if (unit_ptr.next.unwrap()) |next_unit| sec.getUnit(next_unit).prev = unit_ptr.prev; | 332 | if (unit_ptr.next.unwrap()) |next_unit| sec.getUnit(next_unit).prev = unit_ptr.prev; |
| 291 | if (sec.first.unwrap().? == unit) sec.first = unit_ptr.next; | 333 | if (sec.first == unit.toOptional()) sec.first = unit_ptr.next; |
| 292 | if (sec.last.unwrap().? == unit) sec.last = unit_ptr.prev; | 334 | if (sec.last == unit.toOptional()) sec.last = unit_ptr.prev; |
| 293 | } | 335 | } |
| 294 | 336 | ||
| 295 | fn popUnit(sec: *Section, gpa: std.mem.Allocator) void { | 337 | fn popUnit(sec: *Section, gpa: std.mem.Allocator) void { |
| ... | @@ -303,10 +345,10 @@ pub const Section = struct { | ... | @@ -303,10 +345,10 @@ pub const Section = struct { |
| 303 | return &sec.units.items[@intFromEnum(unit)]; | 345 | return &sec.units.items[@intFromEnum(unit)]; |
| 304 | } | 346 | } |
| 305 | 347 | ||
| 306 | fn replaceEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | 348 | fn resizeEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, len: u32) UpdateError!void { |
| 307 | const unit_ptr = sec.getUnit(unit); | 349 | const unit_ptr = sec.getUnit(unit); |
| 308 | const entry_ptr = unit_ptr.getEntry(entry); | 350 | const entry_ptr = unit_ptr.getEntry(entry); |
| 309 | if (contents.len > 0) { | 351 | if (len > 0) { |
| 310 | if (entry_ptr.len == 0) { | 352 | if (entry_ptr.len == 0) { |
| 311 | assert(entry_ptr.prev == .none and entry_ptr.next == .none); | 353 | assert(entry_ptr.prev == .none and entry_ptr.next == .none); |
| 312 | entry_ptr.off = if (unit_ptr.last.unwrap()) |last_entry| off: { | 354 | entry_ptr.off = if (unit_ptr.last.unwrap()) |last_entry| off: { |
| ... | @@ -316,15 +358,27 @@ pub const Section = struct { | ... | @@ -316,15 +358,27 @@ pub const Section = struct { |
| 316 | } else 0; | 358 | } else 0; |
| 317 | entry_ptr.prev = unit_ptr.last; | 359 | entry_ptr.prev = unit_ptr.last; |
| 318 | unit_ptr.last = entry.toOptional(); | 360 | unit_ptr.last = entry.toOptional(); |
| 361 | if (unit_ptr.first == .none) unit_ptr.first = unit_ptr.last; | ||
| 362 | if (entry_ptr.prev.unwrap()) |prev_entry| try unit_ptr.getEntry(prev_entry).pad(unit_ptr, sec, dwarf); | ||
| 319 | } | 363 | } |
| 320 | try entry_ptr.replace(unit_ptr, sec, dwarf, contents); | 364 | try entry_ptr.resize(unit_ptr, sec, dwarf, len); |
| 321 | } | 365 | } |
| 322 | assert(entry_ptr.len == contents.len); | 366 | assert(entry_ptr.len == len); |
| 367 | } | ||
| 368 | |||
| 369 | fn replaceEntry(sec: *Section, unit: Unit.Index, entry: Entry.Index, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | ||
| 370 | try sec.resizeEntry(unit, entry, dwarf, @intCast(contents.len)); | ||
| 371 | const unit_ptr = sec.getUnit(unit); | ||
| 372 | try unit_ptr.getEntry(entry).replace(unit_ptr, sec, dwarf, contents); | ||
| 323 | } | 373 | } |
| 324 | 374 | ||
| 325 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { | 375 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { |
| 376 | if (len <= sec.len) return; | ||
| 326 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 377 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 327 | try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); | 378 | if (sec == &dwarf.debug_frame.section) |
| 379 | try elf_file.growAllocSection(sec.index, len) | ||
| 380 | else | ||
| 381 | try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); | ||
| 328 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; | 382 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; |
| 329 | sec.off = shdr.sh_offset; | 383 | sec.off = shdr.sh_offset; |
| 330 | sec.len = shdr.sh_size; | 384 | sec.len = shdr.sh_size; |
| ... | @@ -366,7 +420,7 @@ pub const Section = struct { | ... | @@ -366,7 +420,7 @@ pub const Section = struct { |
| 366 | } | 420 | } |
| 367 | 421 | ||
| 368 | fn padToIdeal(sec: *Section, actual_size: anytype) @TypeOf(actual_size) { | 422 | fn padToIdeal(sec: *Section, actual_size: anytype) @TypeOf(actual_size) { |
| 369 | return if (sec.pad_to_ideal) Dwarf.padToIdeal(actual_size) else actual_size; | 423 | return @intCast(sec.alignment.forward(if (sec.pad_to_ideal) Dwarf.padToIdeal(actual_size) else actual_size)); |
| 370 | } | 424 | } |
| 371 | }; | 425 | }; |
| 372 | 426 | ||
| ... | @@ -562,6 +616,43 @@ const Unit = struct { | ... | @@ -562,6 +616,43 @@ const Unit = struct { |
| 562 | } else if (sec == &dwarf.debug_aranges.section) fill: { | 616 | } else if (sec == &dwarf.debug_aranges.section) fill: { |
| 563 | trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2); | 617 | trailer.appendNTimesAssumeCapacity(0, @intFromEnum(dwarf.address_size) * 2); |
| 564 | break :fill 0; | 618 | break :fill 0; |
| 619 | } else if (sec == &dwarf.debug_frame.section) fill: { | ||
| 620 | switch (dwarf.debug_frame.header.format) { | ||
| 621 | .none => {}, | ||
| 622 | .debug_frame, .eh_frame => |format| { | ||
| 623 | const unit_len = len - dwarf.unitLengthBytes(); | ||
| 624 | switch (dwarf.format) { | ||
| 625 | .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), | ||
| 626 | .@"64" => { | ||
| 627 | std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); | ||
| 628 | std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); | ||
| 629 | }, | ||
| 630 | } | ||
| 631 | switch (format) { | ||
| 632 | .none => unreachable, | ||
| 633 | .debug_frame => { | ||
| 634 | switch (dwarf.format) { | ||
| 635 | .@"32" => std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian), | ||
| 636 | .@"64" => std.mem.writeInt(u64, trailer.addManyAsArrayAssumeCapacity(8), std.math.maxInt(u64), dwarf.endian), | ||
| 637 | } | ||
| 638 | trailer.appendAssumeCapacity(4); | ||
| 639 | trailer.appendSliceAssumeCapacity("\x00"); | ||
| 640 | trailer.appendAssumeCapacity(@intFromEnum(dwarf.address_size)); | ||
| 641 | trailer.appendAssumeCapacity(0); | ||
| 642 | }, | ||
| 643 | .eh_frame => { | ||
| 644 | std.mem.writeInt(u32, trailer.addManyAsArrayAssumeCapacity(4), 0, dwarf.endian); | ||
| 645 | trailer.appendAssumeCapacity(1); | ||
| 646 | trailer.appendSliceAssumeCapacity("\x00"); | ||
| 647 | }, | ||
| 648 | } | ||
| 649 | uleb128(trailer.fixedWriter(), 1) catch unreachable; | ||
| 650 | sleb128(trailer.fixedWriter(), 1) catch unreachable; | ||
| 651 | uleb128(trailer.fixedWriter(), 0) catch unreachable; | ||
| 652 | }, | ||
| 653 | } | ||
| 654 | trailer.appendNTimesAssumeCapacity(DW.CFA.nop, unit.trailer_len - trailer.items.len); | ||
| 655 | break :fill DW.CFA.nop; | ||
| 565 | } else if (sec == &dwarf.debug_info.section) fill: { | 656 | } else if (sec == &dwarf.debug_info.section) fill: { |
| 566 | assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); | 657 | assert(uleb128Bytes(@intFromEnum(AbbrevCode.null)) == 1); |
| 567 | trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2); | 658 | trailer.appendNTimesAssumeCapacity(@intFromEnum(AbbrevCode.null), 2); |
| ... | @@ -571,7 +662,7 @@ const Unit = struct { | ... | @@ -571,7 +662,7 @@ const Unit = struct { |
| 571 | break :fill DW.RLE.end_of_list; | 662 | break :fill DW.RLE.end_of_list; |
| 572 | } else unreachable; | 663 | } else unreachable; |
| 573 | assert(trailer.items.len == unit.trailer_len); | 664 | assert(trailer.items.len == unit.trailer_len); |
| 574 | trailer.appendNTimesAssumeCapacity(fill_byte, len - trailer.items.len); | 665 | trailer.appendNTimesAssumeCapacity(fill_byte, len - unit.trailer_len); |
| 575 | assert(trailer.items.len == len); | 666 | assert(trailer.items.len == len); |
| 576 | try dwarf.getFile().?.pwriteAll(trailer.items, sec.off + start); | 667 | try dwarf.getFile().?.pwriteAll(trailer.items, sec.off + start); |
| 577 | } | 668 | } |
| ... | @@ -655,6 +746,23 @@ const Entry = struct { | ... | @@ -655,6 +746,23 @@ const Entry = struct { |
| 655 | fn pad(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void { | 746 | fn pad(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) UpdateError!void { |
| 656 | assert(entry.len > 0); | 747 | assert(entry.len > 0); |
| 657 | const start = entry.off + entry.len; | 748 | const start = entry.off + entry.len; |
| 749 | if (sec == &dwarf.debug_frame.section) { | ||
| 750 | const len = if (entry.next.unwrap()) |next_entry| | ||
| 751 | unit.getEntry(next_entry).off - entry.off | ||
| 752 | else | ||
| 753 | entry.len; | ||
| 754 | var unit_len: [8]u8 = undefined; | ||
| 755 | dwarf.writeInt(unit_len[0..dwarf.sectionOffsetBytes()], len - dwarf.unitLengthBytes()); | ||
| 756 | try dwarf.getFile().?.pwriteAll( | ||
| 757 | unit_len[0..dwarf.sectionOffsetBytes()], | ||
| 758 | sec.off + unit.off + unit.header_len + entry.off, | ||
| 759 | ); | ||
| 760 | const buf = try dwarf.gpa.alloc(u8, len - entry.len); | ||
| 761 | defer dwarf.gpa.free(buf); | ||
| 762 | @memset(buf, DW.CFA.nop); | ||
| 763 | try dwarf.getFile().?.pwriteAll(buf, sec.off + unit.off + unit.header_len + start); | ||
| 764 | return; | ||
| 765 | } | ||
| 658 | const len = unit.getEntry(entry.next.unwrap() orelse return).off - start; | 766 | const len = unit.getEntry(entry.next.unwrap() orelse return).off - start; |
| 659 | var buf: [ | 767 | var buf: [ |
| 660 | @max( | 768 | @max( |
| ... | @@ -711,18 +819,20 @@ const Entry = struct { | ... | @@ -711,18 +819,20 @@ const Entry = struct { |
| 711 | try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + unit.off + unit.header_len + start); | 819 | try dwarf.getFile().?.pwriteAll(fbs.getWritten(), sec.off + unit.off + unit.header_len + start); |
| 712 | } | 820 | } |
| 713 | 821 | ||
| 714 | fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | 822 | fn resize(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, len: u32) UpdateError!void { |
| 823 | assert(len > 0); | ||
| 824 | assert(sec.alignment.check(len)); | ||
| 825 | if (entry_ptr.len == len) return; | ||
| 715 | const end = if (entry_ptr.next.unwrap()) |next_entry| | 826 | const end = if (entry_ptr.next.unwrap()) |next_entry| |
| 716 | unit.getEntry(next_entry).off | 827 | unit.getEntry(next_entry).off |
| 717 | else | 828 | else |
| 718 | unit.len -| (unit.header_len + unit.trailer_len); | 829 | unit.len -| (unit.header_len + unit.trailer_len); |
| 719 | if (entry_ptr.off + contents.len > end) { | 830 | if (entry_ptr.off + len > end) { |
| 720 | if (entry_ptr.next.unwrap()) |next_entry| { | 831 | if (entry_ptr.next.unwrap()) |next_entry| { |
| 721 | if (entry_ptr.prev.unwrap()) |prev_entry| { | 832 | if (entry_ptr.prev.unwrap()) |prev_entry| |
| 722 | const prev_entry_ptr = unit.getEntry(prev_entry); | 833 | unit.getEntry(prev_entry).next = entry_ptr.next |
| 723 | prev_entry_ptr.next = entry_ptr.next; | 834 | else |
| 724 | try prev_entry_ptr.pad(unit, sec, dwarf); | 835 | unit.first = entry_ptr.next; |
| 725 | } else unit.first = entry_ptr.next; | ||
| 726 | const next_entry_ptr = unit.getEntry(next_entry); | 836 | const next_entry_ptr = unit.getEntry(next_entry); |
| 727 | const entry = next_entry_ptr.prev; | 837 | const entry = next_entry_ptr.prev; |
| 728 | next_entry_ptr.prev = entry_ptr.prev; | 838 | next_entry_ptr.prev = entry_ptr.prev; |
| ... | @@ -733,12 +843,15 @@ const Entry = struct { | ... | @@ -733,12 +843,15 @@ const Entry = struct { |
| 733 | entry_ptr.off = last_entry_ptr.off + sec.padToIdeal(last_entry_ptr.len); | 843 | entry_ptr.off = last_entry_ptr.off + sec.padToIdeal(last_entry_ptr.len); |
| 734 | unit.last = entry; | 844 | unit.last = entry; |
| 735 | } | 845 | } |
| 736 | try unit.resize(sec, dwarf, 0, @intCast(unit.header_len + entry_ptr.off + sec.padToIdeal(contents.len) + unit.trailer_len)); | 846 | try unit.resize(sec, dwarf, 0, @intCast(unit.header_len + entry_ptr.off + sec.padToIdeal(len) + unit.trailer_len)); |
| 737 | } | 847 | } |
| 738 | entry_ptr.len = @intCast(contents.len); | 848 | entry_ptr.len = len; |
| 739 | if (entry_ptr.prev.unwrap()) |prev_entry| try unit.getEntry(prev_entry).pad(unit, sec, dwarf); | ||
| 740 | try dwarf.getFile().?.pwriteAll(contents, sec.off + unit.off + unit.header_len + entry_ptr.off); | ||
| 741 | try entry_ptr.pad(unit, sec, dwarf); | 849 | try entry_ptr.pad(unit, sec, dwarf); |
| 850 | } | ||
| 851 | |||
| 852 | fn replace(entry_ptr: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf, contents: []const u8) UpdateError!void { | ||
| 853 | assert(contents.len == entry_ptr.len); | ||
| 854 | try dwarf.getFile().?.pwriteAll(contents, sec.off + unit.off + unit.header_len + entry_ptr.off); | ||
| 742 | if (false) { | 855 | if (false) { |
| 743 | const buf = try dwarf.gpa.alloc(u8, sec.len); | 856 | const buf = try dwarf.gpa.alloc(u8, sec.len); |
| 744 | defer dwarf.gpa.free(buf); | 857 | defer dwarf.gpa.free(buf); |
| ... | @@ -844,6 +957,22 @@ const Entry = struct { | ... | @@ -844,6 +957,22 @@ const Entry = struct { |
| 844 | dwarf.sectionOffsetBytes(), | 957 | dwarf.sectionOffsetBytes(), |
| 845 | ); | 958 | ); |
| 846 | } | 959 | } |
| 960 | if (sec == &dwarf.debug_frame.section) switch (DebugFrame.format(dwarf)) { | ||
| 961 | .none, .debug_frame => {}, | ||
| 962 | .eh_frame => return if (dwarf.bin_file.cast(.elf)) |elf_file| { | ||
| 963 | const zo = elf_file.zigObjectPtr().?; | ||
| 964 | const entry_addr: i64 = @intCast(entry_off - sec.off + elf_file.shdrs.items[sec.index].sh_addr); | ||
| 965 | for (entry.external_relocs.items) |reloc| { | ||
| 966 | const symbol = zo.symbol(reloc.target_sym); | ||
| 967 | try dwarf.resolveReloc( | ||
| 968 | entry_off + reloc.source_off, | ||
| 969 | @bitCast((symbol.address(.{}, elf_file) + @as(i64, @intCast(reloc.target_off))) - | ||
| 970 | (entry_addr + reloc.source_off + 4)), | ||
| 971 | 4, | ||
| 972 | ); | ||
| 973 | } | ||
| 974 | } else unreachable, | ||
| 975 | }; | ||
| 847 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 976 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 848 | const zo = elf_file.zigObjectPtr().?; | 977 | const zo = elf_file.zigObjectPtr().?; |
| 849 | for (entry.external_relocs.items) |reloc| { | 978 | for (entry.external_relocs.items) |reloc| { |
| ... | @@ -871,7 +1000,7 @@ const Entry = struct { | ... | @@ -871,7 +1000,7 @@ const Entry = struct { |
| 871 | 1000 | ||
| 872 | const CrossEntryReloc = struct { | 1001 | const CrossEntryReloc = struct { |
| 873 | source_off: u32 = 0, | 1002 | source_off: u32 = 0, |
| 874 | target_entry: Entry.Index, | 1003 | target_entry: Entry.Index.Optional = .none, |
| 875 | target_off: u32 = 0, | 1004 | target_off: u32 = 0, |
| 876 | }; | 1005 | }; |
| 877 | const CrossUnitReloc = struct { | 1006 | const CrossUnitReloc = struct { |
| ... | @@ -937,14 +1066,14 @@ pub const Loc = union(enum) { | ... | @@ -937,14 +1066,14 @@ pub const Loc = union(enum) { |
| 937 | } | 1066 | } |
| 938 | } | 1067 | } |
| 939 | 1068 | ||
| 940 | fn write(loc: Loc, wip: anytype) UpdateError!void { | 1069 | fn write(loc: Loc, adapter: anytype) UpdateError!void { |
| 941 | const writer = wip.infoWriter(); | 1070 | const writer = adapter.writer(); |
| 942 | switch (loc) { | 1071 | switch (loc) { |
| 943 | .empty => unreachable, | 1072 | .empty => {}, |
| 944 | .addr => |addr| { | 1073 | .addr => |addr| { |
| 945 | try writer.writeByte(DW.OP.addr); | 1074 | try writer.writeByte(DW.OP.addr); |
| 946 | switch (addr) { | 1075 | switch (addr) { |
| 947 | .sym => |sym_index| try wip.addrSym(sym_index), | 1076 | .sym => |sym_index| try adapter.addrSym(sym_index), |
| 948 | } | 1077 | } |
| 949 | }, | 1078 | }, |
| 950 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { | 1079 | .constu => |constu| if (std.math.cast(u5, constu)) |lit| { |
| ... | @@ -953,45 +1082,45 @@ pub const Loc = union(enum) { | ... | @@ -953,45 +1082,45 @@ pub const Loc = union(enum) { |
| 953 | try writer.writeAll(&.{ DW.OP.const1u, const1u }); | 1082 | try writer.writeAll(&.{ DW.OP.const1u, const1u }); |
| 954 | } else if (std.math.cast(u16, constu)) |const2u| { | 1083 | } else if (std.math.cast(u16, constu)) |const2u| { |
| 955 | try writer.writeByte(DW.OP.const2u); | 1084 | try writer.writeByte(DW.OP.const2u); |
| 956 | try writer.writeInt(u16, const2u, wip.dwarf.endian); | 1085 | try writer.writeInt(u16, const2u, adapter.endian()); |
| 957 | } else if (std.math.cast(u21, constu)) |const3u| { | 1086 | } else if (std.math.cast(u21, constu)) |const3u| { |
| 958 | try writer.writeByte(DW.OP.constu); | 1087 | try writer.writeByte(DW.OP.constu); |
| 959 | try uleb128(writer, const3u); | 1088 | try uleb128(writer, const3u); |
| 960 | } else if (std.math.cast(u32, constu)) |const4u| { | 1089 | } else if (std.math.cast(u32, constu)) |const4u| { |
| 961 | try writer.writeByte(DW.OP.const4u); | 1090 | try writer.writeByte(DW.OP.const4u); |
| 962 | try writer.writeInt(u32, const4u, wip.dwarf.endian); | 1091 | try writer.writeInt(u32, const4u, adapter.endian()); |
| 963 | } else if (std.math.cast(u49, constu)) |const7u| { | 1092 | } else if (std.math.cast(u49, constu)) |const7u| { |
| 964 | try writer.writeByte(DW.OP.constu); | 1093 | try writer.writeByte(DW.OP.constu); |
| 965 | try uleb128(writer, const7u); | 1094 | try uleb128(writer, const7u); |
| 966 | } else { | 1095 | } else { |
| 967 | try writer.writeByte(DW.OP.const8u); | 1096 | try writer.writeByte(DW.OP.const8u); |
| 968 | try writer.writeInt(u64, constu, wip.dwarf.endian); | 1097 | try writer.writeInt(u64, constu, adapter.endian()); |
| 969 | }, | 1098 | }, |
| 970 | .consts => |consts| if (std.math.cast(i8, consts)) |const1s| { | 1099 | .consts => |consts| if (std.math.cast(i8, consts)) |const1s| { |
| 971 | try writer.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); | 1100 | try writer.writeAll(&.{ DW.OP.const1s, @bitCast(const1s) }); |
| 972 | } else if (std.math.cast(i16, consts)) |const2s| { | 1101 | } else if (std.math.cast(i16, consts)) |const2s| { |
| 973 | try writer.writeByte(DW.OP.const2s); | 1102 | try writer.writeByte(DW.OP.const2s); |
| 974 | try writer.writeInt(i16, const2s, wip.dwarf.endian); | 1103 | try writer.writeInt(i16, const2s, adapter.endian()); |
| 975 | } else if (std.math.cast(i21, consts)) |const3s| { | 1104 | } else if (std.math.cast(i21, consts)) |const3s| { |
| 976 | try writer.writeByte(DW.OP.consts); | 1105 | try writer.writeByte(DW.OP.consts); |
| 977 | try sleb128(writer, const3s); | 1106 | try sleb128(writer, const3s); |
| 978 | } else if (std.math.cast(i32, consts)) |const4s| { | 1107 | } else if (std.math.cast(i32, consts)) |const4s| { |
| 979 | try writer.writeByte(DW.OP.const4s); | 1108 | try writer.writeByte(DW.OP.const4s); |
| 980 | try writer.writeInt(i32, const4s, wip.dwarf.endian); | 1109 | try writer.writeInt(i32, const4s, adapter.endian()); |
| 981 | } else if (std.math.cast(i49, consts)) |const7s| { | 1110 | } else if (std.math.cast(i49, consts)) |const7s| { |
| 982 | try writer.writeByte(DW.OP.consts); | 1111 | try writer.writeByte(DW.OP.consts); |
| 983 | try sleb128(writer, const7s); | 1112 | try sleb128(writer, const7s); |
| 984 | } else { | 1113 | } else { |
| 985 | try writer.writeByte(DW.OP.const8s); | 1114 | try writer.writeByte(DW.OP.const8s); |
| 986 | try writer.writeInt(i64, consts, wip.dwarf.endian); | 1115 | try writer.writeInt(i64, consts, adapter.endian()); |
| 987 | }, | 1116 | }, |
| 988 | .plus => |plus| done: { | 1117 | .plus => |plus| done: { |
| 989 | if (plus[0].getConst(u0)) |_| { | 1118 | if (plus[0].getConst(u0)) |_| { |
| 990 | try plus[1].write(wip); | 1119 | try plus[1].write(adapter); |
| 991 | break :done; | 1120 | break :done; |
| 992 | } | 1121 | } |
| 993 | if (plus[1].getConst(u0)) |_| { | 1122 | if (plus[1].getConst(u0)) |_| { |
| 994 | try plus[0].write(wip); | 1123 | try plus[0].write(adapter); |
| 995 | break :done; | 1124 | break :done; |
| 996 | } | 1125 | } |
| 997 | if (plus[0].getBaseReg()) |breg| { | 1126 | if (plus[0].getBaseReg()) |breg| { |
| ... | @@ -1009,19 +1138,19 @@ pub const Loc = union(enum) { | ... | @@ -1009,19 +1138,19 @@ pub const Loc = union(enum) { |
| 1009 | } | 1138 | } |
| 1010 | } | 1139 | } |
| 1011 | if (plus[0].getConst(u64)) |uconst| { | 1140 | if (plus[0].getConst(u64)) |uconst| { |
| 1012 | try plus[1].write(wip); | 1141 | try plus[1].write(adapter); |
| 1013 | try writer.writeByte(DW.OP.plus_uconst); | 1142 | try writer.writeByte(DW.OP.plus_uconst); |
| 1014 | try uleb128(writer, uconst); | 1143 | try uleb128(writer, uconst); |
| 1015 | break :done; | 1144 | break :done; |
| 1016 | } | 1145 | } |
| 1017 | if (plus[1].getConst(u64)) |uconst| { | 1146 | if (plus[1].getConst(u64)) |uconst| { |
| 1018 | try plus[0].write(wip); | 1147 | try plus[0].write(adapter); |
| 1019 | try writer.writeByte(DW.OP.plus_uconst); | 1148 | try writer.writeByte(DW.OP.plus_uconst); |
| 1020 | try uleb128(writer, uconst); | 1149 | try uleb128(writer, uconst); |
| 1021 | break :done; | 1150 | break :done; |
| 1022 | } | 1151 | } |
| 1023 | try plus[0].write(wip); | 1152 | try plus[0].write(adapter); |
| 1024 | try plus[1].write(wip); | 1153 | try plus[1].write(adapter); |
| 1025 | try writer.writeByte(DW.OP.plus); | 1154 | try writer.writeByte(DW.OP.plus); |
| 1026 | }, | 1155 | }, |
| 1027 | .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, writer), | 1156 | .reg => |reg| try writeReg(reg, DW.OP.reg0, DW.OP.regx, writer), |
| ... | @@ -1031,7 +1160,7 @@ pub const Loc = union(enum) { | ... | @@ -1031,7 +1160,7 @@ pub const Loc = union(enum) { |
| 1031 | }, | 1160 | }, |
| 1032 | .push_object_address => try writer.writeByte(DW.OP.push_object_address), | 1161 | .push_object_address => try writer.writeByte(DW.OP.push_object_address), |
| 1033 | .form_tls_address => |addr| { | 1162 | .form_tls_address => |addr| { |
| 1034 | try addr.write(wip); | 1163 | try addr.write(adapter); |
| 1035 | try writer.writeByte(DW.OP.form_tls_address); | 1164 | try writer.writeByte(DW.OP.form_tls_address); |
| 1036 | }, | 1165 | }, |
| 1037 | .implicit_value => |value| { | 1166 | .implicit_value => |value| { |
| ... | @@ -1040,7 +1169,7 @@ pub const Loc = union(enum) { | ... | @@ -1040,7 +1169,7 @@ pub const Loc = union(enum) { |
| 1040 | try writer.writeAll(value); | 1169 | try writer.writeAll(value); |
| 1041 | }, | 1170 | }, |
| 1042 | .stack_value => |value| { | 1171 | .stack_value => |value| { |
| 1043 | try value.write(wip); | 1172 | try value.write(adapter); |
| 1044 | try writer.writeByte(DW.OP.stack_value); | 1173 | try writer.writeByte(DW.OP.stack_value); |
| 1045 | }, | 1174 | }, |
| 1046 | .wasm_ext => |wasm_ext| { | 1175 | .wasm_ext => |wasm_ext| { |
| ... | @@ -1055,7 +1184,7 @@ pub const Loc = union(enum) { | ... | @@ -1055,7 +1184,7 @@ pub const Loc = union(enum) { |
| 1055 | try uleb128(writer, global_u21); | 1184 | try uleb128(writer, global_u21); |
| 1056 | } else { | 1185 | } else { |
| 1057 | try writer.writeByte(DW.OP.WASM_global_u32); | 1186 | try writer.writeByte(DW.OP.WASM_global_u32); |
| 1058 | try writer.writeInt(u32, global, wip.dwarf.endian); | 1187 | try writer.writeInt(u32, global, adapter.endian()); |
| 1059 | }, | 1188 | }, |
| 1060 | .operand_stack => |operand_stack| { | 1189 | .operand_stack => |operand_stack| { |
| 1061 | try writer.writeByte(DW.OP.WASM_operand_stack); | 1190 | try writer.writeByte(DW.OP.WASM_operand_stack); |
| ... | @@ -1067,6 +1196,153 @@ pub const Loc = union(enum) { | ... | @@ -1067,6 +1196,153 @@ pub const Loc = union(enum) { |
| 1067 | } | 1196 | } |
| 1068 | }; | 1197 | }; |
| 1069 | 1198 | ||
| 1199 | pub const Cfa = union(enum) { | ||
| 1200 | nop, | ||
| 1201 | advance_loc: u32, | ||
| 1202 | offset: RegOff, | ||
| 1203 | rel_offset: RegOff, | ||
| 1204 | restore: u32, | ||
| 1205 | undefined: u32, | ||
| 1206 | same_value: u32, | ||
| 1207 | register: [2]u32, | ||
| 1208 | remember_state, | ||
| 1209 | restore_state, | ||
| 1210 | def_cfa: RegOff, | ||
| 1211 | def_cfa_register: u32, | ||
| 1212 | def_cfa_offset: i64, | ||
| 1213 | adjust_cfa_offset: i64, | ||
| 1214 | def_cfa_expression: Loc, | ||
| 1215 | expression: RegExpr, | ||
| 1216 | val_offset: RegOff, | ||
| 1217 | val_expression: RegExpr, | ||
| 1218 | escape: []const u8, | ||
| 1219 | |||
| 1220 | const RegOff = struct { reg: u32, off: i64 }; | ||
| 1221 | const RegExpr = struct { reg: u32, expr: Loc }; | ||
| 1222 | |||
| 1223 | fn write(cfa: Cfa, wip_nav: *WipNav) UpdateError!void { | ||
| 1224 | const writer = wip_nav.debug_frame.writer(wip_nav.dwarf.gpa); | ||
| 1225 | switch (cfa) { | ||
| 1226 | .nop => try writer.writeByte(DW.CFA.nop), | ||
| 1227 | .advance_loc => |loc| { | ||
| 1228 | const delta = @divExact(loc - wip_nav.cfi.loc, wip_nav.dwarf.debug_frame.header.code_alignment_factor); | ||
| 1229 | if (delta == 0) {} else if (std.math.cast(u6, delta)) |small_delta| | ||
| 1230 | try writer.writeByte(@as(u8, DW.CFA.advance_loc) + small_delta) | ||
| 1231 | else if (std.math.cast(u8, delta)) |ubyte_delta| | ||
| 1232 | try writer.writeAll(&.{ DW.CFA.advance_loc1, ubyte_delta }) | ||
| 1233 | else if (std.math.cast(u16, delta)) |uhalf_delta| { | ||
| 1234 | try writer.writeByte(DW.CFA.advance_loc2); | ||
| 1235 | try writer.writeInt(u16, uhalf_delta, wip_nav.dwarf.endian); | ||
| 1236 | } else if (std.math.cast(u32, delta)) |uword_delta| { | ||
| 1237 | try writer.writeByte(DW.CFA.advance_loc4); | ||
| 1238 | try writer.writeInt(u32, uword_delta, wip_nav.dwarf.endian); | ||
| 1239 | } | ||
| 1240 | wip_nav.cfi.loc = loc; | ||
| 1241 | }, | ||
| 1242 | .offset, .rel_offset => |reg_off| { | ||
| 1243 | const factored_off = @divExact(reg_off.off - switch (cfa) { | ||
| 1244 | else => unreachable, | ||
| 1245 | .offset => 0, | ||
| 1246 | .rel_offset => wip_nav.cfi.cfa.off, | ||
| 1247 | }, wip_nav.dwarf.debug_frame.header.data_alignment_factor); | ||
| 1248 | if (std.math.cast(u63, factored_off)) |unsigned_off| { | ||
| 1249 | if (std.math.cast(u6, reg_off.reg)) |small_reg| { | ||
| 1250 | try writer.writeByte(@as(u8, DW.CFA.offset) + small_reg); | ||
| 1251 | } else { | ||
| 1252 | try writer.writeByte(DW.CFA.offset_extended); | ||
| 1253 | try uleb128(writer, reg_off.reg); | ||
| 1254 | } | ||
| 1255 | try uleb128(writer, unsigned_off); | ||
| 1256 | } else { | ||
| 1257 | try writer.writeByte(DW.CFA.offset_extended_sf); | ||
| 1258 | try uleb128(writer, reg_off.reg); | ||
| 1259 | try sleb128(writer, factored_off); | ||
| 1260 | } | ||
| 1261 | }, | ||
| 1262 | .restore => |reg| if (std.math.cast(u6, reg)) |small_reg| | ||
| 1263 | try writer.writeByte(@as(u8, DW.CFA.restore) + small_reg) | ||
| 1264 | else { | ||
| 1265 | try writer.writeByte(DW.CFA.restore_extended); | ||
| 1266 | try uleb128(writer, reg); | ||
| 1267 | }, | ||
| 1268 | .undefined => |reg| { | ||
| 1269 | try writer.writeByte(DW.CFA.undefined); | ||
| 1270 | try uleb128(writer, reg); | ||
| 1271 | }, | ||
| 1272 | .same_value => |reg| { | ||
| 1273 | try writer.writeByte(DW.CFA.same_value); | ||
| 1274 | try uleb128(writer, reg); | ||
| 1275 | }, | ||
| 1276 | .register => |regs| if (regs[0] != regs[1]) { | ||
| 1277 | try writer.writeByte(DW.CFA.register); | ||
| 1278 | for (regs) |reg| try uleb128(writer, reg); | ||
| 1279 | } else { | ||
| 1280 | try writer.writeByte(DW.CFA.same_value); | ||
| 1281 | try uleb128(writer, regs[0]); | ||
| 1282 | }, | ||
| 1283 | .remember_state => try writer.writeByte(DW.CFA.remember_state), | ||
| 1284 | .restore_state => try writer.writeByte(DW.CFA.restore_state), | ||
| 1285 | .def_cfa, .def_cfa_register, .def_cfa_offset, .adjust_cfa_offset => { | ||
| 1286 | const reg_off: RegOff = switch (cfa) { | ||
| 1287 | else => unreachable, | ||
| 1288 | .def_cfa => |reg_off| reg_off, | ||
| 1289 | .def_cfa_register => |reg| .{ .reg = reg, .off = wip_nav.cfi.cfa.off }, | ||
| 1290 | .def_cfa_offset => |off| .{ .reg = wip_nav.cfi.cfa.reg, .off = off }, | ||
| 1291 | .adjust_cfa_offset => |off| .{ .reg = wip_nav.cfi.cfa.reg, .off = wip_nav.cfi.cfa.off + off }, | ||
| 1292 | }; | ||
| 1293 | const changed_reg = reg_off.reg != wip_nav.cfi.cfa.reg; | ||
| 1294 | const unsigned_off = std.math.cast(u63, reg_off.off); | ||
| 1295 | if (reg_off.off == wip_nav.cfi.cfa.off) { | ||
| 1296 | if (changed_reg) { | ||
| 1297 | try writer.writeByte(DW.CFA.def_cfa_register); | ||
| 1298 | try uleb128(writer, reg_off.reg); | ||
| 1299 | } | ||
| 1300 | } else if (switch (wip_nav.dwarf.debug_frame.header.data_alignment_factor) { | ||
| 1301 | 0 => unreachable, | ||
| 1302 | 1 => unsigned_off != null, | ||
| 1303 | else => |data_alignment_factor| @rem(reg_off.off, data_alignment_factor) != 0, | ||
| 1304 | }) { | ||
| 1305 | try writer.writeByte(if (changed_reg) DW.CFA.def_cfa else DW.CFA.def_cfa_offset); | ||
| 1306 | if (changed_reg) try uleb128(writer, reg_off.reg); | ||
| 1307 | try uleb128(writer, unsigned_off.?); | ||
| 1308 | } else { | ||
| 1309 | try writer.writeByte(if (changed_reg) DW.CFA.def_cfa_sf else DW.CFA.def_cfa_offset_sf); | ||
| 1310 | if (changed_reg) try uleb128(writer, reg_off.reg); | ||
| 1311 | try sleb128(writer, @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor)); | ||
| 1312 | } | ||
| 1313 | wip_nav.cfi.cfa = reg_off; | ||
| 1314 | }, | ||
| 1315 | .def_cfa_expression => |expr| { | ||
| 1316 | try writer.writeByte(DW.CFA.def_cfa_expression); | ||
| 1317 | try wip_nav.frameExprloc(expr); | ||
| 1318 | }, | ||
| 1319 | .expression => |reg_expr| { | ||
| 1320 | try writer.writeByte(DW.CFA.expression); | ||
| 1321 | try uleb128(writer, reg_expr.reg); | ||
| 1322 | try wip_nav.frameExprloc(reg_expr.expr); | ||
| 1323 | }, | ||
| 1324 | .val_offset => |reg_off| { | ||
| 1325 | const factored_off = @divExact(reg_off.off, wip_nav.dwarf.debug_frame.header.data_alignment_factor); | ||
| 1326 | if (std.math.cast(u63, factored_off)) |unsigned_off| { | ||
| 1327 | try writer.writeByte(DW.CFA.val_offset); | ||
| 1328 | try uleb128(writer, reg_off.reg); | ||
| 1329 | try uleb128(writer, unsigned_off); | ||
| 1330 | } else { | ||
| 1331 | try writer.writeByte(DW.CFA.val_offset_sf); | ||
| 1332 | try uleb128(writer, reg_off.reg); | ||
| 1333 | try sleb128(writer, factored_off); | ||
| 1334 | } | ||
| 1335 | }, | ||
| 1336 | .val_expression => |reg_expr| { | ||
| 1337 | try writer.writeByte(DW.CFA.val_expression); | ||
| 1338 | try uleb128(writer, reg_expr.reg); | ||
| 1339 | try wip_nav.frameExprloc(reg_expr.expr); | ||
| 1340 | }, | ||
| 1341 | .escape => |bytes| try writer.writeAll(bytes), | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | }; | ||
| 1345 | |||
| 1070 | pub const WipNav = struct { | 1346 | pub const WipNav = struct { |
| 1071 | dwarf: *Dwarf, | 1347 | dwarf: *Dwarf, |
| 1072 | pt: Zcu.PerThread, | 1348 | pt: Zcu.PerThread, |
| ... | @@ -1080,6 +1356,11 @@ pub const WipNav = struct { | ... | @@ -1080,6 +1356,11 @@ pub const WipNav = struct { |
| 1080 | abbrev_code: u32, | 1356 | abbrev_code: u32, |
| 1081 | high_reloc: u32, | 1357 | high_reloc: u32, |
| 1082 | }), | 1358 | }), |
| 1359 | cfi: struct { | ||
| 1360 | loc: u32, | ||
| 1361 | cfa: Cfa.RegOff, | ||
| 1362 | }, | ||
| 1363 | debug_frame: std.ArrayListUnmanaged(u8), | ||
| 1083 | debug_info: std.ArrayListUnmanaged(u8), | 1364 | debug_info: std.ArrayListUnmanaged(u8), |
| 1084 | debug_line: std.ArrayListUnmanaged(u8), | 1365 | debug_line: std.ArrayListUnmanaged(u8), |
| 1085 | debug_loclists: std.ArrayListUnmanaged(u8), | 1366 | debug_loclists: std.ArrayListUnmanaged(u8), |
| ... | @@ -1088,14 +1369,19 @@ pub const WipNav = struct { | ... | @@ -1088,14 +1369,19 @@ pub const WipNav = struct { |
| 1088 | pub fn deinit(wip_nav: *WipNav) void { | 1369 | pub fn deinit(wip_nav: *WipNav) void { |
| 1089 | const gpa = wip_nav.dwarf.gpa; | 1370 | const gpa = wip_nav.dwarf.gpa; |
| 1090 | if (wip_nav.func != .none) wip_nav.inlined_funcs.deinit(gpa); | 1371 | if (wip_nav.func != .none) wip_nav.inlined_funcs.deinit(gpa); |
| 1372 | wip_nav.debug_frame.deinit(gpa); | ||
| 1091 | wip_nav.debug_info.deinit(gpa); | 1373 | wip_nav.debug_info.deinit(gpa); |
| 1092 | wip_nav.debug_line.deinit(gpa); | 1374 | wip_nav.debug_line.deinit(gpa); |
| 1093 | wip_nav.debug_loclists.deinit(gpa); | 1375 | wip_nav.debug_loclists.deinit(gpa); |
| 1094 | wip_nav.pending_types.deinit(gpa); | 1376 | wip_nav.pending_types.deinit(gpa); |
| 1095 | } | 1377 | } |
| 1096 | 1378 | ||
| 1097 | pub fn infoWriter(wip_nav: *WipNav) std.ArrayListUnmanaged(u8).Writer { | 1379 | pub fn genDebugFrame(wip_nav: *WipNav, loc: u32, cfa: Cfa) UpdateError!void { |
| 1098 | return wip_nav.debug_info.writer(wip_nav.dwarf.gpa); | 1380 | assert(wip_nav.func != .none); |
| 1381 | if (wip_nav.dwarf.debug_frame.header.format == .none) return; | ||
| 1382 | const loc_cfa: Cfa = .{ .advance_loc = loc }; | ||
| 1383 | try loc_cfa.write(wip_nav); | ||
| 1384 | try cfa.write(wip_nav); | ||
| 1099 | } | 1385 | } |
| 1100 | 1386 | ||
| 1101 | pub const LocalTag = enum { local_arg, local_var }; | 1387 | pub const LocalTag = enum { local_arg, local_var }; |
| ... | @@ -1301,7 +1587,7 @@ pub const WipNav = struct { | ... | @@ -1301,7 +1587,7 @@ pub const WipNav = struct { |
| 1301 | } else { | 1587 | } else { |
| 1302 | try entry_ptr.cross_entry_relocs.append(gpa, .{ | 1588 | try entry_ptr.cross_entry_relocs.append(gpa, .{ |
| 1303 | .source_off = @intCast(wip_nav.debug_info.items.len), | 1589 | .source_off = @intCast(wip_nav.debug_info.items.len), |
| 1304 | .target_entry = entry, | 1590 | .target_entry = entry.toOptional(), |
| 1305 | .target_off = off, | 1591 | .target_off = off, |
| 1306 | }); | 1592 | }); |
| 1307 | } | 1593 | } |
| ... | @@ -1312,7 +1598,45 @@ pub const WipNav = struct { | ... | @@ -1312,7 +1598,45 @@ pub const WipNav = struct { |
| 1312 | try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0); | 1598 | try wip_nav.infoSectionOffset(.debug_str, StringSection.unit, try wip_nav.dwarf.debug_str.addString(wip_nav.dwarf, str), 0); |
| 1313 | } | 1599 | } |
| 1314 | 1600 | ||
| 1315 | fn addrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void { | 1601 | const ExprLocCounter = struct { |
| 1602 | const Stream = std.io.CountingWriter(std.io.NullWriter); | ||
| 1603 | stream: Stream, | ||
| 1604 | address_size: AddressSize, | ||
| 1605 | fn writer(counter: *ExprLocCounter) Stream.Writer { | ||
| 1606 | return counter.stream.writer(); | ||
| 1607 | } | ||
| 1608 | fn endian(_: ExprLocCounter) std.builtin.Endian { | ||
| 1609 | return @import("builtin").cpu.arch.endian(); | ||
| 1610 | } | ||
| 1611 | fn addrSym(counter: *ExprLocCounter, _: u32) error{}!void { | ||
| 1612 | counter.stream.bytes_written += @intFromEnum(counter.address_size); | ||
| 1613 | } | ||
| 1614 | }; | ||
| 1615 | |||
| 1616 | fn exprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { | ||
| 1617 | var counter: ExprLocCounter = .{ | ||
| 1618 | .stream = std.io.countingWriter(std.io.null_writer), | ||
| 1619 | .address_size = wip_nav.dwarf.address_size, | ||
| 1620 | }; | ||
| 1621 | try loc.write(&counter); | ||
| 1622 | |||
| 1623 | const adapter: struct { | ||
| 1624 | wip_nav: *WipNav, | ||
| 1625 | fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { | ||
| 1626 | return ctx.wip_nav.debug_info.writer(ctx.wip_nav.dwarf.gpa); | ||
| 1627 | } | ||
| 1628 | fn endian(ctx: @This()) std.builtin.Endian { | ||
| 1629 | return ctx.wip_nav.dwarf.endian; | ||
| 1630 | } | ||
| 1631 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { | ||
| 1632 | try ctx.wip_nav.infoAddrSym(sym_index); | ||
| 1633 | } | ||
| 1634 | } = .{ .wip_nav = wip_nav }; | ||
| 1635 | try uleb128(adapter.writer(), counter.stream.bytes_written); | ||
| 1636 | try loc.write(adapter); | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | fn infoAddrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void { | ||
| 1316 | const dwarf = wip_nav.dwarf; | 1640 | const dwarf = wip_nav.dwarf; |
| 1317 | try dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ | 1641 | try dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ |
| 1318 | .source_off = @intCast(wip_nav.debug_info.items.len), | 1642 | .source_off = @intCast(wip_nav.debug_info.items.len), |
| ... | @@ -1321,25 +1645,36 @@ pub const WipNav = struct { | ... | @@ -1321,25 +1645,36 @@ pub const WipNav = struct { |
| 1321 | try wip_nav.debug_info.appendNTimes(dwarf.gpa, 0, @intFromEnum(dwarf.address_size)); | 1645 | try wip_nav.debug_info.appendNTimes(dwarf.gpa, 0, @intFromEnum(dwarf.address_size)); |
| 1322 | } | 1646 | } |
| 1323 | 1647 | ||
| 1324 | fn exprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { | 1648 | fn frameExprloc(wip_nav: *WipNav, loc: Loc) UpdateError!void { |
| 1325 | if (loc == .empty) return; | 1649 | var counter: ExprLocCounter = .{ |
| 1326 | var wip: struct { | 1650 | .stream = std.io.countingWriter(std.io.null_writer), |
| 1327 | const Info = std.io.CountingWriter(std.io.NullWriter); | 1651 | .address_size = wip_nav.dwarf.address_size, |
| 1328 | dwarf: *Dwarf, | 1652 | }; |
| 1329 | debug_info: Info, | 1653 | try loc.write(&counter); |
| 1330 | fn infoWriter(wip: *@This()) Info.Writer { | 1654 | |
| 1331 | return wip.debug_info.writer(); | 1655 | const adapter: struct { |
| 1656 | wip_nav: *WipNav, | ||
| 1657 | fn writer(ctx: @This()) std.ArrayListUnmanaged(u8).Writer { | ||
| 1658 | return ctx.wip_nav.debug_frame.writer(ctx.wip_nav.dwarf.gpa); | ||
| 1332 | } | 1659 | } |
| 1333 | fn addrSym(wip: *@This(), _: u32) error{}!void { | 1660 | fn endian(ctx: @This()) std.builtin.Endian { |
| 1334 | wip.debug_info.bytes_written += @intFromEnum(wip.dwarf.address_size); | 1661 | return ctx.wip_nav.dwarf.endian; |
| 1335 | } | 1662 | } |
| 1336 | } = .{ | 1663 | fn addrSym(ctx: @This(), sym_index: u32) UpdateError!void { |
| 1337 | .dwarf = wip_nav.dwarf, | 1664 | try ctx.wip_nav.frameAddrSym(sym_index); |
| 1338 | .debug_info = std.io.countingWriter(std.io.null_writer), | 1665 | } |
| 1339 | }; | 1666 | } = .{ .wip_nav = wip_nav }; |
| 1340 | try loc.write(&wip); | 1667 | try uleb128(adapter.writer(), counter.stream.bytes_written); |
| 1341 | try uleb128(wip_nav.debug_info.writer(wip_nav.dwarf.gpa), wip.debug_info.bytes_written); | 1668 | try loc.write(adapter); |
| 1342 | try loc.write(wip_nav); | 1669 | } |
| 1670 | |||
| 1671 | fn frameAddrSym(wip_nav: *WipNav, sym_index: u32) UpdateError!void { | ||
| 1672 | const dwarf = wip_nav.dwarf; | ||
| 1673 | try dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ | ||
| 1674 | .source_off = @intCast(wip_nav.debug_frame.items.len), | ||
| 1675 | .target_sym = sym_index, | ||
| 1676 | }); | ||
| 1677 | try wip_nav.debug_frame.appendNTimes(dwarf.gpa, 0, @intFromEnum(dwarf.address_size)); | ||
| 1343 | } | 1678 | } |
| 1344 | 1679 | ||
| 1345 | fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } { | 1680 | fn getTypeEntry(wip_nav: *WipNav, ty: Type) UpdateError!struct { Unit.Index, Entry.Index } { |
| ... | @@ -1387,7 +1722,7 @@ pub const WipNav = struct { | ... | @@ -1387,7 +1722,7 @@ pub const WipNav = struct { |
| 1387 | 1722 | ||
| 1388 | fn finishForward(wip_nav: *WipNav, reloc_index: u32) void { | 1723 | fn finishForward(wip_nav: *WipNav, reloc_index: u32) void { |
| 1389 | const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index]; | 1724 | const reloc = &wip_nav.dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).cross_entry_relocs.items[reloc_index]; |
| 1390 | reloc.target_entry = wip_nav.entry; | 1725 | reloc.target_entry = wip_nav.entry.toOptional(); |
| 1391 | reloc.target_off = @intCast(wip_nav.debug_info.items.len); | 1726 | reloc.target_off = @intCast(wip_nav.debug_info.items.len); |
| 1392 | } | 1727 | } |
| 1393 | 1728 | ||
| ... | @@ -1490,6 +1825,28 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { | ... | @@ -1490,6 +1825,28 @@ pub fn init(lf: *link.File, format: DW.Format) Dwarf { |
| 1490 | 1825 | ||
| 1491 | .debug_abbrev = .{ .section = Section.init }, | 1826 | .debug_abbrev = .{ .section = Section.init }, |
| 1492 | .debug_aranges = .{ .section = Section.init }, | 1827 | .debug_aranges = .{ .section = Section.init }, |
| 1828 | .debug_frame = .{ | ||
| 1829 | .header = if (target.cpu.arch == .x86_64 and target.ofmt == .elf) header: { | ||
| 1830 | const Register = @import("../arch/x86_64/bits.zig").Register; | ||
| 1831 | break :header comptime .{ | ||
| 1832 | .format = .eh_frame, | ||
| 1833 | .code_alignment_factor = 1, | ||
| 1834 | .data_alignment_factor = -8, | ||
| 1835 | .return_address_register = Register.rip.dwarfNum(), | ||
| 1836 | .initial_instructions = &.{ | ||
| 1837 | .{ .def_cfa = .{ .reg = Register.rsp.dwarfNum(), .off = 8 } }, | ||
| 1838 | .{ .offset = .{ .reg = Register.rip.dwarfNum(), .off = -8 } }, | ||
| 1839 | }, | ||
| 1840 | }; | ||
| 1841 | } else .{ | ||
| 1842 | .format = .none, | ||
| 1843 | .code_alignment_factor = undefined, | ||
| 1844 | .data_alignment_factor = undefined, | ||
| 1845 | .return_address_register = undefined, | ||
| 1846 | .initial_instructions = &.{}, | ||
| 1847 | }, | ||
| 1848 | .section = Section.init, | ||
| 1849 | }, | ||
| 1493 | .debug_info = .{ .section = Section.init }, | 1850 | .debug_info = .{ .section = Section.init }, |
| 1494 | .debug_line = .{ | 1851 | .debug_line = .{ |
| 1495 | .header = switch (target.cpu.arch) { | 1852 | .header = switch (target.cpu.arch) { |
| ... | @@ -1524,6 +1881,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1524,6 +1881,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1524 | for ([_]*Section{ | 1881 | for ([_]*Section{ |
| 1525 | &dwarf.debug_abbrev.section, | 1882 | &dwarf.debug_abbrev.section, |
| 1526 | &dwarf.debug_aranges.section, | 1883 | &dwarf.debug_aranges.section, |
| 1884 | &dwarf.debug_frame.section, | ||
| 1527 | &dwarf.debug_info.section, | 1885 | &dwarf.debug_info.section, |
| 1528 | &dwarf.debug_line.section, | 1886 | &dwarf.debug_line.section, |
| 1529 | &dwarf.debug_line_str.section, | 1887 | &dwarf.debug_line_str.section, |
| ... | @@ -1533,6 +1891,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1533,6 +1891,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1533 | }, [_]u32{ | 1891 | }, [_]u32{ |
| 1534 | elf_file.debug_abbrev_section_index.?, | 1892 | elf_file.debug_abbrev_section_index.?, |
| 1535 | elf_file.debug_aranges_section_index.?, | 1893 | elf_file.debug_aranges_section_index.?, |
| 1894 | elf_file.eh_frame_section_index.?, | ||
| 1536 | elf_file.debug_info_section_index.?, | 1895 | elf_file.debug_info_section_index.?, |
| 1537 | elf_file.debug_line_section_index.?, | 1896 | elf_file.debug_line_section_index.?, |
| 1538 | elf_file.debug_line_str_section_index.?, | 1897 | elf_file.debug_line_str_section_index.?, |
| ... | @@ -1612,6 +1971,12 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { | ... | @@ -1612,6 +1971,12 @@ pub fn initMetadata(dwarf: *Dwarf) UpdateError!void { |
| 1612 | dwarf.debug_aranges.section.pad_to_ideal = false; | 1971 | dwarf.debug_aranges.section.pad_to_ideal = false; |
| 1613 | dwarf.debug_aranges.section.alignment = InternPool.Alignment.fromNonzeroByteUnits(@intFromEnum(dwarf.address_size) * 2); | 1972 | dwarf.debug_aranges.section.alignment = InternPool.Alignment.fromNonzeroByteUnits(@intFromEnum(dwarf.address_size) * 2); |
| 1614 | 1973 | ||
| 1974 | dwarf.debug_frame.section.alignment = switch (dwarf.debug_frame.header.format) { | ||
| 1975 | .none => .@"1", | ||
| 1976 | .debug_frame => InternPool.Alignment.fromNonzeroByteUnits(@intFromEnum(dwarf.address_size)), | ||
| 1977 | .eh_frame => .@"4", | ||
| 1978 | }; | ||
| 1979 | |||
| 1615 | dwarf.debug_line_str.section.pad_to_ideal = false; | 1980 | dwarf.debug_line_str.section.pad_to_ideal = false; |
| 1616 | assert(try dwarf.debug_line_str.section.addUnit(0, 0, dwarf) == StringSection.unit); | 1981 | assert(try dwarf.debug_line_str.section.addUnit(0, 0, dwarf) == StringSection.unit); |
| 1617 | errdefer dwarf.debug_line_str.section.popUnit(dwarf.gpa); | 1982 | errdefer dwarf.debug_line_str.section.popUnit(dwarf.gpa); |
| ... | @@ -1633,6 +1998,7 @@ pub fn deinit(dwarf: *Dwarf) void { | ... | @@ -1633,6 +1998,7 @@ pub fn deinit(dwarf: *Dwarf) void { |
| 1633 | dwarf.navs.deinit(gpa); | 1998 | dwarf.navs.deinit(gpa); |
| 1634 | dwarf.debug_abbrev.section.deinit(gpa); | 1999 | dwarf.debug_abbrev.section.deinit(gpa); |
| 1635 | dwarf.debug_aranges.section.deinit(gpa); | 2000 | dwarf.debug_aranges.section.deinit(gpa); |
| 2001 | dwarf.debug_frame.section.deinit(gpa); | ||
| 1636 | dwarf.debug_info.section.deinit(gpa); | 2002 | dwarf.debug_info.section.deinit(gpa); |
| 1637 | dwarf.debug_line.section.deinit(gpa); | 2003 | dwarf.debug_line.section.deinit(gpa); |
| 1638 | dwarf.debug_line_str.deinit(gpa); | 2004 | dwarf.debug_line_str.deinit(gpa); |
| ... | @@ -1660,6 +2026,12 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index { | ... | @@ -1660,6 +2026,12 @@ fn getUnit(dwarf: *Dwarf, mod: *Module) UpdateError!Unit.Index { |
| 1660 | dwarf, | 2026 | dwarf, |
| 1661 | ) == unit); | 2027 | ) == unit); |
| 1662 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); | 2028 | errdefer dwarf.debug_aranges.section.popUnit(dwarf.gpa); |
| 2029 | assert(try dwarf.debug_frame.section.addUnit( | ||
| 2030 | DebugFrame.headerBytes(dwarf), | ||
| 2031 | DebugFrame.trailerBytes(dwarf), | ||
| 2032 | dwarf, | ||
| 2033 | ) == unit); | ||
| 2034 | errdefer dwarf.debug_frame.section.popUnit(dwarf.gpa); | ||
| 1663 | assert(try dwarf.debug_info.section.addUnit( | 2035 | assert(try dwarf.debug_info.section.addUnit( |
| 1664 | DebugInfo.headerBytes(dwarf), | 2036 | DebugInfo.headerBytes(dwarf), |
| 1665 | DebugInfo.trailer_bytes, | 2037 | DebugInfo.trailer_bytes, |
| ... | @@ -1729,6 +2101,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In | ... | @@ -1729,6 +2101,8 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In |
| 1729 | .func_sym_index = undefined, | 2101 | .func_sym_index = undefined, |
| 1730 | .func_high_reloc = undefined, | 2102 | .func_high_reloc = undefined, |
| 1731 | .inlined_funcs = undefined, | 2103 | .inlined_funcs = undefined, |
| 2104 | .cfi = undefined, | ||
| 2105 | .debug_frame = .{}, | ||
| 1732 | .debug_info = .{}, | 2106 | .debug_info = .{}, |
| 1733 | .debug_line = .{}, | 2107 | .debug_line = .{}, |
| 1734 | .debug_loclists = .{}, | 2108 | .debug_loclists = .{}, |
| ... | @@ -1870,6 +2244,50 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In | ... | @@ -1870,6 +2244,50 @@ pub fn initWipNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool.Nav.In |
| 1870 | wip_nav.func = nav_val.toIntern(); | 2244 | wip_nav.func = nav_val.toIntern(); |
| 1871 | wip_nav.func_sym_index = sym_index; | 2245 | wip_nav.func_sym_index = sym_index; |
| 1872 | wip_nav.inlined_funcs = .{}; | 2246 | wip_nav.inlined_funcs = .{}; |
| 2247 | if (dwarf.debug_frame.header.format != .none) wip_nav.cfi = .{ | ||
| 2248 | .loc = 0, | ||
| 2249 | .cfa = dwarf.debug_frame.header.initial_instructions[0].def_cfa, | ||
| 2250 | }; | ||
| 2251 | |||
| 2252 | switch (dwarf.debug_frame.header.format) { | ||
| 2253 | .none => {}, | ||
| 2254 | .debug_frame, .eh_frame => |format| { | ||
| 2255 | const entry = dwarf.debug_frame.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry); | ||
| 2256 | const dfw = wip_nav.debug_frame.writer(dwarf.gpa); | ||
| 2257 | switch (dwarf.format) { | ||
| 2258 | .@"32" => try dfw.writeInt(u32, undefined, dwarf.endian), | ||
| 2259 | .@"64" => { | ||
| 2260 | try dfw.writeInt(u32, std.math.maxInt(u32), dwarf.endian); | ||
| 2261 | try dfw.writeInt(u64, undefined, dwarf.endian); | ||
| 2262 | }, | ||
| 2263 | } | ||
| 2264 | switch (format) { | ||
| 2265 | .none => unreachable, | ||
| 2266 | .debug_frame => { | ||
| 2267 | try entry.cross_entry_relocs.append(dwarf.gpa, .{ | ||
| 2268 | .source_off = @intCast(wip_nav.debug_frame.items.len), | ||
| 2269 | }); | ||
| 2270 | try dfw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); | ||
| 2271 | try entry.external_relocs.append(dwarf.gpa, .{ | ||
| 2272 | .source_off = @intCast(wip_nav.debug_frame.items.len), | ||
| 2273 | .target_sym = sym_index, | ||
| 2274 | }); | ||
| 2275 | try dfw.writeByteNTimes(0, @intFromEnum(dwarf.address_size)); | ||
| 2276 | try dfw.writeByteNTimes(undefined, @intFromEnum(dwarf.address_size)); | ||
| 2277 | }, | ||
| 2278 | .eh_frame => { | ||
| 2279 | try dfw.writeInt(u32, undefined, dwarf.endian); | ||
| 2280 | try entry.external_relocs.append(dwarf.gpa, .{ | ||
| 2281 | .source_off = @intCast(wip_nav.debug_frame.items.len), | ||
| 2282 | .target_sym = sym_index, | ||
| 2283 | }); | ||
| 2284 | try dfw.writeByteNTimes(0, dwarf.sectionOffsetBytes()); | ||
| 2285 | try dfw.writeInt(u32, undefined, dwarf.endian); | ||
| 2286 | try uleb128(dfw, 0); | ||
| 2287 | }, | ||
| 2288 | } | ||
| 2289 | }, | ||
| 2290 | } | ||
| 1873 | 2291 | ||
| 1874 | const diw = wip_nav.debug_info.writer(dwarf.gpa); | 2292 | const diw = wip_nav.debug_info.writer(dwarf.gpa); |
| 1875 | try wip_nav.abbrevCode(.decl_func); | 2293 | try wip_nav.abbrevCode(.decl_func); |
| ... | @@ -1953,49 +2371,84 @@ pub fn finishWipNav( | ... | @@ -1953,49 +2371,84 @@ pub fn finishWipNav( |
| 1953 | log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)}); | 2371 | log.debug("finishWipNav({})", .{nav.fqn.fmt(ip)}); |
| 1954 | 2372 | ||
| 1955 | if (wip_nav.func != .none) { | 2373 | if (wip_nav.func != .none) { |
| 1956 | const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs; | 2374 | { |
| 1957 | external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size; | 2375 | const external_relocs = &dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs; |
| 1958 | if (wip_nav.any_children) { | 2376 | try external_relocs.append(dwarf.gpa, .{ .target_sym = sym.index }); |
| 1959 | const diw = wip_nav.debug_info.writer(dwarf.gpa); | 2377 | var entry: [8 + 8]u8 = undefined; |
| 1960 | try uleb128(diw, @intFromEnum(AbbrevCode.null)); | 2378 | @memset(entry[0..@intFromEnum(dwarf.address_size)], 0); |
| 1961 | } else std.leb.writeUnsignedFixed( | 2379 | dwarf.writeInt(entry[@intFromEnum(dwarf.address_size)..][0..@intFromEnum(dwarf.address_size)], sym.size); |
| 1962 | AbbrevCode.decl_bytes, | 2380 | try dwarf.debug_aranges.section.replaceEntry( |
| 1963 | wip_nav.debug_info.items[0..AbbrevCode.decl_bytes], | 2381 | wip_nav.unit, |
| 1964 | try dwarf.refAbbrevCode(.decl_empty_func), | 2382 | wip_nav.entry, |
| 1965 | ); | 2383 | dwarf, |
| 1966 | 2384 | entry[0 .. @intFromEnum(dwarf.address_size) * 2], | |
| 1967 | var aranges_entry = [1]u8{0} ** (8 + 8); | 2385 | ); |
| 1968 | try dwarf.debug_aranges.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.append(dwarf.gpa, .{ | 2386 | } |
| 1969 | .target_sym = sym.index, | 2387 | switch (dwarf.debug_frame.header.format) { |
| 1970 | }); | 2388 | .none => {}, |
| 1971 | dwarf.writeInt(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0); | 2389 | .debug_frame, .eh_frame => |format| { |
| 1972 | dwarf.writeInt(aranges_entry[@intFromEnum(dwarf.address_size)..][0..@intFromEnum(dwarf.address_size)], sym.size); | 2390 | try wip_nav.debug_frame.appendNTimes( |
| 1973 | 2391 | dwarf.gpa, | |
| 1974 | @memset(aranges_entry[0..@intFromEnum(dwarf.address_size)], 0); | 2392 | DW.CFA.nop, |
| 1975 | try dwarf.debug_aranges.section.replaceEntry( | 2393 | @intCast(dwarf.debug_frame.section.alignment.forward(wip_nav.debug_frame.items.len) - wip_nav.debug_frame.items.len), |
| 1976 | wip_nav.unit, | 2394 | ); |
| 1977 | wip_nav.entry, | 2395 | const contents = wip_nav.debug_frame.items; |
| 1978 | dwarf, | 2396 | try dwarf.debug_frame.section.resizeEntry(wip_nav.unit, wip_nav.entry, dwarf, @intCast(contents.len)); |
| 1979 | aranges_entry[0 .. @intFromEnum(dwarf.address_size) * 2], | 2397 | const unit = dwarf.debug_frame.section.getUnit(wip_nav.unit); |
| 1980 | ); | 2398 | const entry = unit.getEntry(wip_nav.entry); |
| 1981 | 2399 | const unit_len = (if (entry.next.unwrap()) |next_entry| | |
| 1982 | try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{ | 2400 | unit.getEntry(next_entry).off - entry.off |
| 1983 | .{ | 2401 | else |
| 1984 | .source_off = 1, | 2402 | entry.len) - dwarf.unitLengthBytes(); |
| 1985 | .target_sym = sym.index, | 2403 | dwarf.writeInt(contents[dwarf.unitLengthBytes() - dwarf.sectionOffsetBytes() ..][0..dwarf.sectionOffsetBytes()], unit_len); |
| 1986 | }, | 2404 | switch (format) { |
| 1987 | .{ | 2405 | .none => unreachable, |
| 1988 | .source_off = 1 + @intFromEnum(dwarf.address_size), | 2406 | .debug_frame => dwarf.writeInt(contents[dwarf.unitLengthBytes() + dwarf.sectionOffsetBytes() + |
| 1989 | .target_sym = sym.index, | 2407 | @intFromEnum(dwarf.address_size) ..][0..@intFromEnum(dwarf.address_size)], sym.size), |
| 1990 | .target_off = sym.size, | 2408 | .eh_frame => { |
| 2409 | std.mem.writeInt( | ||
| 2410 | u32, | ||
| 2411 | contents[dwarf.unitLengthBytes()..][0..4], | ||
| 2412 | unit.header_len + entry.off + dwarf.unitLengthBytes(), | ||
| 2413 | dwarf.endian, | ||
| 2414 | ); | ||
| 2415 | std.mem.writeInt(u32, contents[dwarf.unitLengthBytes() + 4 + 4 ..][0..4], @intCast(sym.size), dwarf.endian); | ||
| 2416 | }, | ||
| 2417 | } | ||
| 2418 | try entry.replace(unit, &dwarf.debug_frame.section, dwarf, contents); | ||
| 1991 | }, | 2419 | }, |
| 1992 | }); | 2420 | } |
| 1993 | try dwarf.debug_rnglists.section.replaceEntry( | 2421 | { |
| 1994 | wip_nav.unit, | 2422 | const external_relocs = &dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs; |
| 1995 | wip_nav.entry, | 2423 | external_relocs.items[wip_nav.func_high_reloc].target_off = sym.size; |
| 1996 | dwarf, | 2424 | if (wip_nav.any_children) { |
| 1997 | ([1]u8{DW.RLE.start_end} ++ [1]u8{0} ** (8 + 8))[0 .. 1 + @intFromEnum(dwarf.address_size) + @intFromEnum(dwarf.address_size)], | 2425 | const diw = wip_nav.debug_info.writer(dwarf.gpa); |
| 1998 | ); | 2426 | try uleb128(diw, @intFromEnum(AbbrevCode.null)); |
| 2427 | } else std.leb.writeUnsignedFixed( | ||
| 2428 | AbbrevCode.decl_bytes, | ||
| 2429 | wip_nav.debug_info.items[0..AbbrevCode.decl_bytes], | ||
| 2430 | try dwarf.refAbbrevCode(.decl_empty_func), | ||
| 2431 | ); | ||
| 2432 | } | ||
| 2433 | { | ||
| 2434 | try dwarf.debug_rnglists.section.getUnit(wip_nav.unit).getEntry(wip_nav.entry).external_relocs.appendSlice(dwarf.gpa, &.{ | ||
| 2435 | .{ | ||
| 2436 | .source_off = 1, | ||
| 2437 | .target_sym = sym.index, | ||
| 2438 | }, | ||
| 2439 | .{ | ||
| 2440 | .source_off = 1 + @intFromEnum(dwarf.address_size), | ||
| 2441 | .target_sym = sym.index, | ||
| 2442 | .target_off = sym.size, | ||
| 2443 | }, | ||
| 2444 | }); | ||
| 2445 | try dwarf.debug_rnglists.section.replaceEntry( | ||
| 2446 | wip_nav.unit, | ||
| 2447 | wip_nav.entry, | ||
| 2448 | dwarf, | ||
| 2449 | ([1]u8{DW.RLE.start_end} ++ [1]u8{0} ** (8 + 8))[0 .. 1 + @intFromEnum(dwarf.address_size) + @intFromEnum(dwarf.address_size)], | ||
| 2450 | ); | ||
| 2451 | } | ||
| 1999 | } | 2452 | } |
| 2000 | 2453 | ||
| 2001 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); | 2454 | try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items); |
| ... | @@ -2038,6 +2491,8 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool | ... | @@ -2038,6 +2491,8 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool |
| 2038 | .func_sym_index = undefined, | 2491 | .func_sym_index = undefined, |
| 2039 | .func_high_reloc = undefined, | 2492 | .func_high_reloc = undefined, |
| 2040 | .inlined_funcs = undefined, | 2493 | .inlined_funcs = undefined, |
| 2494 | .cfi = undefined, | ||
| 2495 | .debug_frame = .{}, | ||
| 2041 | .debug_info = .{}, | 2496 | .debug_info = .{}, |
| 2042 | .debug_line = .{}, | 2497 | .debug_line = .{}, |
| 2043 | .debug_loclists = .{}, | 2498 | .debug_loclists = .{}, |
| ... | @@ -2546,6 +3001,8 @@ fn updateType( | ... | @@ -2546,6 +3001,8 @@ fn updateType( |
| 2546 | .func_sym_index = undefined, | 3001 | .func_sym_index = undefined, |
| 2547 | .func_high_reloc = undefined, | 3002 | .func_high_reloc = undefined, |
| 2548 | .inlined_funcs = undefined, | 3003 | .inlined_funcs = undefined, |
| 3004 | .cfi = undefined, | ||
| 3005 | .debug_frame = .{}, | ||
| 2549 | .debug_info = .{}, | 3006 | .debug_info = .{}, |
| 2550 | .debug_line = .{}, | 3007 | .debug_line = .{}, |
| 2551 | .debug_loclists = .{}, | 3008 | .debug_loclists = .{}, |
| ... | @@ -2999,6 +3456,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP | ... | @@ -2999,6 +3456,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP |
| 2999 | .func_sym_index = undefined, | 3456 | .func_sym_index = undefined, |
| 3000 | .func_high_reloc = undefined, | 3457 | .func_high_reloc = undefined, |
| 3001 | .inlined_funcs = undefined, | 3458 | .inlined_funcs = undefined, |
| 3459 | .cfi = undefined, | ||
| 3460 | .debug_frame = .{}, | ||
| 3002 | .debug_info = .{}, | 3461 | .debug_info = .{}, |
| 3003 | .debug_line = .{}, | 3462 | .debug_line = .{}, |
| 3004 | .debug_loclists = .{}, | 3463 | .debug_loclists = .{}, |
| ... | @@ -3062,6 +3521,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP | ... | @@ -3062,6 +3521,8 @@ pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternP |
| 3062 | .func_sym_index = undefined, | 3521 | .func_sym_index = undefined, |
| 3063 | .func_high_reloc = undefined, | 3522 | .func_high_reloc = undefined, |
| 3064 | .inlined_funcs = undefined, | 3523 | .inlined_funcs = undefined, |
| 3524 | .cfi = undefined, | ||
| 3525 | .debug_frame = .{}, | ||
| 3065 | .debug_info = .{}, | 3526 | .debug_info = .{}, |
| 3066 | .debug_line = .{}, | 3527 | .debug_line = .{}, |
| 3067 | .debug_loclists = .{}, | 3528 | .debug_loclists = .{}, |
| ... | @@ -3255,6 +3716,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3255,6 +3716,8 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3255 | .func_sym_index = undefined, | 3716 | .func_sym_index = undefined, |
| 3256 | .func_high_reloc = undefined, | 3717 | .func_high_reloc = undefined, |
| 3257 | .inlined_funcs = undefined, | 3718 | .inlined_funcs = undefined, |
| 3719 | .cfi = undefined, | ||
| 3720 | .debug_frame = .{}, | ||
| 3258 | .debug_info = .{}, | 3721 | .debug_info = .{}, |
| 3259 | .debug_line = .{}, | 3722 | .debug_line = .{}, |
| 3260 | .debug_loclists = .{}, | 3723 | .debug_loclists = .{}, |
| ... | @@ -3306,13 +3769,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3306,13 +3769,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3306 | else | 3769 | else |
| 3307 | dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); | 3770 | dwarf.debug_aranges.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); |
| 3308 | switch (dwarf.format) { | 3771 | switch (dwarf.format) { |
| 3309 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), @intCast(unit_len), dwarf.endian), | 3772 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), |
| 3310 | .@"64" => { | 3773 | .@"64" => { |
| 3311 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), std.math.maxInt(u32), dwarf.endian); | 3774 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); |
| 3312 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(@sizeOf(u64)), unit_len, dwarf.endian); | 3775 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); |
| 3313 | }, | 3776 | }, |
| 3314 | } | 3777 | } |
| 3315 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 2, dwarf.endian); | 3778 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 2, dwarf.endian); |
| 3316 | unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ | 3779 | unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ |
| 3317 | .source_off = @intCast(header.items.len), | 3780 | .source_off = @intCast(header.items.len), |
| 3318 | .target_sec = .debug_info, | 3781 | .target_sec = .debug_info, |
| ... | @@ -3326,6 +3789,49 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3326,6 +3789,49 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3326 | } | 3789 | } |
| 3327 | dwarf.debug_aranges.section.dirty = false; | 3790 | dwarf.debug_aranges.section.dirty = false; |
| 3328 | } | 3791 | } |
| 3792 | if (dwarf.debug_frame.section.dirty) { | ||
| 3793 | const target = dwarf.bin_file.comp.root_mod.resolved_target.result; | ||
| 3794 | switch (dwarf.debug_frame.header.format) { | ||
| 3795 | .none => {}, | ||
| 3796 | .debug_frame => unreachable, | ||
| 3797 | .eh_frame => switch (target.cpu.arch) { | ||
| 3798 | .x86_64 => { | ||
| 3799 | dev.check(.x86_64_backend); | ||
| 3800 | const Register = @import("../arch/x86_64/bits.zig").Register; | ||
| 3801 | for (dwarf.debug_frame.section.units.items) |*unit| { | ||
| 3802 | header.clearRetainingCapacity(); | ||
| 3803 | try header.ensureTotalCapacity(unit.header_len); | ||
| 3804 | const unit_len = unit.header_len - dwarf.unitLengthBytes(); | ||
| 3805 | switch (dwarf.format) { | ||
| 3806 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), | ||
| 3807 | .@"64" => { | ||
| 3808 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); | ||
| 3809 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); | ||
| 3810 | }, | ||
| 3811 | } | ||
| 3812 | header.appendNTimesAssumeCapacity(0, 4); | ||
| 3813 | header.appendAssumeCapacity(1); | ||
| 3814 | header.appendSliceAssumeCapacity("zR\x00"); | ||
| 3815 | uleb128(header.fixedWriter(), dwarf.debug_frame.header.code_alignment_factor) catch unreachable; | ||
| 3816 | sleb128(header.fixedWriter(), dwarf.debug_frame.header.data_alignment_factor) catch unreachable; | ||
| 3817 | uleb128(header.fixedWriter(), dwarf.debug_frame.header.return_address_register) catch unreachable; | ||
| 3818 | uleb128(header.fixedWriter(), 1) catch unreachable; | ||
| 3819 | header.appendAssumeCapacity(0x10 | 0x08 | 0x03); | ||
| 3820 | header.appendAssumeCapacity(DW.CFA.def_cfa_sf); | ||
| 3821 | uleb128(header.fixedWriter(), Register.rsp.dwarfNum()) catch unreachable; | ||
| 3822 | sleb128(header.fixedWriter(), -1) catch unreachable; | ||
| 3823 | header.appendAssumeCapacity(@as(u8, DW.CFA.offset) + Register.rip.dwarfNum()); | ||
| 3824 | uleb128(header.fixedWriter(), 1) catch unreachable; | ||
| 3825 | header.appendNTimesAssumeCapacity(DW.CFA.nop, unit.header_len - header.items.len); | ||
| 3826 | try unit.replaceHeader(&dwarf.debug_frame.section, dwarf, header.items); | ||
| 3827 | try unit.writeTrailer(&dwarf.debug_frame.section, dwarf); | ||
| 3828 | } | ||
| 3829 | }, | ||
| 3830 | else => unreachable, | ||
| 3831 | }, | ||
| 3832 | } | ||
| 3833 | dwarf.debug_frame.section.dirty = false; | ||
| 3834 | } | ||
| 3329 | if (dwarf.debug_info.section.dirty) { | 3835 | if (dwarf.debug_info.section.dirty) { |
| 3330 | for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| { | 3836 | for (dwarf.mods.keys(), dwarf.mods.values(), dwarf.debug_info.section.units.items, 0..) |mod, mod_info, *unit_ptr, unit_index| { |
| 3331 | const unit: Unit.Index = @enumFromInt(unit_index); | 3837 | const unit: Unit.Index = @enumFromInt(unit_index); |
| ... | @@ -3339,13 +3845,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3339,13 +3845,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3339 | else | 3845 | else |
| 3340 | dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); | 3846 | dwarf.debug_info.section.len) - unit_ptr.off - dwarf.unitLengthBytes(); |
| 3341 | switch (dwarf.format) { | 3847 | switch (dwarf.format) { |
| 3342 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), @intCast(unit_len), dwarf.endian), | 3848 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), |
| 3343 | .@"64" => { | 3849 | .@"64" => { |
| 3344 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), std.math.maxInt(u32), dwarf.endian); | 3850 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); |
| 3345 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(@sizeOf(u64)), unit_len, dwarf.endian); | 3851 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); |
| 3346 | }, | 3852 | }, |
| 3347 | } | 3853 | } |
| 3348 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 5, dwarf.endian); | 3854 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); |
| 3349 | header.appendSliceAssumeCapacity(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }); | 3855 | header.appendSliceAssumeCapacity(&.{ DW.UT.compile, @intFromEnum(dwarf.address_size) }); |
| 3350 | unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ | 3856 | unit_ptr.cross_section_relocs.appendAssumeCapacity(.{ |
| 3351 | .source_off = @intCast(header.items.len), | 3857 | .source_off = @intCast(header.items.len), |
| ... | @@ -3438,13 +3944,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3438,13 +3944,13 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3438 | else | 3944 | else |
| 3439 | dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes(); | 3945 | dwarf.debug_line.section.len) - unit.off - dwarf.unitLengthBytes(); |
| 3440 | switch (dwarf.format) { | 3946 | switch (dwarf.format) { |
| 3441 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), @intCast(unit_len), dwarf.endian), | 3947 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), |
| 3442 | .@"64" => { | 3948 | .@"64" => { |
| 3443 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), std.math.maxInt(u32), dwarf.endian); | 3949 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); |
| 3444 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(@sizeOf(u64)), unit_len, dwarf.endian); | 3950 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); |
| 3445 | }, | 3951 | }, |
| 3446 | } | 3952 | } |
| 3447 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 5, dwarf.endian); | 3953 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); |
| 3448 | header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); | 3954 | header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); |
| 3449 | dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len); | 3955 | dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), unit.header_len - header.items.len); |
| 3450 | const StandardOpcode = DeclValEnum(DW.LNS); | 3956 | const StandardOpcode = DeclValEnum(DW.LNS); |
| ... | @@ -3540,15 +4046,15 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3540,15 +4046,15 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3540 | else | 4046 | else |
| 3541 | dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes(); | 4047 | dwarf.debug_rnglists.section.len) - unit.off - dwarf.unitLengthBytes(); |
| 3542 | switch (dwarf.format) { | 4048 | switch (dwarf.format) { |
| 3543 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), @intCast(unit_len), dwarf.endian), | 4049 | .@"32" => std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), @intCast(unit_len), dwarf.endian), |
| 3544 | .@"64" => { | 4050 | .@"64" => { |
| 3545 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), std.math.maxInt(u32), dwarf.endian); | 4051 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), std.math.maxInt(u32), dwarf.endian); |
| 3546 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(@sizeOf(u64)), unit_len, dwarf.endian); | 4052 | std.mem.writeInt(u64, header.addManyAsArrayAssumeCapacity(8), unit_len, dwarf.endian); |
| 3547 | }, | 4053 | }, |
| 3548 | } | 4054 | } |
| 3549 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(@sizeOf(u16)), 5, dwarf.endian); | 4055 | std.mem.writeInt(u16, header.addManyAsArrayAssumeCapacity(2), 5, dwarf.endian); |
| 3550 | header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); | 4056 | header.appendSliceAssumeCapacity(&.{ @intFromEnum(dwarf.address_size), 0 }); |
| 3551 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(@sizeOf(u32)), 1, dwarf.endian); | 4057 | std.mem.writeInt(u32, header.addManyAsArrayAssumeCapacity(4), 1, dwarf.endian); |
| 3552 | dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), dwarf.sectionOffsetBytes() * 1); | 4058 | dwarf.writeInt(header.addManyAsSliceAssumeCapacity(dwarf.sectionOffsetBytes()), dwarf.sectionOffsetBytes() * 1); |
| 3553 | try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header.items); | 4059 | try unit.replaceHeader(&dwarf.debug_rnglists.section, dwarf, header.items); |
| 3554 | try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf); | 4060 | try unit.writeTrailer(&dwarf.debug_rnglists.section, dwarf); |
| ... | @@ -3557,6 +4063,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { | ... | @@ -3557,6 +4063,7 @@ pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void { |
| 3557 | } | 4063 | } |
| 3558 | assert(!dwarf.debug_abbrev.section.dirty); | 4064 | assert(!dwarf.debug_abbrev.section.dirty); |
| 3559 | assert(!dwarf.debug_aranges.section.dirty); | 4065 | assert(!dwarf.debug_aranges.section.dirty); |
| 4066 | assert(!dwarf.debug_frame.section.dirty); | ||
| 3560 | assert(!dwarf.debug_info.section.dirty); | 4067 | assert(!dwarf.debug_info.section.dirty); |
| 3561 | assert(!dwarf.debug_line.section.dirty); | 4068 | assert(!dwarf.debug_line.section.dirty); |
| 3562 | assert(!dwarf.debug_line_str.section.dirty); | 4069 | assert(!dwarf.debug_line_str.section.dirty); |
| ... | @@ -3569,6 +4076,7 @@ pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void { | ... | @@ -3569,6 +4076,7 @@ pub fn resolveRelocs(dwarf: *Dwarf) RelocError!void { |
| 3569 | for ([_]*Section{ | 4076 | for ([_]*Section{ |
| 3570 | &dwarf.debug_abbrev.section, | 4077 | &dwarf.debug_abbrev.section, |
| 3571 | &dwarf.debug_aranges.section, | 4078 | &dwarf.debug_aranges.section, |
| 4079 | &dwarf.debug_frame.section, | ||
| 3572 | &dwarf.debug_info.section, | 4080 | &dwarf.debug_info.section, |
| 3573 | &dwarf.debug_line.section, | 4081 | &dwarf.debug_line.section, |
| 3574 | &dwarf.debug_line_str.section, | 4082 | &dwarf.debug_line_str.section, |
| ... | @@ -4147,6 +4655,7 @@ fn getFile(dwarf: *Dwarf) ?std.fs.File { | ... | @@ -4147,6 +4655,7 @@ fn getFile(dwarf: *Dwarf) ?std.fs.File { |
| 4147 | 4655 | ||
| 4148 | fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index { | 4656 | fn addCommonEntry(dwarf: *Dwarf, unit: Unit.Index) UpdateError!Entry.Index { |
| 4149 | const entry = try dwarf.debug_aranges.section.getUnit(unit).addEntry(dwarf.gpa); | 4657 | const entry = try dwarf.debug_aranges.section.getUnit(unit).addEntry(dwarf.gpa); |
| 4658 | assert(try dwarf.debug_frame.section.getUnit(unit).addEntry(dwarf.gpa) == entry); | ||
| 4150 | assert(try dwarf.debug_info.section.getUnit(unit).addEntry(dwarf.gpa) == entry); | 4659 | assert(try dwarf.debug_info.section.getUnit(unit).addEntry(dwarf.gpa) == entry); |
| 4151 | assert(try dwarf.debug_line.section.getUnit(unit).addEntry(dwarf.gpa) == entry); | 4660 | assert(try dwarf.debug_line.section.getUnit(unit).addEntry(dwarf.gpa) == entry); |
| 4152 | assert(try dwarf.debug_loclists.section.getUnit(unit).addEntry(dwarf.gpa) == entry); | 4661 | assert(try dwarf.debug_loclists.section.getUnit(unit).addEntry(dwarf.gpa) == entry); |
| ... | @@ -4190,6 +4699,12 @@ fn uleb128Bytes(value: anytype) u32 { | ... | @@ -4190,6 +4699,12 @@ fn uleb128Bytes(value: anytype) u32 { |
| 4190 | return @intCast(cw.bytes_written); | 4699 | return @intCast(cw.bytes_written); |
| 4191 | } | 4700 | } |
| 4192 | 4701 | ||
| 4702 | fn sleb128Bytes(value: anytype) u32 { | ||
| 4703 | var cw = std.io.countingWriter(std.io.null_writer); | ||
| 4704 | try sleb128(cw.writer(), value); | ||
| 4705 | return @intCast(cw.bytes_written); | ||
| 4706 | } | ||
| 4707 | |||
| 4193 | /// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional | 4708 | /// overrides `-fno-incremental` for testing incremental debug info until `-fincremental` is functional |
| 4194 | const force_incremental = false; | 4709 | const force_incremental = false; |
| 4195 | inline fn incremental(dwarf: Dwarf) bool { | 4710 | inline fn incremental(dwarf: Dwarf) bool { |
| ... | @@ -4206,6 +4721,7 @@ const Zcu = @import("../Zcu.zig"); | ... | @@ -4206,6 +4721,7 @@ const Zcu = @import("../Zcu.zig"); |
| 4206 | const Zir = std.zig.Zir; | 4721 | const Zir = std.zig.Zir; |
| 4207 | const assert = std.debug.assert; | 4722 | const assert = std.debug.assert; |
| 4208 | const codegen = @import("../codegen.zig"); | 4723 | const codegen = @import("../codegen.zig"); |
| 4724 | const dev = @import("../dev.zig"); | ||
| 4209 | const link = @import("../link.zig"); | 4725 | const link = @import("../link.zig"); |
| 4210 | const log = std.log.scoped(.dwarf); | 4726 | const log = std.log.scoped(.dwarf); |
| 4211 | const sleb128 = std.leb.writeIleb128; | 4727 | const sleb128 = std.leb.writeIleb128; |
src/link/Elf.zig+80-53| ... | @@ -569,9 +569,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | ... | @@ -569,9 +569,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { |
| 569 | 569 | ||
| 570 | if (shdr.sh_type != elf.SHT_NOBITS) { | 570 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 571 | const allocated_size = self.allocatedSize(shdr.sh_offset); | 571 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 572 | if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | 572 | if (needed_size > allocated_size) { |
| 573 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | ||
| 574 | } else if (needed_size > allocated_size) { | ||
| 575 | const existing_size = shdr.sh_size; | 573 | const existing_size = shdr.sh_size; |
| 576 | shdr.sh_size = 0; | 574 | shdr.sh_size = 0; |
| 577 | // Must move the entire section. | 575 | // Must move the entire section. |
| ... | @@ -590,6 +588,8 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | ... | @@ -590,6 +588,8 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { |
| 590 | 588 | ||
| 591 | shdr.sh_offset = new_offset; | 589 | shdr.sh_offset = new_offset; |
| 592 | if (maybe_phdr) |phdr| phdr.p_offset = new_offset; | 590 | if (maybe_phdr) |phdr| phdr.p_offset = new_offset; |
| 591 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | ||
| 592 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | ||
| 593 | } | 593 | } |
| 594 | if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; | 594 | if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; |
| 595 | } | 595 | } |
| ... | @@ -621,9 +621,7 @@ pub fn growNonAllocSection( | ... | @@ -621,9 +621,7 @@ pub fn growNonAllocSection( |
| 621 | assert(shdr.sh_flags & elf.SHF_ALLOC == 0); | 621 | assert(shdr.sh_flags & elf.SHF_ALLOC == 0); |
| 622 | 622 | ||
| 623 | const allocated_size = self.allocatedSize(shdr.sh_offset); | 623 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 624 | if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | 624 | if (needed_size > allocated_size) { |
| 625 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | ||
| 626 | } else if (needed_size > allocated_size) { | ||
| 627 | const existing_size = shdr.sh_size; | 625 | const existing_size = shdr.sh_size; |
| 628 | shdr.sh_size = 0; | 626 | shdr.sh_size = 0; |
| 629 | // Move all the symbols to a new file location. | 627 | // Move all the symbols to a new file location. |
| ... | @@ -646,6 +644,8 @@ pub fn growNonAllocSection( | ... | @@ -646,6 +644,8 @@ pub fn growNonAllocSection( |
| 646 | } | 644 | } |
| 647 | 645 | ||
| 648 | shdr.sh_offset = new_offset; | 646 | shdr.sh_offset = new_offset; |
| 647 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | ||
| 648 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); | ||
| 649 | } | 649 | } |
| 650 | shdr.sh_size = needed_size; | 650 | shdr.sh_size = needed_size; |
| 651 | 651 | ||
| ... | @@ -699,7 +699,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -699,7 +699,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 699 | const sub_prog_node = prog_node.start("ELF Flush", 0); | 699 | const sub_prog_node = prog_node.start("ELF Flush", 0); |
| 700 | defer sub_prog_node.end(); | 700 | defer sub_prog_node.end(); |
| 701 | 701 | ||
| 702 | const target = comp.root_mod.resolved_target.result; | 702 | const target = self.getTarget(); |
| 703 | const link_mode = comp.config.link_mode; | 703 | const link_mode = comp.config.link_mode; |
| 704 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | 704 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. |
| 705 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | 705 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| ... | @@ -1053,7 +1053,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { | ... | @@ -1053,7 +1053,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1053 | defer arena_allocator.deinit(); | 1053 | defer arena_allocator.deinit(); |
| 1054 | const arena = arena_allocator.allocator(); | 1054 | const arena = arena_allocator.allocator(); |
| 1055 | 1055 | ||
| 1056 | const target = self.base.comp.root_mod.resolved_target.result; | 1056 | const target = self.getTarget(); |
| 1057 | const link_mode = self.base.comp.config.link_mode; | 1057 | const link_mode = self.base.comp.config.link_mode; |
| 1058 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. | 1058 | const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type. |
| 1059 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); | 1059 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path}); |
| ... | @@ -1498,15 +1498,13 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { | ... | @@ -1498,15 +1498,13 @@ fn parseLdScript(self: *Elf, lib: SystemLib) ParseError!void { |
| 1498 | } | 1498 | } |
| 1499 | 1499 | ||
| 1500 | pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void { | 1500 | pub fn validateEFlags(self: *Elf, file_index: File.Index, e_flags: elf.Elf64_Word) !void { |
| 1501 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 1502 | |||
| 1503 | if (self.first_eflags == null) { | 1501 | if (self.first_eflags == null) { |
| 1504 | self.first_eflags = e_flags; | 1502 | self.first_eflags = e_flags; |
| 1505 | return; // there isn't anything to conflict with yet | 1503 | return; // there isn't anything to conflict with yet |
| 1506 | } | 1504 | } |
| 1507 | const self_eflags: *elf.Elf64_Word = &self.first_eflags.?; | 1505 | const self_eflags: *elf.Elf64_Word = &self.first_eflags.?; |
| 1508 | 1506 | ||
| 1509 | switch (target.cpu.arch) { | 1507 | switch (self.getTarget().cpu.arch) { |
| 1510 | .riscv64 => { | 1508 | .riscv64 => { |
| 1511 | if (e_flags != self_eflags.*) { | 1509 | if (e_flags != self_eflags.*) { |
| 1512 | const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags); | 1510 | const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags); |
| ... | @@ -1549,7 +1547,7 @@ fn accessLibPath( | ... | @@ -1549,7 +1547,7 @@ fn accessLibPath( |
| 1549 | link_mode: ?std.builtin.LinkMode, | 1547 | link_mode: ?std.builtin.LinkMode, |
| 1550 | ) !bool { | 1548 | ) !bool { |
| 1551 | const sep = fs.path.sep_str; | 1549 | const sep = fs.path.sep_str; |
| 1552 | const target = self.base.comp.root_mod.resolved_target.result; | 1550 | const target = self.getTarget(); |
| 1553 | test_path.clearRetainingCapacity(); | 1551 | test_path.clearRetainingCapacity(); |
| 1554 | const prefix = if (link_mode != null) "lib" else ""; | 1552 | const prefix = if (link_mode != null) "lib" else ""; |
| 1555 | const suffix = if (link_mode) |mode| switch (mode) { | 1553 | const suffix = if (link_mode) |mode| switch (mode) { |
| ... | @@ -1779,7 +1777,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -1779,7 +1777,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 1779 | const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; | 1777 | const is_exe_or_dyn_lib = is_dyn_lib or output_mode == .Exe; |
| 1780 | const have_dynamic_linker = comp.config.link_libc and | 1778 | const have_dynamic_linker = comp.config.link_libc and |
| 1781 | link_mode == .dynamic and is_exe_or_dyn_lib; | 1779 | link_mode == .dynamic and is_exe_or_dyn_lib; |
| 1782 | const target = comp.root_mod.resolved_target.result; | 1780 | const target = self.getTarget(); |
| 1783 | const compiler_rt_path: ?[]const u8 = blk: { | 1781 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1784 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | 1782 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| 1785 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; | 1783 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| ... | @@ -2353,8 +2351,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s | ... | @@ -2353,8 +2351,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s |
| 2353 | 2351 | ||
| 2354 | pub fn writeShdrTable(self: *Elf) !void { | 2352 | pub fn writeShdrTable(self: *Elf) !void { |
| 2355 | const gpa = self.base.comp.gpa; | 2353 | const gpa = self.base.comp.gpa; |
| 2356 | const target = self.base.comp.root_mod.resolved_target.result; | 2354 | const target_endian = self.getTarget().cpu.arch.endian(); |
| 2357 | const target_endian = target.cpu.arch.endian(); | ||
| 2358 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); | 2355 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 2359 | const shsize: u64 = switch (self.ptr_width) { | 2356 | const shsize: u64 = switch (self.ptr_width) { |
| 2360 | .p32 => @sizeOf(elf.Elf32_Shdr), | 2357 | .p32 => @sizeOf(elf.Elf32_Shdr), |
| ... | @@ -2410,8 +2407,7 @@ pub fn writeShdrTable(self: *Elf) !void { | ... | @@ -2410,8 +2407,7 @@ pub fn writeShdrTable(self: *Elf) !void { |
| 2410 | 2407 | ||
| 2411 | fn writePhdrTable(self: *Elf) !void { | 2408 | fn writePhdrTable(self: *Elf) !void { |
| 2412 | const gpa = self.base.comp.gpa; | 2409 | const gpa = self.base.comp.gpa; |
| 2413 | const target = self.base.comp.root_mod.resolved_target.result; | 2410 | const target_endian = self.getTarget().cpu.arch.endian(); |
| 2414 | const target_endian = target.cpu.arch.endian(); | ||
| 2415 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); | 2411 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 2416 | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; | 2412 | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; |
| 2417 | 2413 | ||
| ... | @@ -2464,7 +2460,7 @@ pub fn writeElfHeader(self: *Elf) !void { | ... | @@ -2464,7 +2460,7 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2464 | }; | 2460 | }; |
| 2465 | index += 1; | 2461 | index += 1; |
| 2466 | 2462 | ||
| 2467 | const target = comp.root_mod.resolved_target.result; | 2463 | const target = self.getTarget(); |
| 2468 | const endian = target.cpu.arch.endian(); | 2464 | const endian = target.cpu.arch.endian(); |
| 2469 | hdr_buf[index] = switch (endian) { | 2465 | hdr_buf[index] = switch (endian) { |
| 2470 | .little => elf.ELFDATA2LSB, | 2466 | .little => elf.ELFDATA2LSB, |
| ... | @@ -2772,21 +2768,25 @@ fn initOutputSections(self: *Elf) !void { | ... | @@ -2772,21 +2768,25 @@ fn initOutputSections(self: *Elf) !void { |
| 2772 | 2768 | ||
| 2773 | fn initSyntheticSections(self: *Elf) !void { | 2769 | fn initSyntheticSections(self: *Elf) !void { |
| 2774 | const comp = self.base.comp; | 2770 | const comp = self.base.comp; |
| 2775 | const target = comp.root_mod.resolved_target.result; | 2771 | const target = self.getTarget(); |
| 2776 | const ptr_size = self.ptrWidthBytes(); | 2772 | const ptr_size = self.ptrWidthBytes(); |
| 2777 | 2773 | ||
| 2778 | const needs_eh_frame = for (self.objects.items) |index| { | 2774 | const needs_eh_frame = for (self.objects.items) |index| { |
| 2779 | if (self.file(index).?.object.cies.items.len > 0) break true; | 2775 | if (self.file(index).?.object.cies.items.len > 0) break true; |
| 2780 | } else false; | 2776 | } else false; |
| 2781 | if (needs_eh_frame) { | 2777 | if (needs_eh_frame) { |
| 2782 | self.eh_frame_section_index = try self.addSection(.{ | 2778 | if (self.eh_frame_section_index == null) { |
| 2783 | .name = try self.insertShString(".eh_frame"), | 2779 | self.eh_frame_section_index = try self.addSection(.{ |
| 2784 | .type = elf.SHT_PROGBITS, | 2780 | .name = try self.insertShString(".eh_frame"), |
| 2785 | .flags = elf.SHF_ALLOC, | 2781 | .type = if (target.cpu.arch == .x86_64) |
| 2786 | .addralign = ptr_size, | 2782 | elf.SHT_X86_64_UNWIND |
| 2787 | .offset = std.math.maxInt(u64), | 2783 | else |
| 2788 | }); | 2784 | elf.SHT_PROGBITS, |
| 2789 | 2785 | .flags = elf.SHF_ALLOC, | |
| 2786 | .addralign = ptr_size, | ||
| 2787 | .offset = std.math.maxInt(u64), | ||
| 2788 | }); | ||
| 2789 | } | ||
| 2790 | if (comp.link_eh_frame_hdr) { | 2790 | if (comp.link_eh_frame_hdr) { |
| 2791 | self.eh_frame_hdr_section_index = try self.addSection(.{ | 2791 | self.eh_frame_hdr_section_index = try self.addSection(.{ |
| 2792 | .name = try self.insertShString(".eh_frame_hdr"), | 2792 | .name = try self.insertShString(".eh_frame_hdr"), |
| ... | @@ -3446,7 +3446,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { | ... | @@ -3446,7 +3446,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3446 | } | 3446 | } |
| 3447 | 3447 | ||
| 3448 | fn updateSectionSizes(self: *Elf) !void { | 3448 | fn updateSectionSizes(self: *Elf) !void { |
| 3449 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 3450 | const slice = self.sections.slice(); | 3449 | const slice = self.sections.slice(); |
| 3451 | for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| { | 3450 | for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| { |
| 3452 | if (atom_list.items.len == 0) continue; | 3451 | if (atom_list.items.len == 0) continue; |
| ... | @@ -3474,7 +3473,11 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3474,7 +3473,11 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3474 | 3473 | ||
| 3475 | const shdrs = slice.items(.shdr); | 3474 | const shdrs = slice.items(.shdr); |
| 3476 | if (self.eh_frame_section_index) |index| { | 3475 | if (self.eh_frame_section_index) |index| { |
| 3477 | shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self); | 3476 | shdrs[index].sh_size = existing_size: { |
| 3477 | const zo = self.zigObjectPtr() orelse break :existing_size 0; | ||
| 3478 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 3479 | break :existing_size sym.atom(self).?.size; | ||
| 3480 | } + try eh_frame.calcEhFrameSize(self); | ||
| 3478 | } | 3481 | } |
| 3479 | 3482 | ||
| 3480 | if (self.eh_frame_hdr_section_index) |index| { | 3483 | if (self.eh_frame_hdr_section_index) |index| { |
| ... | @@ -3517,7 +3520,7 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3517,7 +3520,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3517 | } | 3520 | } |
| 3518 | 3521 | ||
| 3519 | if (self.interp_section_index) |index| { | 3522 | if (self.interp_section_index) |index| { |
| 3520 | shdrs[index].sh_size = target.dynamic_linker.get().?.len + 1; | 3523 | shdrs[index].sh_size = self.getTarget().dynamic_linker.get().?.len + 1; |
| 3521 | } | 3524 | } |
| 3522 | 3525 | ||
| 3523 | if (self.hash_section_index) |index| { | 3526 | if (self.hash_section_index) |index| { |
| ... | @@ -3759,10 +3762,10 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -3759,10 +3762,10 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3759 | } | 3762 | } |
| 3760 | 3763 | ||
| 3761 | const first = slice.items(.shdr)[cover.items[0]]; | 3764 | const first = slice.items(.shdr)[cover.items[0]]; |
| 3762 | var off = try self.findFreeSpace(filesz, @"align"); | 3765 | var new_offset = try self.findFreeSpace(filesz, @"align"); |
| 3763 | const phndx = try self.addPhdr(.{ | 3766 | const phndx = try self.addPhdr(.{ |
| 3764 | .type = elf.PT_LOAD, | 3767 | .type = elf.PT_LOAD, |
| 3765 | .offset = off, | 3768 | .offset = new_offset, |
| 3766 | .addr = first.sh_addr, | 3769 | .addr = first.sh_addr, |
| 3767 | .memsz = memsz, | 3770 | .memsz = memsz, |
| 3768 | .filesz = filesz, | 3771 | .filesz = filesz, |
| ... | @@ -3777,9 +3780,28 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -3777,9 +3780,28 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3777 | shdr.sh_offset = 0; | 3780 | shdr.sh_offset = 0; |
| 3778 | continue; | 3781 | continue; |
| 3779 | } | 3782 | } |
| 3780 | off = alignment.@"align"(shndx, shdr.sh_addralign, off); | 3783 | new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset); |
| 3781 | shdr.sh_offset = off; | 3784 | |
| 3782 | off += shdr.sh_size; | 3785 | if (shndx == self.eh_frame_section_index) eh_frame: { |
| 3786 | const zo = self.zigObjectPtr() orelse break :eh_frame; | ||
| 3787 | const sym = zo.symbol(zo.eh_frame_index orelse break :eh_frame); | ||
| 3788 | const existing_size = sym.atom(self).?.size; | ||
| 3789 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ | ||
| 3790 | self.getShString(shdr.sh_name), | ||
| 3791 | shdr.sh_offset, | ||
| 3792 | new_offset, | ||
| 3793 | }); | ||
| 3794 | const amt = try self.base.file.?.copyRangeAll( | ||
| 3795 | shdr.sh_offset, | ||
| 3796 | self.base.file.?, | ||
| 3797 | new_offset, | ||
| 3798 | existing_size, | ||
| 3799 | ); | ||
| 3800 | if (amt != existing_size) return error.InputOutput; | ||
| 3801 | } | ||
| 3802 | |||
| 3803 | shdr.sh_offset = new_offset; | ||
| 3804 | new_offset += shdr.sh_size; | ||
| 3783 | } | 3805 | } |
| 3784 | 3806 | ||
| 3785 | addr = mem.alignForward(u64, addr, self.page_size); | 3807 | addr = mem.alignForward(u64, addr, self.page_size); |
| ... | @@ -3910,9 +3932,9 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -3910,9 +3932,9 @@ fn writeAtoms(self: *Elf) !void { |
| 3910 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | 3932 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); |
| 3911 | 3933 | ||
| 3912 | // TODO really, really handle debug section separately | 3934 | // TODO really, really handle debug section separately |
| 3913 | const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: { | 3935 | const base_offset = if (self.isDebugSection(@intCast(shndx))) base_offset: { |
| 3914 | const zo = self.zigObjectPtr().?; | 3936 | const zo = self.zigObjectPtr().?; |
| 3915 | break :blk for ([_]Symbol.Index{ | 3937 | for ([_]Symbol.Index{ |
| 3916 | zo.debug_info_index.?, | 3938 | zo.debug_info_index.?, |
| 3917 | zo.debug_abbrev_index.?, | 3939 | zo.debug_abbrev_index.?, |
| 3918 | zo.debug_aranges_index.?, | 3940 | zo.debug_aranges_index.?, |
| ... | @@ -3924,8 +3946,13 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -3924,8 +3946,13 @@ fn writeAtoms(self: *Elf) !void { |
| 3924 | }) |sym_index| { | 3946 | }) |sym_index| { |
| 3925 | const sym = zo.symbol(sym_index); | 3947 | const sym = zo.symbol(sym_index); |
| 3926 | const atom_ptr = sym.atom(self).?; | 3948 | const atom_ptr = sym.atom(self).?; |
| 3927 | if (atom_ptr.output_section_index == shndx) break atom_ptr.size; | 3949 | if (atom_ptr.output_section_index == shndx) break :base_offset atom_ptr.size; |
| 3928 | } else 0; | 3950 | } |
| 3951 | break :base_offset 0; | ||
| 3952 | } else if (@as(u32, @intCast(shndx)) == self.eh_frame_section_index) base_offset: { | ||
| 3953 | const zo = self.zigObjectPtr() orelse break :base_offset 0; | ||
| 3954 | const sym = zo.symbol(zo.eh_frame_index orelse break :base_offset 0); | ||
| 3955 | break :base_offset sym.atom(self).?.size; | ||
| 3929 | } else 0; | 3956 | } else 0; |
| 3930 | const sh_offset = shdr.sh_offset + base_offset; | 3957 | const sh_offset = shdr.sh_offset + base_offset; |
| 3931 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; | 3958 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; |
| ... | @@ -4082,12 +4109,11 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4082,12 +4109,11 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4082 | 4109 | ||
| 4083 | fn writeSyntheticSections(self: *Elf) !void { | 4110 | fn writeSyntheticSections(self: *Elf) !void { |
| 4084 | const gpa = self.base.comp.gpa; | 4111 | const gpa = self.base.comp.gpa; |
| 4085 | const target = self.getTarget(); | ||
| 4086 | const slice = self.sections.slice(); | 4112 | const slice = self.sections.slice(); |
| 4087 | 4113 | ||
| 4088 | if (self.interp_section_index) |shndx| { | 4114 | if (self.interp_section_index) |shndx| { |
| 4089 | var buffer: [256]u8 = undefined; | 4115 | var buffer: [256]u8 = undefined; |
| 4090 | const interp = target.dynamic_linker.get().?; | 4116 | const interp = self.getTarget().dynamic_linker.get().?; |
| 4091 | @memcpy(buffer[0..interp.len], interp); | 4117 | @memcpy(buffer[0..interp.len], interp); |
| 4092 | buffer[interp.len] = 0; | 4118 | buffer[interp.len] = 0; |
| 4093 | const contents = buffer[0 .. interp.len + 1]; | 4119 | const contents = buffer[0 .. interp.len + 1]; |
| ... | @@ -4144,12 +4170,18 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4144,12 +4170,18 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4144 | } | 4170 | } |
| 4145 | 4171 | ||
| 4146 | if (self.eh_frame_section_index) |shndx| { | 4172 | if (self.eh_frame_section_index) |shndx| { |
| 4173 | const existing_size = existing_size: { | ||
| 4174 | const zo = self.zigObjectPtr() orelse break :existing_size 0; | ||
| 4175 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 4176 | break :existing_size sym.atom(self).?.size; | ||
| 4177 | }; | ||
| 4147 | const shdr = slice.items(.shdr)[shndx]; | 4178 | const shdr = slice.items(.shdr)[shndx]; |
| 4148 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 4179 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 4149 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 4180 | var buffer = try std.ArrayList(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); |
| 4150 | defer buffer.deinit(); | 4181 | defer buffer.deinit(); |
| 4151 | try eh_frame.writeEhFrame(self, buffer.writer()); | 4182 | try eh_frame.writeEhFrame(self, buffer.writer()); |
| 4152 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | 4183 | assert(buffer.items.len == sh_size - existing_size); |
| 4184 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); | ||
| 4153 | } | 4185 | } |
| 4154 | 4186 | ||
| 4155 | if (self.eh_frame_hdr_section_index) |shndx| { | 4187 | if (self.eh_frame_hdr_section_index) |shndx| { |
| ... | @@ -4222,7 +4254,6 @@ pub fn writeShStrtab(self: *Elf) !void { | ... | @@ -4222,7 +4254,6 @@ pub fn writeShStrtab(self: *Elf) !void { |
| 4222 | 4254 | ||
| 4223 | pub fn writeSymtab(self: *Elf) !void { | 4255 | pub fn writeSymtab(self: *Elf) !void { |
| 4224 | const gpa = self.base.comp.gpa; | 4256 | const gpa = self.base.comp.gpa; |
| 4225 | const target = self.getTarget(); | ||
| 4226 | const slice = self.sections.slice(); | 4257 | const slice = self.sections.slice(); |
| 4227 | const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?]; | 4258 | const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?]; |
| 4228 | const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?]; | 4259 | const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?]; |
| ... | @@ -4292,7 +4323,7 @@ pub fn writeSymtab(self: *Elf) !void { | ... | @@ -4292,7 +4323,7 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4292 | self.plt_got.writeSymtab(self); | 4323 | self.plt_got.writeSymtab(self); |
| 4293 | } | 4324 | } |
| 4294 | 4325 | ||
| 4295 | const foreign_endian = target.cpu.arch.endian() != builtin.cpu.arch.endian(); | 4326 | const foreign_endian = self.getTarget().cpu.arch.endian() != builtin.cpu.arch.endian(); |
| 4296 | switch (self.ptr_width) { | 4327 | switch (self.ptr_width) { |
| 4297 | .p32 => { | 4328 | .p32 => { |
| 4298 | const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len); | 4329 | const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len); |
| ... | @@ -4630,10 +4661,8 @@ pub fn isZigSection(self: Elf, shndx: u32) bool { | ... | @@ -4630,10 +4661,8 @@ pub fn isZigSection(self: Elf, shndx: u32) bool { |
| 4630 | self.zig_data_rel_ro_section_index, | 4661 | self.zig_data_rel_ro_section_index, |
| 4631 | self.zig_data_section_index, | 4662 | self.zig_data_section_index, |
| 4632 | self.zig_bss_section_index, | 4663 | self.zig_bss_section_index, |
| 4633 | }) |maybe_index| { | 4664 | }) |index| { |
| 4634 | if (maybe_index) |index| { | 4665 | if (index == shndx) return true; |
| 4635 | if (index == shndx) return true; | ||
| 4636 | } | ||
| 4637 | } | 4666 | } |
| 4638 | return false; | 4667 | return false; |
| 4639 | } | 4668 | } |
| ... | @@ -4648,10 +4677,8 @@ pub fn isDebugSection(self: Elf, shndx: u32) bool { | ... | @@ -4648,10 +4677,8 @@ pub fn isDebugSection(self: Elf, shndx: u32) bool { |
| 4648 | self.debug_line_str_section_index, | 4677 | self.debug_line_str_section_index, |
| 4649 | self.debug_loclists_section_index, | 4678 | self.debug_loclists_section_index, |
| 4650 | self.debug_rnglists_section_index, | 4679 | self.debug_rnglists_section_index, |
| 4651 | }) |maybe_index| { | 4680 | }) |index| { |
| 4652 | if (maybe_index) |index| { | 4681 | if (index == shndx) return true; |
| 4653 | if (index == shndx) return true; | ||
| 4654 | } | ||
| 4655 | } | 4682 | } |
| 4656 | return false; | 4683 | return false; |
| 4657 | } | 4684 | } |
src/link/Elf/ZigObject.zig+42-9| ... | @@ -49,6 +49,7 @@ debug_line_section_dirty: bool = false, | ... | @@ -49,6 +49,7 @@ debug_line_section_dirty: bool = false, |
| 49 | debug_line_str_section_dirty: bool = false, | 49 | debug_line_str_section_dirty: bool = false, |
| 50 | debug_loclists_section_dirty: bool = false, | 50 | debug_loclists_section_dirty: bool = false, |
| 51 | debug_rnglists_section_dirty: bool = false, | 51 | debug_rnglists_section_dirty: bool = false, |
| 52 | eh_frame_section_dirty: bool = false, | ||
| 52 | 53 | ||
| 53 | debug_info_index: ?Symbol.Index = null, | 54 | debug_info_index: ?Symbol.Index = null, |
| 54 | debug_abbrev_index: ?Symbol.Index = null, | 55 | debug_abbrev_index: ?Symbol.Index = null, |
| ... | @@ -58,6 +59,7 @@ debug_line_index: ?Symbol.Index = null, | ... | @@ -58,6 +59,7 @@ debug_line_index: ?Symbol.Index = null, |
| 58 | debug_line_str_index: ?Symbol.Index = null, | 59 | debug_line_str_index: ?Symbol.Index = null, |
| 59 | debug_loclists_index: ?Symbol.Index = null, | 60 | debug_loclists_index: ?Symbol.Index = null, |
| 60 | debug_rnglists_index: ?Symbol.Index = null, | 61 | debug_rnglists_index: ?Symbol.Index = null, |
| 62 | eh_frame_index: ?Symbol.Index = null, | ||
| 61 | 63 | ||
| 62 | pub const global_symbol_bit: u32 = 0x80000000; | 64 | pub const global_symbol_bit: u32 = 0x80000000; |
| 63 | pub const symbol_mask: u32 = 0x7fffffff; | 65 | pub const symbol_mask: u32 = 0x7fffffff; |
| ... | @@ -72,8 +74,6 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -72,8 +74,6 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 72 | const comp = elf_file.base.comp; | 74 | const comp = elf_file.base.comp; |
| 73 | const gpa = comp.gpa; | 75 | const gpa = comp.gpa; |
| 74 | const ptr_size = elf_file.ptrWidthBytes(); | 76 | const ptr_size = elf_file.ptrWidthBytes(); |
| 75 | const target = elf_file.getTarget(); | ||
| 76 | const ptr_bit_width = target.ptrBitWidth(); | ||
| 77 | 77 | ||
| 78 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section | 78 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section |
| 79 | try self.relocs.append(gpa, .{}); // null relocs section | 79 | try self.relocs.append(gpa, .{}); // null relocs section |
| ... | @@ -113,7 +113,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -113,7 +113,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 113 | .type = elf.PT_LOAD, | 113 | .type = elf.PT_LOAD, |
| 114 | .offset = off, | 114 | .offset = off, |
| 115 | .filesz = filesz, | 115 | .filesz = filesz, |
| 116 | .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000, | 116 | .addr = if (ptr_size >= 4) 0x4000000 else 0x4000, |
| 117 | .memsz = filesz, | 117 | .memsz = filesz, |
| 118 | .@"align" = elf_file.page_size, | 118 | .@"align" = elf_file.page_size, |
| 119 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, | 119 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, |
| ... | @@ -128,7 +128,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -128,7 +128,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 128 | .type = elf.PT_LOAD, | 128 | .type = elf.PT_LOAD, |
| 129 | .offset = off, | 129 | .offset = off, |
| 130 | .filesz = filesz, | 130 | .filesz = filesz, |
| 131 | .addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000, | 131 | .addr = if (ptr_size >= 4) 0xc000000 else 0xa000, |
| 132 | .memsz = filesz, | 132 | .memsz = filesz, |
| 133 | .@"align" = alignment, | 133 | .@"align" = alignment, |
| 134 | .flags = elf.PF_R | elf.PF_W, | 134 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -143,7 +143,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -143,7 +143,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 143 | .type = elf.PT_LOAD, | 143 | .type = elf.PT_LOAD, |
| 144 | .offset = off, | 144 | .offset = off, |
| 145 | .filesz = filesz, | 145 | .filesz = filesz, |
| 146 | .addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000, | 146 | .addr = if (ptr_size >= 4) 0x10000000 else 0xc000, |
| 147 | .memsz = filesz, | 147 | .memsz = filesz, |
| 148 | .@"align" = alignment, | 148 | .@"align" = alignment, |
| 149 | .flags = elf.PF_R | elf.PF_W, | 149 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -154,7 +154,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -154,7 +154,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 154 | const alignment = elf_file.page_size; | 154 | const alignment = elf_file.page_size; |
| 155 | elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{ | 155 | elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{ |
| 156 | .type = elf.PT_LOAD, | 156 | .type = elf.PT_LOAD, |
| 157 | .addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000, | 157 | .addr = if (ptr_size >= 4) 0x14000000 else 0xf000, |
| 158 | .memsz = 1024, | 158 | .memsz = 1024, |
| 159 | .@"align" = alignment, | 159 | .@"align" = alignment, |
| 160 | .flags = elf.PF_R | elf.PF_W, | 160 | .flags = elf.PF_R | elf.PF_W, |
| ... | @@ -354,6 +354,20 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ... | @@ -354,6 +354,20 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { |
| 354 | self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?); | 354 | self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?); |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | if (elf_file.eh_frame_section_index == null) { | ||
| 358 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ | ||
| 359 | .name = try elf_file.insertShString(".eh_frame"), | ||
| 360 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) | ||
| 361 | elf.SHT_X86_64_UNWIND | ||
| 362 | else | ||
| 363 | elf.SHT_PROGBITS, | ||
| 364 | .flags = elf.SHF_ALLOC, | ||
| 365 | .addralign = ptr_size, | ||
| 366 | }); | ||
| 367 | self.eh_frame_section_dirty = true; | ||
| 368 | self.eh_frame_index = try addSectionSymbol(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), elf_file.eh_frame_section_index.?); | ||
| 369 | } | ||
| 370 | |||
| 357 | try dwarf.initMetadata(); | 371 | try dwarf.initMetadata(); |
| 358 | self.dwarf = dwarf; | 372 | self.dwarf = dwarf; |
| 359 | }, | 373 | }, |
| ... | @@ -460,6 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -460,6 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 460 | self.debug_line_str_index.?, | 474 | self.debug_line_str_index.?, |
| 461 | self.debug_loclists_index.?, | 475 | self.debug_loclists_index.?, |
| 462 | self.debug_rnglists_index.?, | 476 | self.debug_rnglists_index.?, |
| 477 | self.eh_frame_index.?, | ||
| 463 | }, [_]*Dwarf.Section{ | 478 | }, [_]*Dwarf.Section{ |
| 464 | &dwarf.debug_info.section, | 479 | &dwarf.debug_info.section, |
| 465 | &dwarf.debug_abbrev.section, | 480 | &dwarf.debug_abbrev.section, |
| ... | @@ -469,7 +484,18 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -469,7 +484,18 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 469 | &dwarf.debug_line_str.section, | 484 | &dwarf.debug_line_str.section, |
| 470 | &dwarf.debug_loclists.section, | 485 | &dwarf.debug_loclists.section, |
| 471 | &dwarf.debug_rnglists.section, | 486 | &dwarf.debug_rnglists.section, |
| 472 | }) |sym_index, sect| { | 487 | &dwarf.debug_frame.section, |
| 488 | }, [_]Dwarf.Section.Index{ | ||
| 489 | .debug_info, | ||
| 490 | .debug_abbrev, | ||
| 491 | .debug_str, | ||
| 492 | .debug_aranges, | ||
| 493 | .debug_line, | ||
| 494 | .debug_line_str, | ||
| 495 | .debug_loclists, | ||
| 496 | .debug_rnglists, | ||
| 497 | .debug_frame, | ||
| 498 | }) |sym_index, sect, sect_index| { | ||
| 473 | const sym = self.symbol(sym_index); | 499 | const sym = self.symbol(sym_index); |
| 474 | const atom_ptr = self.atom(sym.ref.index).?; | 500 | const atom_ptr = self.atom(sym.ref.index).?; |
| 475 | if (!atom_ptr.alive) continue; | 501 | if (!atom_ptr.alive) continue; |
| ... | @@ -509,6 +535,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -509,6 +535,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 509 | for (unit.cross_section_relocs.items) |reloc| { | 535 | for (unit.cross_section_relocs.items) |reloc| { |
| 510 | const target_sym_index = switch (reloc.target_sec) { | 536 | const target_sym_index = switch (reloc.target_sec) { |
| 511 | .debug_abbrev => self.debug_abbrev_index.?, | 537 | .debug_abbrev => self.debug_abbrev_index.?, |
| 538 | .debug_aranges => self.debug_aranges_index.?, | ||
| 539 | .debug_frame => self.eh_frame_index.?, | ||
| 512 | .debug_info => self.debug_info_index.?, | 540 | .debug_info => self.debug_info_index.?, |
| 513 | .debug_line => self.debug_line_index.?, | 541 | .debug_line => self.debug_line_index.?, |
| 514 | .debug_line_str => self.debug_line_str_index.?, | 542 | .debug_line_str => self.debug_line_str_index.?, |
| ... | @@ -547,7 +575,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -547,7 +575,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 547 | entry.external_relocs.items.len); | 575 | entry.external_relocs.items.len); |
| 548 | for (entry.cross_entry_relocs.items) |reloc| { | 576 | for (entry.cross_entry_relocs.items) |reloc| { |
| 549 | const r_offset = entry_off + reloc.source_off; | 577 | const r_offset = entry_off + reloc.source_off; |
| 550 | const r_addend: i64 = @intCast(unit.off + reloc.target_off + unit.header_len + unit.getEntry(reloc.target_entry).assertNonEmpty(unit, sect, dwarf).off); | 578 | const r_addend: i64 = @intCast(unit.off + reloc.target_off + (if (reloc.target_entry.unwrap()) |target_entry| |
| 579 | unit.header_len + unit.getEntry(target_entry).assertNonEmpty(unit, sect, dwarf).off | ||
| 580 | else | ||
| 581 | 0)); | ||
| 551 | const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); | 582 | const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); |
| 552 | log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ | 583 | log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ |
| 553 | self.symbol(sym_index).name(elf_file), | 584 | self.symbol(sym_index).name(elf_file), |
| ... | @@ -584,6 +615,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -584,6 +615,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 584 | for (entry.cross_section_relocs.items) |reloc| { | 615 | for (entry.cross_section_relocs.items) |reloc| { |
| 585 | const target_sym_index = switch (reloc.target_sec) { | 616 | const target_sym_index = switch (reloc.target_sec) { |
| 586 | .debug_abbrev => self.debug_abbrev_index.?, | 617 | .debug_abbrev => self.debug_abbrev_index.?, |
| 618 | .debug_aranges => self.debug_aranges_index.?, | ||
| 619 | .debug_frame => self.eh_frame_index.?, | ||
| 587 | .debug_info => self.debug_info_index.?, | 620 | .debug_info => self.debug_info_index.?, |
| 588 | .debug_line => self.debug_line_index.?, | 621 | .debug_line => self.debug_line_index.?, |
| 589 | .debug_line_str => self.debug_line_str_index.?, | 622 | .debug_line_str => self.debug_line_str_index.?, |
| ... | @@ -617,7 +650,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -617,7 +650,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 617 | const target_sym = self.symbol(reloc.target_sym); | 650 | const target_sym = self.symbol(reloc.target_sym); |
| 618 | const r_offset = entry_off + reloc.source_off; | 651 | const r_offset = entry_off + reloc.source_off; |
| 619 | const r_addend: i64 = @intCast(reloc.target_off); | 652 | const r_addend: i64 = @intCast(reloc.target_off); |
| 620 | const r_type = relocation.dwarf.externalRelocType(target_sym.*, dwarf.address_size, cpu_arch); | 653 | const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch); |
| 621 | log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ | 654 | log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ |
| 622 | target_sym.name(elf_file), | 655 | target_sym.name(elf_file), |
| 623 | r_offset, | 656 | r_offset, |
src/link/Elf/relocatable.zig+27-15| ... | @@ -289,8 +289,6 @@ fn claimUnresolved(elf_file: *Elf) void { | ... | @@ -289,8 +289,6 @@ fn claimUnresolved(elf_file: *Elf) void { |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | fn initSections(elf_file: *Elf) !void { | 291 | fn initSections(elf_file: *Elf) !void { |
| 292 | const ptr_size = elf_file.ptrWidthBytes(); | ||
| 293 | |||
| 294 | for (elf_file.objects.items) |index| { | 292 | for (elf_file.objects.items) |index| { |
| 295 | const object = elf_file.file(index).?.object; | 293 | const object = elf_file.file(index).?.object; |
| 296 | try object.initOutputSections(elf_file); | 294 | try object.initOutputSections(elf_file); |
| ... | @@ -306,13 +304,18 @@ fn initSections(elf_file: *Elf) !void { | ... | @@ -306,13 +304,18 @@ fn initSections(elf_file: *Elf) !void { |
| 306 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; | 304 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; |
| 307 | } else false; | 305 | } else false; |
| 308 | if (needs_eh_frame) { | 306 | if (needs_eh_frame) { |
| 309 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ | 307 | if (elf_file.eh_frame_section_index == null) { |
| 310 | .name = try elf_file.insertShString(".eh_frame"), | 308 | elf_file.eh_frame_section_index = try elf_file.addSection(.{ |
| 311 | .type = elf.SHT_PROGBITS, | 309 | .name = try elf_file.insertShString(".eh_frame"), |
| 312 | .flags = elf.SHF_ALLOC, | 310 | .type = if (elf_file.getTarget().cpu.arch == .x86_64) |
| 313 | .addralign = ptr_size, | 311 | elf.SHT_X86_64_UNWIND |
| 314 | .offset = std.math.maxInt(u64), | 312 | else |
| 315 | }); | 313 | elf.SHT_PROGBITS, |
| 314 | .flags = elf.SHF_ALLOC, | ||
| 315 | .addralign = elf_file.ptrWidthBytes(), | ||
| 316 | .offset = std.math.maxInt(u64), | ||
| 317 | }); | ||
| 318 | } | ||
| 316 | elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr( | 319 | elf_file.eh_frame_rela_section_index = try elf_file.addRelaShdr( |
| 317 | try elf_file.insertShString(".rela.eh_frame"), | 320 | try elf_file.insertShString(".rela.eh_frame"), |
| 318 | elf_file.eh_frame_section_index.?, | 321 | elf_file.eh_frame_section_index.?, |
| ... | @@ -373,7 +376,11 @@ fn updateSectionSizes(elf_file: *Elf) !void { | ... | @@ -373,7 +376,11 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 373 | } | 376 | } |
| 374 | 377 | ||
| 375 | if (elf_file.eh_frame_section_index) |index| { | 378 | if (elf_file.eh_frame_section_index) |index| { |
| 376 | slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); | 379 | slice.items(.shdr)[index].sh_size = existing_size: { |
| 380 | const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; | ||
| 381 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 382 | break :existing_size sym.atom(elf_file).?.size; | ||
| 383 | } + try eh_frame.calcEhFrameSize(elf_file); | ||
| 377 | } | 384 | } |
| 378 | if (elf_file.eh_frame_rela_section_index) |index| { | 385 | if (elf_file.eh_frame_rela_section_index) |index| { |
| 379 | const shdr = &slice.items(.shdr)[index]; | 386 | const shdr = &slice.items(.shdr)[index]; |
| ... | @@ -526,17 +533,22 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -526,17 +533,22 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 526 | } | 533 | } |
| 527 | 534 | ||
| 528 | if (elf_file.eh_frame_section_index) |shndx| { | 535 | if (elf_file.eh_frame_section_index) |shndx| { |
| 536 | const existing_size = existing_size: { | ||
| 537 | const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; | ||
| 538 | const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); | ||
| 539 | break :existing_size sym.atom(elf_file).?.size; | ||
| 540 | }; | ||
| 529 | const shdr = slice.items(.shdr)[shndx]; | 541 | const shdr = slice.items(.shdr)[shndx]; |
| 530 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 542 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 531 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 543 | var buffer = try std.ArrayList(u8).initCapacity(gpa, @intCast(sh_size - existing_size)); |
| 532 | defer buffer.deinit(); | 544 | defer buffer.deinit(); |
| 533 | try eh_frame.writeEhFrameObject(elf_file, buffer.writer()); | 545 | try eh_frame.writeEhFrameObject(elf_file, buffer.writer()); |
| 534 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ | 546 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ |
| 535 | shdr.sh_offset, | 547 | shdr.sh_offset + existing_size, |
| 536 | shdr.sh_offset + shdr.sh_size, | 548 | shdr.sh_offset + sh_size, |
| 537 | }); | 549 | }); |
| 538 | assert(buffer.items.len == sh_size); | 550 | assert(buffer.items.len == sh_size - existing_size); |
| 539 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | 551 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); |
| 540 | } | 552 | } |
| 541 | if (elf_file.eh_frame_rela_section_index) |shndx| { | 553 | if (elf_file.eh_frame_rela_section_index) |shndx| { |
| 542 | const shdr = slice.items(.shdr)[shndx]; | 554 | const shdr = slice.items(.shdr)[shndx]; |
src/link/Elf/relocation.zig+17-10| ... | @@ -108,20 +108,27 @@ pub const dwarf = struct { | ... | @@ -108,20 +108,27 @@ pub const dwarf = struct { |
| 108 | 108 | ||
| 109 | pub fn externalRelocType( | 109 | pub fn externalRelocType( |
| 110 | target: Symbol, | 110 | target: Symbol, |
| 111 | source_section: Dwarf.Section.Index, | ||
| 111 | address_size: Dwarf.AddressSize, | 112 | address_size: Dwarf.AddressSize, |
| 112 | cpu_arch: std.Target.Cpu.Arch, | 113 | cpu_arch: std.Target.Cpu.Arch, |
| 113 | ) u32 { | 114 | ) u32 { |
| 114 | return switch (cpu_arch) { | 115 | return switch (cpu_arch) { |
| 115 | .x86_64 => @intFromEnum(switch (address_size) { | 116 | .x86_64 => @intFromEnum(@as(elf.R_X86_64, switch (source_section) { |
| 116 | .@"32" => if (target.flags.is_tls) elf.R_X86_64.DTPOFF32 else .@"32", | 117 | else => switch (address_size) { |
| 117 | .@"64" => if (target.flags.is_tls) elf.R_X86_64.DTPOFF64 else .@"64", | 118 | .@"32" => if (target.flags.is_tls) .DTPOFF32 else .@"32", |
| 118 | else => unreachable, | 119 | .@"64" => if (target.flags.is_tls) .DTPOFF64 else .@"64", |
| 119 | }), | 120 | else => unreachable, |
| 120 | .riscv64 => @intFromEnum(switch (address_size) { | 121 | }, |
| 121 | .@"32" => elf.R_RISCV.@"32", | 122 | .debug_frame => .PC32, |
| 122 | .@"64" => elf.R_RISCV.@"64", | 123 | })), |
| 123 | else => unreachable, | 124 | .riscv64 => @intFromEnum(@as(elf.R_RISCV, switch (source_section) { |
| 124 | }), | 125 | else => switch (address_size) { |
| 126 | .@"32" => .@"32", | ||
| 127 | .@"64" => .@"64", | ||
| 128 | else => unreachable, | ||
| 129 | }, | ||
| 130 | .debug_frame => unreachable, | ||
| 131 | })), | ||
| 125 | else => @panic("TODO unhandled cpu arch"), | 132 | else => @panic("TODO unhandled cpu arch"), |
| 126 | }; | 133 | }; |
| 127 | } | 134 | } |
src/link/MachO.zig+6-6| ... | @@ -3411,9 +3411,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo | ... | @@ -3411,9 +3411,7 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo |
| 3411 | 3411 | ||
| 3412 | if (!sect.isZerofill()) { | 3412 | if (!sect.isZerofill()) { |
| 3413 | const allocated_size = self.allocatedSize(sect.offset); | 3413 | const allocated_size = self.allocatedSize(sect.offset); |
| 3414 | if (sect.offset + allocated_size == std.math.maxInt(u64)) { | 3414 | if (needed_size > allocated_size) { |
| 3415 | try self.base.file.?.setEndPos(sect.offset + needed_size); | ||
| 3416 | } else if (needed_size > allocated_size) { | ||
| 3417 | const existing_size = sect.size; | 3415 | const existing_size = sect.size; |
| 3418 | sect.size = 0; | 3416 | sect.size = 0; |
| 3419 | 3417 | ||
| ... | @@ -3431,6 +3429,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo | ... | @@ -3431,6 +3429,8 @@ fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !vo |
| 3431 | try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size); | 3429 | try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size); |
| 3432 | 3430 | ||
| 3433 | sect.offset = @intCast(new_offset); | 3431 | sect.offset = @intCast(new_offset); |
| 3432 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { | ||
| 3433 | try self.base.file.?.setEndPos(sect.offset + needed_size); | ||
| 3434 | } | 3434 | } |
| 3435 | seg.filesize = needed_size; | 3435 | seg.filesize = needed_size; |
| 3436 | } | 3436 | } |
| ... | @@ -3456,9 +3456,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void | ... | @@ -3456,9 +3456,7 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void |
| 3456 | 3456 | ||
| 3457 | if (!sect.isZerofill()) { | 3457 | if (!sect.isZerofill()) { |
| 3458 | const allocated_size = self.allocatedSize(sect.offset); | 3458 | const allocated_size = self.allocatedSize(sect.offset); |
| 3459 | if (sect.offset + allocated_size == std.math.maxInt(u64)) { | 3459 | if (needed_size > allocated_size) { |
| 3460 | try self.base.file.?.setEndPos(sect.offset + needed_size); | ||
| 3461 | } else if (needed_size > allocated_size) { | ||
| 3462 | const existing_size = sect.size; | 3460 | const existing_size = sect.size; |
| 3463 | sect.size = 0; | 3461 | sect.size = 0; |
| 3464 | 3462 | ||
| ... | @@ -3480,6 +3478,8 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void | ... | @@ -3480,6 +3478,8 @@ fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void |
| 3480 | 3478 | ||
| 3481 | sect.offset = @intCast(new_offset); | 3479 | sect.offset = @intCast(new_offset); |
| 3482 | sect.addr = new_addr; | 3480 | sect.addr = new_addr; |
| 3481 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { | ||
| 3482 | try self.base.file.?.setEndPos(sect.offset + needed_size); | ||
| 3483 | } | 3483 | } |
| 3484 | } | 3484 | } |
| 3485 | sect.size = needed_size; | 3485 | sect.size = needed_size; |
src/link/MachO/DebugSymbols.zig+3-3| ... | @@ -105,9 +105,7 @@ pub fn growSection( | ... | @@ -105,9 +105,7 @@ pub fn growSection( |
| 105 | const sect = self.getSectionPtr(sect_index); | 105 | const sect = self.getSectionPtr(sect_index); |
| 106 | 106 | ||
| 107 | const allocated_size = self.allocatedSize(sect.offset); | 107 | const allocated_size = self.allocatedSize(sect.offset); |
| 108 | if (sect.offset + allocated_size == std.math.maxInt(u64)) { | 108 | if (needed_size > allocated_size) { |
| 109 | try self.file.setEndPos(sect.offset + needed_size); | ||
| 110 | } else if (needed_size > allocated_size) { | ||
| 111 | const existing_size = sect.size; | 109 | const existing_size = sect.size; |
| 112 | sect.size = 0; // free the space | 110 | sect.size = 0; // free the space |
| 113 | const new_offset = try self.findFreeSpace(needed_size, 1); | 111 | const new_offset = try self.findFreeSpace(needed_size, 1); |
| ... | @@ -130,6 +128,8 @@ pub fn growSection( | ... | @@ -130,6 +128,8 @@ pub fn growSection( |
| 130 | } | 128 | } |
| 131 | 129 | ||
| 132 | sect.offset = @intCast(new_offset); | 130 | sect.offset = @intCast(new_offset); |
| 131 | } else if (sect.offset + allocated_size == std.math.maxInt(u64)) { | ||
| 132 | try self.file.setEndPos(sect.offset + needed_size); | ||
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | sect.size = needed_size; | 135 | sect.size = needed_size; |