| ... | @@ -189,7 +189,7 @@ strings: StringTable = .{}, | ... | @@ -189,7 +189,7 @@ strings: StringTable = .{}, |
| 189 | /// Static archive state. | 189 | /// Static archive state. |
| 190 | /// TODO it may be wise to move it somewhere else, but for the time being, it | 190 | /// TODO it may be wise to move it somewhere else, but for the time being, it |
| 191 | /// is far easier to pollute global state. | 191 | /// is far easier to pollute global state. |
| 192 | ar_symtab: std.ArrayListUnmanaged(struct { u32, File.Index }) = .{}, | 192 | ar_symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .{}, |
| 193 | ar_strtab: StringTable = .{}, | 193 | ar_strtab: StringTable = .{}, |
| 194 | | 194 | |
| 195 | /// When allocating, the ideal_capacity is calculated by | 195 | /// When allocating, the ideal_capacity is calculated by |
| ... | @@ -1532,6 +1532,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1532,6 +1532,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1532 | | 1532 | |
| 1533 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1533 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| 1534 | _ = comp; | 1534 | _ = comp; |
| | 1535 | const gpa = self.base.allocator; |
| 1535 | | 1536 | |
| 1536 | // First, we flush relocatable object file generated with our backends. | 1537 | // First, we flush relocatable object file generated with our backends. |
| 1537 | if (self.zigObjectPtr()) |zig_object| { | 1538 | if (self.zigObjectPtr()) |zig_object| { |
| ... | @@ -1553,28 +1554,162 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void | ... | @@ -1553,28 +1554,162 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void |
| 1553 | try self.writeShStrtab(); | 1554 | try self.writeShStrtab(); |
| 1554 | try self.writeElfHeader(); | 1555 | try self.writeElfHeader(); |
| 1555 | | 1556 | |
| 1556 | // Update ar symbol and string tables. | 1557 | // Update ar symbol table. |
| 1557 | try zig_object.asFile().updateArSymtab(self); | 1558 | try zig_object.asFile().updateArSymtab(self); |
| 1558 | | | |
| 1559 | for (self.ar_symtab.items, 0..) |entry, i| { | | |
| 1560 | std.debug.print("{d}: {s} in {}\n", .{ | | |
| 1561 | i, | | |
| 1562 | self.ar_strtab.getAssumeExists(entry[0]), | | |
| 1563 | self.file(entry[1]).?.fmtPath(), | | |
| 1564 | }); | | |
| 1565 | } | | |
| 1566 | } | 1559 | } |
| 1567 | | 1560 | |
| 1568 | // TODO parse positionals that we want to make part of the archive | 1561 | // TODO parse positionals that we want to make part of the archive |
| 1569 | | 1562 | |
| | 1563 | mem.sort(ArSymtabEntry, self.ar_symtab.items, {}, ArSymtabEntry.lessThan); |
| | 1564 | |
| 1570 | if (build_options.enable_logging) { | 1565 | if (build_options.enable_logging) { |
| 1571 | state_log.debug("{}", .{self.dumpState()}); | 1566 | state_log.debug("{}", .{self.dumpState()}); |
| 1572 | } | 1567 | } |
| 1573 | | 1568 | |
| 1574 | // try self.writeArHdr(); | 1569 | // Save object paths in strtab. |
| 1575 | // TODO beyond this point I expect writing out objects parsed from the cmdline | 1570 | var files = std.AutoHashMap(File.Index, struct { u32, u64, u64 }).init(gpa); |
| | 1571 | defer files.deinit(); |
| | 1572 | try files.ensureUnusedCapacity(@intCast(self.objects.items.len + 1)); |
| | 1573 | |
| | 1574 | if (self.zigObjectPtr()) |zig_object| { |
| | 1575 | files.putAssumeCapacityNoClobber(zig_object.index, .{ try self.ar_strtab.insert(gpa, zig_object.path), 0, 0 }); |
| | 1576 | } |
| | 1577 | |
| | 1578 | // Encode ar symtab in 64bit format. |
| | 1579 | var ar_symtab = std.ArrayList(u8).init(gpa); |
| | 1580 | defer ar_symtab.deinit(); |
| | 1581 | try ar_symtab.ensureTotalCapacityPrecise(8 * (3 * self.ar_symtab.items.len + 1)); |
| | 1582 | |
| | 1583 | // Number of symbols |
| | 1584 | ar_symtab.writer().writeInt(u64, @as(u64, @intCast(self.ar_symtab.items.len)), .big) catch unreachable; |
| | 1585 | |
| | 1586 | // Offsets which we will relocate later. |
| | 1587 | for (0..self.ar_symtab.items.len) |_| { |
| | 1588 | ar_symtab.writer().writeInt(u64, 0, .big) catch unreachable; |
| | 1589 | } |
| | 1590 | |
| | 1591 | // ASCII offsets into the strtab. |
| | 1592 | for (self.ar_symtab.items) |entry| { |
| | 1593 | ar_symtab.writer().print("/{d}", .{entry.off}) catch unreachable; |
| | 1594 | } |
| | 1595 | |
| | 1596 | // Align to 8bytes if required |
| | 1597 | { |
| | 1598 | const end = ar_symtab.items.len; |
| | 1599 | const aligned = mem.alignForward(usize, end, 8); |
| | 1600 | ar_symtab.writer().writeByteNTimes(0, aligned - end) catch unreachable; |
| | 1601 | } |
| | 1602 | |
| | 1603 | assert(mem.isAligned(ar_symtab.items.len, 8)); |
| 1576 | | 1604 | |
| 1577 | try self.writeArMagic(); | 1605 | // Calculate required size for headers before ZigObject pos in file. |
| | 1606 | if (self.zigObjectPtr()) |zig_object| { |
| | 1607 | var file_off: u64 = 0; |
| | 1608 | // Magic |
| | 1609 | file_off += Archive.SARMAG; |
| | 1610 | // Symtab |
| | 1611 | file_off += @sizeOf(Archive.ar_hdr) + @as(u64, @intCast(ar_symtab.items.len)); |
| | 1612 | // Strtab |
| | 1613 | file_off += @sizeOf(Archive.ar_hdr) + @as(u64, @intCast(self.ar_strtab.buffer.items.len)); |
| | 1614 | // And because we are nice, we will align to 8 bytes. |
| | 1615 | file_off = mem.alignForward(u64, file_off, 8); |
| | 1616 | |
| | 1617 | const files_ptr = files.getPtr(zig_object.index).?; |
| | 1618 | files_ptr[1] = file_off; |
| | 1619 | |
| | 1620 | // Move ZigObject into place. |
| | 1621 | { |
| | 1622 | var end_pos: u64 = self.shdr_table_offset.?; |
| | 1623 | for (self.shdrs.items) |shdr| { |
| | 1624 | end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); |
| | 1625 | } |
| | 1626 | const contents = try gpa.alloc(u8, end_pos); |
| | 1627 | defer gpa.free(contents); |
| | 1628 | const amt = try self.base.file.?.preadAll(contents, 0); |
| | 1629 | if (amt != end_pos) return error.InputOutput; |
| | 1630 | try self.base.file.?.pwriteAll(contents, file_off + @sizeOf(Archive.ar_hdr)); |
| | 1631 | |
| | 1632 | files_ptr[2] = end_pos; |
| | 1633 | } |
| | 1634 | } |
| | 1635 | |
| | 1636 | // Fixup file offsets in the symtab. |
| | 1637 | for (self.ar_symtab.items, 1..) |entry, i| { |
| | 1638 | const file_off = files.get(entry.file_index).?[1]; |
| | 1639 | mem.writeInt(u64, ar_symtab.items[8 * i ..][0..8], file_off, .big); |
| | 1640 | } |
| | 1641 | |
| | 1642 | var pos: usize = Archive.SARMAG; |
| | 1643 | |
| | 1644 | // Write symtab. |
| | 1645 | { |
| | 1646 | const hdr = setArHdr(.{ .kind = .symtab, .name_off = 0, .size = @intCast(ar_symtab.items.len) }); |
| | 1647 | try self.base.file.?.pwriteAll(mem.asBytes(&hdr), pos); |
| | 1648 | pos += @sizeOf(Archive.ar_hdr); |
| | 1649 | try self.base.file.?.pwriteAll(ar_symtab.items, pos); |
| | 1650 | pos += ar_symtab.items.len; |
| | 1651 | } |
| | 1652 | |
| | 1653 | // Write strtab. |
| | 1654 | { |
| | 1655 | const hdr = setArHdr(.{ |
| | 1656 | .kind = .strtab, |
| | 1657 | .name_off = 0, |
| | 1658 | .size = @intCast(mem.alignForward(usize, self.ar_strtab.buffer.items.len, 8)), |
| | 1659 | }); |
| | 1660 | try self.base.file.?.pwriteAll(mem.asBytes(&hdr), pos); |
| | 1661 | pos += @sizeOf(Archive.ar_hdr); |
| | 1662 | try self.base.file.?.pwriteAll(self.ar_strtab.buffer.items, pos); |
| | 1663 | pos += self.ar_strtab.buffer.items.len; |
| | 1664 | } |
| | 1665 | |
| | 1666 | // Zig object if defined |
| | 1667 | if (self.zigObjectPtr()) |zig_object| { |
| | 1668 | const entry = files.get(zig_object.index).?; |
| | 1669 | const hdr = setArHdr(.{ .kind = .object, .name_off = entry[0], .size = @intCast(entry[2]) }); |
| | 1670 | try self.base.file.?.pwriteAll(mem.asBytes(&hdr), entry[1]); |
| | 1671 | } |
| | 1672 | |
| | 1673 | // TODO parsed positionals |
| | 1674 | |
| | 1675 | // Magic bytes. |
| | 1676 | { |
| | 1677 | try self.base.file.?.pwriteAll(Archive.ARMAG, 0); |
| | 1678 | } |
| | 1679 | } |
| | 1680 | |
| | 1681 | fn setArHdr(opts: struct { |
| | 1682 | kind: enum { symtab, strtab, object }, |
| | 1683 | name_off: u32, |
| | 1684 | size: u32, |
| | 1685 | }) Archive.ar_hdr { |
| | 1686 | var hdr: Archive.ar_hdr = .{ |
| | 1687 | .ar_name = undefined, |
| | 1688 | .ar_date = undefined, |
| | 1689 | .ar_uid = undefined, |
| | 1690 | .ar_gid = undefined, |
| | 1691 | .ar_mode = undefined, |
| | 1692 | .ar_size = undefined, |
| | 1693 | .ar_fmag = undefined, |
| | 1694 | }; |
| | 1695 | @memset(mem.asBytes(&hdr), 0x20); |
| | 1696 | @memcpy(&hdr.ar_fmag, Archive.ARFMAG); |
| | 1697 | |
| | 1698 | { |
| | 1699 | var stream = std.io.fixedBufferStream(&hdr.ar_name); |
| | 1700 | const writer = stream.writer(); |
| | 1701 | switch (opts.kind) { |
| | 1702 | .symtab => writer.print("{s}", .{Archive.SYM64NAME}) catch unreachable, |
| | 1703 | .strtab => writer.print("//", .{}) catch unreachable, |
| | 1704 | .object => writer.print("/{d}", .{opts.name_off}) catch unreachable, |
| | 1705 | } |
| | 1706 | } |
| | 1707 | { |
| | 1708 | var stream = std.io.fixedBufferStream(&hdr.ar_size); |
| | 1709 | stream.writer().print("{d}", .{opts.size}) catch unreachable; |
| | 1710 | } |
| | 1711 | |
| | 1712 | return hdr; |
| 1578 | } | 1713 | } |
| 1579 | | 1714 | |
| 1580 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1715 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| ... | @@ -2968,15 +3103,6 @@ fn writeElfHeader(self: *Elf) !void { | ... | @@ -2968,15 +3103,6 @@ fn writeElfHeader(self: *Elf) !void { |
| 2968 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); | 3103 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 2969 | } | 3104 | } |
| 2970 | | 3105 | |
| 2971 | fn writeArMagic(self: *Elf) !void { | | |
| 2972 | // Magic bytes. | | |
| 2973 | var buffer: [@as(usize, Archive.SARMAG) + 1]u8 = undefined; | | |
| 2974 | var stream = std.io.fixedBufferStream(&buffer); | | |
| 2975 | const writer = stream.writer(); | | |
| 2976 | try writer.print("{s}\x00", .{Archive.ARMAG}); | | |
| 2977 | try self.base.file.?.pwriteAll(&buffer, 0); | | |
| 2978 | } | | |
| 2979 | | | |
| 2980 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | 3106 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2981 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); | 3107 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); |
| 2982 | return self.zigObjectPtr().?.freeDecl(self, decl_index); | 3108 | return self.zigObjectPtr().?.freeDecl(self, decl_index); |
| ... | @@ -5683,6 +5809,19 @@ fn fmtDumpState( | ... | @@ -5683,6 +5809,19 @@ fn fmtDumpState( |
| 5683 | } | 5809 | } |
| 5684 | try writer.print("{}\n", .{self.got.fmt(self)}); | 5810 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| 5685 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); | 5811 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); |
| | 5812 | |
| | 5813 | if (self.isStaticLib()) { |
| | 5814 | try writer.writeAll("ar symtab\n"); |
| | 5815 | for (self.ar_symtab.items, 0..) |entry, i| { |
| | 5816 | try writer.print(" {d} : {s} in file({d})\n", .{ |
| | 5817 | i, |
| | 5818 | self.ar_strtab.getAssumeExists(entry.off), |
| | 5819 | entry.file_index, |
| | 5820 | }); |
| | 5821 | } |
| | 5822 | try writer.writeByte('\n'); |
| | 5823 | } |
| | 5824 | |
| 5686 | try writer.writeAll("Output shdrs\n"); | 5825 | try writer.writeAll("Output shdrs\n"); |
| 5687 | for (self.shdrs.items, 0..) |shdr, shndx| { | 5826 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 5688 | try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{ | 5827 | try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{ |
| ... | @@ -5815,6 +5954,19 @@ const LastAtomAndFreeList = struct { | ... | @@ -5815,6 +5954,19 @@ const LastAtomAndFreeList = struct { |
| 5815 | | 5954 | |
| 5816 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList); | 5955 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList); |
| 5817 | | 5956 | |
| | 5957 | const ArSymtabEntry = struct { |
| | 5958 | off: u32, |
| | 5959 | file_index: File.Index, |
| | 5960 | |
| | 5961 | pub fn lessThan(ctx: void, lhs: ArSymtabEntry, rhs: ArSymtabEntry) bool { |
| | 5962 | _ = ctx; |
| | 5963 | if (lhs.off == rhs.off) { |
| | 5964 | return lhs.file_index < rhs.file_index; |
| | 5965 | } |
| | 5966 | return lhs.off < rhs.off; |
| | 5967 | } |
| | 5968 | }; |
| | 5969 | |
| 5818 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; | 5970 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; |
| 5819 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; | 5971 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; |
| 5820 | | 5972 | |