authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-26 08:13:41+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
logb2773cd7120f7120410e1635aaeec026c7bbcdd1
treecd7defea6ddbd23930c3e168b066cfbd75febe61
parent180979ee41e7374ee1b8bc941e2281bb44e41dfd

macho: move initSection into MachO from Zld


4 files changed, 85 insertions(+), 67 deletions(-)

src/link/MachO.zig+36-14
...@@ -2739,6 +2739,34 @@ fn calcPagezeroSize(self: *MachO) u64 {...@@ -2739,6 +2739,34 @@ fn calcPagezeroSize(self: *MachO) u64 {
2739 return aligned_pagezero_vmsize;2739 return aligned_pagezero_vmsize;
2740}2740}
27412741
2742const InitSectionOpts = struct {
2743 flags: u32 = macho.S_REGULAR,
2744 reserved1: u32 = 0,
2745 reserved2: u32 = 0,
2746};
2747
2748pub fn initSection(
2749 gpa: Allocator,
2750 ctx: anytype,
2751 segname: []const u8,
2752 sectname: []const u8,
2753 opts: InitSectionOpts,
2754) !u8 {
2755 log.debug("creating section '{s},{s}'", .{ segname, sectname });
2756 const index = @as(u8, @intCast(ctx.sections.slice().len));
2757 try ctx.sections.append(gpa, .{
2758 .segment_index = undefined, // Segments will be created automatically later down the pipeline
2759 .header = .{
2760 .sectname = makeStaticString(sectname),
2761 .segname = makeStaticString(segname),
2762 .flags = opts.flags,
2763 .reserved1 = opts.reserved1,
2764 .reserved2 = opts.reserved2,
2765 },
2766 });
2767 return index;
2768}
2769
2742fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: struct {2770fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts: struct {
2743 size: u64 = 0,2771 size: u64 = 0,
2744 alignment: u32 = 0,2772 alignment: u32 = 0,
...@@ -2751,7 +2779,6 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts...@@ -2751,7 +2779,6 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
2751 // In incremental context, we create one section per segment pairing. This way,2779 // In incremental context, we create one section per segment pairing. This way,
2752 // we can move the segment in raw file as we please.2780 // we can move the segment in raw file as we please.
2753 const segment_id = @as(u8, @intCast(self.segments.items.len));2781 const segment_id = @as(u8, @intCast(self.segments.items.len));
2754 const section_id = @as(u8, @intCast(self.sections.slice().len));
2755 const vmaddr = blk: {2782 const vmaddr = blk: {
2756 const prev_segment = self.segments.items[segment_id - 1];2783 const prev_segment = self.segments.items[segment_id - 1];
2757 break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, page_size);2784 break :blk mem.alignForward(u64, prev_segment.vmaddr + prev_segment.vmsize, page_size);
...@@ -2782,23 +2809,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts...@@ -2782,23 +2809,18 @@ fn allocateSection(self: *MachO, segname: []const u8, sectname: []const u8, opts
2782 .cmdsize = @sizeOf(macho.segment_command_64) + @sizeOf(macho.section_64),2809 .cmdsize = @sizeOf(macho.segment_command_64) + @sizeOf(macho.section_64),
2783 };2810 };
27842811
2785 var section = macho.section_64{2812 const sect_id = try initSection(gpa, self, sectname, segname, .{
2786 .sectname = makeStaticString(sectname),
2787 .segname = makeStaticString(segname),
2788 .addr = mem.alignForward(u64, vmaddr, opts.alignment),
2789 .offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment),
2790 .size = opts.size,
2791 .@"align" = math.log2(opts.alignment),
2792 .flags = opts.flags,2813 .flags = opts.flags,
2793 .reserved2 = opts.reserved2,2814 .reserved2 = opts.reserved2,
2794 };2815 });
2816 const section = &self.sections.items(.header)[sect_id];
2817 section.addr = mem.alignForward(u64, vmaddr, opts.alignment);
2818 section.offset = mem.alignForward(u32, @as(u32, @intCast(off)), opts.alignment);
2819 section.size = opts.size;
2820 section.@"align" = math.log2(opts.alignment);
2795 assert(!section.isZerofill()); // TODO zerofill sections2821 assert(!section.isZerofill()); // TODO zerofill sections
27962822
2797 try self.sections.append(gpa, .{2823 return sect_id;
2798 .segment_index = segment_id,
2799 .header = section,
2800 });
2801 return section_id;
2802}2824}
28032825
2804fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void {2826fn growSection(self: *MachO, sect_id: u8, needed_size: u64) !void {
src/link/MachO/Atom.zig+35-11
...@@ -106,6 +106,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {...@@ -106,6 +106,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
106}106}
107107
108pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {108pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
109 const gpa = zld.gpa;
109 const segname = sect.segName();110 const segname = sect.segName();
110 const sectname = sect.sectName();111 const sectname = sect.sectName();
111 const res: ?u8 = blk: {112 const res: ?u8 = blk: {
...@@ -126,7 +127,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -126,7 +127,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
126127
127 if (sect.isCode()) {128 if (sect.isCode()) {
128 if (zld.text_section_index == null) {129 if (zld.text_section_index == null) {
129 zld.text_section_index = try zld.initSection(130 zld.text_section_index = try MachO.initSection(
131 gpa,
132 zld,
130 "__TEXT",133 "__TEXT",
131 "__text",134 "__text",
132 .{135 .{
...@@ -148,7 +151,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -148,7 +151,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
148 macho.S_8BYTE_LITERALS,151 macho.S_8BYTE_LITERALS,
149 macho.S_16BYTE_LITERALS,152 macho.S_16BYTE_LITERALS,
150 => {153 => {
151 break :blk zld.getSectionByName("__TEXT", "__const") orelse try zld.initSection(154 break :blk zld.getSectionByName("__TEXT", "__const") orelse try MachO.initSection(
155 gpa,
156 zld,
152 "__TEXT",157 "__TEXT",
153 "__const",158 "__const",
154 .{},159 .{},
...@@ -156,13 +161,17 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -156,13 +161,17 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
156 },161 },
157 macho.S_CSTRING_LITERALS => {162 macho.S_CSTRING_LITERALS => {
158 if (mem.startsWith(u8, sectname, "__objc")) {163 if (mem.startsWith(u8, sectname, "__objc")) {
159 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(164 break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
165 gpa,
166 zld,
160 segname,167 segname,
161 sectname,168 sectname,
162 .{},169 .{},
163 );170 );
164 }171 }
165 break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try zld.initSection(172 break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try MachO.initSection(
173 gpa,
174 zld,
166 "__TEXT",175 "__TEXT",
167 "__cstring",176 "__cstring",
168 .{ .flags = macho.S_CSTRING_LITERALS },177 .{ .flags = macho.S_CSTRING_LITERALS },
...@@ -171,7 +180,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -171,7 +180,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
171 macho.S_MOD_INIT_FUNC_POINTERS,180 macho.S_MOD_INIT_FUNC_POINTERS,
172 macho.S_MOD_TERM_FUNC_POINTERS,181 macho.S_MOD_TERM_FUNC_POINTERS,
173 => {182 => {
174 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(183 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection(
184 gpa,
185 zld,
175 "__DATA_CONST",186 "__DATA_CONST",
176 sectname,187 sectname,
177 .{ .flags = sect.flags },188 .{ .flags = sect.flags },
...@@ -184,14 +195,19 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -184,14 +195,19 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
184 macho.S_THREAD_LOCAL_REGULAR,195 macho.S_THREAD_LOCAL_REGULAR,
185 macho.S_THREAD_LOCAL_ZEROFILL,196 macho.S_THREAD_LOCAL_ZEROFILL,
186 => {197 => {
187 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(198 break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
199 gpa,
200 zld,
188 segname,201 segname,
189 sectname,202 sectname,
190 .{ .flags = sect.flags },203 .{ .flags = sect.flags },
191 );204 );
192 },205 },
193 macho.S_COALESCED => {206 macho.S_COALESCED => {
194 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(207 break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
208 gpa,
209 zld,
210
195 segname,211 segname,
196 sectname,212 sectname,
197 .{},213 .{},
...@@ -205,7 +221,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -205,7 +221,9 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
205 mem.eql(u8, sectname, "__gosymtab") or221 mem.eql(u8, sectname, "__gosymtab") or
206 mem.eql(u8, sectname, "__gopclntab"))222 mem.eql(u8, sectname, "__gopclntab"))
207 {223 {
208 break :blk zld.getSectionByName("__TEXT", sectname) orelse try zld.initSection(224 break :blk zld.getSectionByName("__TEXT", sectname) orelse try MachO.initSection(
225 gpa,
226 zld,
209 "__TEXT",227 "__TEXT",
210 sectname,228 sectname,
211 .{},229 .{},
...@@ -218,20 +236,26 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {...@@ -218,20 +236,26 @@ pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
218 mem.eql(u8, sectname, "__objc_classlist") or236 mem.eql(u8, sectname, "__objc_classlist") or
219 mem.eql(u8, sectname, "__objc_imageinfo"))237 mem.eql(u8, sectname, "__objc_imageinfo"))
220 {238 {
221 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(239 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try MachO.initSection(
240 gpa,
241 zld,
222 "__DATA_CONST",242 "__DATA_CONST",
223 sectname,243 sectname,
224 .{},244 .{},
225 );245 );
226 } else if (mem.eql(u8, sectname, "__data")) {246 } else if (mem.eql(u8, sectname, "__data")) {
227 break :blk zld.getSectionByName("__DATA", "__data") orelse try zld.initSection(247 break :blk zld.getSectionByName("__DATA", "__data") orelse try MachO.initSection(
248 gpa,
249 zld,
228 "__DATA",250 "__DATA",
229 "__data",251 "__data",
230 .{},252 .{},
231 );253 );
232 }254 }
233 }255 }
234 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(256 break :blk zld.getSectionByName(segname, sectname) orelse try MachO.initSection(
257 gpa,
258 zld,
235 segname,259 segname,
236 sectname,260 sectname,
237 .{},261 .{},
src/link/MachO/Object.zig+7-7
...@@ -685,11 +685,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -685,11 +685,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
685685
686 log.debug("parsing __TEXT,__eh_frame section", .{});686 log.debug("parsing __TEXT,__eh_frame section", .{});
687687
688 const gpa = zld.gpa;
689
688 if (zld.getSectionByName("__TEXT", "__eh_frame") == null) {690 if (zld.getSectionByName("__TEXT", "__eh_frame") == null) {
689 _ = try zld.initSection("__TEXT", "__eh_frame", .{});691 _ = try MachO.initSection(gpa, zld, "__TEXT", "__eh_frame", .{});
690 }692 }
691693
692 const gpa = zld.gpa;
693 const cpu_arch = zld.options.target.cpu.arch;694 const cpu_arch = zld.options.target.cpu.arch;
694 try self.parseRelocs(gpa, sect_id);695 try self.parseRelocs(gpa, sect_id);
695 const relocs = self.getRelocs(sect_id);696 const relocs = self.getRelocs(sect_id);
...@@ -779,6 +780,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -779,6 +780,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
779}780}
780781
781fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {782fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
783 const gpa = zld.gpa;
784 const cpu_arch = zld.options.target.cpu.arch;
782 const sect_id = self.unwind_info_sect_id orelse {785 const sect_id = self.unwind_info_sect_id orelse {
783 // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`,786 // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`,
784 // we will try fully synthesising unwind info records to somewhat match Apple ld's787 // we will try fully synthesising unwind info records to somewhat match Apple ld's
...@@ -786,7 +789,7 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -786,7 +789,7 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
786 // we still create the output `__TEXT,__unwind_info` section.789 // we still create the output `__TEXT,__unwind_info` section.
787 if (self.hasEhFrameRecords()) {790 if (self.hasEhFrameRecords()) {
788 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {791 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
789 _ = try zld.initSection("__TEXT", "__unwind_info", .{});792 _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
790 }793 }
791 }794 }
792 return;795 return;
...@@ -794,11 +797,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -794,11 +797,8 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
794797
795 log.debug("parsing unwind info in {s}", .{self.name});798 log.debug("parsing unwind info in {s}", .{self.name});
796799
797 const gpa = zld.gpa;
798 const cpu_arch = zld.options.target.cpu.arch;
799
800 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {800 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
801 _ = try zld.initSection("__TEXT", "__unwind_info", .{});801 _ = try MachO.initSection(gpa, zld, "__TEXT", "__unwind_info", .{});
802 }802 }
803803
804 const unwind_records = self.getUnwindRecords();804 const unwind_records = self.getUnwindRecords();
src/link/MachO/zld.zig+7-35
...@@ -141,7 +141,7 @@ pub const Zld = struct {...@@ -141,7 +141,7 @@ pub const Zld = struct {
141 sym.n_type = macho.N_SECT;141 sym.n_type = macho.N_SECT;
142142
143 const sect_id = self.getSectionByName("__DATA", "__data") orelse143 const sect_id = self.getSectionByName("__DATA", "__data") orelse
144 try self.initSection("__DATA", "__data", .{});144 try MachO.initSection(self.gpa, self, "__DATA", "__data", .{});
145 sym.n_sect = sect_id + 1;145 sym.n_sect = sect_id + 1;
146 self.dyld_private_atom_index = atom_index;146 self.dyld_private_atom_index = atom_index;
147147
...@@ -165,7 +165,7 @@ pub const Zld = struct {...@@ -165,7 +165,7 @@ pub const Zld = struct {
165 const size = sym.n_value;165 const size = sym.n_value;
166 const alignment = (sym.n_desc >> 8) & 0x0f;166 const alignment = (sym.n_desc >> 8) & 0x0f;
167 const sect_id = self.getSectionByName("__DATA", "__bss") orelse167 const sect_id = self.getSectionByName("__DATA", "__bss") orelse
168 try self.initSection("__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });168 try MachO.initSection(gpa, self, "__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
169169
170 sym.* = .{170 sym.* = .{
171 .n_strx = sym.n_strx,171 .n_strx = sym.n_strx,
...@@ -619,7 +619,7 @@ pub const Zld = struct {...@@ -619,7 +619,7 @@ pub const Zld = struct {
619 if (self.got_table.lookup.contains(target)) return;619 if (self.got_table.lookup.contains(target)) return;
620 _ = try self.got_table.allocateEntry(self.gpa, target);620 _ = try self.got_table.allocateEntry(self.gpa, target);
621 if (self.got_section_index == null) {621 if (self.got_section_index == null) {
622 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{622 self.got_section_index = try MachO.initSection(self.gpa, self, "__DATA_CONST", "__got", .{
623 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,623 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
624 });624 });
625 }625 }
...@@ -629,7 +629,7 @@ pub const Zld = struct {...@@ -629,7 +629,7 @@ pub const Zld = struct {
629 if (self.tlv_ptr_table.lookup.contains(target)) return;629 if (self.tlv_ptr_table.lookup.contains(target)) return;
630 _ = try self.tlv_ptr_table.allocateEntry(self.gpa, target);630 _ = try self.tlv_ptr_table.allocateEntry(self.gpa, target);
631 if (self.tlv_ptr_section_index == null) {631 if (self.tlv_ptr_section_index == null) {
632 self.tlv_ptr_section_index = try self.initSection("__DATA", "__thread_ptrs", .{632 self.tlv_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__thread_ptrs", .{
633 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,633 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
634 });634 });
635 }635 }
...@@ -639,18 +639,18 @@ pub const Zld = struct {...@@ -639,18 +639,18 @@ pub const Zld = struct {
639 if (self.stubs_table.lookup.contains(target)) return;639 if (self.stubs_table.lookup.contains(target)) return;
640 _ = try self.stubs_table.allocateEntry(self.gpa, target);640 _ = try self.stubs_table.allocateEntry(self.gpa, target);
641 if (self.stubs_section_index == null) {641 if (self.stubs_section_index == null) {
642 self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{642 self.stubs_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stubs", .{
643 .flags = macho.S_SYMBOL_STUBS |643 .flags = macho.S_SYMBOL_STUBS |
644 macho.S_ATTR_PURE_INSTRUCTIONS |644 macho.S_ATTR_PURE_INSTRUCTIONS |
645 macho.S_ATTR_SOME_INSTRUCTIONS,645 macho.S_ATTR_SOME_INSTRUCTIONS,
646 .reserved2 = stubs.stubSize(self.options.target.cpu.arch),646 .reserved2 = stubs.stubSize(self.options.target.cpu.arch),
647 });647 });
648 self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{648 self.stub_helper_section_index = try MachO.initSection(self.gpa, self, "__TEXT", "__stub_helper", .{
649 .flags = macho.S_REGULAR |649 .flags = macho.S_REGULAR |
650 macho.S_ATTR_PURE_INSTRUCTIONS |650 macho.S_ATTR_PURE_INSTRUCTIONS |
651 macho.S_ATTR_SOME_INSTRUCTIONS,651 macho.S_ATTR_SOME_INSTRUCTIONS,
652 });652 });
653 self.la_symbol_ptr_section_index = try self.initSection("__DATA", "__la_symbol_ptr", .{653 self.la_symbol_ptr_section_index = try MachO.initSection(self.gpa, self, "__DATA", "__la_symbol_ptr", .{
654 .flags = macho.S_LAZY_SYMBOL_POINTERS,654 .flags = macho.S_LAZY_SYMBOL_POINTERS,
655 });655 });
656 }656 }
...@@ -1152,34 +1152,6 @@ pub const Zld = struct {...@@ -1152,34 +1152,6 @@ pub const Zld = struct {
1152 segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size);1152 segment.vmsize = mem.alignForward(u64, segment.vmsize, page_size);
1153 }1153 }
11541154
1155 const InitSectionOpts = struct {
1156 flags: u32 = macho.S_REGULAR,
1157 reserved1: u32 = 0,
1158 reserved2: u32 = 0,
1159 };
1160
1161 pub fn initSection(
1162 self: *Zld,
1163 segname: []const u8,
1164 sectname: []const u8,
1165 opts: InitSectionOpts,
1166 ) !u8 {
1167 const gpa = self.gpa;
1168 log.debug("creating section '{s},{s}'", .{ segname, sectname });
1169 const index = @as(u8, @intCast(self.sections.slice().len));
1170 try self.sections.append(gpa, .{
1171 .segment_index = undefined, // Segments will be created automatically later down the pipeline
1172 .header = .{
1173 .sectname = makeStaticString(sectname),
1174 .segname = makeStaticString(segname),
1175 .flags = opts.flags,
1176 .reserved1 = opts.reserved1,
1177 .reserved2 = opts.reserved2,
1178 },
1179 });
1180 return index;
1181 }
1182
1183 fn writeSegmentHeaders(self: *Zld, writer: anytype) !void {1155 fn writeSegmentHeaders(self: *Zld, writer: anytype) !void {
1184 for (self.segments.items, 0..) |seg, i| {1156 for (self.segments.items, 0..) |seg, i| {
1185 const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));1157 const indexes = self.getSectionIndexes(@as(u8, @intCast(i)));