| ... | @@ -73,9 +73,7 @@ la_symbol_ptr_section_index: ?u16 = null, | ... | @@ -73,9 +73,7 @@ la_symbol_ptr_section_index: ?u16 = null, |
| 73 | data_section_index: ?u16 = null, | 73 | data_section_index: ?u16 = null, |
| 74 | bss_section_index: ?u16 = null, | 74 | bss_section_index: ?u16 = null, |
| 75 | | 75 | |
| 76 | globals: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | 76 | symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{}, |
| 77 | undefs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | | |
| 78 | externs: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | | |
| 79 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 77 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 80 | | 78 | |
| 81 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, | 79 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, |
| ... | @@ -210,20 +208,11 @@ pub fn deinit(self: *Zld) void { | ... | @@ -210,20 +208,11 @@ pub fn deinit(self: *Zld) void { |
| 210 | self.mappings.deinit(self.allocator); | 208 | self.mappings.deinit(self.allocator); |
| 211 | self.unhandled_sections.deinit(self.allocator); | 209 | self.unhandled_sections.deinit(self.allocator); |
| 212 | | 210 | |
| 213 | for (self.globals.items()) |*entry| { | 211 | for (self.symtab.items()) |*entry| { |
| 214 | self.allocator.free(entry.key); | 212 | self.allocator.free(entry.key); |
| 215 | } | 213 | } |
| 216 | self.globals.deinit(self.allocator); | 214 | self.symtab.deinit(self.allocator); |
| 217 | | 215 | self.strtab.deinit(self.allocator); |
| 218 | for (self.undefs.items()) |*entry| { | | |
| 219 | self.allocator.free(entry.key); | | |
| 220 | } | | |
| 221 | self.undefs.deinit(self.allocator); | | |
| 222 | | | |
| 223 | for (self.externs.items()) |*entry| { | | |
| 224 | self.allocator.free(entry.key); | | |
| 225 | } | | |
| 226 | self.externs.deinit(self.allocator); | | |
| 227 | } | 216 | } |
| 228 | | 217 | |
| 229 | pub fn closeFiles(self: Zld) void { | 218 | pub fn closeFiles(self: Zld) void { |
| ... | @@ -276,10 +265,11 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { | ... | @@ -276,10 +265,11 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { |
| 276 | try self.resolveSymbols(); | 265 | try self.resolveSymbols(); |
| 277 | try self.updateMetadata(); | 266 | try self.updateMetadata(); |
| 278 | try self.sortSections(); | 267 | try self.sortSections(); |
| 279 | try self.allocateTextSegment(); | 268 | self.printSymtab(); |
| 280 | try self.allocateDataConstSegment(); | 269 | // try self.allocateTextSegment(); |
| 281 | try self.allocateDataSegment(); | 270 | // try self.allocateDataConstSegment(); |
| 282 | self.allocateLinkeditSegment(); | 271 | // try self.allocateDataSegment(); |
| | 272 | // self.allocateLinkeditSegment(); |
| 283 | // try self.writeStubHelperCommon(); | 273 | // try self.writeStubHelperCommon(); |
| 284 | // try self.doRelocs(); | 274 | // try self.doRelocs(); |
| 285 | // try self.flush(); | 275 | // try self.flush(); |
| ... | @@ -1216,48 +1206,64 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void { | ... | @@ -1216,48 +1206,64 @@ fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void { |
| 1216 | log.warn("resolving symbols in '{s}'", .{object.name}); | 1206 | log.warn("resolving symbols in '{s}'", .{object.name}); |
| 1217 | | 1207 | |
| 1218 | for (object.symtab.items) |sym, sym_id| { | 1208 | for (object.symtab.items) |sym, sym_id| { |
| 1219 | if (sym.isLocal()) continue; // If symbol is local to CU, we don't put it in the global symbol table. | 1209 | switch (sym.tag) { |
| 1220 | | 1210 | .Local, .Stab => continue, // If symbol is local to CU, we don't put it in the global symbol table. |
| 1221 | const sym_name = object.getString(sym.inner.n_strx); | 1211 | .Weak, .Strong => { |
| 1222 | if (sym.isGlobal()) { | 1212 | const sym_name = object.getString(sym.inner.n_strx); |
| 1223 | const global = self.globals.getEntry(sym_name) orelse { | 1213 | const global = self.symtab.getEntry(sym_name) orelse { |
| 1224 | const name = try self.allocator.dupe(u8, sym_name); | 1214 | // Put new global symbol into the symbol table. |
| 1225 | try self.globals.putNoClobber(self.allocator, name, .{ | 1215 | const name = try self.allocator.dupe(u8, sym_name); |
| 1226 | .inner = sym.inner, | 1216 | try self.symtab.putNoClobber(self.allocator, name, .{ |
| 1227 | .file = object_id, | 1217 | .tag = sym.tag, |
| 1228 | .index = @intCast(u32, sym_id), | 1218 | .inner = .{ |
| 1229 | }); | 1219 | .n_strx = 0, // This will be populated later. |
| | 1220 | .n_value = 0, // This will be populated later, |
| | 1221 | .n_type = macho.N_SECT | macho.N_EXT, |
| | 1222 | .n_desc = 0, |
| | 1223 | .n_sect = 0, // This will be populated later. |
| | 1224 | }, |
| | 1225 | .file = object_id, |
| | 1226 | .index = @intCast(u32, sym_id), |
| | 1227 | }); |
| | 1228 | continue; |
| | 1229 | }; |
| 1230 | | 1230 | |
| 1231 | if (self.undefs.swapRemove(sym_name)) |undef| { | 1231 | if (sym.tag == .Weak) continue; // If symbol is weak, nothing to do. |
| 1232 | self.allocator.free(undef.key); | 1232 | if (global.value.tag == .Strong) { // If both symbols are strong, we have a collision. |
| | 1233 | log.err("symbol '{s}' defined multiple times", .{sym_name}); |
| | 1234 | return error.MultipleSymbolDefinitions; |
| 1233 | } | 1235 | } |
| 1234 | | 1236 | |
| 1235 | continue; | 1237 | global.value = .{ |
| 1236 | }; | 1238 | .tag = .Strong, |
| 1237 | | 1239 | .inner = .{ |
| 1238 | if (sym.isWeakDef()) continue; // If symbol is weak, nothing to do. | 1240 | .n_strx = 0, // This will be populated later. |
| 1239 | if (!global.value.isWeakDef()) { // If both symbols are strong, we have a collision. | 1241 | .n_value = 0, // This will be populated later, |
| 1240 | log.err("symbol '{s}' defined multiple times", .{sym_name}); | 1242 | .n_type = macho.N_SECT | macho.N_EXT, |
| 1241 | return error.MultipleSymbolDefinitions; | 1243 | .n_desc = 0, |
| 1242 | } | 1244 | .n_sect = 0, // This will be populated later. |
| 1243 | | 1245 | }, |
| 1244 | global.value = .{ | 1246 | .file = object_id, |
| 1245 | .inner = sym.inner, | 1247 | .index = @intCast(u32, sym_id), |
| 1246 | .file = object_id, | 1248 | }; |
| 1247 | .index = @intCast(u32, sym_id), | 1249 | }, |
| 1248 | }; | 1250 | .Undef => { |
| 1249 | } else if (sym.isUndef()) { | 1251 | const sym_name = object.getString(sym.inner.n_strx); |
| 1250 | if (self.globals.contains(sym_name)) continue; // Nothing to do if we already found a definition. | 1252 | if (self.symtab.contains(sym_name)) continue; // Nothing to do if we already found a definition. |
| 1251 | if (self.undefs.contains(sym_name)) continue; // No need to reinsert the undef ref. | | |
| 1252 | | 1253 | |
| 1253 | const name = try self.allocator.dupe(u8, sym_name); | 1254 | const name = try self.allocator.dupe(u8, sym_name); |
| 1254 | try self.undefs.putNoClobber(self.allocator, name, .{ | 1255 | try self.symtab.putNoClobber(self.allocator, name, .{ |
| 1255 | .inner = sym.inner, | 1256 | .tag = .Undef, |
| 1256 | }); | 1257 | .inner = .{ |
| 1257 | } else { | 1258 | .n_strx = 0, |
| 1258 | // Oh no, unhandled symbol type, report back to the user. | 1259 | .n_value = 0, |
| 1259 | log.err("unhandled symbol type for symbol {any}", .{sym}); | 1260 | .n_type = 0, |
| 1260 | return error.UnhandledSymbolType; | 1261 | .n_desc = 0, |
| | 1262 | .n_sect = 0, |
| | 1263 | }, |
| | 1264 | }); |
| | 1265 | }, |
| | 1266 | .Import => unreachable, // We don't expect any imports just yet. |
| 1261 | } | 1267 | } |
| 1262 | } | 1268 | } |
| 1263 | } | 1269 | } |
| ... | @@ -1274,7 +1280,9 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1274,7 +1280,9 @@ fn resolveSymbols(self: *Zld) !void { |
| 1274 | var archive = &self.archives.items[next]; | 1280 | var archive = &self.archives.items[next]; |
| 1275 | var hit: bool = false; | 1281 | var hit: bool = false; |
| 1276 | | 1282 | |
| 1277 | for (self.undefs.items()) |entry| { | 1283 | for (self.symtab.items()) |entry| { |
| | 1284 | if (entry.value.tag != .Undef) continue; |
| | 1285 | |
| 1278 | const sym_name = entry.key; | 1286 | const sym_name = entry.key; |
| 1279 | | 1287 | |
| 1280 | // Check if the entry exists in a static archive. | 1288 | // Check if the entry exists in a static archive. |
| ... | @@ -1306,9 +1314,10 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1306,9 +1314,10 @@ fn resolveSymbols(self: *Zld) !void { |
| 1306 | // Third pass, resolve symbols in dynamic libraries. | 1314 | // Third pass, resolve symbols in dynamic libraries. |
| 1307 | // TODO Implement libSystem as a hard-coded library, or ship with | 1315 | // TODO Implement libSystem as a hard-coded library, or ship with |
| 1308 | // a libSystem.B.tbd definition file? | 1316 | // a libSystem.B.tbd definition file? |
| 1309 | while (self.undefs.items().len > 0) { | 1317 | for (self.symtab.items()) |*entry| { |
| 1310 | const entry = self.undefs.pop(); | 1318 | if (entry.value.tag != .Undef) continue; |
| 1311 | try self.externs.putNoClobber(self.allocator, entry.key, .{ | 1319 | entry.value = .{ |
| | 1320 | .tag = .Import, |
| 1312 | .inner = .{ | 1321 | .inner = .{ |
| 1313 | .n_strx = 0, // This will be populated once we write the string table. | 1322 | .n_strx = 0, // This will be populated once we write the string table. |
| 1314 | .n_type = macho.N_UNDF | macho.N_EXT, | 1323 | .n_type = macho.N_UNDF | macho.N_EXT, |
| ... | @@ -1317,30 +1326,19 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1317,30 +1326,19 @@ fn resolveSymbols(self: *Zld) !void { |
| 1317 | .n_value = 0, | 1326 | .n_value = 0, |
| 1318 | }, | 1327 | }, |
| 1319 | .file = 0, | 1328 | .file = 0, |
| 1320 | }); | 1329 | }; |
| 1321 | } | 1330 | } |
| 1322 | | 1331 | |
| 1323 | // If there are any undefs left, flag an error. | 1332 | // If there are any undefs left, flag an error. |
| 1324 | if (self.undefs.items().len > 0) { | 1333 | var has_unresolved = false; |
| 1325 | for (self.undefs.items()) |entry| { | 1334 | for (self.symtab.items()) |entry| { |
| 1326 | log.err("undefined reference to symbol '{s}'", .{entry.key}); | 1335 | if (entry.value.tag != .Undef) continue; |
| 1327 | } | 1336 | has_unresolved = true; |
| 1328 | | 1337 | log.err("undefined reference to symbol '{s}'", .{entry.key}); |
| | 1338 | } |
| | 1339 | if (has_unresolved) { |
| 1329 | return error.UndefinedSymbolReference; | 1340 | return error.UndefinedSymbolReference; |
| 1330 | } | 1341 | } |
| 1331 | | | |
| 1332 | // Finally, put in a reference to 'dyld_stub_binder'. | | |
| 1333 | const name = try self.allocator.dupe(u8, "dyld_stub_binder"); | | |
| 1334 | try self.externs.putNoClobber(self.allocator, name, .{ | | |
| 1335 | .inner = .{ | | |
| 1336 | .n_strx = 0, // This will be populated once we write the string table. | | |
| 1337 | .n_type = std.macho.N_UNDF | std.macho.N_EXT, | | |
| 1338 | .n_sect = 0, | | |
| 1339 | .n_desc = std.macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | std.macho.N_SYMBOL_RESOLVER, | | |
| 1340 | .n_value = 0, | | |
| 1341 | }, | | |
| 1342 | .file = 0, | | |
| 1343 | }); | | |
| 1344 | } | 1342 | } |
| 1345 | | 1343 | |
| 1346 | fn doRelocs(self: *Zld) !void { | 1344 | fn doRelocs(self: *Zld) !void { |
| ... | @@ -3261,18 +3259,8 @@ fn aarch64IsArithmetic(inst: *const [4]u8) callconv(.Inline) bool { | ... | @@ -3261,18 +3259,8 @@ fn aarch64IsArithmetic(inst: *const [4]u8) callconv(.Inline) bool { |
| 3261 | } | 3259 | } |
| 3262 | | 3260 | |
| 3263 | fn printSymtab(self: Zld) void { | 3261 | fn printSymtab(self: Zld) void { |
| 3264 | log.warn("globals", .{}); | 3262 | log.warn("symtab", .{}); |
| 3265 | for (self.globals.items()) |entry| { | 3263 | for (self.symtab.items()) |entry| { |
| 3266 | log.warn(" | {s} => {any}", .{ entry.key, entry.value }); | | |
| 3267 | } | | |
| 3268 | | | |
| 3269 | log.warn("externs", .{}); | | |
| 3270 | for (self.externs.items()) |entry| { | | |
| 3271 | log.warn(" | {s} => {any}", .{ entry.key, entry.value }); | | |
| 3272 | } | | |
| 3273 | | | |
| 3274 | log.warn("undefs", .{}); | | |
| 3275 | for (self.undefs.items()) |entry| { | | |
| 3276 | log.warn(" | {s} => {any}", .{ entry.key, entry.value }); | 3264 | log.warn(" | {s} => {any}", .{ entry.key, entry.value }); |
| 3277 | } | 3265 | } |
| 3278 | } | 3266 | } |