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 {
903903 self.base.allocator.free(result.stderr);
904904 }
905905 if (result.stdout.len != 0) {
906 log.warn("unexpected LD stdout: {s}", .{result.stdout});
906 log.debug("unexpected LD stdout: {s}", .{result.stdout});
907907 }
908908 if (result.stderr.len != 0) {
909 log.warn("unexpected LD stderr: {s}", .{result.stderr});
909 log.debug("unexpected LD stderr: {s}", .{result.stderr});
910910 }
911911 if (result.term != .Exited or result.term.Exited != 0) {
912912 // TODO parse this output and surface with the Compilation API rather than
......@@ -971,7 +971,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
971971 }
972972
973973 if (stderr.len != 0) {
974 log.warn("unexpected LLD stderr:\n{s}", .{stderr});
974 log.debug("unexpected LLD stderr:\n{s}", .{stderr});
975975 }
976976 }
977977 }
......@@ -981,11 +981,11 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
981981 // Update the file with the digest. If it fails we can continue; it only
982982 // means that the next invocation will have an unnecessary cache miss.
983983 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)});
985985 };
986986 // Again failure here only means an unnecessary cache miss.
987987 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)});
989989 };
990990 // We hang on to this lock so that the output file path can be used without
991991 // other processes clobbering it.
src/link/MachO/Archive.zig+4-3
......@@ -126,7 +126,7 @@ pub fn parse(self: *Archive) !void {
126126 }
127127
128128 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.? });
130130 defer self.allocator.free(embedded_name);
131131
132132 try self.parseTableOfContents(reader);
......@@ -208,13 +208,14 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
208208
209209 const object_name = try parseName(self.allocator, object_header, reader);
210210 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
214215 const name = name: {
215216 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
216217 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 });
218219 };
219220
220221 var object = Object.init(self.allocator);
src/link/MachO/Object.zig+43-43
......@@ -41,9 +41,10 @@ dwarf_debug_str_index: ?u16 = null,
4141dwarf_debug_line_index: ?u16 = null,
4242dwarf_debug_ranges_index: ?u16 = null,
4343
44symtab: std.ArrayListUnmanaged(Symbol) = .{},
44symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
4545strtab: std.ArrayListUnmanaged(u8) = .{},
4646
47locals: std.StringArrayHashMapUnmanaged(Symbol) = .{},
4748stabs: std.ArrayListUnmanaged(Stab) = .{},
4849tu_path: ?[]const u8 = null,
4950tu_mtime: ?u64 = null,
......@@ -71,7 +72,6 @@ const Stab = struct {
7172 tag: Tag,
7273 symbol: u32,
7374 size: ?u64 = null,
74 source_sect_id: u16,
7575
7676 const Tag = enum {
7777 function,
......@@ -161,6 +161,11 @@ pub fn deinit(self: *Object) void {
161161 }
162162 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
164169 self.symtab.deinit(self.allocator);
165170 self.strtab.deinit(self.allocator);
166171 self.stabs.deinit(self.allocator);
......@@ -271,7 +276,7 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
271276 cmd.LinkeditData.dataoff += offset;
272277 },
273278 else => {
274 log.warn("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
279 log.debug("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
275280 },
276281 }
277282 self.load_commands.appendAssumeCapacity(cmd);
......@@ -279,13 +284,13 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
279284}
280285
281286pub fn parseSections(self: *Object) !void {
282 log.warn("parsing sections in {s}", .{self.name.?});
287 log.debug("parsing sections in {s}", .{self.name.?});
283288 const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
284289
285290 try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
286291
287292 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) });
289294 // Read sections' code
290295 var code = try self.allocator.alloc(u8, sect.size);
291296 _ = try self.file.?.preadAll(code, sect.offset);
......@@ -321,42 +326,39 @@ pub fn parseSymtab(self: *Object) !void {
321326 defer self.allocator.free(symtab);
322327
323328 _ = 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);
327 var reader = stream.reader();
332 var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
333 defer self.allocator.free(strtab);
328334
329 while (true) {
330 const symbol = reader.readStruct(macho.nlist_64) catch |err| switch (err) {
331 error.EndOfStream => break,
332 else => |e| return e,
333 };
335 _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
336 try self.strtab.appendSlice(self.allocator, strtab);
337
338 for (self.symtab.items) |sym, sym_id| {
339 if (Symbol.isStab(sym) or Symbol.isUndef(sym)) continue;
340
341 const sym_name = self.getString(sym.n_strx);
334342 const tag: Symbol.Tag = tag: {
335 if (Symbol.isLocal(symbol)) {
336 if (Symbol.isStab(symbol))
337 break :tag .stab
338 else
339 break :tag .local;
340 } else if (Symbol.isGlobal(symbol)) {
341 if (Symbol.isWeakDef(symbol))
342 break :tag .weak
343 else
344 break :tag .strong;
345 } else {
346 break :tag .undef;
343 if (Symbol.isLocal(sym)) {
344 if (self.arch.? == .aarch64 and mem.startsWith(u8, sym_name, "l")) continue;
345 break :tag .local;
346 }
347 if (Symbol.isWeakDef(sym)) {
348 break :tag .weak;
347349 }
350 break :tag .strong;
348351 };
349 self.symtab.appendAssumeCapacity(.{
352 const name = try self.allocator.dupe(u8, sym_name);
353
354 try self.locals.putNoClobber(self.allocator, name, .{
350355 .tag = tag,
351 .inner = symbol,
356 .name = name,
357 .address = 0,
358 .section = 0,
359 .index = @intCast(u32, sym_id),
352360 });
353361 }
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);
360362}
361363
362364pub fn parseDebugInfo(self: *Object) !void {
......@@ -366,13 +368,13 @@ pub fn parseDebugInfo(self: *Object) !void {
366368 };
367369 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
371373 // We assume there is only one CU.
372374 const compile_unit = debug_info.inner.findCompileUnit(0x0) catch |err| switch (err) {
373375 error.MissingDebugInfo => {
374376 // 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.?});
376378 return;
377379 },
378380 else => |e| return e,
......@@ -387,30 +389,28 @@ pub fn parseDebugInfo(self: *Object) !void {
387389 break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
388390 };
389391
390 for (self.symtab.items) |sym, index| {
391 if (sym.tag == .undef) continue;
392
393 const sym_name = self.getString(sym.inner.n_strx);
392 for (self.locals.items()) |entry, index| {
393 const local = entry.value;
394 const source_sym = self.symtab.items[local.index.?];
394395 const size = blk: for (debug_info.inner.func_list.items) |func| {
395396 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) {
397398 break :blk range.end - range.start;
398399 }
399400 }
400401 } else null;
401
402402 const tag: Stab.Tag = tag: {
403403 if (size != null) break :tag .function;
404 switch (sym.tag) {
404 switch (local.tag) {
405405 .weak, .strong => break :tag .global,
406406 else => break :tag .static,
407407 }
408408 };
409
409410 try self.stabs.append(self.allocator, .{
410411 .tag = tag,
411412 .size = size,
412413 .symbol = @intCast(u32, index),
413 .source_sect_id = sym.inner.n_sect - 1,
414414 });
415415 }
416416}
src/link/MachO/Symbol.zig+11-6
......@@ -3,8 +3,9 @@ const Symbol = @This();
33const std = @import("std");
44const macho = std.macho;
55
6const Allocator = std.mem.Allocator;
7
68pub const Tag = enum {
7 stab,
89 local,
910 weak,
1011 strong,
......@@ -13,9 +14,9 @@ pub const Tag = enum {
1314};
1415
1516tag: Tag,
16
17/// MachO representation of this symbol.
18inner: macho.nlist_64,
17name: []u8,
18address: u64,
19section: u8,
1920
2021/// Index of file where to locate this symbol.
2122/// Depending on context, this is either an object file, or a dylib.
......@@ -24,6 +25,10 @@ file: ?u16 = null,
2425/// Index of this symbol within the file's symbol table.
2526index: ?u32 = null,
2627
28pub fn deinit(self: *Symbol, allocator: *Allocator) void {
29 allocator.free(self.name);
30}
31
2732pub fn isStab(sym: macho.nlist_64) bool {
2833 return (macho.N_STAB & sym.n_type) != 0;
2934}
......@@ -50,9 +55,9 @@ pub fn isWeakDef(sym: macho.nlist_64) bool {
5055 return sym.n_desc == macho.N_WEAK_DEF;
5156}
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.
5459pub fn isLocal(sym: macho.nlist_64) bool {
55 return isStab(sym) or (isSect(sym) and !isExt(sym));
60 return isSect(sym) and !isExt(sym);
5661}
5762
5863/// 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,
7575
7676symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},
7777strtab: std.ArrayListUnmanaged(u8) = .{},
78strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
7879
7980threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
8081local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
......@@ -94,7 +95,6 @@ const GotEntry = struct {
9495 index: u32,
9596 target_addr: u64,
9697 file: u16,
97 local_index: u32,
9898};
9999
100100const MappingKey = struct {
......@@ -153,10 +153,18 @@ pub fn deinit(self: *Zld) void {
153153 self.unhandled_sections.deinit(self.allocator);
154154
155155 for (self.symtab.items()) |*entry| {
156 self.allocator.free(entry.key);
156 entry.value.deinit(self.allocator);
157157 }
158158 self.symtab.deinit(self.allocator);
159159 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);
160168}
161169
162170pub fn closeFiles(self: Zld) void {
......@@ -274,7 +282,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
274282 continue;
275283 }
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});
278286 }
279287
280288 // Based on our classification, proceed with parsing.
......@@ -326,7 +334,7 @@ fn mapAndUpdateSections(
326334 .target_sect_id = target_sect_id,
327335 .offset = @intCast(u32, offset),
328336 });
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}", .{
330338 object.name,
331339 parseName(&source_sect.segname),
332340 parseName(&source_sect.sectname),
......@@ -536,7 +544,7 @@ fn updateMetadata(self: *Zld) !void {
536544 });
537545 },
538546 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 });
540548 },
541549 }
542550 }
......@@ -560,7 +568,7 @@ fn updateMetadata(self: *Zld) !void {
560568
561569 const segname = parseName(&source_sect.segname);
562570 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 });
564572 try self.unhandled_sections.putNoClobber(self.allocator, .{
565573 .object_id = object_id,
566574 .source_sect_id = source_sect_id,
......@@ -874,15 +882,9 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
874882
875883fn allocateSymbols(self: *Zld) !void {
876884 for (self.objects.items) |*object, object_id| {
877 for (object.symtab.items) |*sym| {
878 switch (sym.tag) {
879 .import => unreachable,
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;
885 for (object.locals.items()) |*entry| {
886 const source_sym = object.symtab.items[entry.value.index.?];
887 const source_sect_id = source_sym.n_sect - 1;
886888
887889 // TODO I am more and more convinced we should store the mapping as part of the Object struct.
888890 const target_mapping = self.mappings.get(.{
......@@ -894,7 +896,7 @@ fn allocateSymbols(self: *Zld) !void {
894896 .source_sect_id = source_sect_id,
895897 }) != 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});
898900 return error.SectionNotMappedForSymbol;
899901 };
900902
......@@ -903,9 +905,9 @@ fn allocateSymbols(self: *Zld) !void {
903905 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
904906 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
905907 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
910912 // TODO there might be a more generic way of doing this.
911913 var n_sect: u8 = 0;
......@@ -918,8 +920,8 @@ fn allocateSymbols(self: *Zld) !void {
918920 n_sect += @intCast(u8, cmd.Segment.sections.items.len);
919921 }
920922
921 sym.inner.n_value = n_value;
922 sym.inner.n_sect = n_sect;
923 entry.value.address = n_value;
924 entry.value.section = n_sect;
923925 }
924926 }
925927
......@@ -927,15 +929,13 @@ fn allocateSymbols(self: *Zld) !void {
927929 if (entry.value.tag == .import) continue;
928930
929931 const object_id = entry.value.file orelse unreachable;
930 const index = entry.value.index orelse unreachable;
931
932932 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;
938 entry.value.inner.n_sect = sym.inner.n_sect;
937 entry.value.address = local.address;
938 entry.value.section = local.section;
939939 }
940940}
941941
......@@ -944,19 +944,15 @@ fn allocateStubsAndGotEntries(self: *Zld) !void {
944944 if (entry.value.tag == .import) continue;
945945
946946 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
951947 entry.value.target_addr = target_addr: {
952 if (sym.tag == .undef) {
953 const glob = self.symtab.get(sym_name) orelse unreachable;
954 break :target_addr glob.inner.n_value;
948 if (object.locals.get(entry.key)) |local| {
949 break :target_addr local.address;
955950 }
956 break :target_addr sym.inner.n_value;
951 const global = self.symtab.get(entry.key) orelse unreachable;
952 break :target_addr global.address;
957953 };
958954
959 log.warn("resolving GOT entry '{s}' at 0x{x}", .{
955 log.debug("resolving GOT entry '{s}' at 0x{x}", .{
960956 entry.key,
961957 entry.value.target_addr,
962958 });
......@@ -1114,7 +1110,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
11141110 var buf: [@sizeOf(u64)]u8 = undefined;
11151111 mem.writeIntLittle(u64, &buf, end);
11161112 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 });
11181114 try self.file.?.pwriteAll(&buf, off);
11191115}
11201116
......@@ -1127,7 +1123,7 @@ fn writeStub(self: *Zld, index: u32) !void {
11271123 const stub_off = stubs.offset + index * stubs.reserved2;
11281124 const stub_addr = stubs.addr + index * stubs.reserved2;
11291125 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});
11311127 var code = try self.allocator.alloc(u8, stubs.reserved2);
11321128 defer self.allocator.free(code);
11331129 switch (self.arch.?) {
......@@ -1232,71 +1228,52 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
12321228
12331229fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void {
12341230 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
12371233 for (object.symtab.items) |sym, sym_id| {
1238 switch (sym.tag) {
1239 .local, .stab => continue, // If symbol is local to CU, we don't put it in the global symbol table.
1240 .weak, .strong => {
1241 const sym_name = object.getString(sym.inner.n_strx);
1242 const global = self.symtab.getEntry(sym_name) orelse {
1243 // Put new global symbol into the symbol table.
1244 const name = try self.allocator.dupe(u8, sym_name);
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
1234 if (Symbol.isLocal(sym)) {
1235 // If symbol is local to CU, we don't put it in the global symbol table.
1236 continue;
1237 } else if (Symbol.isGlobal(sym)) {
1238 const sym_name = object.getString(sym.n_strx);
1239 const global = self.symtab.getEntry(sym_name) orelse {
1240 // Put new global symbol into the symbol table.
12861241 const name = try self.allocator.dupe(u8, sym_name);
12871242 try self.symtab.putNoClobber(self.allocator, name, .{
1288 .tag = .undef,
1289 .inner = .{
1290 .n_strx = 0,
1291 .n_value = 0,
1292 .n_type = 0,
1293 .n_desc = 0,
1294 .n_sect = 0,
1295 },
1243 .tag = if (Symbol.isWeakDef(sym)) .weak else .strong,
1244 .name = name,
1245 .address = 0,
1246 .section = 0,
1247 .file = object_id,
1248 .index = @intCast(u32, sym_id),
12961249 });
1297 },
1298 .import => unreachable, // We don't expect any imports just yet.
1299 }
1250 continue;
1251 };
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;
13001277 }
13011278}
13021279
......@@ -1316,7 +1293,7 @@ fn resolveSymbols(self: *Zld) !void {
13161293 for (self.symtab.items()) |entry| {
13171294 if (entry.value.tag != .undef) continue;
13181295
1319 const sym_name = entry.key;
1296 const sym_name = entry.value.name;
13201297
13211298 // Check if the entry exists in a static archive.
13221299 const offsets = archive.toc.get(sym_name) orelse {
......@@ -1349,25 +1326,18 @@ fn resolveSymbols(self: *Zld) !void {
13491326 // a libSystem.B.tbd definition file?
13501327 for (self.symtab.items()) |*entry| {
13511328 if (entry.value.tag != .undef) continue;
1352 entry.value = .{
1353 .tag = .import,
1354 .inner = .{
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 };
1329
1330 entry.value.tag = .import;
1331 entry.value.file = 0;
13631332 }
13641333
13651334 // If there are any undefs left, flag an error.
13661335 var has_unresolved = false;
13671336 for (self.symtab.items()) |entry| {
13681337 if (entry.value.tag != .undef) continue;
1338
13691339 has_unresolved = true;
1370 log.err("undefined reference to symbol '{s}'", .{entry.key});
1340 log.err("undefined reference to symbol '{s}'", .{entry.value.name});
13711341 }
13721342 if (has_unresolved) {
13731343 return error.UndefinedSymbolReference;
......@@ -1377,20 +1347,16 @@ fn resolveSymbols(self: *Zld) !void {
13771347 var name = try self.allocator.dupe(u8, "dyld_stub_binder");
13781348 try self.symtab.putNoClobber(self.allocator, name, .{
13791349 .tag = .import,
1380 .inner = .{
1381 .n_strx = 0, // This will be populated once we write the string table.
1382 .n_type = macho.N_UNDF | macho.N_EXT,
1383 .n_sect = 0,
1384 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
1385 .n_value = 0,
1386 },
1350 .name = name,
1351 .address = 0,
1352 .section = 0,
13871353 .file = 0,
13881354 });
13891355}
13901356
13911357fn resolveStubsAndGotEntries(self: *Zld) !void {
13921358 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
13951361 for (object.sections.items) |sect| {
13961362 const relocs = sect.relocs orelse continue;
......@@ -1399,7 +1365,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
13991365 .unsigned => continue,
14001366 .got_page, .got_page_off => {
14011367 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
14041370 if (self.got_entries.contains(sym_name)) continue;
14051371
......@@ -1412,16 +1378,15 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14121378 .index = index,
14131379 .target_addr = 0,
14141380 .file = if (is_import) 0 else @intCast(u16, object_id),
1415 .local_index = if (is_import) 0 else reloc.target.symbol,
14161381 });
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) });
14191384 },
14201385 else => {
14211386 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
14261391 const in_globals = self.symtab.get(sym_name) orelse unreachable;
14271392
......@@ -1432,7 +1397,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14321397 const index = @intCast(u32, self.stubs.items().len);
14331398 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) });
14361401 },
14371402 }
14381403 }
......@@ -1447,15 +1412,14 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14471412 .index = index,
14481413 .target_addr = 0,
14491414 .file = 0,
1450 .local_index = 0,
14511415 });
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")});
14541418}
14551419
14561420fn resolveRelocsAndWriteSections(self: *Zld) !void {
14571421 for (self.objects.items) |object, object_id| {
1458 log.warn("relocating object {s}", .{object.name});
1422 log.debug("relocating object {s}", .{object.name});
14591423
14601424 for (object.sections.items) |sect, source_sect_id| {
14611425 const segname = parseName(&sect.inner.segname);
......@@ -1466,7 +1430,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
14661430 .object_id = @intCast(u16, object_id),
14671431 .source_sect_id = @intCast(u16, source_sect_id),
14681432 }) orelse {
1469 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
1433 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });
14701434 continue;
14711435 };
14721436 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
......@@ -1517,7 +1481,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15171481 // Calculate the offset to the initializer.
15181482 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
15191483 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
15221486 // TODO we don't want to save offset to tlv_bootstrap
15231487 if (mem.eql(u8, sym_name, "__tlv_bootstrap")) break :tlv;
......@@ -1540,7 +1504,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15401504 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
15411505 const got = dc_seg.sections.items[self.got_section_index.?];
15421506 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);
15441508 const entry = self.got_entries.get(sym_name) orelse unreachable;
15451509 args.target_addr = got.addr + entry.index * @sizeOf(u64);
15461510 },
......@@ -1553,7 +1517,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15531517 }
15541518 }
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}", .{
15571521 segname,
15581522 sectname,
15591523 object.name,
......@@ -1565,7 +1529,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15651529 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
15661530 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
15671531 {
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}", .{
15691533 parseName(&target_sect.segname),
15701534 parseName(&target_sect.sectname),
15711535 target_sect_off,
......@@ -1589,33 +1553,46 @@ fn relocTargetAddr(self: *Zld, object_id: u16, target: Relocation.Target) !u64 {
15891553 switch (target) {
15901554 .symbol => |sym_id| {
15911555 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) {
1595 .stab, .local, .weak, .strong => {
1596 log.warn(" | local symbol '{s}'", .{sym_name});
1597 break :blk sym.inner.n_value;
1598 },
1599 else => {
1600 if (self.stubs.get(sym_name)) |index| {
1601 log.warn(" | symbol stub '{s}'", .{sym_name});
1602 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1603 const stubs = segment.sections.items[self.stubs_section_index.?];
1604 break :blk stubs.addr + index * stubs.reserved2;
1605 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1606 log.warn(" | symbol '__tlv_bootstrap'", .{});
1607 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1608 const tlv = segment.sections.items[self.tlv_section_index.?];
1609 break :blk tlv.addr;
1610 } else {
1611 const global = self.symtab.get(sym_name) orelse {
1612 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1613 return error.FailedToResolveRelocationTarget;
1614 };
1615 log.warn(" | global symbol '{s}'", .{sym_name});
1616 break :blk global.inner.n_value;
1617 }
1618 },
1558 if (Symbol.isSect(sym)) {
1559 log.debug(" | local symbol '{s}'", .{sym_name});
1560 if (object.locals.get(sym_name)) |local| {
1561 break :blk local.address;
1562 }
1563 // For temp locals, i.e., symbols prefixed with l... we relocate
1564 // based on section addressing.
1565 const source_sect_id = sym.n_sect - 1;
1566 const target_mapping = self.mappings.get(.{
1567 .object_id = object_id,
1568 .source_sect_id = source_sect_id,
1569 }) orelse unreachable;
1570
1571 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1572 const source_sect = source_seg.sections.items[source_sect_id];
1573 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1574 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1575 const target_addr = target_sect.addr + target_mapping.offset;
1576 break :blk sym.n_value - source_sect.addr + target_addr;
1577 } else {
1578 if (self.stubs.get(sym_name)) |index| {
1579 log.debug(" | symbol stub '{s}'", .{sym_name});
1580 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1581 const stubs = segment.sections.items[self.stubs_section_index.?];
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 }
16191596 }
16201597 },
16211598 .section => |sect_id| {
......@@ -2082,7 +2059,6 @@ fn flush(self: *Zld) !void {
20822059 symtab.symoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
20832060 }
20842061
2085 try self.populateStringTable();
20862062 try self.writeDebugInfo();
20872063 try self.writeSymbolTable();
20882064 try self.writeStringTable();
......@@ -2123,7 +2099,7 @@ fn writeGotEntries(self: *Zld) !void {
21232099 try writer.writeIntLittle(u64, entry.value.target_addr);
21242100 }
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
21282104 try self.file.?.pwriteAll(buffer, sect.offset);
21292105}
......@@ -2135,7 +2111,7 @@ fn setEntryPoint(self: *Zld) !void {
21352111 const text = seg.sections.items[self.text_section_index.?];
21362112 const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;
21372113 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);
21392115}
21402116
21412117fn writeRebaseInfoTable(self: *Zld) !void {
......@@ -2228,7 +2204,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22282204 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
22292205 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
22332209 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
22342210}
......@@ -2291,7 +2267,7 @@ fn writeBindInfoTable(self: *Zld) !void {
22912267 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
22922268 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
22962272 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
22972273}
......@@ -2337,7 +2313,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
23372313 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
23382314 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
23422318 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
23432319 try self.populateLazyBindOffsetsInStubHelper(buffer);
......@@ -2416,11 +2392,11 @@ fn writeExportInfo(self: *Zld) !void {
24162392
24172393 // TODO export items for dylibs
24182394 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
24212397 try trie.put(.{
24222398 .name = "_main",
2423 .vmaddr_offset = sym.inner.n_value - text_segment.inner.vmaddr,
2399 .vmaddr_offset = sym.address - text_segment.inner.vmaddr,
24242400 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
24252401 });
24262402
......@@ -2439,7 +2415,7 @@ fn writeExportInfo(self: *Zld) !void {
24392415 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
24402416 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
24442420 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
24452421}
......@@ -2478,31 +2454,24 @@ fn writeDebugInfo(self: *Zld) !void {
24782454 });
24792455
24802456 for (object.stabs.items) |stab| {
2481 const sym = object.symtab.items[stab.symbol];
2482
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 }
2457 const entry = object.locals.items()[stab.symbol];
2458 const sym = entry.value;
24902459
24912460 switch (stab.tag) {
24922461 .function => {
24932462 try stabs.append(.{
24942463 .n_strx = 0,
24952464 .n_type = macho.N_BNSYM,
2496 .n_sect = sym.inner.n_sect,
2465 .n_sect = sym.section,
24972466 .n_desc = 0,
2498 .n_value = sym.inner.n_value,
2467 .n_value = sym.address,
24992468 });
25002469 try stabs.append(.{
2501 .n_strx = sym.inner.n_strx,
2470 .n_strx = try self.makeString(sym.name),
25022471 .n_type = macho.N_FUN,
2503 .n_sect = sym.inner.n_sect,
2472 .n_sect = sym.section,
25042473 .n_desc = 0,
2505 .n_value = sym.inner.n_value,
2474 .n_value = sym.address,
25062475 });
25072476 try stabs.append(.{
25082477 .n_strx = 0,
......@@ -2514,14 +2483,14 @@ fn writeDebugInfo(self: *Zld) !void {
25142483 try stabs.append(.{
25152484 .n_strx = 0,
25162485 .n_type = macho.N_ENSYM,
2517 .n_sect = sym.inner.n_sect,
2486 .n_sect = sym.section,
25182487 .n_desc = 0,
25192488 .n_value = stab.size.?,
25202489 });
25212490 },
25222491 .global => {
25232492 try stabs.append(.{
2524 .n_strx = sym.inner.n_strx,
2493 .n_strx = try self.makeString(sym.name),
25252494 .n_type = macho.N_GSYM,
25262495 .n_sect = 0,
25272496 .n_desc = 0,
......@@ -2530,11 +2499,11 @@ fn writeDebugInfo(self: *Zld) !void {
25302499 },
25312500 .static => {
25322501 try stabs.append(.{
2533 .n_strx = sym.inner.n_strx,
2502 .n_strx = try self.makeString(sym.name),
25342503 .n_type = macho.N_STSYM,
2535 .n_sect = sym.inner.n_sect,
2504 .n_sect = sym.section,
25362505 .n_desc = 0,
2537 .n_value = sym.inner.n_value,
2506 .n_value = sym.address,
25382507 });
25392508 },
25402509 }
......@@ -2560,7 +2529,7 @@ fn writeDebugInfo(self: *Zld) !void {
25602529
25612530 const stabs_off = symtab.symoff;
25622531 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 });
25642533 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25652534
25662535 linkedit.inner.filesize += stabs_size;
......@@ -2599,13 +2568,17 @@ fn writeSymbolTable(self: *Zld) !void {
25992568 defer locals.deinit();
26002569
26012570 for (self.objects.items) |object| {
2602 for (object.symtab.items) |sym| {
2603 switch (sym.tag) {
2604 .stab, .local => {},
2605 else => continue,
2606 }
2607
2608 try locals.append(sym.inner);
2571 for (object.locals.items()) |entry| {
2572 const sym = entry.value;
2573 if (sym.tag != .local) continue;
2574
2575 try locals.append(.{
2576 .n_strx = try self.makeString(sym.name),
2577 .n_type = macho.N_SECT,
2578 .n_sect = sym.section,
2579 .n_desc = 0,
2580 .n_value = sym.address,
2581 });
26092582 }
26102583 }
26112584
......@@ -2620,13 +2593,26 @@ fn writeSymbolTable(self: *Zld) !void {
26202593
26212594 var undef_id: u32 = 0;
26222595 for (self.symtab.items()) |entry| {
2623 switch (entry.value.tag) {
2596 const sym = entry.value;
2597 switch (sym.tag) {
26242598 .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 });
26262606 },
26272607 .import => {
2628 try undefs.append(entry.value.inner);
2629 try undefs_ids.putNoClobber(entry.key, undef_id);
2608 try undefs.append(.{
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);
26302616 undef_id += 1;
26312617 },
26322618 else => unreachable,
......@@ -2639,17 +2625,17 @@ fn writeSymbolTable(self: *Zld) !void {
26392625
26402626 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
26412627 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 });
26432629 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
26442630
26452631 const exports_off = locals_off + locals_size;
26462632 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 });
26482634 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
26492635
26502636 const undefs_off = exports_off + exports_size;
26512637 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 });
26532639 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26542640
26552641 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
......@@ -2679,7 +2665,7 @@ fn writeSymbolTable(self: *Zld) !void {
26792665 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
26802666 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}", .{
26832669 dysymtab.indirectsymoff,
26842670 dysymtab.indirectsymoff + needed_size,
26852671 });
......@@ -2722,7 +2708,7 @@ fn writeStringTable(self: *Zld) !void {
27222708 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
27232709 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
27272713 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
27282714
......@@ -2768,7 +2754,7 @@ fn writeDataInCode(self: *Zld) !void {
27682754 dice_cmd.datasize = datasize;
27692755 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
27732759 try self.file.?.pwriteAll(buf.items, fileoff);
27742760}
......@@ -2789,7 +2775,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
27892775 seg.inner.filesize += needed_size;
27902776 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
27942780 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
27952781 // except for code signature data.
......@@ -2815,7 +2801,7 @@ fn writeCodeSignature(self: *Zld) !void {
28152801 var stream = std.io.fixedBufferStream(buffer);
28162802 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 });
28192805 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
28202806}
28212807
......@@ -2833,7 +2819,7 @@ fn writeLoadCommands(self: *Zld) !void {
28332819 }
28342820
28352821 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 });
28372823 try self.file.?.pwriteAll(buffer, off);
28382824}
28392825
......@@ -2871,7 +2857,7 @@ fn writeHeader(self: *Zld) !void {
28712857 for (self.load_commands.items) |cmd| {
28722858 header.sizeofcmds += cmd.cmdsize();
28732859 }
2874 log.warn("writing Mach-O header {}", .{header});
2860 log.debug("writing Mach-O header {}", .{header});
28752861 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
28762862}
28772863
......@@ -2883,11 +2869,17 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
28832869}
28842870
28852871fn 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
28862877 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
28872878 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 });
28892880 self.strtab.appendSliceAssumeCapacity(bytes);
28902881 self.strtab.appendAssumeCapacity(0);
2882 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);
28912883 return offset;
28922884}
28932885
src/link/MachO/reloc.zig+16-16
......@@ -29,12 +29,12 @@ pub const Relocation = struct {
2929 };
3030
3131 pub fn resolve(base: *Relocation, args: ResolveArgs) !void {
32 log.warn("{s}", .{base.@"type"});
33 log.warn(" | offset 0x{x}", .{base.offset});
34 log.warn(" | source address 0x{x}", .{args.source_addr});
35 log.warn(" | target address 0x{x}", .{args.target_addr});
32 log.debug("{s}", .{base.@"type"});
33 log.debug(" | offset 0x{x}", .{base.offset});
34 log.debug(" | source address 0x{x}", .{args.source_addr});
35 log.debug(" | target address 0x{x}", .{args.target_addr});
3636 if (args.subtractor) |sub|
37 log.warn(" | subtractor address 0x{x}", .{sub});
37 log.debug(" | subtractor address 0x{x}", .{sub});
3838
3939 return switch (base.@"type") {
4040 .branch => @fieldParentPtr(Branch, "base", base).resolve(args.source_addr, args.target_addr),
......@@ -82,7 +82,7 @@ pub const Relocation = struct {
8282 pub fn resolve(branch: Branch, source_addr: u64, target_addr: u64) !void {
8383 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
8787 var inst = branch.inst;
8888 inst.UnconditionalBranchImmediate.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
......@@ -109,8 +109,8 @@ pub const Relocation = struct {
109109 else
110110 @intCast(i64, target_addr) + unsigned.addend;
111111
112 log.warn(" | calculated addend 0x{x}", .{unsigned.addend});
113 log.warn(" | calculated unsigned value 0x{x}", .{result});
112 log.debug(" | calculated addend 0x{x}", .{unsigned.addend});
113 log.debug(" | calculated unsigned value 0x{x}", .{result});
114114
115115 if (unsigned.is_64bit) {
116116 mem.writeIntLittle(
......@@ -142,8 +142,8 @@ pub const Relocation = struct {
142142 const target_page = @intCast(i32, ta >> 12);
143143 const pages = @bitCast(u21, @intCast(i21, target_page - source_page));
144144
145 log.warn(" | calculated addend 0x{x}", .{page.addend});
146 log.warn(" | moving by {} pages", .{pages});
145 log.debug(" | calculated addend 0x{x}", .{page.addend});
146 log.debug(" | moving by {} pages", .{pages});
147147
148148 var inst = page.inst;
149149 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
......@@ -170,8 +170,8 @@ pub const Relocation = struct {
170170 const ta = if (page_off.addend) |a| target_addr + a else target_addr;
171171 const narrowed = @truncate(u12, ta);
172172
173 log.warn(" | narrowed address within the page 0x{x}", .{narrowed});
174 log.warn(" | {s} opcode", .{page_off.op_kind});
173 log.debug(" | narrowed address within the page 0x{x}", .{narrowed});
174 log.debug(" | {s} opcode", .{page_off.op_kind});
175175
176176 var inst = page_off.inst;
177177 if (page_off.op_kind == .arithmetic) {
......@@ -209,7 +209,7 @@ pub const Relocation = struct {
209209 const target_page = @intCast(i32, target_addr >> 12);
210210 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
214214 var inst = page.inst;
215215 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
......@@ -229,7 +229,7 @@ pub const Relocation = struct {
229229 pub fn resolve(page_off: GotPageOff, target_addr: u64) !void {
230230 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
234234 var inst = page_off.inst;
235235 const offset = try math.divExact(u12, narrowed, 8);
......@@ -251,7 +251,7 @@ pub const Relocation = struct {
251251 const target_page = @intCast(i32, target_addr >> 12);
252252 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
256256 var inst = page.inst;
257257 inst.PCRelativeAddress.immhi = @truncate(u19, pages >> 2);
......@@ -273,7 +273,7 @@ pub const Relocation = struct {
273273 pub fn resolve(page_off: TlvpPageOff, target_addr: u64) !void {
274274 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
278278 var inst = page_off.inst;
279279 inst.AddSubtractImmediate.imm12 = narrowed;