| author | |
| committer | |
| log | 0b2133d4412e8f3c67a1eb6ddbb43afc02196703 |
| tree | 8c288057862097a13b0fb0ab313af3a1c2696556 |
| parent | bd9d8bd462799c552eed9812484add68e498a3ee |
2 files changed, 134 insertions(+), 3 deletions(-)
src/link/MachO.zig+78-1| ... | ... | @@ -82,6 +82,18 @@ lazy_bind: LazyBindSection = .{}, |
| 82 | 82 | export_trie: ExportTrieSection = .{}, |
| 83 | 83 | unwind_info: UnwindInfo = .{}, |
| 84 | 84 | |
| 85 | /// Tracked loadable segments during incremental linking. | |
| 86 | zig_text_seg_index: ?u8 = null, | |
| 87 | zig_data_const_seg_index: ?u8 = null, | |
| 88 | zig_data_seg_index: ?u8 = null, | |
| 89 | ||
| 90 | /// Tracked section headers with incremental updates to Zig object. | |
| 91 | zig_text_section_index: ?u8 = null, | |
| 92 | zig_data_const_section_index: ?u8 = null, | |
| 93 | zig_data_section_index: ?u8 = null, | |
| 94 | zig_bss_section_index: ?u8 = null, | |
| 95 | zig_got_section_index: ?u8 = null, | |
| 96 | ||
| 85 | 97 | has_tlv: bool = false, |
| 86 | 98 | binds_to_weak: bool = false, |
| 87 | 99 | weak_defines: bool = false, |
| ... | ... | @@ -234,8 +246,11 @@ pub fn createEmpty( |
| 234 | 246 | } }); |
| 235 | 247 | self.zig_object = index; |
| 236 | 248 | 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 | }); | |
| 237 | 253 | |
| 238 | // TODO init metadata | |
| 239 | 254 | // TODO init dwarf |
| 240 | 255 | |
| 241 | 256 | // if (comp.config.debug_format != .strip) { |
| ... | ... | @@ -3103,6 +3118,45 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { |
| 3103 | 3118 | return start; |
| 3104 | 3119 | } |
| 3105 | 3120 | |
| 3121 | const 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 | |
| 3128 | fn 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 | ||
| 3106 | 3160 | pub fn getTarget(self: MachO) std.Target { |
| 3107 | 3161 | return self.base.comp.root_mod.resolved_target.result; |
| 3108 | 3162 | } |
| ... | ... | @@ -3148,6 +3202,29 @@ inline fn requiresThunks(self: MachO) bool { |
| 3148 | 3202 | return self.getTarget().cpu.arch == .aarch64; |
| 3149 | 3203 | } |
| 3150 | 3204 | |
| 3205 | pub 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 | ||
| 3151 | 3228 | const AddSectionOpts = struct { |
| 3152 | 3229 | flags: u32 = macho.S_REGULAR, |
| 3153 | 3230 | reserved1: u32 = 0, |
src/link/MachO/ZigObject.zig+56-2| ... | ... | @@ -295,7 +295,8 @@ pub fn updateDecl( |
| 295 | 295 | return; |
| 296 | 296 | }, |
| 297 | 297 | }; |
| 298 | _ = code; | |
| 298 | const sect_index = try self.getDeclOutputSection(macho_file, decl, code); | |
| 299 | _ = sect_index; | |
| 299 | 300 | // const addr = try self.updateDeclCode(decl_index, code); |
| 300 | 301 | |
| 301 | 302 | // if (decl_state) |*ds| { |
| ... | ... | @@ -313,6 +314,59 @@ pub fn updateDecl( |
| 313 | 314 | // try self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); |
| 314 | 315 | } |
| 315 | 316 | |
| 317 | fn 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 | ||
| 316 | 370 | pub fn lowerUnnamedConst( |
| 317 | 371 | self: *ZigObject, |
| 318 | 372 | macho_file: *MachO, |
| ... | ... | @@ -386,7 +440,7 @@ pub fn getOrCreateMetadataForDecl( |
| 386 | 440 | const sym_index = try self.addAtom(macho_file); |
| 387 | 441 | const mod = macho_file.base.comp.module.?; |
| 388 | 442 | 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); | |
| 390 | 444 | if (decl.getOwnedVariable(mod)) |variable| { |
| 391 | 445 | if (variable.is_threadlocal and any_non_single_threaded) { |
| 392 | 446 | sym.flags.tlv = true; |