authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-26 07:56:49+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log180979ee41e7374ee1b8bc941e2281bb44e41dfd
tree485ffd92d423bd118e64c4db0bf45114ac74b726
parentf29d9ec61cf9d533035749fe614f5071e80bc3d0

macho: move getOutputSection into Atom


3 files changed, 166 insertions(+), 168 deletions(-)

src/link/MachO/Atom.zig+158-20
......@@ -1,23 +1,3 @@
1const Atom = @This();
2
3const std = @import("std");
4const build_options = @import("build_options");
5const aarch64 = @import("../../arch/aarch64/bits.zig");
6const assert = std.debug.assert;
7const log = std.log.scoped(.link);
8const macho = std.macho;
9const math = std.math;
10const mem = std.mem;
11const meta = std.meta;
12const trace = @import("../../tracy.zig").trace;
13
14const Allocator = mem.Allocator;
15const Arch = std.Target.Cpu.Arch;
16const MachO = @import("../MachO.zig");
17pub const Relocation = @import("Relocation.zig");
18const SymbolWithLoc = MachO.SymbolWithLoc;
19const Zld = @import("zld.zig").Zld;
20
211/// Each Atom always gets a symbol with the fully qualified name.
222/// The symbol can reside in any object file context structure in `symtab` array
233/// (see `Object`), or if the symbol is a synthetic symbol such as a GOT cell or
......@@ -125,6 +105,144 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
125105 return surplus >= MachO.min_text_capacity;
126106}
127107
108pub fn getOutputSection(zld: *Zld, sect: macho.section_64) !?u8 {
109 const segname = sect.segName();
110 const sectname = sect.sectName();
111 const res: ?u8 = blk: {
112 if (mem.eql(u8, "__LLVM", segname)) {
113 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
114 sect.flags, segname, sectname,
115 });
116 break :blk null;
117 }
118
119 // We handle unwind info separately.
120 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
121 break :blk null;
122 }
123 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
124 break :blk null;
125 }
126
127 if (sect.isCode()) {
128 if (zld.text_section_index == null) {
129 zld.text_section_index = try zld.initSection(
130 "__TEXT",
131 "__text",
132 .{
133 .flags = macho.S_REGULAR |
134 macho.S_ATTR_PURE_INSTRUCTIONS |
135 macho.S_ATTR_SOME_INSTRUCTIONS,
136 },
137 );
138 }
139 break :blk zld.text_section_index.?;
140 }
141
142 if (sect.isDebug()) {
143 break :blk null;
144 }
145
146 switch (sect.type()) {
147 macho.S_4BYTE_LITERALS,
148 macho.S_8BYTE_LITERALS,
149 macho.S_16BYTE_LITERALS,
150 => {
151 break :blk zld.getSectionByName("__TEXT", "__const") orelse try zld.initSection(
152 "__TEXT",
153 "__const",
154 .{},
155 );
156 },
157 macho.S_CSTRING_LITERALS => {
158 if (mem.startsWith(u8, sectname, "__objc")) {
159 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
160 segname,
161 sectname,
162 .{},
163 );
164 }
165 break :blk zld.getSectionByName("__TEXT", "__cstring") orelse try zld.initSection(
166 "__TEXT",
167 "__cstring",
168 .{ .flags = macho.S_CSTRING_LITERALS },
169 );
170 },
171 macho.S_MOD_INIT_FUNC_POINTERS,
172 macho.S_MOD_TERM_FUNC_POINTERS,
173 => {
174 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
175 "__DATA_CONST",
176 sectname,
177 .{ .flags = sect.flags },
178 );
179 },
180 macho.S_LITERAL_POINTERS,
181 macho.S_ZEROFILL,
182 macho.S_THREAD_LOCAL_VARIABLES,
183 macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
184 macho.S_THREAD_LOCAL_REGULAR,
185 macho.S_THREAD_LOCAL_ZEROFILL,
186 => {
187 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
188 segname,
189 sectname,
190 .{ .flags = sect.flags },
191 );
192 },
193 macho.S_COALESCED => {
194 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
195 segname,
196 sectname,
197 .{},
198 );
199 },
200 macho.S_REGULAR => {
201 if (mem.eql(u8, segname, "__TEXT")) {
202 if (mem.eql(u8, sectname, "__rodata") or
203 mem.eql(u8, sectname, "__typelink") or
204 mem.eql(u8, sectname, "__itablink") or
205 mem.eql(u8, sectname, "__gosymtab") or
206 mem.eql(u8, sectname, "__gopclntab"))
207 {
208 break :blk zld.getSectionByName("__TEXT", sectname) orelse try zld.initSection(
209 "__TEXT",
210 sectname,
211 .{},
212 );
213 }
214 }
215 if (mem.eql(u8, segname, "__DATA")) {
216 if (mem.eql(u8, sectname, "__const") or
217 mem.eql(u8, sectname, "__cfstring") or
218 mem.eql(u8, sectname, "__objc_classlist") or
219 mem.eql(u8, sectname, "__objc_imageinfo"))
220 {
221 break :blk zld.getSectionByName("__DATA_CONST", sectname) orelse try zld.initSection(
222 "__DATA_CONST",
223 sectname,
224 .{},
225 );
226 } else if (mem.eql(u8, sectname, "__data")) {
227 break :blk zld.getSectionByName("__DATA", "__data") orelse try zld.initSection(
228 "__DATA",
229 "__data",
230 .{},
231 );
232 }
233 }
234 break :blk zld.getSectionByName(segname, sectname) orelse try zld.initSection(
235 segname,
236 sectname,
237 .{},
238 );
239 },
240 else => break :blk null,
241 }
242 };
243 return res;
244}
245
128246pub fn addRelocation(macho_file: *MachO, atom_index: Index, reloc: Relocation) !void {
129247 return addRelocations(macho_file, atom_index, &[_]Relocation{reloc});
130248}
......@@ -1112,3 +1230,23 @@ pub fn relocIsStub(zld: *Zld, rel: macho.relocation_info) bool {
11121230 else => unreachable,
11131231 }
11141232}
1233
1234const Atom = @This();
1235
1236const std = @import("std");
1237const build_options = @import("build_options");
1238const aarch64 = @import("../../arch/aarch64/bits.zig");
1239const assert = std.debug.assert;
1240const log = std.log.scoped(.link);
1241const macho = std.macho;
1242const math = std.math;
1243const mem = std.mem;
1244const meta = std.meta;
1245const trace = @import("../../tracy.zig").trace;
1246
1247const Allocator = mem.Allocator;
1248const Arch = std.Target.Cpu.Arch;
1249const MachO = @import("../MachO.zig");
1250pub const Relocation = @import("Relocation.zig");
1251const SymbolWithLoc = MachO.SymbolWithLoc;
1252const Zld = @import("zld.zig").Zld;
src/link/MachO/Object.zig+3-3
......@@ -377,7 +377,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
377377 const sections = self.getSourceSections();
378378 for (sections, 0..) |sect, id| {
379379 if (sect.isDebug()) continue;
380 const out_sect_id = (try zld.getOutputSection(sect)) orelse {
380 const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse {
381381 log.debug(" unhandled section '{s},{s}'", .{ sect.segName(), sect.sectName() });
382382 continue;
383383 };
......@@ -397,7 +397,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
397397 if (self.in_symtab == null) {
398398 for (sections, 0..) |sect, id| {
399399 if (sect.isDebug()) continue;
400 const out_sect_id = (try zld.getOutputSection(sect)) orelse continue;
400 const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse continue;
401401 if (sect.size == 0) continue;
402402
403403 const sect_id = @as(u8, @intCast(id));
......@@ -456,7 +456,7 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
456456 log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });
457457
458458 // Get output segment/section in the final artifact.
459 const out_sect_id = (try zld.getOutputSection(sect)) orelse continue;
459 const out_sect_id = (try Atom.getOutputSection(zld, sect)) orelse continue;
460460
461461 log.debug(" output sect({d}, '{s},{s}')", .{
462462 out_sect_id + 1,
src/link/MachO/zld.zig+5-145
......@@ -95,144 +95,6 @@ pub const Zld = struct {
9595
9696 atoms: std.ArrayListUnmanaged(Atom) = .{},
9797
98 pub fn getOutputSection(self: *Zld, sect: macho.section_64) !?u8 {
99 const segname = sect.segName();
100 const sectname = sect.sectName();
101 const res: ?u8 = blk: {
102 if (mem.eql(u8, "__LLVM", segname)) {
103 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
104 sect.flags, segname, sectname,
105 });
106 break :blk null;
107 }
108
109 // We handle unwind info separately.
110 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
111 break :blk null;
112 }
113 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
114 break :blk null;
115 }
116
117 if (sect.isCode()) {
118 if (self.text_section_index == null) {
119 self.text_section_index = try self.initSection(
120 "__TEXT",
121 "__text",
122 .{
123 .flags = macho.S_REGULAR |
124 macho.S_ATTR_PURE_INSTRUCTIONS |
125 macho.S_ATTR_SOME_INSTRUCTIONS,
126 },
127 );
128 }
129 break :blk self.text_section_index.?;
130 }
131
132 if (sect.isDebug()) {
133 break :blk null;
134 }
135
136 switch (sect.type()) {
137 macho.S_4BYTE_LITERALS,
138 macho.S_8BYTE_LITERALS,
139 macho.S_16BYTE_LITERALS,
140 => {
141 break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(
142 "__TEXT",
143 "__const",
144 .{},
145 );
146 },
147 macho.S_CSTRING_LITERALS => {
148 if (mem.startsWith(u8, sectname, "__objc")) {
149 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
150 segname,
151 sectname,
152 .{},
153 );
154 }
155 break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(
156 "__TEXT",
157 "__cstring",
158 .{ .flags = macho.S_CSTRING_LITERALS },
159 );
160 },
161 macho.S_MOD_INIT_FUNC_POINTERS,
162 macho.S_MOD_TERM_FUNC_POINTERS,
163 => {
164 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
165 "__DATA_CONST",
166 sectname,
167 .{ .flags = sect.flags },
168 );
169 },
170 macho.S_LITERAL_POINTERS,
171 macho.S_ZEROFILL,
172 macho.S_THREAD_LOCAL_VARIABLES,
173 macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
174 macho.S_THREAD_LOCAL_REGULAR,
175 macho.S_THREAD_LOCAL_ZEROFILL,
176 => {
177 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
178 segname,
179 sectname,
180 .{ .flags = sect.flags },
181 );
182 },
183 macho.S_COALESCED => {
184 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
185 segname,
186 sectname,
187 .{},
188 );
189 },
190 macho.S_REGULAR => {
191 if (mem.eql(u8, segname, "__TEXT")) {
192 if (mem.eql(u8, sectname, "__rodata") or
193 mem.eql(u8, sectname, "__typelink") or
194 mem.eql(u8, sectname, "__itablink") or
195 mem.eql(u8, sectname, "__gosymtab") or
196 mem.eql(u8, sectname, "__gopclntab"))
197 {
198 break :blk self.getSectionByName("__TEXT", sectname) orelse try self.initSection(
199 "__TEXT",
200 sectname,
201 .{},
202 );
203 }
204 }
205 if (mem.eql(u8, segname, "__DATA")) {
206 if (mem.eql(u8, sectname, "__const") or
207 mem.eql(u8, sectname, "__cfstring") or
208 mem.eql(u8, sectname, "__objc_classlist") or
209 mem.eql(u8, sectname, "__objc_imageinfo"))
210 {
211 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
212 "__DATA_CONST",
213 sectname,
214 .{},
215 );
216 } else if (mem.eql(u8, sectname, "__data")) {
217 break :blk self.getSectionByName("__DATA", "__data") orelse try self.initSection(
218 "__DATA",
219 "__data",
220 .{},
221 );
222 }
223 }
224 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
225 segname,
226 sectname,
227 .{},
228 );
229 },
230 else => break :blk null,
231 }
232 };
233 return res;
234 }
235
23698 pub fn addAtomToSection(self: *Zld, atom_index: Atom.Index) void {
23799 const atom = self.getAtomPtr(atom_index);
238100 const sym = self.getSymbol(atom.getSymbolWithLoc());
......@@ -278,7 +140,8 @@ pub const Zld = struct {
278140 const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
279141 sym.n_type = macho.N_SECT;
280142
281 const sect_id = self.getSectionByName("__DATA", "__data") orelse try self.initSection("__DATA", "__data", .{});
143 const sect_id = self.getSectionByName("__DATA", "__data") orelse
144 try self.initSection("__DATA", "__data", .{});
282145 sym.n_sect = sect_id + 1;
283146 self.dyld_private_atom_index = atom_index;
284147
......@@ -301,16 +164,13 @@ pub const Zld = struct {
301164 // text blocks for each tentative definition.
302165 const size = sym.n_value;
303166 const alignment = (sym.n_desc >> 8) & 0x0f;
304 const n_sect = (try self.getOutputSection(.{
305 .segname = makeStaticString("__DATA"),
306 .sectname = makeStaticString("__bss"),
307 .flags = macho.S_ZEROFILL,
308 })).? + 1;
167 const sect_id = self.getSectionByName("__DATA", "__bss") orelse
168 try self.initSection("__DATA", "__bss", .{ .flags = macho.S_ZEROFILL });
309169
310170 sym.* = .{
311171 .n_strx = sym.n_strx,
312172 .n_type = macho.N_SECT | macho.N_EXT,
313 .n_sect = n_sect,
173 .n_sect = sect_id + 1,
314174 .n_desc = 0,
315175 .n_value = 0,
316176 };