authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-17 14:55:40+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:41+01:00
log0b2133d4412e8f3c67a1eb6ddbb43afc02196703
tree8c288057862097a13b0fb0ab313af3a1c2696556
parentbd9d8bd462799c552eed9812484add68e498a3ee

macho: init metadata and partially implement updateDecl


2 files changed, 134 insertions(+), 3 deletions(-)

src/link/MachO.zig+78-1
......@@ -82,6 +82,18 @@ lazy_bind: LazyBindSection = .{},
8282export_trie: ExportTrieSection = .{},
8383unwind_info: UnwindInfo = .{},
8484
85/// Tracked loadable segments during incremental linking.
86zig_text_seg_index: ?u8 = null,
87zig_data_const_seg_index: ?u8 = null,
88zig_data_seg_index: ?u8 = null,
89
90/// Tracked section headers with incremental updates to Zig object.
91zig_text_section_index: ?u8 = null,
92zig_data_const_section_index: ?u8 = null,
93zig_data_section_index: ?u8 = null,
94zig_bss_section_index: ?u8 = null,
95zig_got_section_index: ?u8 = null,
96
8597has_tlv: bool = false,
8698binds_to_weak: bool = false,
8799weak_defines: bool = false,
......@@ -234,8 +246,11 @@ pub fn createEmpty(
234246 } });
235247 self.zig_object = index;
236248 try self.getZigObject().?.init(self);
249 try self.initMetadata(.{
250 .symbol_count_hint = options.symbol_count_hint,
251 .program_code_size_hint = options.program_code_size_hint,
252 });
237253
238 // TODO init metadata
239254 // TODO init dwarf
240255
241256 // if (comp.config.debug_format != .strip) {
......@@ -3103,6 +3118,45 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {
31033118 return start;
31043119}
31053120
3121const InitMetadataOptions = struct {
3122 symbol_count_hint: u64,
3123 program_code_size_hint: u64,
3124};
3125
3126// TODO: move to ZigObject
3127// TODO: bring back pre-alloc of segments/sections
3128fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3129 _ = options;
3130
3131 if (!self.base.isRelocatable()) {
3132 // TODO: If we are not emitting a relocatable object file, init segments.
3133 }
3134
3135 if (self.zig_text_section_index == null) {
3136 self.zig_text_section_index = try self.addSection("__TEXT", "__text", .{
3137 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3138 });
3139 }
3140
3141 if (self.zig_got_section_index == null and !self.base.isRelocatable()) {
3142 self.zig_got_section_index = try self.addSection("__DATA_CONST", "__got_zig", .{});
3143 }
3144
3145 if (self.zig_data_const_section_index == null) {
3146 self.zig_data_const_section_index = try self.addSection("__DATA_CONST", "__const", .{});
3147 }
3148
3149 if (self.zig_data_section_index == null) {
3150 self.zig_data_section_index = try self.addSection("__DATA", "__data", .{});
3151 }
3152
3153 if (self.zig_bss_section_index == null) {
3154 self.zig_bss_section_index = try self.addSection("__DATA", "_bss", .{
3155 .flags = macho.S_ZEROFILL,
3156 });
3157 }
3158}
3159
31063160pub fn getTarget(self: MachO) std.Target {
31073161 return self.base.comp.root_mod.resolved_target.result;
31083162}
......@@ -3148,6 +3202,29 @@ inline fn requiresThunks(self: MachO) bool {
31483202 return self.getTarget().cpu.arch == .aarch64;
31493203}
31503204
3205pub fn addSegment(self: *MachO, name: []const u8, opts: struct {
3206 vmaddr: u64 = 0,
3207 vmsize: u64 = 0,
3208 fileoff: u64 = 0,
3209 filesize: u64 = 0,
3210 prot: macho.vm_prot_t = macho.PROT.NONE,
3211}) error{OutOfMemory}!u8 {
3212 const gpa = self.base.comp.gpa;
3213 const index = @as(u8, @intCast(self.segments.items.len));
3214 try self.segments.append(gpa, .{
3215 .segname = makeStaticString(name),
3216 .vmaddr = opts.vmaddr,
3217 .vmsize = opts.vmsize,
3218 .fileoff = opts.fileoff,
3219 .filesize = opts.filesize,
3220 .maxprot = opts.prot,
3221 .initprot = opts.prot,
3222 .nsects = 0,
3223 .cmdsize = @sizeOf(macho.segment_command_64),
3224 });
3225 return index;
3226}
3227
31513228const AddSectionOpts = struct {
31523229 flags: u32 = macho.S_REGULAR,
31533230 reserved1: u32 = 0,
src/link/MachO/ZigObject.zig+56-2
......@@ -295,7 +295,8 @@ pub fn updateDecl(
295295 return;
296296 },
297297 };
298 _ = code;
298 const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
299 _ = sect_index;
299300 // const addr = try self.updateDeclCode(decl_index, code);
300301
301302 // if (decl_state) |*ds| {
......@@ -313,6 +314,59 @@ pub fn updateDecl(
313314 // try self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
314315}
315316
317fn getDeclOutputSection(
318 self: *ZigObject,
319 macho_file: *MachO,
320 decl: *const Module.Decl,
321 code: []const u8,
322) error{OutOfMemory}!u8 {
323 _ = self;
324 const mod = macho_file.base.comp.module.?;
325 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
326 const sect_id: u8 = switch (decl.ty.zigTypeTag(mod)) {
327 .Fn => macho_file.zig_text_section_index.?,
328 else => blk: {
329 if (decl.getOwnedVariable(mod)) |variable| {
330 if (variable.is_threadlocal and any_non_single_threaded) {
331 const is_all_zeroes = for (code) |byte| {
332 if (byte != 0) break false;
333 } else true;
334 if (is_all_zeroes) break :blk macho_file.getSectionByName("__DATA", "__thread_bss") orelse try macho_file.addSection(
335 "__DATA",
336 "__thread_bss",
337 .{ .flags = macho.S_THREAD_LOCAL_ZEROFILL },
338 );
339 break :blk macho_file.getSectionByName("__DATA", "__thread_data") orelse try macho_file.addSection(
340 "__DATA",
341 "__thread_data",
342 .{ .flags = macho.S_THREAD_LOCAL_REGULAR },
343 );
344 }
345
346 if (variable.is_const) break :blk macho_file.zig_data_const_section_index.?;
347 if (Value.fromInterned(variable.init).isUndefDeep(mod)) {
348 // TODO: get the optimize_mode from the Module that owns the decl instead
349 // of using the root module here.
350 break :blk switch (macho_file.base.comp.root_mod.optimize_mode) {
351 .Debug, .ReleaseSafe => macho_file.zig_data_section_index.?,
352 .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_section_index.?,
353 };
354 }
355
356 // TODO I blatantly copied the logic from the Wasm linker, but is there a less
357 // intrusive check for all zeroes than this?
358 const is_all_zeroes = for (code) |byte| {
359 if (byte != 0) break false;
360 } else true;
361 if (is_all_zeroes) break :blk macho_file.zig_bss_section_index.?;
362 break :blk macho_file.zig_data_section_index.?;
363 }
364 break :blk macho_file.zig_data_const_section_index.?;
365 },
366 };
367 return sect_id;
368}
369
316370pub fn lowerUnnamedConst(
317371 self: *ZigObject,
318372 macho_file: *MachO,
......@@ -386,7 +440,7 @@ pub fn getOrCreateMetadataForDecl(
386440 const sym_index = try self.addAtom(macho_file);
387441 const mod = macho_file.base.comp.module.?;
388442 const decl = mod.declPtr(decl_index);
389 const sym = macho_file.getSymbol(self.symbols.items[sym_index]);
443 const sym = macho_file.getSymbol(sym_index);
390444 if (decl.getOwnedVariable(mod)) |variable| {
391445 if (variable.is_threadlocal and any_non_single_threaded) {
392446 sym.flags.tlv = true;