authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-04-10 17:57:07+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-04-13 10:56:03+02:00
logb1f9db75f3380c9a563972a197c5d1c363c6f215
treedeb372d7d0031b1f467576ec7072cd940206964c
parent3b7c9dd6bd9a921b8104894d7bdbb55eca90e056

zld: save locals per TU


6 files changed, 280 insertions(+), 282 deletions(-)

src/link/MachO.zig+5-5
...@@ -903,10 +903,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -903,10 +903,10 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
903 self.base.allocator.free(result.stderr);903 self.base.allocator.free(result.stderr);
904 }904 }
905 if (result.stdout.len != 0) {905 if (result.stdout.len != 0) {
906 log.warn("unexpected LD stdout: {s}", .{result.stdout});906 log.debug("unexpected LD stdout: {s}", .{result.stdout});
907 }907 }
908 if (result.stderr.len != 0) {908 if (result.stderr.len != 0) {
909 log.warn("unexpected LD stderr: {s}", .{result.stderr});909 log.debug("unexpected LD stderr: {s}", .{result.stderr});
910 }910 }
911 if (result.term != .Exited or result.term.Exited != 0) {911 if (result.term != .Exited or result.term.Exited != 0) {
912 // TODO parse this output and surface with the Compilation API rather than912 // TODO parse this output and surface with the Compilation API rather than
...@@ -971,7 +971,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -971,7 +971,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
971 }971 }
972972
973 if (stderr.len != 0) {973 if (stderr.len != 0) {
974 log.warn("unexpected LLD stderr:\n{s}", .{stderr});974 log.debug("unexpected LLD stderr:\n{s}", .{stderr});
975 }975 }
976 }976 }
977 }977 }
...@@ -981,11 +981,11 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -981,11 +981,11 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
981 // Update the file with the digest. If it fails we can continue; it only981 // Update the file with the digest. If it fails we can continue; it only
982 // means that the next invocation will have an unnecessary cache miss.982 // means that the next invocation will have an unnecessary cache miss.
983 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {983 Cache.writeSmallFile(directory.handle, id_symlink_basename, &digest) catch |err| {
984 log.warn("failed to save linking hash digest file: {s}", .{@errorName(err)});984 log.debug("failed to save linking hash digest file: {s}", .{@errorName(err)});
985 };985 };
986 // Again failure here only means an unnecessary cache miss.986 // Again failure here only means an unnecessary cache miss.
987 man.writeManifest() catch |err| {987 man.writeManifest() catch |err| {
988 log.warn("failed to write cache manifest when linking: {s}", .{@errorName(err)});988 log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)});
989 };989 };
990 // We hang on to this lock so that the output file path can be used without990 // We hang on to this lock so that the output file path can be used without
991 // other processes clobbering it.991 // other processes clobbering it.
src/link/MachO/Archive.zig+4-3
...@@ -126,7 +126,7 @@ pub fn parse(self: *Archive) !void {...@@ -126,7 +126,7 @@ pub fn parse(self: *Archive) !void {
126 }126 }
127127
128 var embedded_name = try parseName(self.allocator, self.header.?, reader);128 var embedded_name = try parseName(self.allocator, self.header.?, reader);
129 log.warn("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name.? });129 log.debug("parsing archive '{s}' at '{s}'", .{ embedded_name, self.name.? });
130 defer self.allocator.free(embedded_name);130 defer self.allocator.free(embedded_name);
131131
132 try self.parseTableOfContents(reader);132 try self.parseTableOfContents(reader);
...@@ -208,13 +208,14 @@ pub fn parseObject(self: Archive, offset: u32) !Object {...@@ -208,13 +208,14 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
208208
209 const object_name = try parseName(self.allocator, object_header, reader);209 const object_name = try parseName(self.allocator, object_header, reader);
210 defer self.allocator.free(object_name);210 defer self.allocator.free(object_name);
211 const object_basename = std.fs.path.basename(object_name);
211212
212 log.warn("extracting object '{s}' from archive '{s}'", .{ object_name, self.name.? });213 log.debug("extracting object '{s}' from archive '{s}'", .{ object_basename, self.name.? });
213214
214 const name = name: {215 const name = name: {
215 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;216 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
216 const path = try std.os.realpath(self.name.?, &buffer);217 const path = try std.os.realpath(self.name.?, &buffer);
217 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });218 break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_basename });
218 };219 };
219220
220 var object = Object.init(self.allocator);221 var object = Object.init(self.allocator);
src/link/MachO/Object.zig+43-43
...@@ -41,9 +41,10 @@ dwarf_debug_str_index: ?u16 = null,...@@ -41,9 +41,10 @@ dwarf_debug_str_index: ?u16 = null,
41dwarf_debug_line_index: ?u16 = null,41dwarf_debug_line_index: ?u16 = null,
42dwarf_debug_ranges_index: ?u16 = null,42dwarf_debug_ranges_index: ?u16 = null,
4343
44symtab: std.ArrayListUnmanaged(Symbol) = .{},44symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
45strtab: std.ArrayListUnmanaged(u8) = .{},45strtab: std.ArrayListUnmanaged(u8) = .{},
4646
47locals: std.StringArrayHashMapUnmanaged(Symbol) = .{},
47stabs: std.ArrayListUnmanaged(Stab) = .{},48stabs: std.ArrayListUnmanaged(Stab) = .{},
48tu_path: ?[]const u8 = null,49tu_path: ?[]const u8 = null,
49tu_mtime: ?u64 = null,50tu_mtime: ?u64 = null,
...@@ -71,7 +72,6 @@ const Stab = struct {...@@ -71,7 +72,6 @@ const Stab = struct {
71 tag: Tag,72 tag: Tag,
72 symbol: u32,73 symbol: u32,
73 size: ?u64 = null,74 size: ?u64 = null,
74 source_sect_id: u16,
7575
76 const Tag = enum {76 const Tag = enum {
77 function,77 function,
...@@ -161,6 +161,11 @@ pub fn deinit(self: *Object) void {...@@ -161,6 +161,11 @@ pub fn deinit(self: *Object) void {
161 }161 }
162 self.sections.deinit(self.allocator);162 self.sections.deinit(self.allocator);
163163
164 for (self.locals.items()) |*entry| {
165 entry.value.deinit(self.allocator);
166 }
167 self.locals.deinit(self.allocator);
168
164 self.symtab.deinit(self.allocator);169 self.symtab.deinit(self.allocator);
165 self.strtab.deinit(self.allocator);170 self.strtab.deinit(self.allocator);
166 self.stabs.deinit(self.allocator);171 self.stabs.deinit(self.allocator);
...@@ -271,7 +276,7 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -271,7 +276,7 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
271 cmd.LinkeditData.dataoff += offset;276 cmd.LinkeditData.dataoff += offset;
272 },277 },
273 else => {278 else => {
274 log.warn("Unknown load command detected: 0x{x}.", .{cmd.cmd()});279 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
275 },280 },
276 }281 }
277 self.load_commands.appendAssumeCapacity(cmd);282 self.load_commands.appendAssumeCapacity(cmd);
...@@ -279,13 +284,13 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {...@@ -279,13 +284,13 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
279}284}
280285
281pub fn parseSections(self: *Object) !void {286pub fn parseSections(self: *Object) !void {
282 log.warn("parsing sections in {s}", .{self.name.?});287 log.debug("parsing sections in {s}", .{self.name.?});
283 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;288 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
284289
285 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);290 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
286291
287 for (seg.sections.items) |sect| {292 for (seg.sections.items) |sect| {
288 log.warn("parsing section '{s},{s}'", .{ parseName(&sect.segname), parseName(&sect.sectname) });293 log.debug("parsing section '{s},{s}'", .{ parseName(&sect.segname), parseName(&sect.sectname) });
289 // Read sections' code294 // Read sections' code
290 var code = try self.allocator.alloc(u8, sect.size);295 var code = try self.allocator.alloc(u8, sect.size);
291 _ = try self.file.?.preadAll(code, sect.offset);296 _ = try self.file.?.preadAll(code, sect.offset);
...@@ -321,42 +326,39 @@ pub fn parseSymtab(self: *Object) !void {...@@ -321,42 +326,39 @@ pub fn parseSymtab(self: *Object) !void {
321 defer self.allocator.free(symtab);326 defer self.allocator.free(symtab);
322327
323 _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff);328 _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff);
324 try self.symtab.ensureCapacity(self.allocator, symtab_cmd.nsyms);329 const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));
330 try self.symtab.appendSlice(self.allocator, slice);
325331
326 var stream = std.io.fixedBufferStream(symtab);332 var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
327 var reader = stream.reader();333 defer self.allocator.free(strtab);
328334
329 while (true) {335 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
330 const symbol = reader.readStruct(macho.nlist_64) catch |err| switch (err) {336 try self.strtab.appendSlice(self.allocator, strtab);
331 error.EndOfStream => break,337
332 else => |e| return e,338 for (self.symtab.items) |sym, sym_id| {
333 };339 if (Symbol.isStab(sym) or Symbol.isUndef(sym)) continue;
340
341 const sym_name = self.getString(sym.n_strx);
334 const tag: Symbol.Tag = tag: {342 const tag: Symbol.Tag = tag: {
335 if (Symbol.isLocal(symbol)) {343 if (Symbol.isLocal(sym)) {
336 if (Symbol.isStab(symbol))344 if (self.arch.? == .aarch64 and mem.startsWith(u8, sym_name, "l")) continue;
337 break :tag .stab345 break :tag .local;
338 else346 }
339 break :tag .local;347 if (Symbol.isWeakDef(sym)) {
340 } else if (Symbol.isGlobal(symbol)) {348 break :tag .weak;
341 if (Symbol.isWeakDef(symbol))
342 break :tag .weak
343 else
344 break :tag .strong;
345 } else {
346 break :tag .undef;
347 }349 }
350 break :tag .strong;
348 };351 };
349 self.symtab.appendAssumeCapacity(.{352 const name = try self.allocator.dupe(u8, sym_name);
353
354 try self.locals.putNoClobber(self.allocator, name, .{
350 .tag = tag,355 .tag = tag,
351 .inner = symbol,356 .name = name,
357 .address = 0,
358 .section = 0,
359 .index = @intCast(u32, sym_id),
352 });360 });
353 }361 }
354
355 var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
356 defer self.allocator.free(strtab);
357
358 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
359 try self.strtab.appendSlice(self.allocator, strtab);
360}362}
361363
362pub fn parseDebugInfo(self: *Object) !void {364pub fn parseDebugInfo(self: *Object) !void {
...@@ -366,13 +368,13 @@ pub fn parseDebugInfo(self: *Object) !void {...@@ -366,13 +368,13 @@ pub fn parseDebugInfo(self: *Object) !void {
366 };368 };
367 defer debug_info.deinit(self.allocator);369 defer debug_info.deinit(self.allocator);
368370
369 log.warn("parsing debug info in '{s}'", .{self.name.?});371 log.debug("parsing debug info in '{s}'", .{self.name.?});
370372
371 // We assume there is only one CU.373 // We assume there is only one CU.
372 const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {374 const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {
373 error.MissingDebugInfo => {375 error.MissingDebugInfo => {
374 // TODO audit cases with missing debug info and audit our dwarf.zig module.376 // TODO audit cases with missing debug info and audit our dwarf.zig module.
375 log.warn("invalid or missing debug info in {s}; skipping", .{self.name.?});377 log.debug("invalid or missing debug info in {s}; skipping", .{self.name.?});
376 return;378 return;
377 },379 },
378 else => |e| return e,380 else => |e| return e,
...@@ -387,30 +389,28 @@ pub fn parseDebugInfo(self: *Object) !void {...@@ -387,30 +389,28 @@ pub fn parseDebugInfo(self: *Object) !void {
387 break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));389 break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
388 };390 };
389391
390 for (self.symtab.items) |sym, index| {392 for (self.locals.items()) |entry, index| {
391 if (sym.tag == .undef) continue;393 const local = entry.value;
392394 const source_sym = self.symtab.items[local.index.?];
393 const sym_name = self.getString(sym.inner.n_strx);
394 const size = blk: for (debug_info.inner.func_list.items) |func| {395 const size = blk: for (debug_info.inner.func_list.items) |func| {
395 if (func.pc_range) |range| {396 if (func.pc_range) |range| {
396 if (sym.inner.n_value >= range.start and sym.inner.n_value < range.end) {397 if (source_sym.n_value >= range.start and source_sym.n_value < range.end) {
397 break :blk range.end - range.start;398 break :blk range.end - range.start;
398 }399 }
399 }400 }
400 } else null;401 } else null;
401
402 const tag: Stab.Tag = tag: {402 const tag: Stab.Tag = tag: {
403 if (size != null) break :tag .function;403 if (size != null) break :tag .function;
404 switch (sym.tag) {404 switch (local.tag) {
405 .weak, .strong => break :tag .global,405 .weak, .strong => break :tag .global,
406 else => break :tag .static,406 else => break :tag .static,
407 }407 }
408 };408 };
409
409 try self.stabs.append(self.allocator, .{410 try self.stabs.append(self.allocator, .{
410 .tag = tag,411 .tag = tag,
411 .size = size,412 .size = size,
412 .symbol = @intCast(u32, index),413 .symbol = @intCast(u32, index),
413 .source_sect_id = sym.inner.n_sect - 1,
414 });414 });
415 }415 }
416}416}
src/link/MachO/Symbol.zig+11-6
...@@ -3,8 +3,9 @@ const Symbol = @This();...@@ -3,8 +3,9 @@ const Symbol = @This();
3const std = @import("std");3const std = @import("std");
4const macho = std.macho;4const macho = std.macho;
55
6const Allocator = std.mem.Allocator;
7
6pub const Tag = enum {8pub const Tag = enum {
7 stab,
8 local,9 local,
9 weak,10 weak,
10 strong,11 strong,
...@@ -13,9 +14,9 @@ pub const Tag = enum {...@@ -13,9 +14,9 @@ pub const Tag = enum {
13};14};
1415
15tag: Tag,16tag: Tag,
1617name: []u8,
17/// MachO representation of this symbol.18address: u64,
18inner: macho.nlist_64,19section: u8,
1920
20/// Index of file where to locate this symbol.21/// Index of file where to locate this symbol.
21/// Depending on context, this is either an object file, or a dylib.22/// Depending on context, this is either an object file, or a dylib.
...@@ -24,6 +25,10 @@ file: ?u16 = null,...@@ -24,6 +25,10 @@ file: ?u16 = null,
24/// Index of this symbol within the file's symbol table.25/// Index of this symbol within the file's symbol table.
25index: ?u32 = null,26index: ?u32 = null,
2627
28pub fn deinit(self: *Symbol, allocator: *Allocator) void {
29 allocator.free(self.name);
30}
31
27pub fn isStab(sym: macho.nlist_64) bool {32pub fn isStab(sym: macho.nlist_64) bool {
28 return (macho.N_STAB & sym.n_type) != 0;33 return (macho.N_STAB & sym.n_type) != 0;
29}34}
...@@ -50,9 +55,9 @@ pub fn isWeakDef(sym: macho.nlist_64) bool {...@@ -50,9 +55,9 @@ pub fn isWeakDef(sym: macho.nlist_64) bool {
50 return sym.n_desc == macho.N_WEAK_DEF;55 return sym.n_desc == macho.N_WEAK_DEF;
51}56}
5257
53/// Symbol is local if it is either a stab or it is defined and not an extern.58/// Symbol is local if it is defined and not an extern.
54pub fn isLocal(sym: macho.nlist_64) bool {59pub fn isLocal(sym: macho.nlist_64) bool {
55 return isStab(sym) or (isSect(sym) and !isExt(sym));60 return isSect(sym) and !isExt(sym);
56}61}
5762
58/// Symbol is global if it is defined and an extern.63/// Symbol is global if it is defined and an extern.
src/link/MachO/Zld.zig+201-209
...@@ -75,6 +75,7 @@ bss_section_index: ?u16 = null,...@@ -75,6 +75,7 @@ bss_section_index: ?u16 = null,
7575
76symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},76symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},
77strtab: std.ArrayListUnmanaged(u8) = .{},77strtab: std.ArrayListUnmanaged(u8) = .{},
78strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
7879
79threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},80threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
80local_rebases: std.ArrayListUnmanaged(Pointer) = .{},81local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
...@@ -94,7 +95,6 @@ const GotEntry = struct {...@@ -94,7 +95,6 @@ const GotEntry = struct {
94 index: u32,95 index: u32,
95 target_addr: u64,96 target_addr: u64,
96 file: u16,97 file: u16,
97 local_index: u32,
98};98};
9999
100const MappingKey = struct {100const MappingKey = struct {
...@@ -153,10 +153,18 @@ pub fn deinit(self: *Zld) void {...@@ -153,10 +153,18 @@ pub fn deinit(self: *Zld) void {
153 self.unhandled_sections.deinit(self.allocator);153 self.unhandled_sections.deinit(self.allocator);
154154
155 for (self.symtab.items()) |*entry| {155 for (self.symtab.items()) |*entry| {
156 self.allocator.free(entry.key);156 entry.value.deinit(self.allocator);
157 }157 }
158 self.symtab.deinit(self.allocator);158 self.symtab.deinit(self.allocator);
159 self.strtab.deinit(self.allocator);159 self.strtab.deinit(self.allocator);
160
161 {
162 var it = self.strtab_dir.iterator();
163 while (it.next()) |entry| {
164 self.allocator.free(entry.key);
165 }
166 }
167 self.strtab_dir.deinit(self.allocator);
160}168}
161169
162pub fn closeFiles(self: Zld) void {170pub fn closeFiles(self: Zld) void {
...@@ -274,7 +282,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {...@@ -274,7 +282,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
274 continue;282 continue;
275 }283 }
276284
277 log.warn("unexpected input file of unknown type '{s}'", .{file_name});285 log.debug("unexpected input file of unknown type '{s}'", .{file_name});
278 }286 }
279287
280 // Based on our classification, proceed with parsing.288 // Based on our classification, proceed with parsing.
...@@ -326,7 +334,7 @@ fn mapAndUpdateSections(...@@ -326,7 +334,7 @@ fn mapAndUpdateSections(
326 .target_sect_id = target_sect_id,334 .target_sect_id = target_sect_id,
327 .offset = @intCast(u32, offset),335 .offset = @intCast(u32, offset),
328 });336 });
329 log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{337 log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{
330 object.name,338 object.name,
331 parseName(&source_sect.segname),339 parseName(&source_sect.segname),
332 parseName(&source_sect.sectname),340 parseName(&source_sect.sectname),
...@@ -536,7 +544,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -536,7 +544,7 @@ fn updateMetadata(self: *Zld) !void {
536 });544 });
537 },545 },
538 else => {546 else => {
539 log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });547 log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });
540 },548 },
541 }549 }
542 }550 }
...@@ -560,7 +568,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -560,7 +568,7 @@ fn updateMetadata(self: *Zld) !void {
560568
561 const segname = parseName(&source_sect.segname);569 const segname = parseName(&source_sect.segname);
562 const sectname = parseName(&source_sect.sectname);570 const sectname = parseName(&source_sect.sectname);
563 log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname });571 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });
564 try self.unhandled_sections.putNoClobber(self.allocator, .{572 try self.unhandled_sections.putNoClobber(self.allocator, .{
565 .object_id = object_id,573 .object_id = object_id,
566 .source_sect_id = source_sect_id,574 .source_sect_id = source_sect_id,
...@@ -874,15 +882,9 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {...@@ -874,15 +882,9 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
874882
875fn allocateSymbols(self: *Zld) !void {883fn allocateSymbols(self: *Zld) !void {
876 for (self.objects.items) |*object, object_id| {884 for (self.objects.items) |*object, object_id| {
877 for (object.symtab.items) |*sym| {885 for (object.locals.items()) |*entry| {
878 switch (sym.tag) {886 const source_sym = object.symtab.items[entry.value.index.?];
879 .import => unreachable,887 const source_sect_id = source_sym.n_sect - 1;
880 .undef => continue,
881 else => {},
882 }
883
884 const sym_name = object.getString(sym.inner.n_strx);
885 const source_sect_id = sym.inner.n_sect - 1;
886888
887 // TODO I am more and more convinced we should store the mapping as part of the Object struct.889 // TODO I am more and more convinced we should store the mapping as part of the Object struct.
888 const target_mapping = self.mappings.get(.{890 const target_mapping = self.mappings.get(.{
...@@ -894,7 +896,7 @@ fn allocateSymbols(self: *Zld) !void {...@@ -894,7 +896,7 @@ fn allocateSymbols(self: *Zld) !void {
894 .source_sect_id = source_sect_id,896 .source_sect_id = source_sect_id,
895 }) != null) continue;897 }) != null) continue;
896898
897 log.err("section not mapped for symbol '{s}': {}", .{ sym_name, sym });899 log.err("section not mapped for symbol '{s}'", .{entry.value.name});
898 return error.SectionNotMappedForSymbol;900 return error.SectionNotMappedForSymbol;
899 };901 };
900902
...@@ -903,9 +905,9 @@ fn allocateSymbols(self: *Zld) !void {...@@ -903,9 +905,9 @@ fn allocateSymbols(self: *Zld) !void {
903 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;905 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
904 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];906 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
905 const target_addr = target_sect.addr + target_mapping.offset;907 const target_addr = target_sect.addr + target_mapping.offset;
906 const n_value = sym.inner.n_value - source_sect.addr + target_addr;908 const n_value = source_sym.n_value - source_sect.addr + target_addr;
907909
908 log.warn("resolving local symbol '{s}' at 0x{x}", .{ sym_name, n_value });910 log.debug("resolving local symbol '{s}' at 0x{x}", .{ entry.value.name, n_value });
909911
910 // TODO there might be a more generic way of doing this.912 // TODO there might be a more generic way of doing this.
911 var n_sect: u8 = 0;913 var n_sect: u8 = 0;
...@@ -918,8 +920,8 @@ fn allocateSymbols(self: *Zld) !void {...@@ -918,8 +920,8 @@ fn allocateSymbols(self: *Zld) !void {
918 n_sect += @intCast(u8, cmd.Segment.sections.items.len);920 n_sect += @intCast(u8, cmd.Segment.sections.items.len);
919 }921 }
920922
921 sym.inner.n_value = n_value;923 entry.value.address = n_value;
922 sym.inner.n_sect = n_sect;924 entry.value.section = n_sect;
923 }925 }
924 }926 }
925927
...@@ -927,15 +929,13 @@ fn allocateSymbols(self: *Zld) !void {...@@ -927,15 +929,13 @@ fn allocateSymbols(self: *Zld) !void {
927 if (entry.value.tag == .import) continue;929 if (entry.value.tag == .import) continue;
928930
929 const object_id = entry.value.file orelse unreachable;931 const object_id = entry.value.file orelse unreachable;
930 const index = entry.value.index orelse unreachable;
931
932 const object = self.objects.items[object_id];932 const object = self.objects.items[object_id];
933 const sym = object.symtab.items[index];933 const local = object.locals.get(entry.key) orelse unreachable;
934934
935 log.warn("resolving {} symbol '{s}' at 0x{x}", .{ entry.value.tag, entry.key, sym.inner.n_value });935 log.debug("resolving {} symbol '{s}' at 0x{x}", .{ entry.value.tag, entry.key, local.address });
936936
937 entry.value.inner.n_value = sym.inner.n_value;937 entry.value.address = local.address;
938 entry.value.inner.n_sect = sym.inner.n_sect;938 entry.value.section = local.section;
939 }939 }
940}940}
941941
...@@ -944,19 +944,15 @@ fn allocateStubsAndGotEntries(self: *Zld) !void {...@@ -944,19 +944,15 @@ fn allocateStubsAndGotEntries(self: *Zld) !void {
944 if (entry.value.tag == .import) continue;944 if (entry.value.tag == .import) continue;
945945
946 const object = self.objects.items[entry.value.file];946 const object = self.objects.items[entry.value.file];
947 const sym = object.symtab.items[entry.value.local_index];
948 const sym_name = object.getString(sym.inner.n_strx);
949 assert(mem.eql(u8, sym_name, entry.key));
950
951 entry.value.target_addr = target_addr: {947 entry.value.target_addr = target_addr: {
952 if (sym.tag == .undef) {948 if (object.locals.get(entry.key)) |local| {
953 const glob = self.symtab.get(sym_name) orelse unreachable;949 break :target_addr local.address;
954 break :target_addr glob.inner.n_value;
955 }950 }
956 break :target_addr sym.inner.n_value;951 const global = self.symtab.get(entry.key) orelse unreachable;
952 break :target_addr global.address;
957 };953 };
958954
959 log.warn("resolving GOT entry '{s}' at 0x{x}", .{955 log.debug("resolving GOT entry '{s}' at 0x{x}", .{
960 entry.key,956 entry.key,
961 entry.value.target_addr,957 entry.value.target_addr,
962 });958 });
...@@ -1114,7 +1110,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -1114,7 +1110,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
1114 var buf: [@sizeOf(u64)]u8 = undefined;1110 var buf: [@sizeOf(u64)]u8 = undefined;
1115 mem.writeIntLittle(u64, &buf, end);1111 mem.writeIntLittle(u64, &buf, end);
1116 const off = la_symbol_ptr.offset + index * @sizeOf(u64);1112 const off = la_symbol_ptr.offset + index * @sizeOf(u64);
1117 log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });1113 log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });
1118 try self.file.?.pwriteAll(&buf, off);1114 try self.file.?.pwriteAll(&buf, off);
1119}1115}
11201116
...@@ -1127,7 +1123,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -1127,7 +1123,7 @@ fn writeStub(self: *Zld, index: u32) !void {
1127 const stub_off = stubs.offset + index * stubs.reserved2;1123 const stub_off = stubs.offset + index * stubs.reserved2;
1128 const stub_addr = stubs.addr + index * stubs.reserved2;1124 const stub_addr = stubs.addr + index * stubs.reserved2;
1129 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);1125 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);
1130 log.warn("writing stub at 0x{x}", .{stub_off});1126 log.debug("writing stub at 0x{x}", .{stub_off});
1131 var code = try self.allocator.alloc(u8, stubs.reserved2);1127 var code = try self.allocator.alloc(u8, stubs.reserved2);
1132 defer self.allocator.free(code);1128 defer self.allocator.free(code);
1133 switch (self.arch.?) {1129 switch (self.arch.?) {
...@@ -1232,71 +1228,52 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {...@@ -1232,71 +1228,52 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
12321228
1233fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {1229fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
1234 const object = self.objects.items[object_id];1230 const object = self.objects.items[object_id];
1235 log.warn("resolving symbols in '{s}'", .{object.name});1231 log.debug("resolving symbols in '{s}'", .{object.name});
12361232
1237 for (object.symtab.items) |sym, sym_id| {1233 for (object.symtab.items) |sym, sym_id| {
1238 switch (sym.tag) {1234 if (Symbol.isLocal(sym)) {
1239 .local, .stab => continue, // If symbol is local to CU, we don't put it in the global symbol table.1235 // If symbol is local to CU, we don't put it in the global symbol table.
1240 .weak, .strong => {1236 continue;
1241 const sym_name = object.getString(sym.inner.n_strx);1237 } else if (Symbol.isGlobal(sym)) {
1242 const global = self.symtab.getEntry(sym_name) orelse {1238 const sym_name = object.getString(sym.n_strx);
1243 // Put new global symbol into the symbol table.1239 const global = self.symtab.getEntry(sym_name) orelse {
1244 const name = try self.allocator.dupe(u8, sym_name);1240 // Put new global symbol into the symbol table.
1245 try self.symtab.putNoClobber(self.allocator, name, .{
1246 .tag = sym.tag,
1247 .inner = .{
1248 .n_strx = 0, // This will be populated later.
1249 .n_value = 0, // This will be populated later,
1250 .n_type = macho.N_SECT | macho.N_EXT,
1251 .n_desc = 0,
1252 .n_sect = 0, // This will be populated later.
1253 },
1254 .file = object_id,
1255 .index = @intCast(u32, sym_id),
1256 });
1257 continue;
1258 };
1259
1260 switch (global.value.tag) {
1261 .weak => continue, // If symbol is weak, nothing to do.
1262 .strong => {
1263 log.err("symbol '{s}' defined multiple times", .{sym_name});
1264 return error.MultipleSymbolDefinitions;
1265 },
1266 else => {},
1267 }
1268
1269 global.value = .{
1270 .tag = .strong,
1271 .inner = .{
1272 .n_strx = 0, // This will be populated later.
1273 .n_value = 0, // This will be populated later,
1274 .n_type = macho.N_SECT | macho.N_EXT,
1275 .n_desc = 0,
1276 .n_sect = 0, // This will be populated later.
1277 },
1278 .file = object_id,
1279 .index = @intCast(u32, sym_id),
1280 };
1281 },
1282 .undef => {
1283 const sym_name = object.getString(sym.inner.n_strx);
1284 if (self.symtab.contains(sym_name)) continue; // Nothing to do if we already found a definition.
1285
1286 const name = try self.allocator.dupe(u8, sym_name);1241 const name = try self.allocator.dupe(u8, sym_name);
1287 try self.symtab.putNoClobber(self.allocator, name, .{1242 try self.symtab.putNoClobber(self.allocator, name, .{
1288 .tag = .undef,1243 .tag = if (Symbol.isWeakDef(sym)) .weak else .strong,
1289 .inner = .{1244 .name = name,
1290 .n_strx = 0,1245 .address = 0,
1291 .n_value = 0,1246 .section = 0,
1292 .n_type = 0,1247 .file = object_id,
1293 .n_desc = 0,1248 .index = @intCast(u32, sym_id),
1294 .n_sect = 0,
1295 },
1296 });1249 });
1297 },1250 continue;
1298 .import => unreachable, // We don't expect any imports just yet.1251 };
1299 }1252
1253 switch (global.value.tag) {
1254 .weak => continue, // If symbol is weak, nothing to do.
1255 .strong => {
1256 log.err("symbol '{s}' defined multiple times", .{sym_name});
1257 return error.MultipleSymbolDefinitions;
1258 },
1259 else => {},
1260 }
1261
1262 global.value.tag = .strong;
1263 global.value.file = object_id;
1264 global.value.index = @intCast(u32, sym_id);
1265 } else if (Symbol.isUndef(sym)) {
1266 const sym_name = object.getString(sym.n_strx);
1267 if (self.symtab.contains(sym_name)) continue; // Nothing to do if we already found a definition.
1268
1269 const name = try self.allocator.dupe(u8, sym_name);
1270 try self.symtab.putNoClobber(self.allocator, name, .{
1271 .tag = .undef,
1272 .name = name,
1273 .address = 0,
1274 .section = 0,
1275 });
1276 } else unreachable;
1300 }1277 }
1301}1278}
13021279
...@@ -1316,7 +1293,7 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1316,7 +1293,7 @@ fn resolveSymbols(self: *Zld) !void {
1316 for (self.symtab.items()) |entry| {1293 for (self.symtab.items()) |entry| {
1317 if (entry.value.tag != .undef) continue;1294 if (entry.value.tag != .undef) continue;
13181295
1319 const sym_name = entry.key;1296 const sym_name = entry.value.name;
13201297
1321 // Check if the entry exists in a static archive.1298 // Check if the entry exists in a static archive.
1322 const offsets = archive.toc.get(sym_name) orelse {1299 const offsets = archive.toc.get(sym_name) orelse {
...@@ -1349,25 +1326,18 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1349,25 +1326,18 @@ fn resolveSymbols(self: *Zld) !void {
1349 // a libSystem.B.tbd definition file?1326 // a libSystem.B.tbd definition file?
1350 for (self.symtab.items()) |*entry| {1327 for (self.symtab.items()) |*entry| {
1351 if (entry.value.tag != .undef) continue;1328 if (entry.value.tag != .undef) continue;
1352 entry.value = .{1329
1353 .tag = .import,1330 entry.value.tag = .import;
1354 .inner = .{1331 entry.value.file = 0;
1355 .n_strx = 0, // This will be populated once we write the string table.
1356 .n_type = macho.N_UNDF | macho.N_EXT,
1357 .n_sect = 0,
1358 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1359 .n_value = 0,
1360 },
1361 .file = 0,
1362 };
1363 }1332 }
13641333
1365 // If there are any undefs left, flag an error.1334 // If there are any undefs left, flag an error.
1366 var has_unresolved = false;1335 var has_unresolved = false;
1367 for (self.symtab.items()) |entry| {1336 for (self.symtab.items()) |entry| {
1368 if (entry.value.tag != .undef) continue;1337 if (entry.value.tag != .undef) continue;
1338
1369 has_unresolved = true;1339 has_unresolved = true;
1370 log.err("undefined reference to symbol '{s}'", .{entry.key});1340 log.err("undefined reference to symbol '{s}'", .{entry.value.name});
1371 }1341 }
1372 if (has_unresolved) {1342 if (has_unresolved) {
1373 return error.UndefinedSymbolReference;1343 return error.UndefinedSymbolReference;
...@@ -1377,20 +1347,16 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1377,20 +1347,16 @@ fn resolveSymbols(self: *Zld) !void {
1377 var name = try self.allocator.dupe(u8, "dyld_stub_binder");1347 var name = try self.allocator.dupe(u8, "dyld_stub_binder");
1378 try self.symtab.putNoClobber(self.allocator, name, .{1348 try self.symtab.putNoClobber(self.allocator, name, .{
1379 .tag = .import,1349 .tag = .import,
1380 .inner = .{1350 .name = name,
1381 .n_strx = 0, // This will be populated once we write the string table.1351 .address = 0,
1382 .n_type = macho.N_UNDF | macho.N_EXT,1352 .section = 0,
1383 .n_sect = 0,
1384 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1385 .n_value = 0,
1386 },
1387 .file = 0,1353 .file = 0,
1388 });1354 });
1389}1355}
13901356
1391fn resolveStubsAndGotEntries(self: *Zld) !void {1357fn resolveStubsAndGotEntries(self: *Zld) !void {
1392 for (self.objects.items) |object, object_id| {1358 for (self.objects.items) |object, object_id| {
1393 log.warn("resolving stubs and got entries from {s}", .{object.name});1359 log.debug("resolving stubs and got entries from {s}", .{object.name});
13941360
1395 for (object.sections.items) |sect| {1361 for (object.sections.items) |sect| {
1396 const relocs = sect.relocs orelse continue;1362 const relocs = sect.relocs orelse continue;
...@@ -1399,7 +1365,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1399,7 +1365,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1399 .unsigned => continue,1365 .unsigned => continue,
1400 .got_page, .got_page_off => {1366 .got_page, .got_page_off => {
1401 const sym = object.symtab.items[reloc.target.symbol];1367 const sym = object.symtab.items[reloc.target.symbol];
1402 const sym_name = object.getString(sym.inner.n_strx);1368 const sym_name = object.getString(sym.n_strx);
14031369
1404 if (self.got_entries.contains(sym_name)) continue;1370 if (self.got_entries.contains(sym_name)) continue;
14051371
...@@ -1412,16 +1378,15 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1412,16 +1378,15 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1412 .index = index,1378 .index = index,
1413 .target_addr = 0,1379 .target_addr = 0,
1414 .file = if (is_import) 0 else @intCast(u16, object_id),1380 .file = if (is_import) 0 else @intCast(u16, object_id),
1415 .local_index = if (is_import) 0 else reloc.target.symbol,
1416 });1381 });
14171382
1418 log.warn(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) });1383 log.debug(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) });
1419 },1384 },
1420 else => {1385 else => {
1421 const sym = object.symtab.items[reloc.target.symbol];1386 const sym = object.symtab.items[reloc.target.symbol];
1422 const sym_name = object.getString(sym.inner.n_strx);1387 const sym_name = object.getString(sym.n_strx);
14231388
1424 if (sym.tag != .undef) continue;1389 if (!Symbol.isUndef(sym)) continue;
14251390
1426 const in_globals = self.symtab.get(sym_name) orelse unreachable;1391 const in_globals = self.symtab.get(sym_name) orelse unreachable;
14271392
...@@ -1432,7 +1397,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1432,7 +1397,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1432 const index = @intCast(u32, self.stubs.items().len);1397 const index = @intCast(u32, self.stubs.items().len);
1433 try self.stubs.putNoClobber(self.allocator, name, index);1398 try self.stubs.putNoClobber(self.allocator, name, index);
14341399
1435 log.warn(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) });1400 log.debug(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) });
1436 },1401 },
1437 }1402 }
1438 }1403 }
...@@ -1447,15 +1412,14 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1447,15 +1412,14 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1447 .index = index,1412 .index = index,
1448 .target_addr = 0,1413 .target_addr = 0,
1449 .file = 0,1414 .file = 0,
1450 .local_index = 0,
1451 });1415 });
14521416
1453 log.warn(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")});1417 log.debug(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")});
1454}1418}
14551419
1456fn resolveRelocsAndWriteSections(self: *Zld) !void {1420fn resolveRelocsAndWriteSections(self: *Zld) !void {
1457 for (self.objects.items) |object, object_id| {1421 for (self.objects.items) |object, object_id| {
1458 log.warn("relocating object {s}", .{object.name});1422 log.debug("relocating object {s}", .{object.name});
14591423
1460 for (object.sections.items) |sect, source_sect_id| {1424 for (object.sections.items) |sect, source_sect_id| {
1461 const segname = parseName(&sect.inner.segname);1425 const segname = parseName(&sect.inner.segname);
...@@ -1466,7 +1430,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1466,7 +1430,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1466 .object_id = @intCast(u16, object_id),1430 .object_id = @intCast(u16, object_id),
1467 .source_sect_id = @intCast(u16, source_sect_id),1431 .source_sect_id = @intCast(u16, source_sect_id),
1468 }) orelse {1432 }) orelse {
1469 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });1433 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });
1470 continue;1434 continue;
1471 };1435 };
1472 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1436 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
...@@ -1517,7 +1481,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1517,7 +1481,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1517 // Calculate the offset to the initializer.1481 // Calculate the offset to the initializer.
1518 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {1482 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1519 const sym = object.symtab.items[rel.target.symbol];1483 const sym = object.symtab.items[rel.target.symbol];
1520 const sym_name = object.getString(sym.inner.n_strx);1484 const sym_name = object.getString(sym.n_strx);
15211485
1522 // TODO we don't want to save offset to tlv_bootstrap1486 // TODO we don't want to save offset to tlv_bootstrap
1523 if (mem.eql(u8, sym_name, "__tlv_bootstrap")) break :tlv;1487 if (mem.eql(u8, sym_name, "__tlv_bootstrap")) break :tlv;
...@@ -1540,7 +1504,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1540,7 +1504,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1540 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;1504 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1541 const got = dc_seg.sections.items[self.got_section_index.?];1505 const got = dc_seg.sections.items[self.got_section_index.?];
1542 const sym = object.symtab.items[rel.target.symbol];1506 const sym = object.symtab.items[rel.target.symbol];
1543 const sym_name = object.getString(sym.inner.n_strx);1507 const sym_name = object.getString(sym.n_strx);
1544 const entry = self.got_entries.get(sym_name) orelse unreachable;1508 const entry = self.got_entries.get(sym_name) orelse unreachable;
1545 args.target_addr = got.addr + entry.index * @sizeOf(u64);1509 args.target_addr = got.addr + entry.index * @sizeOf(u64);
1546 },1510 },
...@@ -1553,7 +1517,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1553,7 +1517,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1553 }1517 }
1554 }1518 }
15551519
1556 log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{1520 log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
1557 segname,1521 segname,
1558 sectname,1522 sectname,
1559 object.name,1523 object.name,
...@@ -1565,7 +1529,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1565,7 +1529,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1565 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or1529 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
1566 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)1530 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
1567 {1531 {
1568 log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{1532 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1569 parseName(&target_sect.segname),1533 parseName(&target_sect.segname),
1570 parseName(&target_sect.sectname),1534 parseName(&target_sect.sectname),
1571 target_sect_off,1535 target_sect_off,
...@@ -1589,33 +1553,46 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: Relocation.Target) !u64 {...@@ -1589,33 +1553,46 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: Relocation.Target) !u64 {
1589 switch (target) {1553 switch (target) {
1590 .symbol => |sym_id| {1554 .symbol => |sym_id| {
1591 const sym = object.symtab.items[sym_id];1555 const sym = object.symtab.items[sym_id];
1592 const sym_name = object.getString(sym.inner.n_strx);1556 const sym_name = object.getString(sym.n_strx);
15931557
1594 switch (sym.tag) {1558 if (Symbol.isSect(sym)) {
1595 .stab, .local, .weak, .strong => {1559 log.debug(" | local symbol '{s}'", .{sym_name});
1596 log.warn(" | local symbol '{s}'", .{sym_name});1560 if (object.locals.get(sym_name)) |local| {
1597 break :blk sym.inner.n_value;1561 break :blk local.address;
1598 },1562 }
1599 else => {1563 // For temp locals, i.e., symbols prefixed with l... we relocate
1600 if (self.stubs.get(sym_name)) |index| {1564 // based on section addressing.
1601 log.warn(" | symbol stub '{s}'", .{sym_name});1565 const source_sect_id = sym.n_sect - 1;
1602 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;1566 const target_mapping = self.mappings.get(.{
1603 const stubs = segment.sections.items[self.stubs_section_index.?];1567 .object_id = object_id,
1604 break :blk stubs.addr + index * stubs.reserved2;1568 .source_sect_id = source_sect_id,
1605 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {1569 }) orelse unreachable;
1606 log.warn(" | symbol '__tlv_bootstrap'", .{});1570
1607 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1571 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1608 const tlv = segment.sections.items[self.tlv_section_index.?];1572 const source_sect = source_seg.sections.items[source_sect_id];
1609 break :blk tlv.addr;1573 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1610 } else {1574 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1611 const global = self.symtab.get(sym_name) orelse {1575 const target_addr = target_sect.addr + target_mapping.offset;
1612 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});1576 break :blk sym.n_value - source_sect.addr + target_addr;
1613 return error.FailedToResolveRelocationTarget;1577 } else {
1614 };1578 if (self.stubs.get(sym_name)) |index| {
1615 log.warn(" | global symbol '{s}'", .{sym_name});1579 log.debug(" | symbol stub '{s}'", .{sym_name});
1616 break :blk global.inner.n_value;1580 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1617 }1581 const stubs = segment.sections.items[self.stubs_section_index.?];
1618 },1582 break :blk stubs.addr + index * stubs.reserved2;
1583 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1584 log.debug(" | symbol '__tlv_bootstrap'", .{});
1585 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1586 const tlv = segment.sections.items[self.tlv_section_index.?];
1587 break :blk tlv.addr;
1588 } else {
1589 const global = self.symtab.get(sym_name) orelse {
1590 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1591 return error.FailedToResolveRelocationTarget;
1592 };
1593 log.debug(" | global symbol '{s}'", .{sym_name});
1594 break :blk global.address;
1595 }
1619 }1596 }
1620 },1597 },
1621 .section => |sect_id| {1598 .section => |sect_id| {
...@@ -2082,7 +2059,6 @@ fn flush(self: *Zld) !void {...@@ -2082,7 +2059,6 @@ fn flush(self: *Zld) !void {
2082 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);2059 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
2083 }2060 }
20842061
2085 try self.populateStringTable();
2086 try self.writeDebugInfo();2062 try self.writeDebugInfo();
2087 try self.writeSymbolTable();2063 try self.writeSymbolTable();
2088 try self.writeStringTable();2064 try self.writeStringTable();
...@@ -2123,7 +2099,7 @@ fn writeGotEntries(self: *Zld) !void {...@@ -2123,7 +2099,7 @@ fn writeGotEntries(self: *Zld) !void {
2123 try writer.writeIntLittle(u64, entry.value.target_addr);2099 try writer.writeIntLittle(u64, entry.value.target_addr);
2124 }2100 }
21252101
2126 log.warn("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len });2102 log.debug("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len });
21272103
2128 try self.file.?.pwriteAll(buffer, sect.offset);2104 try self.file.?.pwriteAll(buffer, sect.offset);
2129}2105}
...@@ -2135,7 +2111,7 @@ fn setEntryPoint(self: *Zld) !void {...@@ -2135,7 +2111,7 @@ fn setEntryPoint(self: *Zld) !void {
2135 const text = seg.sections.items[self.text_section_index.?];2111 const text = seg.sections.items[self.text_section_index.?];
2136 const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;2112 const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;
2137 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;2113 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;
2138 ec.entryoff = @intCast(u32, entry_sym.inner.n_value - seg.inner.vmaddr);2114 ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr);
2139}2115}
21402116
2141fn writeRebaseInfoTable(self: *Zld) !void {2117fn writeRebaseInfoTable(self: *Zld) !void {
...@@ -2228,7 +2204,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2228,7 +2204,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2228 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));2204 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
2229 seg.inner.filesize += dyld_info.rebase_size;2205 seg.inner.filesize += dyld_info.rebase_size;
22302206
2231 log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });2207 log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
22322208
2233 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);2209 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
2234}2210}
...@@ -2291,7 +2267,7 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2291,7 +2267,7 @@ fn writeBindInfoTable(self: *Zld) !void {
2291 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2267 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2292 seg.inner.filesize += dyld_info.bind_size;2268 seg.inner.filesize += dyld_info.bind_size;
22932269
2294 log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });2270 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
22952271
2296 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);2272 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
2297}2273}
...@@ -2337,7 +2313,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -2337,7 +2313,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
2337 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2313 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2338 seg.inner.filesize += dyld_info.lazy_bind_size;2314 seg.inner.filesize += dyld_info.lazy_bind_size;
23392315
2340 log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });2316 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
23412317
2342 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);2318 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
2343 try self.populateLazyBindOffsetsInStubHelper(buffer);2319 try self.populateLazyBindOffsetsInStubHelper(buffer);
...@@ -2416,11 +2392,11 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2416,11 +2392,11 @@ fn writeExportInfo(self: *Zld) !void {
24162392
2417 // TODO export items for dylibs2393 // TODO export items for dylibs
2418 const sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;2394 const sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;
2419 assert(sym.inner.n_value >= text_segment.inner.vmaddr);2395 assert(sym.address >= text_segment.inner.vmaddr);
24202396
2421 try trie.put(.{2397 try trie.put(.{
2422 .name = "_main",2398 .name = "_main",
2423 .vmaddr_offset = sym.inner.n_value - text_segment.inner.vmaddr,2399 .vmaddr_offset = sym.address - text_segment.inner.vmaddr,
2424 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,2400 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
2425 });2401 });
24262402
...@@ -2439,7 +2415,7 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2439,7 +2415,7 @@ fn writeExportInfo(self: *Zld) !void {
2439 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2415 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2440 seg.inner.filesize += dyld_info.export_size;2416 seg.inner.filesize += dyld_info.export_size;
24412417
2442 log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });2418 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
24432419
2444 try self.file.?.pwriteAll(buffer, dyld_info.export_off);2420 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
2445}2421}
...@@ -2478,31 +2454,24 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2478,31 +2454,24 @@ fn writeDebugInfo(self: *Zld) !void {
2478 });2454 });
24792455
2480 for (object.stabs.items) |stab| {2456 for (object.stabs.items) |stab| {
2481 const sym = object.symtab.items[stab.symbol];2457 const entry = object.locals.items()[stab.symbol];
24822458 const sym = entry.value;
2483 // TODO We should clean this up.
2484 if (self.unhandled_sections.contains(.{
2485 .object_id = @intCast(u16, object_id),
2486 .source_sect_id = stab.source_sect_id,
2487 })) {
2488 continue;
2489 }
24902459
2491 switch (stab.tag) {2460 switch (stab.tag) {
2492 .function => {2461 .function => {
2493 try stabs.append(.{2462 try stabs.append(.{
2494 .n_strx = 0,2463 .n_strx = 0,
2495 .n_type = macho.N_BNSYM,2464 .n_type = macho.N_BNSYM,
2496 .n_sect = sym.inner.n_sect,2465 .n_sect = sym.section,
2497 .n_desc = 0,2466 .n_desc = 0,
2498 .n_value = sym.inner.n_value,2467 .n_value = sym.address,
2499 });2468 });
2500 try stabs.append(.{2469 try stabs.append(.{
2501 .n_strx = sym.inner.n_strx,2470 .n_strx = try self.makeString(sym.name),
2502 .n_type = macho.N_FUN,2471 .n_type = macho.N_FUN,
2503 .n_sect = sym.inner.n_sect,2472 .n_sect = sym.section,
2504 .n_desc = 0,2473 .n_desc = 0,
2505 .n_value = sym.inner.n_value,2474 .n_value = sym.address,
2506 });2475 });
2507 try stabs.append(.{2476 try stabs.append(.{
2508 .n_strx = 0,2477 .n_strx = 0,
...@@ -2514,14 +2483,14 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2514,14 +2483,14 @@ fn writeDebugInfo(self: *Zld) !void {
2514 try stabs.append(.{2483 try stabs.append(.{
2515 .n_strx = 0,2484 .n_strx = 0,
2516 .n_type = macho.N_ENSYM,2485 .n_type = macho.N_ENSYM,
2517 .n_sect = sym.inner.n_sect,2486 .n_sect = sym.section,
2518 .n_desc = 0,2487 .n_desc = 0,
2519 .n_value = stab.size.?,2488 .n_value = stab.size.?,
2520 });2489 });
2521 },2490 },
2522 .global => {2491 .global => {
2523 try stabs.append(.{2492 try stabs.append(.{
2524 .n_strx = sym.inner.n_strx,2493 .n_strx = try self.makeString(sym.name),
2525 .n_type = macho.N_GSYM,2494 .n_type = macho.N_GSYM,
2526 .n_sect = 0,2495 .n_sect = 0,
2527 .n_desc = 0,2496 .n_desc = 0,
...@@ -2530,11 +2499,11 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2530,11 +2499,11 @@ fn writeDebugInfo(self: *Zld) !void {
2530 },2499 },
2531 .static => {2500 .static => {
2532 try stabs.append(.{2501 try stabs.append(.{
2533 .n_strx = sym.inner.n_strx,2502 .n_strx = try self.makeString(sym.name),
2534 .n_type = macho.N_STSYM,2503 .n_type = macho.N_STSYM,
2535 .n_sect = sym.inner.n_sect,2504 .n_sect = sym.section,
2536 .n_desc = 0,2505 .n_desc = 0,
2537 .n_value = sym.inner.n_value,2506 .n_value = sym.address,
2538 });2507 });
2539 },2508 },
2540 }2509 }
...@@ -2560,7 +2529,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2560,7 +2529,7 @@ fn writeDebugInfo(self: *Zld) !void {
25602529
2561 const stabs_off = symtab.symoff;2530 const stabs_off = symtab.symoff;
2562 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);2531 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);
2563 log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });2532 log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });
2564 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);2533 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25652534
2566 linkedit.inner.filesize += stabs_size;2535 linkedit.inner.filesize += stabs_size;
...@@ -2599,13 +2568,17 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2599,13 +2568,17 @@ fn writeSymbolTable(self: *Zld) !void {
2599 defer locals.deinit();2568 defer locals.deinit();
26002569
2601 for (self.objects.items) |object| {2570 for (self.objects.items) |object| {
2602 for (object.symtab.items) |sym| {2571 for (object.locals.items()) |entry| {
2603 switch (sym.tag) {2572 const sym = entry.value;
2604 .stab, .local => {},2573 if (sym.tag != .local) continue;
2605 else => continue,2574
2606 }2575 try locals.append(.{
26072576 .n_strx = try self.makeString(sym.name),
2608 try locals.append(sym.inner);2577 .n_type = macho.N_SECT,
2578 .n_sect = sym.section,
2579 .n_desc = 0,
2580 .n_value = sym.address,
2581 });
2609 }2582 }
2610 }2583 }
26112584
...@@ -2620,13 +2593,26 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2620,13 +2593,26 @@ fn writeSymbolTable(self: *Zld) !void {
26202593
2621 var undef_id: u32 = 0;2594 var undef_id: u32 = 0;
2622 for (self.symtab.items()) |entry| {2595 for (self.symtab.items()) |entry| {
2623 switch (entry.value.tag) {2596 const sym = entry.value;
2597 switch (sym.tag) {
2624 .weak, .strong => {2598 .weak, .strong => {
2625 try exports.append(entry.value.inner);2599 try exports.append(.{
2600 .n_strx = try self.makeString(sym.name),
2601 .n_type = macho.N_SECT | macho.N_EXT,
2602 .n_sect = sym.section,
2603 .n_desc = 0,
2604 .n_value = sym.address,
2605 });
2626 },2606 },
2627 .import => {2607 .import => {
2628 try undefs.append(entry.value.inner);2608 try undefs.append(.{
2629 try undefs_ids.putNoClobber(entry.key, undef_id);2609 .n_strx = try self.makeString(sym.name),
2610 .n_type = macho.N_UNDF | macho.N_EXT,
2611 .n_sect = 0,
2612 .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2613 .n_value = 0,
2614 });
2615 try undefs_ids.putNoClobber(sym.name, undef_id);
2630 undef_id += 1;2616 undef_id += 1;
2631 },2617 },
2632 else => unreachable,2618 else => unreachable,
...@@ -2639,17 +2625,17 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2639,17 +2625,17 @@ fn writeSymbolTable(self: *Zld) !void {
26392625
2640 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);2626 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
2641 const locals_size = nlocals * @sizeOf(macho.nlist_64);2627 const locals_size = nlocals * @sizeOf(macho.nlist_64);
2642 log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });2628 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
2643 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);2629 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
26442630
2645 const exports_off = locals_off + locals_size;2631 const exports_off = locals_off + locals_size;
2646 const exports_size = nexports * @sizeOf(macho.nlist_64);2632 const exports_size = nexports * @sizeOf(macho.nlist_64);
2647 log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });2633 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
2648 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);2634 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
26492635
2650 const undefs_off = exports_off + exports_size;2636 const undefs_off = exports_off + exports_size;
2651 const undefs_size = nundefs * @sizeOf(macho.nlist_64);2637 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
2652 log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });2638 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
2653 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);2639 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26542640
2655 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);2641 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
...@@ -2679,7 +2665,7 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2679,7 +2665,7 @@ fn writeSymbolTable(self: *Zld) !void {
2679 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);2665 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
2680 seg.inner.filesize += needed_size;2666 seg.inner.filesize += needed_size;
26812667
2682 log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{2668 log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{
2683 dysymtab.indirectsymoff,2669 dysymtab.indirectsymoff,
2684 dysymtab.indirectsymoff + needed_size,2670 dysymtab.indirectsymoff + needed_size,
2685 });2671 });
...@@ -2722,7 +2708,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2722,7 +2708,7 @@ fn writeStringTable(self: *Zld) !void {
2722 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));2708 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
2723 seg.inner.filesize += symtab.strsize;2709 seg.inner.filesize += symtab.strsize;
27242710
2725 log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });2711 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
27262712
2727 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);2713 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
27282714
...@@ -2768,7 +2754,7 @@ fn writeDataInCode(self: *Zld) !void {...@@ -2768,7 +2754,7 @@ fn writeDataInCode(self: *Zld) !void {
2768 dice_cmd.datasize = datasize;2754 dice_cmd.datasize = datasize;
2769 seg.inner.filesize += datasize;2755 seg.inner.filesize += datasize;
27702756
2771 log.warn("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize });2757 log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize });
27722758
2773 try self.file.?.pwriteAll(buf.items, fileoff);2759 try self.file.?.pwriteAll(buf.items, fileoff);
2774}2760}
...@@ -2789,7 +2775,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -2789,7 +2775,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
2789 seg.inner.filesize += needed_size;2775 seg.inner.filesize += needed_size;
2790 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2776 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
27912777
2792 log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });2778 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
27932779
2794 // Pad out the space. We need to do this to calculate valid hashes for everything in the file2780 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
2795 // except for code signature data.2781 // except for code signature data.
...@@ -2815,7 +2801,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -2815,7 +2801,7 @@ fn writeCodeSignature(self: *Zld) !void {
2815 var stream = std.io.fixedBufferStream(buffer);2801 var stream = std.io.fixedBufferStream(buffer);
2816 try code_sig.write(stream.writer());2802 try code_sig.write(stream.writer());
28172803
2818 log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });2804 log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });
2819 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);2805 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
2820}2806}
28212807
...@@ -2833,7 +2819,7 @@ fn writeLoadCommands(self: *Zld) !void {...@@ -2833,7 +2819,7 @@ fn writeLoadCommands(self: *Zld) !void {
2833 }2819 }
28342820
2835 const off = @sizeOf(macho.mach_header_64);2821 const off = @sizeOf(macho.mach_header_64);
2836 log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });2822 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
2837 try self.file.?.pwriteAll(buffer, off);2823 try self.file.?.pwriteAll(buffer, off);
2838}2824}
28392825
...@@ -2871,7 +2857,7 @@ fn writeHeader(self: *Zld) !void {...@@ -2871,7 +2857,7 @@ fn writeHeader(self: *Zld) !void {
2871 for (self.load_commands.items) |cmd| {2857 for (self.load_commands.items) |cmd| {
2872 header.sizeofcmds += cmd.cmdsize();2858 header.sizeofcmds += cmd.cmdsize();
2873 }2859 }
2874 log.warn("writing Mach-O header {}", .{header});2860 log.debug("writing Mach-O header {}", .{header});
2875 try self.file.?.pwriteAll(mem.asBytes(&header), 0);2861 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
2876}2862}
28772863
...@@ -2883,11 +2869,17 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -2883,11 +2869,17 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
2883}2869}
28842870
2885fn makeString(self: *Zld, bytes: []const u8) !u32 {2871fn makeString(self: *Zld, bytes: []const u8) !u32 {
2872 if (self.strtab_dir.get(bytes)) |offset| {
2873 log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });
2874 return offset;
2875 }
2876
2886 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);2877 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
2887 const offset = @intCast(u32, self.strtab.items.len);2878 const offset = @intCast(u32, self.strtab.items.len);
2888 log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });2879 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
2889 self.strtab.appendSliceAssumeCapacity(bytes);2880 self.strtab.appendSliceAssumeCapacity(bytes);
2890 self.strtab.appendAssumeCapacity(0);2881 self.strtab.appendAssumeCapacity(0);
2882 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);
2891 return offset;2883 return offset;
2892}2884}
28932885
src/link/MachO/reloc.zig+16-16
...@@ -29,12 +29,12 @@ pub const Relocation = struct {...@@ -29,12 +29,12 @@ pub const Relocation = struct {
29 };29 };
3030
31 pub fn resolve(base: *Relocation, args: ResolveArgs) !void {31 pub fn resolve(base: *Relocation, args: ResolveArgs) !void {
32 log.warn("{s}", .{base.@"type"});32 log.debug("{s}", .{base.@"type"});
33 log.warn(" | offset 0x{x}", .{base.offset});33 log.debug(" | offset 0x{x}", .{base.offset});
34 log.warn(" | source address 0x{x}", .{args.source_addr});34 log.debug(" | source address 0x{x}", .{args.source_addr});
35 log.warn(" | target address 0x{x}", .{args.target_addr});35 log.debug(" | target address 0x{x}", .{args.target_addr});
36 if (args.subtractor) |sub|36 if (args.subtractor) |sub|
37 log.warn(" | subtractor address 0x{x}", .{sub});37 log.debug(" | subtractor address 0x{x}", .{sub});
3838
39 return switch (base.@"type") {39 return switch (base.@"type") {
40 .branch => @fieldParentPtr(Branch, "base", base).resolve(args.source_addr, args.target_addr),40 .branch => @fieldParentPtr(Branch, "base", base).resolve(args.source_addr, args.target_addr),
...@@ -82,7 +82,7 @@ pub const Relocation = struct {...@@ -82,7 +82,7 @@ pub const Relocation = struct {
82 pub fn resolve(branch: Branch, source_addr: u64, target_addr: u64) !void {82 pub fn resolve(branch: Branch, source_addr: u64, target_addr: u64) !void {
83 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));83 const displacement = try math.cast(i28, @intCast(i64, target_addr) - @intCast(i64, source_addr));
8484
85 log.warn(" | displacement 0x{x}", .{displacement});85 log.debug(" | displacement 0x{x}", .{displacement});
8686
87 var inst = branch.inst;87 var inst = branch.inst;
88 inst.UnconditionalBranchImmediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);88 inst.UnconditionalBranchImmediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
...@@ -109,8 +109,8 @@ pub const Relocation = struct {...@@ -109,8 +109,8 @@ pub const Relocation = struct {
109 else109 else
110 @intCast(i64, target_addr) + unsigned.addend;110 @intCast(i64, target_addr) + unsigned.addend;
111111
112 log.warn(" | calculated addend 0x{x}", .{unsigned.addend});112 log.debug(" | calculated addend 0x{x}", .{unsigned.addend});
113 log.warn(" | calculated unsigned value 0x{x}", .{result});113 log.debug(" | calculated unsigned value 0x{x}", .{result});
114114
115 if (unsigned.is_64bit) {115 if (unsigned.is_64bit) {
116 mem.writeIntLittle(116 mem.writeIntLittle(
...@@ -142,8 +142,8 @@ pub const Relocation = struct {...@@ -142,8 +142,8 @@ pub const Relocation = struct {
142 const target_page = @intCast(i32, ta >> 12);142 const target_page = @intCast(i32, ta >> 12);
143 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));143 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
144144
145 log.warn(" | calculated addend 0x{x}", .{page.addend});145 log.debug(" | calculated addend 0x{x}", .{page.addend});
146 log.warn(" | moving by {} pages", .{pages});146 log.debug(" | moving by {} pages", .{pages});
147147
148 var inst = page.inst;148 var inst = page.inst;
149 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);149 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
...@@ -170,8 +170,8 @@ pub const Relocation = struct {...@@ -170,8 +170,8 @@ pub const Relocation = struct {
170 const ta = if (page_off.addend) |a| target_addr + a else target_addr;170 const ta = if (page_off.addend) |a| target_addr + a else target_addr;
171 const narrowed = @truncate(u12, ta);171 const narrowed = @truncate(u12, ta);
172172
173 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});173 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
174 log.warn(" | {s} opcode", .{page_off.op_kind});174 log.debug(" | {s} opcode", .{page_off.op_kind});
175175
176 var inst = page_off.inst;176 var inst = page_off.inst;
177 if (page_off.op_kind == .arithmetic) {177 if (page_off.op_kind == .arithmetic) {
...@@ -209,7 +209,7 @@ pub const Relocation = struct {...@@ -209,7 +209,7 @@ pub const Relocation = struct {
209 const target_page = @intCast(i32, target_addr >> 12);209 const target_page = @intCast(i32, target_addr >> 12);
210 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));210 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
211211
212 log.warn(" | moving by {} pages", .{pages});212 log.debug(" | moving by {} pages", .{pages});
213213
214 var inst = page.inst;214 var inst = page.inst;
215 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);215 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
...@@ -229,7 +229,7 @@ pub const Relocation = struct {...@@ -229,7 +229,7 @@ pub const Relocation = struct {
229 pub fn resolve(page_off: GotPageOff, target_addr: u64) !void {229 pub fn resolve(page_off: GotPageOff, target_addr: u64) !void {
230 const narrowed = @truncate(u12, target_addr);230 const narrowed = @truncate(u12, target_addr);
231231
232 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});232 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
233233
234 var inst = page_off.inst;234 var inst = page_off.inst;
235 const offset = try math.divExact(u12, narrowed, 8);235 const offset = try math.divExact(u12, narrowed, 8);
...@@ -251,7 +251,7 @@ pub const Relocation = struct {...@@ -251,7 +251,7 @@ pub const Relocation = struct {
251 const target_page = @intCast(i32, target_addr >> 12);251 const target_page = @intCast(i32, target_addr >> 12);
252 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));252 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
253253
254 log.warn(" | moving by {} pages", .{pages});254 log.debug(" | moving by {} pages", .{pages});
255255
256 var inst = page.inst;256 var inst = page.inst;
257 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);257 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
...@@ -273,7 +273,7 @@ pub const Relocation = struct {...@@ -273,7 +273,7 @@ pub const Relocation = struct {
273 pub fn resolve(page_off: TlvpPageOff, target_addr: u64) !void {273 pub fn resolve(page_off: TlvpPageOff, target_addr: u64) !void {
274 const narrowed = @truncate(u12, target_addr);274 const narrowed = @truncate(u12, target_addr);
275275
276 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});276 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
277277
278 var inst = page_off.inst;278 var inst = page_off.inst;
279 inst.AddSubtractImmediate.imm12 = narrowed;279 inst.AddSubtractImmediate.imm12 = narrowed;