| ... | ... | @@ -189,7 +189,7 @@ strings: StringTable = .{}, |
| 189 | 189 | /// Static archive state. |
| 190 | 190 | /// TODO it may be wise to move it somewhere else, but for the time being, it |
| 191 | 191 | /// is far easier to pollute global state. |
| 192 | | ar_symtab: std.ArrayListUnmanaged(struct { u32, File.Index }) = .{}, |
| 192 | ar_symtab: std.ArrayListUnmanaged(ArSymtabEntry) = .{}, |
| 193 | 193 | ar_strtab: StringTable = .{}, |
| 194 | 194 | |
| 195 | 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 | 1532 | |
| 1533 | 1533 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| 1534 | 1534 | _ = comp; |
| 1535 | const gpa = self.base.allocator; |
| 1535 | 1536 | |
| 1536 | 1537 | // First, we flush relocatable object file generated with our backends. |
| 1537 | 1538 | if (self.zigObjectPtr()) |zig_object| { |
| ... | ... | @@ -1553,28 +1554,162 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void |
| 1553 | 1554 | try self.writeShStrtab(); |
| 1554 | 1555 | try self.writeElfHeader(); |
| 1555 | 1556 | |
| 1556 | | // Update ar symbol and string tables. |
| 1557 | // Update ar symbol table. |
| 1557 | 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 | 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 | 1565 | if (build_options.enable_logging) { |
| 1571 | 1566 | state_log.debug("{}", .{self.dumpState()}); |
| 1572 | 1567 | } |
| 1573 | 1568 | |
| 1574 | | // try self.writeArHdr(); |
| 1575 | | // TODO beyond this point I expect writing out objects parsed from the cmdline |
| 1569 | // Save object paths in strtab. |
| 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 | 1715 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { |
| ... | ... | @@ -2968,15 +3103,6 @@ fn writeElfHeader(self: *Elf) !void { |
| 2968 | 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 | 3106 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2981 | 3107 | if (self.llvm_object) |llvm_object| return llvm_object.freeDecl(decl_index); |
| 2982 | 3108 | return self.zigObjectPtr().?.freeDecl(self, decl_index); |
| ... | ... | @@ -5683,6 +5809,19 @@ fn fmtDumpState( |
| 5683 | 5809 | } |
| 5684 | 5810 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| 5685 | 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 | 5825 | try writer.writeAll("Output shdrs\n"); |
| 5687 | 5826 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 5688 | 5827 | try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{ |
| ... | ... | @@ -5815,6 +5954,19 @@ const LastAtomAndFreeList = struct { |
| 5815 | 5954 | |
| 5816 | 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 | 5970 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; |
| 5819 | 5971 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; |
| 5820 | 5972 | |