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,...@@ -65,9 +65,9 @@ stub_helper_section_index: ?u16 = null,
65text_const_section_index: ?u16 = null,65text_const_section_index: ?u16 = null,
66cstring_section_index: ?u16 = null,66cstring_section_index: ?u16 = null,
67ustring_section_index: ?u16 = null,67ustring_section_index: ?u16 = null,
68gcc_except_tab: ?u16 = null,68gcc_except_tab_section_index: ?u16 = null,
69unwind_info: ?u16 = null,69unwind_info_section_index: ?u16 = null,
70eh_frame: ?u16 = null,70eh_frame_section_index: ?u16 = null,
7171
72// __DATA_CONST segment sections72// __DATA_CONST segment sections
73got_section_index: ?u16 = null,73got_section_index: ?u16 = null,
...@@ -412,7 +412,7 @@ fn mapAndUpdateSections(...@@ -412,7 +412,7 @@ fn mapAndUpdateSections(
412 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);412 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
413 const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);413 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}", .{
416 object.name.?,416 object.name.?,
417 parseName(&source_sect.inner.segname),417 parseName(&source_sect.inner.segname),
418 parseName(&source_sect.inner.sectname),418 parseName(&source_sect.inner.sectname),
...@@ -625,8 +625,24 @@ fn updateMetadata(self: *Zld) !void {...@@ -625,8 +625,24 @@ fn updateMetadata(self: *Zld) !void {
625 },625 },
626 macho.S_COALESCED => {626 macho.S_COALESCED => {
627 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {627 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}'", .{628 // TODO I believe __eh_frame is currently part of __unwind_info section
629 sect.flags(), segname, sectname,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,
630 });646 });
631 continue;647 continue;
632 }648 }
...@@ -682,9 +698,9 @@ fn updateMetadata(self: *Zld) !void {...@@ -682,9 +698,9 @@ fn updateMetadata(self: *Zld) !void {
682 .reserved3 = 0,698 .reserved3 = 0,
683 });699 });
684 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {700 } 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);
688 try text_seg.addSection(self.allocator, .{704 try text_seg.addSection(self.allocator, .{
689 .sectname = makeStaticString("__gcc_except_tab"),705 .sectname = makeStaticString("__gcc_except_tab"),
690 .segname = makeStaticString("__TEXT"),706 .segname = makeStaticString("__TEXT"),
...@@ -818,7 +834,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -818,7 +834,7 @@ fn updateMetadata(self: *Zld) !void {
818 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);834 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
819 continue;835 continue;
820 }836 }
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() });
822 }838 }
823 }839 }
824840
...@@ -976,7 +992,13 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {...@@ -976,7 +992,13 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
976 };992 };
977 },993 },
978 macho.S_COALESCED => {994 macho.S_COALESCED => {
979 // TODO coalesced sections995 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
980 break :blk null;1002 break :blk null;
981 },1003 },
982 macho.S_REGULAR => {1004 macho.S_REGULAR => {
...@@ -1000,7 +1022,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {...@@ -1000,7 +1022,7 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
1000 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {1022 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
1001 break :blk .{1023 break :blk .{
1002 .seg = self.text_segment_cmd_index.?,1024 .seg = self.text_segment_cmd_index.?,
1003 .sect = self.gcc_except_tab.?,1025 .sect = self.gcc_except_tab_section_index.?,
1004 };1026 };
1005 } else {1027 } else {
1006 break :blk .{1028 break :blk .{
...@@ -1058,10 +1080,11 @@ fn sortSections(self: *Zld) !void {...@@ -1058,10 +1080,11 @@ fn sortSections(self: *Zld) !void {
1058 &self.text_section_index,1080 &self.text_section_index,
1059 &self.stubs_section_index,1081 &self.stubs_section_index,
1060 &self.stub_helper_section_index,1082 &self.stub_helper_section_index,
1061 &self.gcc_except_tab,1083 &self.gcc_except_tab_section_index,
1062 &self.text_const_section_index,
1063 &self.cstring_section_index,1084 &self.cstring_section_index,
1064 &self.ustring_section_index,1085 &self.ustring_section_index,
1086 &self.text_const_section_index,
1087 &self.eh_frame_section_index,
1065 };1088 };
1066 for (indices) |maybe_index| {1089 for (indices) |maybe_index| {
1067 const new_index: u16 = if (maybe_index.*) |index| blk: {1090 const new_index: u16 = if (maybe_index.*) |index| blk: {
...@@ -1846,7 +1869,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1846,7 +1869,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1846 for (relocs) |rel| {1869 for (relocs) |rel| {
1847 switch (rel.@"type") {1870 switch (rel.@"type") {
1848 .unsigned => continue,1871 .unsigned => continue,
1849 .got_page, .got_page_off, .got_load, .got => {1872 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1850 const sym = rel.target.symbol.getTopmostAlias();1873 const sym = rel.target.symbol.getTopmostAlias();
1851 if (sym.got_index != null) continue;1874 if (sym.got_index != null) continue;
18521875
...@@ -1864,9 +1887,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1864,9 +1887,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
18641887
1865 if (sym.stubs_index != null) continue;1888 if (sym.stubs_index != null) continue;
1866 if (sym.@"type" != .proxy) continue;1889 if (sym.@"type" != .proxy) continue;
1867 // if (sym.cast(Symbol.Regular)) |reg| {
1868 // if (!reg.weak_ref) continue;
1869 // }
18701890
1871 const index = @intCast(u32, self.stubs.items.len);1891 const index = @intCast(u32, self.stubs.items.len);
1872 sym.stubs_index = index;1892 sym.stubs_index = index;
...@@ -1977,7 +1997,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1977,7 +1997,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1977 });1997 });
1978 }1998 }
1979 },1999 },
1980 .got_page, .got_page_off, .got_load, .got => {2000 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1981 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2001 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1982 const got = dc_seg.sections.items[self.got_section_index.?];2002 const got = dc_seg.sections.items[self.got_section_index.?];
1983 const final = rel.target.symbol.getTopmostAlias();2003 const final = rel.target.symbol.getTopmostAlias();
src/link/MachO/reloc.zig+2
...@@ -52,6 +52,7 @@ pub const Relocation = struct {...@@ -52,6 +52,7 @@ pub const Relocation = struct {
52 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),52 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),
53 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),53 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),
54 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),54 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),
55 .pointer_to_got => @fieldParentPtr(aarch64.PointerToGot, "base", base).resolve(args),
55 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),56 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),
56 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),57 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),
57 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),58 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),
...@@ -70,6 +71,7 @@ pub const Relocation = struct {...@@ -70,6 +71,7 @@ pub const Relocation = struct {
70 got_page,71 got_page,
71 got_page_off,72 got_page_off,
72 tlvp_page,73 tlvp_page,
74 pointer_to_got,
73 tlvp_page_off,75 tlvp_page_off,
74 branch_x86_64,76 branch_x86_64,
75 signed,77 signed,
src/link/MachO/reloc/aarch64.zig+40-3
...@@ -141,6 +141,20 @@ pub const GotPageOff = struct {...@@ -141,6 +141,20 @@ pub const GotPageOff = struct {
141 }141 }
142};142};
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
144pub const TlvpPage = struct {158pub const TlvpPage = struct {
145 base: Relocation,159 base: Relocation,
146 /// Always .PCRelativeAddress160 /// Always .PCRelativeAddress
...@@ -228,9 +242,7 @@ pub const Parser = struct {...@@ -228,9 +242,7 @@ pub const Parser = struct {
228 try parser.parseTlvpLoadPageOff(rel);242 try parser.parseTlvpLoadPageOff(rel);
229 },243 },
230 .ARM64_RELOC_POINTER_TO_GOT => {244 .ARM64_RELOC_POINTER_TO_GOT => {
231 // TODO Handle pointer to GOT. This reloc seems to appear in245 try parser.parsePointerToGot(rel);
232 // __LD,__compact_unwind section which we currently don't handle.
233 log.debug("Unhandled relocation ARM64_RELOC_POINTER_TO_GOT", .{});
234 },246 },
235 }247 }
236 }248 }
...@@ -583,6 +595,31 @@ pub const Parser = struct {...@@ -583,6 +595,31 @@ pub const Parser = struct {
583 log.debug(" | emitting {}", .{unsigned});595 log.debug(" | emitting {}", .{unsigned});
584 try parser.parsed.append(&unsigned.base);596 try parser.parsed.append(&unsigned.base);
585 }597 }
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 }
586};623};
587624
588inline fn isArithmeticOp(inst: *const [4]u8) bool {625inline fn isArithmeticOp(inst: *const [4]u8) bool {
src/link/MachO/reloc/x86_64.zig+7-1
...@@ -66,11 +66,15 @@ pub const GotLoad = struct {...@@ -66,11 +66,15 @@ pub const GotLoad = struct {
6666
67pub const Got = struct {67pub const Got = struct {
68 base: Relocation,68 base: Relocation,
69 addend: i32,
6970
70 pub const base_type: Relocation.Type = .got;71 pub const base_type: Relocation.Type = .got;
7172
72 pub fn resolve(got: Got, args: Relocation.ResolveArgs) !void {73 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 );
74 log.debug(" | displacement 0x{x}", .{displacement});78 log.debug(" | displacement 0x{x}", .{displacement});
75 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));79 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));
76 }80 }
...@@ -237,6 +241,7 @@ pub const Parser = struct {...@@ -237,6 +241,7 @@ pub const Parser = struct {
237 const offset = @intCast(u32, rel.r_address);241 const offset = @intCast(u32, rel.r_address);
238 const inst = parser.code[offset..][0..4];242 const inst = parser.code[offset..][0..4];
239 const target = Relocation.Target.from_reloc(rel, parser.symbols);243 const target = Relocation.Target.from_reloc(rel, parser.symbols);
244 const addend = mem.readIntLittle(i32, inst);
240245
241 var got = try parser.allocator.create(Got);246 var got = try parser.allocator.create(Got);
242 errdefer parser.allocator.destroy(got);247 errdefer parser.allocator.destroy(got);
...@@ -248,6 +253,7 @@ pub const Parser = struct {...@@ -248,6 +253,7 @@ pub const Parser = struct {
248 .offset = offset,253 .offset = offset,
249 .target = target,254 .target = target,
250 },255 },
256 .addend = addend,
251 };257 };
252258
253 log.debug(" | emitting {}", .{got});259 log.debug(" | emitting {}", .{got});