| ... | @@ -570,7 +570,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { | ... | @@ -570,7 +570,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 570 | return null; | 570 | return null; |
| 571 | } | 571 | } |
| 572 | | 572 | |
| 573 | fn allocatedSize(self: *Elf, start: u64) u64 { | 573 | pub fn allocatedSize(self: *Elf, start: u64) u64 { |
| 574 | if (start == 0) return 0; | 574 | if (start == 0) return 0; |
| 575 | var min_pos: u64 = std.math.maxInt(u64); | 575 | var min_pos: u64 = std.math.maxInt(u64); |
| 576 | if (self.shdr_table_offset) |off| { | 576 | if (self.shdr_table_offset) |off| { |
| ... | @@ -597,7 +597,7 @@ fn allocatedVirtualSize(self: *Elf, start: u64) u64 { | ... | @@ -597,7 +597,7 @@ fn allocatedVirtualSize(self: *Elf, start: u64) u64 { |
| 597 | return min_pos - start; | 597 | return min_pos - start; |
| 598 | } | 598 | } |
| 599 | | 599 | |
| 600 | fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { | 600 | pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) u64 { |
| 601 | var start: u64 = 0; | 601 | var start: u64 = 0; |
| 602 | while (self.detectAllocCollision(start, object_size)) |item_end| { | 602 | while (self.detectAllocCollision(start, object_size)) |item_end| { |
| 603 | start = mem.alignForward(u64, item_end, min_alignment); | 603 | start = mem.alignForward(u64, item_end, min_alignment); |
| ... | @@ -1083,8 +1083,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1083,8 +1083,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1083 | }; | 1083 | }; |
| 1084 | | 1084 | |
| 1085 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); | 1085 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); |
| 1086 | if (self.base.isStaticLib()) return self.flushStaticLib(comp, module_obj_path); | 1086 | if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path); |
| 1087 | if (self.base.isObject()) return self.flushObject(comp, module_obj_path); | 1087 | if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path); |
| 1088 | | 1088 | |
| 1089 | // Here we will parse input positional and library files (if referenced). | 1089 | // Here we will parse input positional and library files (if referenced). |
| 1090 | // This will roughly match in any linker backend we support. | 1090 | // This will roughly match in any linker backend we support. |
| ... | @@ -1388,222 +1388,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1388,222 +1388,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1388 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | 1388 | if (comp.link_errors.items.len > 0) return error.FlushFailure; |
| 1389 | } | 1389 | } |
| 1390 | | 1390 | |
| 1391 | pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | | |
| 1392 | const gpa = comp.gpa; | | |
| 1393 | | | |
| 1394 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | | |
| 1395 | defer positionals.deinit(); | | |
| 1396 | | | |
| 1397 | try positionals.ensureUnusedCapacity(comp.objects.len); | | |
| 1398 | positionals.appendSliceAssumeCapacity(comp.objects); | | |
| 1399 | | | |
| 1400 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | | |
| 1401 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | | |
| 1402 | // in this set. | | |
| 1403 | for (comp.c_object_table.keys()) |key| { | | |
| 1404 | try positionals.append(.{ .path = key.status.success.object_path }); | | |
| 1405 | } | | |
| 1406 | | | |
| 1407 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | | |
| 1408 | | | |
| 1409 | for (positionals.items) |obj| { | | |
| 1410 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | | |
| 1411 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported | | |
| 1412 | else => |e| try self.reportParseError( | | |
| 1413 | obj.path, | | |
| 1414 | "unexpected error: parsing input file failed with error {s}", | | |
| 1415 | .{@errorName(e)}, | | |
| 1416 | ), | | |
| 1417 | }; | | |
| 1418 | } | | |
| 1419 | | | |
| 1420 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | | |
| 1421 | | | |
| 1422 | // First, we flush relocatable object file generated with our backends. | | |
| 1423 | if (self.zigObjectPtr()) |zig_object| { | | |
| 1424 | zig_object.resolveSymbols(self); | | |
| 1425 | zig_object.claimUnresolvedObject(self); | | |
| 1426 | | | |
| 1427 | try self.initSymtab(); | | |
| 1428 | try self.initShStrtab(); | | |
| 1429 | try self.sortShdrs(); | | |
| 1430 | try zig_object.addAtomsToRelaSections(self); | | |
| 1431 | try self.updateSectionSizesObject(); | | |
| 1432 | | | |
| 1433 | try self.allocateAllocSectionsObject(); | | |
| 1434 | try self.allocateNonAllocSections(); | | |
| 1435 | | | |
| 1436 | if (build_options.enable_logging) { | | |
| 1437 | state_log.debug("{}", .{self.dumpState()}); | | |
| 1438 | } | | |
| 1439 | | | |
| 1440 | try self.writeSyntheticSectionsObject(); | | |
| 1441 | try self.writeShdrTable(); | | |
| 1442 | try self.writeElfHeader(); | | |
| 1443 | | | |
| 1444 | // TODO we can avoid reading in the file contents we just wrote if we give the linker | | |
| 1445 | // ability to write directly to a buffer. | | |
| 1446 | try zig_object.readFileContents(self); | | |
| 1447 | } | | |
| 1448 | | | |
| 1449 | var files = std.ArrayList(File.Index).init(gpa); | | |
| 1450 | defer files.deinit(); | | |
| 1451 | try files.ensureTotalCapacityPrecise(self.objects.items.len + 1); | | |
| 1452 | if (self.zigObjectPtr()) |zig_object| files.appendAssumeCapacity(zig_object.index); | | |
| 1453 | for (self.objects.items) |index| files.appendAssumeCapacity(index); | | |
| 1454 | | | |
| 1455 | // Update ar symtab from parsed objects | | |
| 1456 | var ar_symtab: Archive.ArSymtab = .{}; | | |
| 1457 | defer ar_symtab.deinit(gpa); | | |
| 1458 | | | |
| 1459 | for (files.items) |index| { | | |
| 1460 | try self.file(index).?.updateArSymtab(&ar_symtab, self); | | |
| 1461 | } | | |
| 1462 | | | |
| 1463 | ar_symtab.sort(); | | |
| 1464 | | | |
| 1465 | // Save object paths in filenames strtab. | | |
| 1466 | var ar_strtab: Archive.ArStrtab = .{}; | | |
| 1467 | defer ar_strtab.deinit(gpa); | | |
| 1468 | | | |
| 1469 | for (files.items) |index| { | | |
| 1470 | const file_ptr = self.file(index).?; | | |
| 1471 | try file_ptr.updateArStrtab(gpa, &ar_strtab); | | |
| 1472 | try file_ptr.updateArSize(self); | | |
| 1473 | } | | |
| 1474 | | | |
| 1475 | // Update file offsets of contributing objects. | | |
| 1476 | const total_size: usize = blk: { | | |
| 1477 | var pos: usize = elf.ARMAG.len; | | |
| 1478 | pos += @sizeOf(elf.ar_hdr) + ar_symtab.size(.p64); | | |
| 1479 | | | |
| 1480 | if (ar_strtab.size() > 0) { | | |
| 1481 | pos = mem.alignForward(usize, pos, 2); | | |
| 1482 | pos += @sizeOf(elf.ar_hdr) + ar_strtab.size(); | | |
| 1483 | } | | |
| 1484 | | | |
| 1485 | for (files.items) |index| { | | |
| 1486 | const file_ptr = self.file(index).?; | | |
| 1487 | const state = switch (file_ptr) { | | |
| 1488 | .zig_object => |x| &x.output_ar_state, | | |
| 1489 | .object => |x| &x.output_ar_state, | | |
| 1490 | else => unreachable, | | |
| 1491 | }; | | |
| 1492 | pos = mem.alignForward(usize, pos, 2); | | |
| 1493 | state.file_off = pos; | | |
| 1494 | pos += @sizeOf(elf.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow); | | |
| 1495 | } | | |
| 1496 | | | |
| 1497 | break :blk pos; | | |
| 1498 | }; | | |
| 1499 | | | |
| 1500 | if (build_options.enable_logging) { | | |
| 1501 | state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(self)}); | | |
| 1502 | state_log.debug("ar_strtab\n{}\n", .{ar_strtab}); | | |
| 1503 | } | | |
| 1504 | | | |
| 1505 | var buffer = std.ArrayList(u8).init(gpa); | | |
| 1506 | defer buffer.deinit(); | | |
| 1507 | try buffer.ensureTotalCapacityPrecise(total_size); | | |
| 1508 | | | |
| 1509 | // Write magic | | |
| 1510 | try buffer.writer().writeAll(elf.ARMAG); | | |
| 1511 | | | |
| 1512 | // Write symtab | | |
| 1513 | try ar_symtab.write(.p64, self, buffer.writer()); | | |
| 1514 | | | |
| 1515 | // Write strtab | | |
| 1516 | if (ar_strtab.size() > 0) { | | |
| 1517 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | | |
| 1518 | try ar_strtab.write(buffer.writer()); | | |
| 1519 | } | | |
| 1520 | | | |
| 1521 | // Write object files | | |
| 1522 | for (files.items) |index| { | | |
| 1523 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | | |
| 1524 | try self.file(index).?.writeAr(self, buffer.writer()); | | |
| 1525 | } | | |
| 1526 | | | |
| 1527 | assert(buffer.items.len == total_size); | | |
| 1528 | | | |
| 1529 | try self.base.file.?.setEndPos(total_size); | | |
| 1530 | try self.base.file.?.pwriteAll(buffer.items, 0); | | |
| 1531 | | | |
| 1532 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | | |
| 1533 | } | | |
| 1534 | | | |
| 1535 | pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | | |
| 1536 | const gpa = self.base.comp.gpa; | | |
| 1537 | | | |
| 1538 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | | |
| 1539 | defer positionals.deinit(); | | |
| 1540 | try positionals.ensureUnusedCapacity(comp.objects.len); | | |
| 1541 | positionals.appendSliceAssumeCapacity(comp.objects); | | |
| 1542 | | | |
| 1543 | // This is a set of object files emitted by clang in a single `build-exe` invocation. | | |
| 1544 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up | | |
| 1545 | // in this set. | | |
| 1546 | for (comp.c_object_table.keys()) |key| { | | |
| 1547 | try positionals.append(.{ .path = key.status.success.object_path }); | | |
| 1548 | } | | |
| 1549 | | | |
| 1550 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | | |
| 1551 | | | |
| 1552 | for (positionals.items) |obj| { | | |
| 1553 | self.parsePositional(obj.path, obj.must_link) catch |err| switch (err) { | | |
| 1554 | error.MalformedObject, error.MalformedArchive, error.InvalidCpuArch => continue, // already reported | | |
| 1555 | else => |e| try self.reportParseError( | | |
| 1556 | obj.path, | | |
| 1557 | "unexpected error: parsing input file failed with error {s}", | | |
| 1558 | .{@errorName(e)}, | | |
| 1559 | ), | | |
| 1560 | }; | | |
| 1561 | } | | |
| 1562 | | | |
| 1563 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | | |
| 1564 | | | |
| 1565 | // Init all objects | | |
| 1566 | for (self.objects.items) |index| { | | |
| 1567 | try self.file(index).?.object.init(self); | | |
| 1568 | } | | |
| 1569 | | | |
| 1570 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | | |
| 1571 | | | |
| 1572 | // Now, we are ready to resolve the symbols across all input files. | | |
| 1573 | // We will first resolve the files in the ZigObject, next in the parsed | | |
| 1574 | // input Object files. | | |
| 1575 | self.resolveSymbols(); | | |
| 1576 | self.markEhFrameAtomsDead(); | | |
| 1577 | self.claimUnresolvedObject(); | | |
| 1578 | | | |
| 1579 | try self.initSectionsObject(); | | |
| 1580 | try self.sortShdrs(); | | |
| 1581 | if (self.zigObjectPtr()) |zig_object| { | | |
| 1582 | try zig_object.addAtomsToRelaSections(self); | | |
| 1583 | } | | |
| 1584 | for (self.objects.items) |index| { | | |
| 1585 | const object = self.file(index).?.object; | | |
| 1586 | try object.addAtomsToOutputSections(self); | | |
| 1587 | try object.addAtomsToRelaSections(self); | | |
| 1588 | } | | |
| 1589 | try self.updateSectionSizesObject(); | | |
| 1590 | | | |
| 1591 | try self.allocateAllocSectionsObject(); | | |
| 1592 | try self.allocateNonAllocSections(); | | |
| 1593 | self.allocateAtoms(); | | |
| 1594 | | | |
| 1595 | if (build_options.enable_logging) { | | |
| 1596 | state_log.debug("{}", .{self.dumpState()}); | | |
| 1597 | } | | |
| 1598 | | | |
| 1599 | try self.writeAtomsObject(); | | |
| 1600 | try self.writeSyntheticSectionsObject(); | | |
| 1601 | try self.writeShdrTable(); | | |
| 1602 | try self.writeElfHeader(); | | |
| 1603 | | | |
| 1604 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | | |
| 1605 | } | | |
| 1606 | | | |
| 1607 | /// --verbose-link output | 1391 | /// --verbose-link output |
| 1608 | fn dumpArgv(self: *Elf, comp: *Compilation) !void { | 1392 | fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| 1609 | const gpa = self.base.comp.gpa; | 1393 | const gpa = self.base.comp.gpa; |
| ... | @@ -1880,7 +1664,7 @@ const ParseError = error{ | ... | @@ -1880,7 +1664,7 @@ const ParseError = error{ |
| 1880 | InvalidCharacter, | 1664 | InvalidCharacter, |
| 1881 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; | 1665 | } || LdScript.Error || std.os.AccessError || std.os.SeekError || std.fs.File.OpenError || std.fs.File.ReadError; |
| 1882 | | 1666 | |
| 1883 | fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { | 1667 | pub fn parsePositional(self: *Elf, path: []const u8, must_link: bool) ParseError!void { |
| 1884 | const tracy = trace(@src()); | 1668 | const tracy = trace(@src()); |
| 1885 | defer tracy.end(); | 1669 | defer tracy.end(); |
| 1886 | if (try Object.isObject(path)) { | 1670 | if (try Object.isObject(path)) { |
| ... | @@ -2089,7 +1873,7 @@ fn accessLibPath( | ... | @@ -2089,7 +1873,7 @@ fn accessLibPath( |
| 2089 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. | 1873 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. |
| 2090 | /// 5. Remove references to dead objects/shared objects | 1874 | /// 5. Remove references to dead objects/shared objects |
| 2091 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. | 1875 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| 2092 | fn resolveSymbols(self: *Elf) void { | 1876 | pub fn resolveSymbols(self: *Elf) void { |
| 2093 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. | 1877 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. |
| 2094 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); | 1878 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); |
| 2095 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). | 1879 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| ... | @@ -2173,7 +1957,7 @@ fn markLive(self: *Elf) void { | ... | @@ -2173,7 +1957,7 @@ fn markLive(self: *Elf) void { |
| 2173 | } | 1957 | } |
| 2174 | } | 1958 | } |
| 2175 | | 1959 | |
| 2176 | fn markEhFrameAtomsDead(self: *Elf) void { | 1960 | pub fn markEhFrameAtomsDead(self: *Elf) void { |
| 2177 | for (self.objects.items) |index| { | 1961 | for (self.objects.items) |index| { |
| 2178 | const file_ptr = self.file(index).?; | 1962 | const file_ptr = self.file(index).?; |
| 2179 | if (!file_ptr.isAlive()) continue; | 1963 | if (!file_ptr.isAlive()) continue; |
| ... | @@ -2239,15 +2023,6 @@ fn claimUnresolved(self: *Elf) void { | ... | @@ -2239,15 +2023,6 @@ fn claimUnresolved(self: *Elf) void { |
| 2239 | } | 2023 | } |
| 2240 | } | 2024 | } |
| 2241 | | 2025 | |
| 2242 | fn claimUnresolvedObject(self: *Elf) void { | | |
| 2243 | if (self.zigObjectPtr()) |zig_object| { | | |
| 2244 | zig_object.claimUnresolvedObject(self); | | |
| 2245 | } | | |
| 2246 | for (self.objects.items) |index| { | | |
| 2247 | self.file(index).?.object.claimUnresolvedObject(self); | | |
| 2248 | } | | |
| 2249 | } | | |
| 2250 | | | |
| 2251 | /// In scanRelocs we will go over all live atoms and scan their relocs. | 2026 | /// In scanRelocs we will go over all live atoms and scan their relocs. |
| 2252 | /// This will help us work out what synthetics to emit, GOT indirection, etc. | 2027 | /// This will help us work out what synthetics to emit, GOT indirection, etc. |
| 2253 | /// This is also the point where we will report undefined symbols for any | 2028 | /// This is also the point where we will report undefined symbols for any |
| ... | @@ -2985,7 +2760,7 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) | ... | @@ -2985,7 +2760,7 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) |
| 2985 | } | 2760 | } |
| 2986 | } | 2761 | } |
| 2987 | | 2762 | |
| 2988 | fn writeShdrTable(self: *Elf) !void { | 2763 | pub fn writeShdrTable(self: *Elf) !void { |
| 2989 | const gpa = self.base.comp.gpa; | 2764 | const gpa = self.base.comp.gpa; |
| 2990 | const target = self.base.comp.root_mod.resolved_target.result; | 2765 | const target = self.base.comp.root_mod.resolved_target.result; |
| 2991 | const target_endian = target.cpu.arch.endian(); | 2766 | const target_endian = target.cpu.arch.endian(); |
| ... | @@ -3082,7 +2857,7 @@ fn writePhdrTable(self: *Elf) !void { | ... | @@ -3082,7 +2857,7 @@ fn writePhdrTable(self: *Elf) !void { |
| 3082 | } | 2857 | } |
| 3083 | } | 2858 | } |
| 3084 | | 2859 | |
| 3085 | fn writeElfHeader(self: *Elf) !void { | 2860 | pub fn writeElfHeader(self: *Elf) !void { |
| 3086 | const comp = self.base.comp; | 2861 | const comp = self.base.comp; |
| 3087 | if (comp.link_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable | 2862 | if (comp.link_errors.items.len > 0) return; // We had errors, so skip flushing to render the output unusable |
| 3088 | | 2863 | |
| ... | @@ -3658,61 +3433,7 @@ fn initSyntheticSections(self: *Elf) !void { | ... | @@ -3658,61 +3433,7 @@ fn initSyntheticSections(self: *Elf) !void { |
| 3658 | try self.initShStrtab(); | 3433 | try self.initShStrtab(); |
| 3659 | } | 3434 | } |
| 3660 | | 3435 | |
| 3661 | fn initSectionsObject(self: *Elf) !void { | 3436 | pub fn initSymtab(self: *Elf) !void { |
| 3662 | const ptr_size = self.ptrWidthBytes(); | | |
| 3663 | | | |
| 3664 | for (self.objects.items) |index| { | | |
| 3665 | const object = self.file(index).?.object; | | |
| 3666 | try object.initOutputSections(self); | | |
| 3667 | try object.initRelaSections(self); | | |
| 3668 | } | | |
| 3669 | | | |
| 3670 | const needs_eh_frame = for (self.objects.items) |index| { | | |
| 3671 | if (self.file(index).?.object.cies.items.len > 0) break true; | | |
| 3672 | } else false; | | |
| 3673 | if (needs_eh_frame) { | | |
| 3674 | self.eh_frame_section_index = try self.addSection(.{ | | |
| 3675 | .name = ".eh_frame", | | |
| 3676 | .type = elf.SHT_PROGBITS, | | |
| 3677 | .flags = elf.SHF_ALLOC, | | |
| 3678 | .addralign = ptr_size, | | |
| 3679 | .offset = std.math.maxInt(u64), | | |
| 3680 | }); | | |
| 3681 | self.eh_frame_rela_section_index = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?); | | |
| 3682 | } | | |
| 3683 | | | |
| 3684 | try self.initComdatGroups(); | | |
| 3685 | try self.initSymtab(); | | |
| 3686 | try self.initShStrtab(); | | |
| 3687 | } | | |
| 3688 | | | |
| 3689 | fn initComdatGroups(self: *Elf) !void { | | |
| 3690 | const gpa = self.base.comp.gpa; | | |
| 3691 | | | |
| 3692 | for (self.objects.items) |index| { | | |
| 3693 | const object = self.file(index).?.object; | | |
| 3694 | | | |
| 3695 | for (object.comdat_groups.items) |cg_index| { | | |
| 3696 | const cg = self.comdatGroup(cg_index); | | |
| 3697 | const cg_owner = self.comdatGroupOwner(cg.owner); | | |
| 3698 | if (cg_owner.file != index) continue; | | |
| 3699 | | | |
| 3700 | const cg_sec = try self.comdat_group_sections.addOne(gpa); | | |
| 3701 | cg_sec.* = .{ | | |
| 3702 | .shndx = try self.addSection(.{ | | |
| 3703 | .name = ".group", | | |
| 3704 | .type = elf.SHT_GROUP, | | |
| 3705 | .entsize = @sizeOf(u32), | | |
| 3706 | .addralign = @alignOf(u32), | | |
| 3707 | .offset = std.math.maxInt(u64), | | |
| 3708 | }), | | |
| 3709 | .cg_index = cg_index, | | |
| 3710 | }; | | |
| 3711 | } | | |
| 3712 | } | | |
| 3713 | } | | |
| 3714 | | | |
| 3715 | fn initSymtab(self: *Elf) !void { | | |
| 3716 | const small_ptr = switch (self.ptr_width) { | 3437 | const small_ptr = switch (self.ptr_width) { |
| 3717 | .p32 => true, | 3438 | .p32 => true, |
| 3718 | .p64 => false, | 3439 | .p64 => false, |
| ... | @@ -3737,7 +3458,7 @@ fn initSymtab(self: *Elf) !void { | ... | @@ -3737,7 +3458,7 @@ fn initSymtab(self: *Elf) !void { |
| 3737 | } | 3458 | } |
| 3738 | } | 3459 | } |
| 3739 | | 3460 | |
| 3740 | fn initShStrtab(self: *Elf) !void { | 3461 | pub fn initShStrtab(self: *Elf) !void { |
| 3741 | if (self.shstrtab_section_index == null) { | 3462 | if (self.shstrtab_section_index == null) { |
| 3742 | self.shstrtab_section_index = try self.addSection(.{ | 3463 | self.shstrtab_section_index = try self.addSection(.{ |
| 3743 | .name = ".shstrtab", | 3464 | .name = ".shstrtab", |
| ... | @@ -4043,7 +3764,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 { | ... | @@ -4043,7 +3764,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 { |
| 4043 | } | 3764 | } |
| 4044 | } | 3765 | } |
| 4045 | | 3766 | |
| 4046 | fn sortShdrs(self: *Elf) !void { | 3767 | pub fn sortShdrs(self: *Elf) !void { |
| 4047 | const Entry = struct { | 3768 | const Entry = struct { |
| 4048 | shndx: u16, | 3769 | shndx: u16, |
| 4049 | | 3770 | |
| ... | @@ -4355,58 +4076,7 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4355,58 +4076,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4355 | self.updateShStrtabSize(); | 4076 | self.updateShStrtabSize(); |
| 4356 | } | 4077 | } |
| 4357 | | 4078 | |
| 4358 | fn updateSectionSizesObject(self: *Elf) !void { | 4079 | pub fn updateShStrtabSize(self: *Elf) void { |
| 4359 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { | | |
| 4360 | const shdr = &self.shdrs.items[shndx]; | | |
| 4361 | for (atom_list.items) |atom_index| { | | |
| 4362 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 4363 | if (!atom_ptr.flags.alive) continue; | | |
| 4364 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | | |
| 4365 | const padding = offset - shdr.sh_size; | | |
| 4366 | atom_ptr.value = offset; | | |
| 4367 | shdr.sh_size += padding + atom_ptr.size; | | |
| 4368 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); | | |
| 4369 | } | | |
| 4370 | } | | |
| 4371 | | | |
| 4372 | for (self.output_rela_sections.values()) |sec| { | | |
| 4373 | const shdr = &self.shdrs.items[sec.shndx]; | | |
| 4374 | for (sec.atom_list.items) |atom_index| { | | |
| 4375 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 4376 | if (!atom_ptr.flags.alive) continue; | | |
| 4377 | const relocs = atom_ptr.relocs(self); | | |
| 4378 | shdr.sh_size += shdr.sh_entsize * relocs.len; | | |
| 4379 | } | | |
| 4380 | | | |
| 4381 | if (shdr.sh_size == 0) shdr.sh_offset = 0; | | |
| 4382 | } | | |
| 4383 | | | |
| 4384 | if (self.eh_frame_section_index) |index| { | | |
| 4385 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); | | |
| 4386 | } | | |
| 4387 | if (self.eh_frame_rela_section_index) |index| { | | |
| 4388 | const shdr = &self.shdrs.items[index]; | | |
| 4389 | shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize; | | |
| 4390 | } | | |
| 4391 | | | |
| 4392 | try self.updateSymtabSize(); | | |
| 4393 | self.updateComdatGroupsSizes(); | | |
| 4394 | self.updateShStrtabSize(); | | |
| 4395 | } | | |
| 4396 | | | |
| 4397 | fn updateComdatGroupsSizes(self: *Elf) void { | | |
| 4398 | for (self.comdat_group_sections.items) |cg| { | | |
| 4399 | const shdr = &self.shdrs.items[cg.shndx]; | | |
| 4400 | shdr.sh_size = cg.size(self); | | |
| 4401 | shdr.sh_link = self.symtab_section_index.?; | | |
| 4402 | | | |
| 4403 | const sym = self.symbol(cg.symbol(self)); | | |
| 4404 | shdr.sh_info = sym.outputSymtabIndex(self) orelse | | |
| 4405 | self.sectionSymbolOutputSymtabIndex(sym.outputShndx().?); | | |
| 4406 | } | | |
| 4407 | } | | |
| 4408 | | | |
| 4409 | fn updateShStrtabSize(self: *Elf) void { | | |
| 4410 | if (self.shstrtab_section_index) |index| { | 4080 | if (self.shstrtab_section_index) |index| { |
| 4411 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; | 4081 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; |
| 4412 | } | 4082 | } |
| ... | @@ -4491,7 +4161,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | ... | @@ -4491,7 +4161,7 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 4491 | | 4161 | |
| 4492 | /// Allocates alloc sections and creates load segments for sections | 4162 | /// Allocates alloc sections and creates load segments for sections |
| 4493 | /// extracted from input object files. | 4163 | /// extracted from input object files. |
| 4494 | fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { | 4164 | pub fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { |
| 4495 | // We use this struct to track maximum alignment of all TLS sections. | 4165 | // We use this struct to track maximum alignment of all TLS sections. |
| 4496 | // According to https://github.com/rui314/mold/commit/bd46edf3f0fe9e1a787ea453c4657d535622e61f in mold, | 4166 | // According to https://github.com/rui314/mold/commit/bd46edf3f0fe9e1a787ea453c4657d535622e61f in mold, |
| 4497 | // in-file offsets have to be aligned against the start of TLS program header. | 4167 | // in-file offsets have to be aligned against the start of TLS program header. |
| ... | @@ -4638,27 +4308,8 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { | ... | @@ -4638,27 +4308,8 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { |
| 4638 | } | 4308 | } |
| 4639 | } | 4309 | } |
| 4640 | | 4310 | |
| 4641 | /// Allocates alloc sections when merging relocatable objects files together. | | |
| 4642 | fn allocateAllocSectionsObject(self: *Elf) !void { | | |
| 4643 | for (self.shdrs.items) |*shdr| { | | |
| 4644 | if (shdr.sh_type == elf.SHT_NULL) continue; | | |
| 4645 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | | |
| 4646 | if (shdr.sh_type == elf.SHT_NOBITS) { | | |
| 4647 | shdr.sh_offset = 0; | | |
| 4648 | continue; | | |
| 4649 | } | | |
| 4650 | const needed_size = shdr.sh_size; | | |
| 4651 | if (needed_size > self.allocatedSize(shdr.sh_offset)) { | | |
| 4652 | shdr.sh_size = 0; | | |
| 4653 | const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign); | | |
| 4654 | shdr.sh_offset = new_offset; | | |
| 4655 | shdr.sh_size = needed_size; | | |
| 4656 | } | | |
| 4657 | } | | |
| 4658 | } | | |
| 4659 | | | |
| 4660 | /// Allocates non-alloc sections (debug info, symtabs, etc.). | 4311 | /// Allocates non-alloc sections (debug info, symtabs, etc.). |
| 4661 | fn allocateNonAllocSections(self: *Elf) !void { | 4312 | pub fn allocateNonAllocSections(self: *Elf) !void { |
| 4662 | for (self.shdrs.items, 0..) |*shdr, shndx| { | 4313 | for (self.shdrs.items, 0..) |*shdr, shndx| { |
| 4663 | if (shdr.sh_type == elf.SHT_NULL) continue; | 4314 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4664 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue; | 4315 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue; |
| ... | @@ -4757,7 +4408,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -4757,7 +4408,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4757 | } | 4408 | } |
| 4758 | } | 4409 | } |
| 4759 | | 4410 | |
| 4760 | fn allocateAtoms(self: *Elf) void { | 4411 | pub fn allocateAtoms(self: *Elf) void { |
| 4761 | if (self.zigObjectPtr()) |zig_object| { | 4412 | if (self.zigObjectPtr()) |zig_object| { |
| 4762 | zig_object.allocateTlvAtoms(self); | 4413 | zig_object.allocateTlvAtoms(self); |
| 4763 | } | 4414 | } |
| ... | @@ -4854,76 +4505,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4854,76 +4505,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4854 | try self.reportUndefinedSymbols(&undefs); | 4505 | try self.reportUndefinedSymbols(&undefs); |
| 4855 | } | 4506 | } |
| 4856 | | 4507 | |
| 4857 | fn writeAtomsObject(self: *Elf) !void { | 4508 | pub fn updateSymtabSize(self: *Elf) !void { |
| 4858 | const gpa = self.base.comp.gpa; | | |
| 4859 | | | |
| 4860 | // TODO iterate over `output_sections` directly | | |
| 4861 | for (self.shdrs.items, 0..) |shdr, shndx| { | | |
| 4862 | if (shdr.sh_type == elf.SHT_NULL) continue; | | |
| 4863 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | | |
| 4864 | | | |
| 4865 | const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue; | | |
| 4866 | if (atom_list.items.len == 0) continue; | | |
| 4867 | | | |
| 4868 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | | |
| 4869 | | | |
| 4870 | // TODO really, really handle debug section separately | | |
| 4871 | const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: { | | |
| 4872 | const zig_object = self.zigObjectPtr().?; | | |
| 4873 | if (shndx == self.debug_info_section_index.?) | | |
| 4874 | break :blk zig_object.debug_info_section_zig_size; | | |
| 4875 | if (shndx == self.debug_abbrev_section_index.?) | | |
| 4876 | break :blk zig_object.debug_abbrev_section_zig_size; | | |
| 4877 | if (shndx == self.debug_str_section_index.?) | | |
| 4878 | break :blk zig_object.debug_str_section_zig_size; | | |
| 4879 | if (shndx == self.debug_aranges_section_index.?) | | |
| 4880 | break :blk zig_object.debug_aranges_section_zig_size; | | |
| 4881 | if (shndx == self.debug_line_section_index.?) | | |
| 4882 | break :blk zig_object.debug_line_section_zig_size; | | |
| 4883 | unreachable; | | |
| 4884 | } else 0; | | |
| 4885 | const sh_offset = shdr.sh_offset + base_offset; | | |
| 4886 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; | | |
| 4887 | | | |
| 4888 | const buffer = try gpa.alloc(u8, sh_size); | | |
| 4889 | defer gpa.free(buffer); | | |
| 4890 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and | | |
| 4891 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) | | |
| 4892 | 0xcc // int3 | | |
| 4893 | else | | |
| 4894 | 0; | | |
| 4895 | @memset(buffer, padding_byte); | | |
| 4896 | | | |
| 4897 | for (atom_list.items) |atom_index| { | | |
| 4898 | const atom_ptr = self.atom(atom_index).?; | | |
| 4899 | assert(atom_ptr.flags.alive); | | |
| 4900 | | | |
| 4901 | const offset = math.cast(usize, atom_ptr.value - shdr.sh_addr - base_offset) orelse | | |
| 4902 | return error.Overflow; | | |
| 4903 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | | |
| 4904 | | | |
| 4905 | log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{ | | |
| 4906 | atom_index, | | |
| 4907 | sh_offset + offset, | | |
| 4908 | sh_offset + offset + size, | | |
| 4909 | }); | | |
| 4910 | | | |
| 4911 | // TODO decompress directly into provided buffer | | |
| 4912 | const out_code = buffer[offset..][0..size]; | | |
| 4913 | const in_code = switch (atom_ptr.file(self).?) { | | |
| 4914 | .object => |x| try x.codeDecompressAlloc(self, atom_index), | | |
| 4915 | .zig_object => |x| try x.codeAlloc(self, atom_index), | | |
| 4916 | else => unreachable, | | |
| 4917 | }; | | |
| 4918 | defer gpa.free(in_code); | | |
| 4919 | @memcpy(out_code, in_code); | | |
| 4920 | } | | |
| 4921 | | | |
| 4922 | try self.base.file.?.pwriteAll(buffer, sh_offset); | | |
| 4923 | } | | |
| 4924 | } | | |
| 4925 | | | |
| 4926 | fn updateSymtabSize(self: *Elf) !void { | | |
| 4927 | var nlocals: u32 = 0; | 4509 | var nlocals: u32 = 0; |
| 4928 | var nglobals: u32 = 0; | 4510 | var nglobals: u32 = 0; |
| 4929 | var strsize: u32 = 0; | 4511 | var strsize: u32 = 0; |
| ... | @@ -5141,94 +4723,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -5141,94 +4723,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 5141 | try self.writeShStrtab(); | 4723 | try self.writeShStrtab(); |
| 5142 | } | 4724 | } |
| 5143 | | 4725 | |
| 5144 | fn writeSyntheticSectionsObject(self: *Elf) !void { | 4726 | pub fn writeShStrtab(self: *Elf) !void { |
| 5145 | const gpa = self.base.comp.gpa; | | |
| 5146 | | | |
| 5147 | for (self.output_rela_sections.values()) |sec| { | | |
| 5148 | if (sec.atom_list.items.len == 0) continue; | | |
| 5149 | | | |
| 5150 | const shdr = self.shdrs.items[sec.shndx]; | | |
| 5151 | | | |
| 5152 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse | | |
| 5153 | return error.Overflow; | | |
| 5154 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); | | |
| 5155 | defer relocs.deinit(); | | |
| 5156 | | | |
| 5157 | for (sec.atom_list.items) |atom_index| { | | |
| 5158 | const atom_ptr = self.atom(atom_index) orelse continue; | | |
| 5159 | if (!atom_ptr.flags.alive) continue; | | |
| 5160 | try atom_ptr.writeRelocs(self, &relocs); | | |
| 5161 | } | | |
| 5162 | assert(relocs.items.len == num_relocs); | | |
| 5163 | | | |
| 5164 | const SortRelocs = struct { | | |
| 5165 | pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool { | | |
| 5166 | _ = ctx; | | |
| 5167 | return lhs.r_offset < rhs.r_offset; | | |
| 5168 | } | | |
| 5169 | }; | | |
| 5170 | | | |
| 5171 | mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan); | | |
| 5172 | | | |
| 5173 | log.debug("writing {s} from 0x{x} to 0x{x}", .{ | | |
| 5174 | self.getShString(shdr.sh_name), | | |
| 5175 | shdr.sh_offset, | | |
| 5176 | shdr.sh_offset + shdr.sh_size, | | |
| 5177 | }); | | |
| 5178 | | | |
| 5179 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset); | | |
| 5180 | } | | |
| 5181 | | | |
| 5182 | if (self.eh_frame_section_index) |shndx| { | | |
| 5183 | const shdr = self.shdrs.items[shndx]; | | |
| 5184 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | | |
| 5185 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | | |
| 5186 | defer buffer.deinit(); | | |
| 5187 | try eh_frame.writeEhFrameObject(self, buffer.writer()); | | |
| 5188 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ | | |
| 5189 | shdr.sh_offset, | | |
| 5190 | shdr.sh_offset + shdr.sh_size, | | |
| 5191 | }); | | |
| 5192 | assert(buffer.items.len == sh_size); | | |
| 5193 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | | |
| 5194 | } | | |
| 5195 | if (self.eh_frame_rela_section_index) |shndx| { | | |
| 5196 | const shdr = self.shdrs.items[shndx]; | | |
| 5197 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | | |
| 5198 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | | |
| 5199 | defer buffer.deinit(); | | |
| 5200 | try eh_frame.writeEhFrameRelocs(self, buffer.writer()); | | |
| 5201 | assert(buffer.items.len == sh_size); | | |
| 5202 | log.debug("writing .rela.eh_frame from 0x{x} to 0x{x}", .{ | | |
| 5203 | shdr.sh_offset, | | |
| 5204 | shdr.sh_offset + shdr.sh_size, | | |
| 5205 | }); | | |
| 5206 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | | |
| 5207 | } | | |
| 5208 | | | |
| 5209 | try self.writeComdatGroups(); | | |
| 5210 | try self.writeSymtab(); | | |
| 5211 | try self.writeShStrtab(); | | |
| 5212 | } | | |
| 5213 | | | |
| 5214 | fn writeComdatGroups(self: *Elf) !void { | | |
| 5215 | const gpa = self.base.comp.gpa; | | |
| 5216 | for (self.comdat_group_sections.items) |cgs| { | | |
| 5217 | const shdr = self.shdrs.items[cgs.shndx]; | | |
| 5218 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | | |
| 5219 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | | |
| 5220 | defer buffer.deinit(); | | |
| 5221 | try cgs.write(self, buffer.writer()); | | |
| 5222 | assert(buffer.items.len == sh_size); | | |
| 5223 | log.debug("writing COMDAT group from 0x{x} to 0x{x}", .{ | | |
| 5224 | shdr.sh_offset, | | |
| 5225 | shdr.sh_offset + shdr.sh_size, | | |
| 5226 | }); | | |
| 5227 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | | |
| 5228 | } | | |
| 5229 | } | | |
| 5230 | | | |
| 5231 | fn writeShStrtab(self: *Elf) !void { | | |
| 5232 | if (self.shstrtab_section_index) |index| { | 4727 | if (self.shstrtab_section_index) |index| { |
| 5233 | const shdr = self.shdrs.items[index]; | 4728 | const shdr = self.shdrs.items[index]; |
| 5234 | log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); | 4729 | log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); |
| ... | @@ -5236,7 +4731,7 @@ fn writeShStrtab(self: *Elf) !void { | ... | @@ -5236,7 +4731,7 @@ fn writeShStrtab(self: *Elf) !void { |
| 5236 | } | 4731 | } |
| 5237 | } | 4732 | } |
| 5238 | | 4733 | |
| 5239 | fn writeSymtab(self: *Elf) !void { | 4734 | pub fn writeSymtab(self: *Elf) !void { |
| 5240 | const target = self.base.comp.root_mod.resolved_target.result; | 4735 | const target = self.base.comp.root_mod.resolved_target.result; |
| 5241 | const gpa = self.base.comp.gpa; | 4736 | const gpa = self.base.comp.gpa; |
| 5242 | const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; | 4737 | const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; |
| ... | @@ -5367,7 +4862,7 @@ pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { | ... | @@ -5367,7 +4862,7 @@ pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { |
| 5367 | } | 4862 | } |
| 5368 | | 4863 | |
| 5369 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. | 4864 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. |
| 5370 | fn ptrWidthBytes(self: Elf) u8 { | 4865 | pub fn ptrWidthBytes(self: Elf) u8 { |
| 5371 | return switch (self.ptr_width) { | 4866 | return switch (self.ptr_width) { |
| 5372 | .p32 => 4, | 4867 | .p32 => 4, |
| 5373 | .p64 => 8, | 4868 | .p64 => 8, |
| ... | @@ -5713,7 +5208,7 @@ fn addPhdr(self: *Elf, opts: struct { | ... | @@ -5713,7 +5208,7 @@ fn addPhdr(self: *Elf, opts: struct { |
| 5713 | return index; | 5208 | return index; |
| 5714 | } | 5209 | } |
| 5715 | | 5210 | |
| 5716 | fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u16) !u16 { | 5211 | pub fn addRelaShdr(self: *Elf, name: [:0]const u8, shndx: u16) !u16 { |
| 5717 | const entsize: u64 = switch (self.ptr_width) { | 5212 | const entsize: u64 = switch (self.ptr_width) { |
| 5718 | .p32 => @sizeOf(elf.Elf32_Rela), | 5213 | .p32 => @sizeOf(elf.Elf32_Rela), |
| 5719 | .p64 => @sizeOf(elf.Elf64_Rela), | 5214 | .p64 => @sizeOf(elf.Elf64_Rela), |
| ... | @@ -6340,7 +5835,7 @@ fn formatPhdr( | ... | @@ -6340,7 +5835,7 @@ fn formatPhdr( |
| 6340 | }); | 5835 | }); |
| 6341 | } | 5836 | } |
| 6342 | | 5837 | |
| 6343 | fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { | 5838 | pub fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) { |
| 6344 | return .{ .data = self }; | 5839 | return .{ .data = self }; |
| 6345 | } | 5840 | } |
| 6346 | | 5841 | |
| ... | @@ -6579,6 +6074,7 @@ const glibc = @import("../glibc.zig"); | ... | @@ -6579,6 +6074,7 @@ const glibc = @import("../glibc.zig"); |
| 6579 | const link = @import("../link.zig"); | 6074 | const link = @import("../link.zig"); |
| 6580 | const lldMain = @import("../main.zig").lldMain; | 6075 | const lldMain = @import("../main.zig").lldMain; |
| 6581 | const musl = @import("../musl.zig"); | 6076 | const musl = @import("../musl.zig"); |
| | 6077 | const relocatable = @import("Elf/relocatable.zig"); |
| 6582 | const target_util = @import("../target.zig"); | 6078 | const target_util = @import("../target.zig"); |
| 6583 | const trace = @import("../tracy.zig").trace; | 6079 | const trace = @import("../tracy.zig").trace; |
| 6584 | const synthetic_sections = @import("Elf/synthetic_sections.zig"); | 6080 | const synthetic_sections = @import("Elf/synthetic_sections.zig"); |