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