authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-14 16:01:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-14 16:01:58+02:00
log0ca0e884639bcd317e533735f3154ba27fc5934d
treec713d6ae48df5b0f5951e3cd825f458c5ec09ecd
parent5fc25ee8e46e55a399216fc32a786ca7e4de55f7

zld: handle __eh_frame section


4 files changed, 87 insertions(+), 22 deletions(-)

src/link/MachO/Zld.zig+38-18
......@@ -65,9 +65,9 @@ stub_helper_section_index: ?u16 = null,
6565text_const_section_index: ?u16 = null,
6666cstring_section_index: ?u16 = null,
6767ustring_section_index: ?u16 = null,
68gcc_except_tab: ?u16 = null,
69unwind_info: ?u16 = null,
70eh_frame: ?u16 = null,
68gcc_except_tab_section_index: ?u16 = null,
69unwind_info_section_index: ?u16 = null,
70eh_frame_section_index: ?u16 = null,
7171
7272// __DATA_CONST segment sections
7373got_section_index: ?u16 = null,
......@@ -412,7 +412,7 @@ fn mapAndUpdateSections(
412412 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
413413 const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);
414414
415 log.warn("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
415 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
416416 object.name.?,
417417 parseName(&source_sect.inner.segname),
418418 parseName(&source_sect.inner.sectname),
......@@ -625,8 +625,24 @@ fn updateMetadata(self: *Zld) !void {
625625 },
626626 macho.S_COALESCED => {
627627 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
628 log.debug("TODO __eh_frame section: type 0x{x}, name '{s},{s}'", .{
629 sect.flags(), segname, sectname,
628 // TODO I believe __eh_frame is currently part of __unwind_info section
629 // in the latest ld64 output.
630 if (self.eh_frame_section_index != null) continue;
631
632 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
633 try text_seg.addSection(self.allocator, .{
634 .sectname = makeStaticString("__eh_frame"),
635 .segname = makeStaticString("__TEXT"),
636 .addr = 0,
637 .size = 0,
638 .offset = 0,
639 .@"align" = 0,
640 .reloff = 0,
641 .nreloc = 0,
642 .flags = macho.S_REGULAR,
643 .reserved1 = 0,
644 .reserved2 = 0,
645 .reserved3 = 0,
630646 });
631647 continue;
632648 }
......@@ -682,9 +698,9 @@ fn updateMetadata(self: *Zld) !void {
682698 .reserved3 = 0,
683699 });
684700 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
685 if (self.gcc_except_tab != null) continue;
701 if (self.gcc_except_tab_section_index != null) continue;
686702
687 self.gcc_except_tab = @intCast(u16, text_seg.sections.items.len);
703 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
688704 try text_seg.addSection(self.allocator, .{
689705 .sectname = makeStaticString("__gcc_except_tab"),
690706 .segname = makeStaticString("__TEXT"),
......@@ -818,7 +834,7 @@ fn updateMetadata(self: *Zld) !void {
818834 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
819835 continue;
820836 }
821 log.warn("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
837 log.debug("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
822838 }
823839 }
824840
......@@ -976,7 +992,13 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
976992 };
977993 },
978994 macho.S_COALESCED => {
979 // TODO coalesced sections
995 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
996 break :blk .{
997 .seg = self.text_segment_cmd_index.?,
998 .sect = self.eh_frame_section_index.?,
999 };
1000 }
1001
9801002 break :blk null;
9811003 },
9821004 macho.S_REGULAR => {
......@@ -1000,7 +1022,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
10001022 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
10011023 break :blk .{
10021024 .seg = self.text_segment_cmd_index.?,
1003 .sect = self.gcc_except_tab.?,
1025 .sect = self.gcc_except_tab_section_index.?,
10041026 };
10051027 } else {
10061028 break :blk .{
......@@ -1058,10 +1080,11 @@ fn sortSections(self: *Zld) !void {
10581080 &self.text_section_index,
10591081 &self.stubs_section_index,
10601082 &self.stub_helper_section_index,
1061 &self.gcc_except_tab,
1062 &self.text_const_section_index,
1083 &self.gcc_except_tab_section_index,
10631084 &self.cstring_section_index,
10641085 &self.ustring_section_index,
1086 &self.text_const_section_index,
1087 &self.eh_frame_section_index,
10651088 };
10661089 for (indices) |maybe_index| {
10671090 const new_index: u16 = if (maybe_index.*) |index| blk: {
......@@ -1846,7 +1869,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
18461869 for (relocs) |rel| {
18471870 switch (rel.@"type") {
18481871 .unsigned => continue,
1849 .got_page, .got_page_off, .got_load, .got => {
1872 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
18501873 const sym = rel.target.symbol.getTopmostAlias();
18511874 if (sym.got_index != null) continue;
18521875
......@@ -1864,9 +1887,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
18641887
18651888 if (sym.stubs_index != null) continue;
18661889 if (sym.@"type" != .proxy) continue;
1867 // if (sym.cast(Symbol.Regular)) |reg| {
1868 // if (!reg.weak_ref) continue;
1869 // }
18701890
18711891 const index = @intCast(u32, self.stubs.items.len);
18721892 sym.stubs_index = index;
......@@ -1977,7 +1997,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
19771997 });
19781998 }
19791999 },
1980 .got_page, .got_page_off, .got_load, .got => {
2000 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
19812001 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
19822002 const got = dc_seg.sections.items[self.got_section_index.?];
19832003 const final = rel.target.symbol.getTopmostAlias();
src/link/MachO/reloc.zig+2
......@@ -52,6 +52,7 @@ pub const Relocation = struct {
5252 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),
5353 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),
5454 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),
55 .pointer_to_got => @fieldParentPtr(aarch64.PointerToGot, "base", base).resolve(args),
5556 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),
5657 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),
5758 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),
......@@ -70,6 +71,7 @@ pub const Relocation = struct {
7071 got_page,
7172 got_page_off,
7273 tlvp_page,
74 pointer_to_got,
7375 tlvp_page_off,
7476 branch_x86_64,
7577 signed,
src/link/MachO/reloc/aarch64.zig+40-3
......@@ -141,6 +141,20 @@ pub const GotPageOff = struct {
141141 }
142142};
143143
144pub const PointerToGot = struct {
145 base: Relocation,
146
147 pub const base_type: Relocation.Type = .pointer_to_got;
148
149 pub fn resolve(ptr_to_got: PointerToGot, args: Relocation.ResolveArgs) !void {
150 const result = try math.cast(i32, @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr));
151
152 log.debug(" | calculated value 0x{x}", .{result});
153
154 mem.writeIntLittle(u32, ptr_to_got.base.code[0..4], @bitCast(u32, result));
155 }
156};
157
144158pub const TlvpPage = struct {
145159 base: Relocation,
146160 /// Always .PCRelativeAddress
......@@ -228,9 +242,7 @@ pub const Parser = struct {
228242 try parser.parseTlvpLoadPageOff(rel);
229243 },
230244 .ARM64_RELOC_POINTER_TO_GOT => {
231 // TODO Handle pointer to GOT. This reloc seems to appear in
232 // __LD,__compact_unwind section which we currently don't handle.
233 log.debug("Unhandled relocation ARM64_RELOC_POINTER_TO_GOT", .{});
245 try parser.parsePointerToGot(rel);
234246 },
235247 }
236248 }
......@@ -583,6 +595,31 @@ pub const Parser = struct {
583595 log.debug(" | emitting {}", .{unsigned});
584596 try parser.parsed.append(&unsigned.base);
585597 }
598
599 fn parsePointerToGot(parser: *Parser, rel: macho.relocation_info) !void {
600 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
601 assert(rel_type == .ARM64_RELOC_POINTER_TO_GOT);
602 assert(rel.r_pcrel == 1);
603 assert(rel.r_length == 2);
604
605 var ptr_to_got = try parser.allocator.create(PointerToGot);
606 errdefer parser.allocator.destroy(ptr_to_got);
607
608 const target = Relocation.Target.from_reloc(rel, parser.symbols);
609 const offset = @intCast(u32, rel.r_address);
610
611 ptr_to_got.* = .{
612 .base = .{
613 .@"type" = .pointer_to_got,
614 .code = parser.code[offset..][0..4],
615 .offset = offset,
616 .target = target,
617 },
618 };
619
620 log.debug(" | emitting {}", .{ptr_to_got});
621 try parser.parsed.append(&ptr_to_got.base);
622 }
586623};
587624
588625inline fn isArithmeticOp(inst: *const [4]u8) bool {
src/link/MachO/reloc/x86_64.zig+7-1
......@@ -66,11 +66,15 @@ pub const GotLoad = struct {
6666
6767pub const Got = struct {
6868 base: Relocation,
69 addend: i32,
6970
7071 pub const base_type: Relocation.Type = .got;
7172
7273 pub fn resolve(got: Got, args: Relocation.ResolveArgs) !void {
73 const displacement = try math.cast(i32, @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4);
74 const displacement = try math.cast(
75 i32,
76 @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4 + got.addend,
77 );
7478 log.debug(" | displacement 0x{x}", .{displacement});
7579 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));
7680 }
......@@ -237,6 +241,7 @@ pub const Parser = struct {
237241 const offset = @intCast(u32, rel.r_address);
238242 const inst = parser.code[offset..][0..4];
239243 const target = Relocation.Target.from_reloc(rel, parser.symbols);
244 const addend = mem.readIntLittle(i32, inst);
240245
241246 var got = try parser.allocator.create(Got);
242247 errdefer parser.allocator.destroy(got);
......@@ -248,6 +253,7 @@ pub const Parser = struct {
248253 .offset = offset,
249254 .target = target,
250255 },
256 .addend = addend,
251257 };
252258
253259 log.debug(" | emitting {}", .{got});