| ... | @@ -75,6 +75,7 @@ bss_section_index: ?u16 = null, | ... | @@ -75,6 +75,7 @@ bss_section_index: ?u16 = null, |
| 75 | | 75 | |
| 76 | symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | 76 | symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{}, |
| 77 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 77 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| | 78 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, |
| 78 | | 79 | |
| 79 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, | 80 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, |
| 80 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, | 81 | local_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 | }; |
| 99 | | 99 | |
| 100 | const MappingKey = struct { | 100 | const 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); |
| 154 | | 154 | |
| 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 | } |
| 161 | | 169 | |
| 162 | pub fn closeFiles(self: Zld) void { | 170 | pub 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 | } |
| 276 | | 284 | |
| 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 | } |
| 279 | | 287 | |
| 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 { |
| 560 | | 568 | |
| 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 { |
| 874 | | 882 | |
| 875 | fn allocateSymbols(self: *Zld) !void { | 883 | fn 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; | | |
| 886 | | 888 | |
| 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; |
| 896 | | 898 | |
| 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 | }; |
| 900 | | 902 | |
| ... | @@ -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; |
| 907 | | 909 | |
| 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 }); |
| 909 | | 911 | |
| 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 | } |
| 920 | | 922 | |
| 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 | } |
| 925 | | 927 | |
| ... | @@ -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; |
| 928 | | 930 | |
| 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; |
| 934 | | 934 | |
| 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 }); |
| 936 | | 936 | |
| 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 | } |
| 941 | | 941 | |
| ... | @@ -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; |
| 945 | | 945 | |
| 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 | }; |
| 958 | | 954 | |
| 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 | } |
| 1120 | | 1116 | |
| ... | @@ -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 { |
| 1232 | | 1228 | |
| 1233 | fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void { | 1229 | fn 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}); |
| 1236 | | 1232 | |
| 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 | } |
| 1302 | | 1279 | |
| ... | @@ -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; |
| 1318 | | 1295 | |
| 1319 | const sym_name = entry.key; | 1296 | const sym_name = entry.value.name; |
| 1320 | | 1297 | |
| 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 | } |
| 1364 | | 1333 | |
| 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 | } |
| 1390 | | 1356 | |
| 1391 | fn resolveStubsAndGotEntries(self: *Zld) !void { | 1357 | fn 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}); |
| 1394 | | 1360 | |
| 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); |
| 1403 | | 1369 | |
| 1404 | if (self.got_entries.contains(sym_name)) continue; | 1370 | if (self.got_entries.contains(sym_name)) continue; |
| 1405 | | 1371 | |
| ... | @@ -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 | }); |
| 1417 | | 1382 | |
| 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); |
| 1423 | | 1388 | |
| 1424 | if (sym.tag != .undef) continue; | 1389 | if (!Symbol.isUndef(sym)) continue; |
| 1425 | | 1390 | |
| 1426 | const in_globals = self.symtab.get(sym_name) orelse unreachable; | 1391 | const in_globals = self.symtab.get(sym_name) orelse unreachable; |
| 1427 | | 1392 | |
| ... | @@ -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); |
| 1434 | | 1399 | |
| 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 | }); |
| 1452 | | 1416 | |
| 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 | } |
| 1455 | | 1419 | |
| 1456 | fn resolveRelocsAndWriteSections(self: *Zld) !void { | 1420 | fn 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}); |
| 1459 | | 1423 | |
| 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); |
| 1521 | | 1485 | |
| 1522 | // TODO we don't want to save offset to tlv_bootstrap | 1486 | // 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 | } |
| 1555 | | 1519 | |
| 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 or | 1529 | 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); |
| 1593 | | 1557 | |
| 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 | } |
| 2084 | | 2061 | |
| 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 | } |
| 2125 | | 2101 | |
| 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 }); |
| 2127 | | 2103 | |
| 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 | } |
| 2140 | | 2116 | |
| 2141 | fn writeRebaseInfoTable(self: *Zld) !void { | 2117 | fn 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; |
| 2230 | | 2206 | |
| 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 }); |
| 2232 | | 2208 | |
| 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; |
| 2293 | | 2269 | |
| 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 }); |
| 2295 | | 2271 | |
| 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; |
| 2339 | | 2315 | |
| 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 }); |
| 2341 | | 2317 | |
| 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 { |
| 2416 | | 2392 | |
| 2417 | // TODO export items for dylibs | 2393 | // 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); |
| 2420 | | 2396 | |
| 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 | }); |
| 2426 | | 2402 | |
| ... | @@ -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; |
| 2441 | | 2417 | |
| 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 }); |
| 2443 | | 2419 | |
| 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 | }); |
| 2479 | | 2455 | |
| 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]; |
| 2482 | | 2458 | 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 | } | | |
| 2490 | | 2459 | |
| 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 { |
| 2560 | | 2529 | |
| 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); |
| 2565 | | 2534 | |
| 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(); |
| 2600 | | 2569 | |
| 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(.{ |
| 2607 | | 2576 | .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 | } |
| 2611 | | 2584 | |
| ... | @@ -2620,13 +2593,26 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2620,13 +2593,26 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2620 | | 2593 | |
| 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 { |
| 2639 | | 2625 | |
| 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); |
| 2644 | | 2630 | |
| 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); |
| 2649 | | 2635 | |
| 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); |
| 2654 | | 2640 | |
| 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; |
| 2681 | | 2667 | |
| 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; |
| 2724 | | 2710 | |
| 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 }); |
| 2726 | | 2712 | |
| 2727 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); | 2713 | try self.file.?.pwriteAll(self.strtab.items, symtab.stroff); |
| 2728 | | 2714 | |
| ... | @@ -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; |
| 2770 | | 2756 | |
| 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 }); |
| 2772 | | 2758 | |
| 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.?); |
| 2791 | | 2777 | |
| 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 }); |
| 2793 | | 2779 | |
| 2794 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file | 2780 | // 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()); |
| 2817 | | 2803 | |
| 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 | } |
| 2821 | | 2807 | |
| ... | @@ -2833,7 +2819,7 @@ fn writeLoadCommands(self: *Zld) !void { | ... | @@ -2833,7 +2819,7 @@ fn writeLoadCommands(self: *Zld) !void { |
| 2833 | } | 2819 | } |
| 2834 | | 2820 | |
| 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 | } |
| 2839 | | 2825 | |
| ... | @@ -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 | } |
| 2877 | | 2863 | |
| ... | @@ -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 | } |
| 2884 | | 2870 | |
| 2885 | fn makeString(self: *Zld, bytes: []const u8) !u32 { | 2871 | fn 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 | } |
| 2893 | | 2885 | |