| ... | @@ -16,8 +16,8 @@ const Allocator = mem.Allocator; | ... | @@ -16,8 +16,8 @@ const Allocator = mem.Allocator; |
| 16 | const Archive = @import("Archive.zig"); | 16 | const Archive = @import("Archive.zig"); |
| 17 | const CodeSignature = @import("CodeSignature.zig"); | 17 | const CodeSignature = @import("CodeSignature.zig"); |
| 18 | const Dylib = @import("Dylib.zig"); | 18 | const Dylib = @import("Dylib.zig"); |
| 19 | const LibStub = @import("../tapi.zig").LibStub; | | |
| 20 | const Object = @import("Object.zig"); | 19 | const Object = @import("Object.zig"); |
| | 20 | const Stub = @import("Stub.zig"); |
| 21 | const Symbol = @import("Symbol.zig"); | 21 | const Symbol = @import("Symbol.zig"); |
| 22 | const Trie = @import("Trie.zig"); | 22 | const Trie = @import("Trie.zig"); |
| 23 | | 23 | |
| ... | @@ -38,6 +38,10 @@ stack_size: u64 = 0, | ... | @@ -38,6 +38,10 @@ stack_size: u64 = 0, |
| 38 | objects: std.ArrayListUnmanaged(*Object) = .{}, | 38 | objects: std.ArrayListUnmanaged(*Object) = .{}, |
| 39 | archives: std.ArrayListUnmanaged(*Archive) = .{}, | 39 | archives: std.ArrayListUnmanaged(*Archive) = .{}, |
| 40 | dylibs: std.ArrayListUnmanaged(*Dylib) = .{}, | 40 | dylibs: std.ArrayListUnmanaged(*Dylib) = .{}, |
| | 41 | lib_stubs: std.ArrayListUnmanaged(*Stub) = .{}, |
| | 42 | |
| | 43 | libsystem_stub_index: ?u16 = null, |
| | 44 | next_dylib_ordinal: u16 = 1, |
| 41 | | 45 | |
| 42 | load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, | 46 | load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 43 | | 47 | |
| ... | @@ -153,9 +157,20 @@ pub fn deinit(self: *Zld) void { | ... | @@ -153,9 +157,20 @@ pub fn deinit(self: *Zld) void { |
| 153 | } | 157 | } |
| 154 | self.dylibs.deinit(self.allocator); | 158 | self.dylibs.deinit(self.allocator); |
| 155 | | 159 | |
| | 160 | for (self.lib_stubs.items) |stub| { |
| | 161 | stub.deinit(); |
| | 162 | self.allocator.destroy(stub); |
| | 163 | } |
| | 164 | self.lib_stubs.deinit(self.allocator); |
| | 165 | |
| | 166 | for (self.imports.values()) |proxy| { |
| | 167 | proxy.deinit(self.allocator); |
| | 168 | self.allocator.destroy(proxy); |
| | 169 | } |
| | 170 | self.imports.deinit(self.allocator); |
| | 171 | |
| 156 | self.tentatives.deinit(self.allocator); | 172 | self.tentatives.deinit(self.allocator); |
| 157 | self.globals.deinit(self.allocator); | 173 | self.globals.deinit(self.allocator); |
| 158 | self.imports.deinit(self.allocator); | | |
| 159 | self.unresolved.deinit(self.allocator); | 174 | self.unresolved.deinit(self.allocator); |
| 160 | self.strtab.deinit(self.allocator); | 175 | self.strtab.deinit(self.allocator); |
| 161 | | 176 | |
| ... | @@ -245,9 +260,11 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -245,9 +260,11 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 245 | dylib, | 260 | dylib, |
| 246 | stub, | 261 | stub, |
| 247 | }, | 262 | }, |
| 248 | file: fs.File, | 263 | origin: union { |
| | 264 | file: fs.File, |
| | 265 | stub: Stub.LibStub, |
| | 266 | }, |
| 249 | name: []const u8, | 267 | name: []const u8, |
| 250 | stub: ?LibStub = null, | | |
| 251 | }; | 268 | }; |
| 252 | var classified = std.ArrayList(Input).init(self.allocator); | 269 | var classified = std.ArrayList(Input).init(self.allocator); |
| 253 | defer classified.deinit(); | 270 | defer classified.deinit(); |
| ... | @@ -262,45 +279,45 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -262,45 +279,45 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 262 | }; | 279 | }; |
| 263 | | 280 | |
| 264 | try_object: { | 281 | try_object: { |
| 265 | if (!Object.isObject(file)) break :try_object; | 282 | if (!(try Object.isObject(file))) break :try_object; |
| 266 | try classified.append(.{ | 283 | try classified.append(.{ |
| 267 | .kind = .object, | 284 | .kind = .object, |
| 268 | .file = file, | 285 | .origin = .{ .file = file }, |
| 269 | .name = full_path, | 286 | .name = full_path, |
| 270 | }); | 287 | }); |
| 271 | continue; | 288 | continue; |
| 272 | } | 289 | } |
| 273 | | 290 | |
| 274 | try_archive: { | 291 | try_archive: { |
| 275 | if (!Archive.isArchive(file)) break :try_archive; | 292 | if (!(try Archive.isArchive(file))) break :try_archive; |
| 276 | try classified.append(.{ | 293 | try classified.append(.{ |
| 277 | .kind = .archive, | 294 | .kind = .archive, |
| 278 | .file = file, | 295 | .origin = .{ .file = file }, |
| 279 | .name = full_path, | 296 | .name = full_path, |
| 280 | }); | 297 | }); |
| 281 | continue; | 298 | continue; |
| 282 | } | 299 | } |
| 283 | | 300 | |
| 284 | try_dylib: { | 301 | try_dylib: { |
| 285 | if (!Dylib.isDylib(file)) break :try_dylib; | 302 | if (!(try Dylib.isDylib(file))) break :try_dylib; |
| 286 | try classified.append(.{ | 303 | try classified.append(.{ |
| 287 | .kind = .dylib, | 304 | .kind = .dylib, |
| 288 | .file = file, | 305 | .origin = .{ .file = file }, |
| 289 | .name = full_path, | 306 | .name = full_path, |
| 290 | }); | 307 | }); |
| 291 | continue; | 308 | continue; |
| 292 | } | 309 | } |
| 293 | | 310 | |
| 294 | try_stub: { | 311 | try_stub: { |
| 295 | var lib_stub = LibStub.loadFromFile(self.allocator, file) catch { | 312 | var lib_stub = Stub.LibStub.loadFromFile(self.allocator, file) catch { |
| 296 | break :try_stub; | 313 | break :try_stub; |
| 297 | }; | 314 | }; |
| 298 | try classified.append(.{ | 315 | try classified.append(.{ |
| 299 | .kind = .stub, | 316 | .kind = .stub, |
| 300 | .file = file, | 317 | .origin = .{ .stub = lib_stub }, |
| 301 | .name = full_path, | 318 | .name = full_path, |
| 302 | .stub = lib_stub, | | |
| 303 | }); | 319 | }); |
| | 320 | file.close(); |
| 304 | continue; | 321 | continue; |
| 305 | } | 322 | } |
| 306 | | 323 | |
| ... | @@ -318,7 +335,8 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -318,7 +335,8 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 318 | object.* = Object.init(self.allocator); | 335 | object.* = Object.init(self.allocator); |
| 319 | object.arch = self.arch.?; | 336 | object.arch = self.arch.?; |
| 320 | object.name = input.name; | 337 | object.name = input.name; |
| 321 | object.file = input.file; | 338 | object.file = input.origin.file; |
| | 339 | |
| 322 | try object.parse(); | 340 | try object.parse(); |
| 323 | try self.objects.append(self.allocator, object); | 341 | try self.objects.append(self.allocator, object); |
| 324 | }, | 342 | }, |
| ... | @@ -329,40 +347,34 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -329,40 +347,34 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 329 | archive.* = Archive.init(self.allocator); | 347 | archive.* = Archive.init(self.allocator); |
| 330 | archive.arch = self.arch.?; | 348 | archive.arch = self.arch.?; |
| 331 | archive.name = input.name; | 349 | archive.name = input.name; |
| 332 | archive.file = input.file; | 350 | archive.file = input.origin.file; |
| | 351 | |
| 333 | try archive.parse(); | 352 | try archive.parse(); |
| 334 | try self.archives.append(self.allocator, archive); | 353 | try self.archives.append(self.allocator, archive); |
| 335 | }, | 354 | }, |
| 336 | .dylib, .stub => { | 355 | .dylib => { |
| 337 | const dylib = try self.allocator.create(Dylib); | 356 | const dylib = try self.allocator.create(Dylib); |
| 338 | errdefer self.allocator.destroy(dylib); | 357 | errdefer self.allocator.destroy(dylib); |
| 339 | | 358 | |
| 340 | dylib.* = Dylib.init(self.allocator); | 359 | dylib.* = Dylib.init(self.allocator); |
| 341 | dylib.arch = self.arch.?; | 360 | dylib.arch = self.arch.?; |
| 342 | dylib.name = input.name; | 361 | dylib.name = input.name; |
| 343 | dylib.file = input.file; | 362 | dylib.file = input.origin.file; |
| 344 | dylib.ordinal = @intCast(u16, self.dylibs.items.len) + 1; | | |
| 345 | | 363 | |
| 346 | // TODO Defer parsing of the dylibs until they are actually needed | 364 | try dylib.parse(); |
| 347 | if (input.stub) |stub| { | | |
| 348 | try dylib.parseFromStub(stub); | | |
| 349 | } else { | | |
| 350 | try dylib.parse(); | | |
| 351 | } | | |
| 352 | try self.dylibs.append(self.allocator, dylib); | 365 | try self.dylibs.append(self.allocator, dylib); |
| | 366 | }, |
| | 367 | .stub => { |
| | 368 | const stub = try self.allocator.create(Stub); |
| | 369 | errdefer self.allocator.destroy(stub); |
| 353 | | 370 | |
| 354 | // Add LC_LOAD_DYLIB command | 371 | stub.* = Stub.init(self.allocator); |
| 355 | const dylib_id = dylib.id orelse unreachable; | 372 | stub.arch = self.arch.?; |
| 356 | var dylib_cmd = try createLoadDylibCommand( | 373 | stub.name = input.name; |
| 357 | self.allocator, | 374 | stub.lib_stub = input.origin.stub; |
| 358 | dylib_id.name, | 375 | |
| 359 | dylib_id.timestamp, | 376 | try stub.parse(); |
| 360 | dylib_id.current_version, | 377 | try self.lib_stubs.append(self.allocator, stub); |
| 361 | dylib_id.compatibility_version, | | |
| 362 | ); | | |
| 363 | errdefer dylib_cmd.deinit(self.allocator); | | |
| 364 | | | |
| 365 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); | | |
| 366 | }, | 378 | }, |
| 367 | } | 379 | } |
| 368 | } | 380 | } |
| ... | @@ -372,7 +384,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { | ... | @@ -372,7 +384,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 372 | for (libs) |lib| { | 384 | for (libs) |lib| { |
| 373 | const file = try fs.cwd().openFile(lib, .{}); | 385 | const file = try fs.cwd().openFile(lib, .{}); |
| 374 | | 386 | |
| 375 | if (Dylib.isDylib(file)) { | 387 | if (try Dylib.isDylib(file)) { |
| 376 | const dylib = try self.allocator.create(Dylib); | 388 | const dylib = try self.allocator.create(Dylib); |
| 377 | errdefer self.allocator.destroy(dylib); | 389 | errdefer self.allocator.destroy(dylib); |
| 378 | | 390 | |
| ... | @@ -380,57 +392,27 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { | ... | @@ -380,57 +392,27 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 380 | dylib.arch = self.arch.?; | 392 | dylib.arch = self.arch.?; |
| 381 | dylib.name = try self.allocator.dupe(u8, lib); | 393 | dylib.name = try self.allocator.dupe(u8, lib); |
| 382 | dylib.file = file; | 394 | dylib.file = file; |
| 383 | dylib.ordinal = @intCast(u16, self.dylibs.items.len) + 1; | | |
| 384 | | 395 | |
| 385 | // TODO Defer parsing of the dylibs until they are actually needed | | |
| 386 | try dylib.parse(); | 396 | try dylib.parse(); |
| 387 | try self.dylibs.append(self.allocator, dylib); | 397 | try self.dylibs.append(self.allocator, dylib); |
| 388 | | | |
| 389 | // Add LC_LOAD_DYLIB command | | |
| 390 | const dylib_id = dylib.id orelse unreachable; | | |
| 391 | var dylib_cmd = try createLoadDylibCommand( | | |
| 392 | self.allocator, | | |
| 393 | dylib_id.name, | | |
| 394 | dylib_id.timestamp, | | |
| 395 | dylib_id.current_version, | | |
| 396 | dylib_id.compatibility_version, | | |
| 397 | ); | | |
| 398 | errdefer dylib_cmd.deinit(self.allocator); | | |
| 399 | | | |
| 400 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); | | |
| 401 | } else { | 398 | } else { |
| 402 | // Try tbd stub file next. | 399 | // Try tbd stub file next. |
| 403 | if (LibStub.loadFromFile(self.allocator, file)) |*lib_stub| { | 400 | if (Stub.LibStub.loadFromFile(self.allocator, file)) |lib_stub| { |
| 404 | defer lib_stub.deinit(); | 401 | const stub = try self.allocator.create(Stub); |
| 405 | | 402 | errdefer self.allocator.destroy(stub); |
| 406 | const dylib = try self.allocator.create(Dylib); | | |
| 407 | errdefer self.allocator.destroy(dylib); | | |
| 408 | | | |
| 409 | dylib.* = Dylib.init(self.allocator); | | |
| 410 | dylib.arch = self.arch.?; | | |
| 411 | dylib.name = try self.allocator.dupe(u8, lib); | | |
| 412 | dylib.file = file; | | |
| 413 | dylib.ordinal = @intCast(u16, self.dylibs.items.len) + 1; | | |
| 414 | | 403 | |
| 415 | try dylib.parseFromStub(lib_stub.*); | 404 | stub.* = Stub.init(self.allocator); |
| 416 | try self.dylibs.append(self.allocator, dylib); | 405 | stub.arch = self.arch.?; |
| | 406 | stub.name = try self.allocator.dupe(u8, lib); |
| | 407 | stub.lib_stub = lib_stub; |
| 417 | | 408 | |
| 418 | // Add LC_LOAD_DYLIB command | 409 | try stub.parse(); |
| 419 | const dylib_id = dylib.id orelse unreachable; | 410 | try self.lib_stubs.append(self.allocator, stub); |
| 420 | var dylib_cmd = try createLoadDylibCommand( | | |
| 421 | self.allocator, | | |
| 422 | dylib_id.name, | | |
| 423 | dylib_id.timestamp, | | |
| 424 | dylib_id.current_version, | | |
| 425 | dylib_id.compatibility_version, | | |
| 426 | ); | | |
| 427 | errdefer dylib_cmd.deinit(self.allocator); | | |
| 428 | | | |
| 429 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); | | |
| 430 | } else |_| { | 411 | } else |_| { |
| 431 | // TODO this entire logic has to be cleaned up. | 412 | // TODO this entire logic has to be cleaned up. |
| 432 | try file.seekTo(0); | 413 | try file.seekTo(0); |
| 433 | if (Archive.isArchive(file)) { | 414 | |
| | 415 | if (try Archive.isArchive(file)) { |
| 434 | const archive = try self.allocator.create(Archive); | 416 | const archive = try self.allocator.create(Archive); |
| 435 | errdefer self.allocator.destroy(archive); | 417 | errdefer self.allocator.destroy(archive); |
| 436 | | 418 | |
| ... | @@ -438,6 +420,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { | ... | @@ -438,6 +420,7 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 438 | archive.arch = self.arch.?; | 420 | archive.arch = self.arch.?; |
| 439 | archive.name = try self.allocator.dupe(u8, lib); | 421 | archive.name = try self.allocator.dupe(u8, lib); |
| 440 | archive.file = file; | 422 | archive.file = file; |
| | 423 | |
| 441 | try archive.parse(); | 424 | try archive.parse(); |
| 442 | try self.archives.append(self.allocator, archive); | 425 | try self.archives.append(self.allocator, archive); |
| 443 | } else { | 426 | } else { |
| ... | @@ -449,26 +432,28 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { | ... | @@ -449,26 +432,28 @@ fn parseLibs(self: *Zld, libs: []const []const u8) !void { |
| 449 | } | 432 | } |
| 450 | } | 433 | } |
| 451 | | 434 | |
| 452 | fn parseLibSystem(self: *Zld, lib_system_path: []const u8) !void { | 435 | fn parseLibSystem(self: *Zld, libc_stub_path: []const u8) !void { |
| 453 | const file = try fs.cwd().openFile(lib_system_path, .{}); | 436 | const file = try fs.cwd().openFile(libc_stub_path, .{}); |
| | 437 | defer file.close(); |
| | 438 | |
| | 439 | var lib_stub = try Stub.LibStub.loadFromFile(self.allocator, file); |
| 454 | | 440 | |
| 455 | var lib_stub = try LibStub.loadFromFile(self.allocator, file); | 441 | const stub = try self.allocator.create(Stub); |
| 456 | defer lib_stub.deinit(); | 442 | errdefer self.allocator.destroy(stub); |
| 457 | | 443 | |
| 458 | const dylib = try self.allocator.create(Dylib); | 444 | stub.* = Stub.init(self.allocator); |
| 459 | errdefer self.allocator.destroy(dylib); | 445 | stub.arch = self.arch.?; |
| | 446 | stub.name = try self.allocator.dupe(u8, libc_stub_path); |
| | 447 | stub.lib_stub = lib_stub; |
| 460 | | 448 | |
| 461 | dylib.* = Dylib.init(self.allocator); | 449 | try stub.parse(); |
| 462 | dylib.arch = self.arch.?; | | |
| 463 | dylib.name = try self.allocator.dupe(u8, lib_system_path); | | |
| 464 | dylib.file = file; | | |
| 465 | dylib.ordinal = @intCast(u16, self.dylibs.items.len) + 1; | | |
| 466 | | 450 | |
| 467 | try dylib.parseFromStub(lib_stub); | 451 | self.libsystem_stub_index = @intCast(u16, self.lib_stubs.items.len); |
| 468 | try self.dylibs.append(self.allocator, dylib); | 452 | try self.lib_stubs.append(self.allocator, stub); |
| 469 | | 453 | |
| 470 | // Add LC_LOAD_DYLIB command | 454 | // Add LC_LOAD_DYLIB load command. |
| 471 | const dylib_id = dylib.id orelse unreachable; | 455 | stub.ordinal = self.next_dylib_ordinal; |
| | 456 | const dylib_id = stub.id orelse unreachable; |
| 472 | var dylib_cmd = try createLoadDylibCommand( | 457 | var dylib_cmd = try createLoadDylibCommand( |
| 473 | self.allocator, | 458 | self.allocator, |
| 474 | dylib_id.name, | 459 | dylib_id.name, |
| ... | @@ -477,8 +462,8 @@ fn parseLibSystem(self: *Zld, lib_system_path: []const u8) !void { | ... | @@ -477,8 +462,8 @@ fn parseLibSystem(self: *Zld, lib_system_path: []const u8) !void { |
| 477 | dylib_id.compatibility_version, | 462 | dylib_id.compatibility_version, |
| 478 | ); | 463 | ); |
| 479 | errdefer dylib_cmd.deinit(self.allocator); | 464 | errdefer dylib_cmd.deinit(self.allocator); |
| 480 | | | |
| 481 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); | 465 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); |
| | 466 | self.next_dylib_ordinal += 1; |
| 482 | } | 467 | } |
| 483 | | 468 | |
| 484 | fn mapAndUpdateSections( | 469 | fn mapAndUpdateSections( |
| ... | @@ -1906,21 +1891,34 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1906,21 +1891,34 @@ fn resolveSymbols(self: *Zld) !void { |
| 1906 | for (self.unresolved.values()) |value| { | 1891 | for (self.unresolved.values()) |value| { |
| 1907 | unresolved.appendAssumeCapacity(value); | 1892 | unresolved.appendAssumeCapacity(value); |
| 1908 | } | 1893 | } |
| 1909 | self.unresolved.clearAndFree(self.allocator); | 1894 | self.unresolved.clearRetainingCapacity(); |
| 1910 | | 1895 | |
| 1911 | var has_undefined = false; | 1896 | var referenced = std.AutoHashMap(union(enum) { |
| 1912 | while (unresolved.popOrNull()) |undef| { | 1897 | dylib: *Dylib, |
| 1913 | var found = false; | 1898 | stub: *Stub, |
| 1914 | for (self.dylibs.items) |dylib| { | 1899 | }, void).init(self.allocator); |
| 1915 | const proxy = dylib.symbols.get(undef.name) orelse continue; | 1900 | defer referenced.deinit(); |
| 1916 | try self.imports.putNoClobber(self.allocator, proxy.name, proxy); | 1901 | |
| 1917 | undef.alias = proxy; | 1902 | loop: while (unresolved.popOrNull()) |undef| { |
| 1918 | found = true; | 1903 | const proxy = self.imports.get(undef.name) orelse outer: { |
| 1919 | } | 1904 | const proxy = inner: { |
| 1920 | | 1905 | for (self.dylibs.items) |dylib| { |
| 1921 | if (!found) { | 1906 | const proxy = (try dylib.createProxy(undef.name)) orelse continue; |
| 1922 | if (mem.eql(u8, undef.name, "___dso_handle")) { | 1907 | try referenced.put(.{ .dylib = dylib }, {}); |
| 1923 | const proxy = self.imports.get(undef.name) orelse blk: { | 1908 | break :inner proxy; |
| | 1909 | } |
| | 1910 | for (self.lib_stubs.items) |stub, i| { |
| | 1911 | const proxy = (try stub.createProxy(undef.name)) orelse continue; |
| | 1912 | if (self.libsystem_stub_index.? != @intCast(u16, i)) { |
| | 1913 | // LibSystem gets its load command separately. |
| | 1914 | try referenced.put(.{ .stub = stub }, {}); |
| | 1915 | } |
| | 1916 | break :inner proxy; |
| | 1917 | } |
| | 1918 | if (mem.eql(u8, undef.name, "___dso_handle")) { |
| | 1919 | // TODO this is just a temp patch until I work out what to actually |
| | 1920 | // do with ___dso_handle and __mh_execute_header symbols which are |
| | 1921 | // synthetically created by the linker on macOS. |
| 1924 | const name = try self.allocator.dupe(u8, undef.name); | 1922 | const name = try self.allocator.dupe(u8, undef.name); |
| 1925 | const proxy = try self.allocator.create(Symbol.Proxy); | 1923 | const proxy = try self.allocator.create(Symbol.Proxy); |
| 1926 | errdefer self.allocator.destroy(proxy); | 1924 | errdefer self.allocator.destroy(proxy); |
| ... | @@ -1929,26 +1927,69 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1929,26 +1927,69 @@ fn resolveSymbols(self: *Zld) !void { |
| 1929 | .@"type" = .proxy, | 1927 | .@"type" = .proxy, |
| 1930 | .name = name, | 1928 | .name = name, |
| 1931 | }, | 1929 | }, |
| | 1930 | .file = null, |
| 1932 | }; | 1931 | }; |
| 1933 | try self.imports.putNoClobber(self.allocator, name, &proxy.base); | 1932 | break :inner &proxy.base; |
| 1934 | break :blk &proxy.base; | 1933 | } |
| 1935 | }; | 1934 | |
| 1936 | undef.alias = proxy; | 1935 | self.unresolved.putAssumeCapacityNoClobber(undef.name, undef); |
| 1937 | continue; | 1936 | continue :loop; |
| | 1937 | }; |
| | 1938 | |
| | 1939 | try self.imports.putNoClobber(self.allocator, proxy.name, proxy); |
| | 1940 | break :outer proxy; |
| | 1941 | }; |
| | 1942 | undef.alias = proxy; |
| | 1943 | } |
| | 1944 | |
| | 1945 | // Add LC_LOAD_DYLIB load command for each referenced dylib/stub. |
| | 1946 | var it = referenced.iterator(); |
| | 1947 | while (it.next()) |key| { |
| | 1948 | var dylib_cmd = blk: { |
| | 1949 | switch (key.key_ptr.*) { |
| | 1950 | .dylib => |dylib| { |
| | 1951 | dylib.ordinal = self.next_dylib_ordinal; |
| | 1952 | const dylib_id = dylib.id orelse unreachable; |
| | 1953 | break :blk try createLoadDylibCommand( |
| | 1954 | self.allocator, |
| | 1955 | dylib_id.name, |
| | 1956 | dylib_id.timestamp, |
| | 1957 | dylib_id.current_version, |
| | 1958 | dylib_id.compatibility_version, |
| | 1959 | ); |
| | 1960 | }, |
| | 1961 | .stub => |stub| { |
| | 1962 | stub.ordinal = self.next_dylib_ordinal; |
| | 1963 | const dylib_id = stub.id orelse unreachable; |
| | 1964 | break :blk try createLoadDylibCommand( |
| | 1965 | self.allocator, |
| | 1966 | dylib_id.name, |
| | 1967 | dylib_id.timestamp, |
| | 1968 | dylib_id.current_version, |
| | 1969 | dylib_id.compatibility_version, |
| | 1970 | ); |
| | 1971 | }, |
| 1938 | } | 1972 | } |
| | 1973 | }; |
| | 1974 | errdefer dylib_cmd.deinit(self.allocator); |
| | 1975 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); |
| | 1976 | self.next_dylib_ordinal += 1; |
| | 1977 | } |
| 1939 | | 1978 | |
| | 1979 | if (self.unresolved.count() > 0) { |
| | 1980 | for (self.unresolved.values()) |undef| { |
| 1940 | log.err("undefined reference to symbol '{s}'", .{undef.name}); | 1981 | log.err("undefined reference to symbol '{s}'", .{undef.name}); |
| 1941 | log.err(" | referenced in {s}", .{ | 1982 | log.err(" | referenced in {s}", .{ |
| 1942 | undef.cast(Symbol.Unresolved).?.file.name.?, | 1983 | undef.cast(Symbol.Unresolved).?.file.name.?, |
| 1943 | }); | 1984 | }); |
| 1944 | has_undefined = true; | | |
| 1945 | } | 1985 | } |
| 1946 | } | | |
| 1947 | | 1986 | |
| 1948 | if (has_undefined) return error.UndefinedSymbolReference; | 1987 | return error.UndefinedSymbolReference; |
| | 1988 | } |
| 1949 | | 1989 | |
| 1950 | // Finally put dyld_stub_binder as an Import | 1990 | // Finally put dyld_stub_binder as an Import |
| 1951 | const proxy = self.dylibs.items[self.dylibs.items.len - 1].symbols.get("dyld_stub_binder") orelse { | 1991 | const libsystem_stub = self.lib_stubs.items[self.libsystem_stub_index.?]; |
| | 1992 | const proxy = (try libsystem_stub.createProxy("dyld_stub_binder")) orelse { |
| 1952 | log.err("undefined reference to symbol 'dyld_stub_binder'", .{}); | 1993 | log.err("undefined reference to symbol 'dyld_stub_binder'", .{}); |
| 1953 | return error.UndefinedSymbolReference; | 1994 | return error.UndefinedSymbolReference; |
| 1954 | }; | 1995 | }; |
| ... | @@ -2814,7 +2855,7 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2814,7 +2855,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2814 | try pointers.append(.{ | 2855 | try pointers.append(.{ |
| 2815 | .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64), | 2856 | .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64), |
| 2816 | .segment_id = segment_id, | 2857 | .segment_id = segment_id, |
| 2817 | .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, | 2858 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2818 | .name = proxy.base.name, | 2859 | .name = proxy.base.name, |
| 2819 | }); | 2860 | }); |
| 2820 | } | 2861 | } |
| ... | @@ -2833,7 +2874,7 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2833,7 +2874,7 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2833 | try pointers.append(.{ | 2874 | try pointers.append(.{ |
| 2834 | .offset = base_offset, | 2875 | .offset = base_offset, |
| 2835 | .segment_id = segment_id, | 2876 | .segment_id = segment_id, |
| 2836 | .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, | 2877 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2837 | .name = proxy.base.name, | 2878 | .name = proxy.base.name, |
| 2838 | }); | 2879 | }); |
| 2839 | } | 2880 | } |
| ... | @@ -2873,7 +2914,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { | ... | @@ -2873,7 +2914,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2873 | pointers.appendAssumeCapacity(.{ | 2914 | pointers.appendAssumeCapacity(.{ |
| 2874 | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), | 2915 | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2875 | .segment_id = segment_id, | 2916 | .segment_id = segment_id, |
| 2876 | .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, | 2917 | .dylib_ordinal = proxy.dylibOrdinal(), |
| 2877 | .name = sym.name, | 2918 | .name = sym.name, |
| 2878 | }); | 2919 | }); |
| 2879 | } | 2920 | } |
| ... | @@ -3181,12 +3222,11 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -3181,12 +3222,11 @@ fn writeSymbolTable(self: *Zld) !void { |
| 3181 | | 3222 | |
| 3182 | for (self.imports.values()) |sym| { | 3223 | for (self.imports.values()) |sym| { |
| 3183 | const proxy = sym.cast(Symbol.Proxy) orelse unreachable; | 3224 | const proxy = sym.cast(Symbol.Proxy) orelse unreachable; |
| 3184 | const dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0; | | |
| 3185 | try undefs.append(.{ | 3225 | try undefs.append(.{ |
| 3186 | .n_strx = try self.makeString(sym.name), | 3226 | .n_strx = try self.makeString(sym.name), |
| 3187 | .n_type = macho.N_UNDF | macho.N_EXT, | 3227 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 3188 | .n_sect = 0, | 3228 | .n_sect = 0, |
| 3189 | .n_desc = (dylib_ordinal * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, | 3229 | .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, |
| 3190 | .n_value = 0, | 3230 | .n_value = 0, |
| 3191 | }); | 3231 | }); |
| 3192 | } | 3232 | } |