| ... | ... | @@ -38,6 +38,16 @@ pub const Options = struct { |
| 38 | 38 | |
| 39 | 39 | |
| 40 | 40 | pub const File = struct { |
| 41 | pub const LinkBlock = union { |
| 42 | elf: Elf.TextBlock, |
| 43 | c: void, |
| 44 | }; |
| 45 | |
| 46 | pub const LinkFn = union { |
| 47 | elf: Elf.SrcFn, |
| 48 | c: void, |
| 49 | }; |
| 50 | |
| 41 | 51 | tag: Tag, |
| 42 | 52 | options: Options, |
| 43 | 53 | file: ?fs.File, |
| ... | ... | @@ -1720,31 +1730,31 @@ pub const File = struct { |
| 1720 | 1730 | } |
| 1721 | 1731 | |
| 1722 | 1732 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 1723 | | if (decl.link.local_sym_index != 0) return; |
| 1733 | if (decl.link.elf.local_sym_index != 0) return; |
| 1724 | 1734 | |
| 1725 | 1735 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); |
| 1726 | 1736 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 1727 | 1737 | |
| 1728 | 1738 | if (self.local_symbol_free_list.popOrNull()) |i| { |
| 1729 | 1739 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); |
| 1730 | | decl.link.local_sym_index = i; |
| 1740 | decl.link.elf.local_sym_index = i; |
| 1731 | 1741 | } else { |
| 1732 | 1742 | log.debug(.link, "allocating symbol index {} for {}\n", .{ self.local_symbols.items.len, decl.name }); |
| 1733 | | decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len); |
| 1743 | decl.link.elf.local_sym_index = @intCast(u32, self.local_symbols.items.len); |
| 1734 | 1744 | _ = self.local_symbols.addOneAssumeCapacity(); |
| 1735 | 1745 | } |
| 1736 | 1746 | |
| 1737 | 1747 | if (self.offset_table_free_list.popOrNull()) |i| { |
| 1738 | | decl.link.offset_table_index = i; |
| 1748 | decl.link.elf.offset_table_index = i; |
| 1739 | 1749 | } else { |
| 1740 | | decl.link.offset_table_index = @intCast(u32, self.offset_table.items.len); |
| 1750 | decl.link.elf.offset_table_index = @intCast(u32, self.offset_table.items.len); |
| 1741 | 1751 | _ = self.offset_table.addOneAssumeCapacity(); |
| 1742 | 1752 | self.offset_table_count_dirty = true; |
| 1743 | 1753 | } |
| 1744 | 1754 | |
| 1745 | 1755 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1746 | 1756 | |
| 1747 | | self.local_symbols.items[decl.link.local_sym_index] = .{ |
| 1757 | self.local_symbols.items[decl.link.elf.local_sym_index] = .{ |
| 1748 | 1758 | .st_name = 0, |
| 1749 | 1759 | .st_info = 0, |
| 1750 | 1760 | .st_other = 0, |
| ... | ... | @@ -1752,39 +1762,39 @@ pub const File = struct { |
| 1752 | 1762 | .st_value = phdr.p_vaddr, |
| 1753 | 1763 | .st_size = 0, |
| 1754 | 1764 | }; |
| 1755 | | self.offset_table.items[decl.link.offset_table_index] = 0; |
| 1765 | self.offset_table.items[decl.link.elf.offset_table_index] = 0; |
| 1756 | 1766 | } |
| 1757 | 1767 | |
| 1758 | 1768 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 1759 | 1769 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 1760 | | self.freeTextBlock(&decl.link); |
| 1761 | | if (decl.link.local_sym_index != 0) { |
| 1762 | | self.local_symbol_free_list.append(self.base.allocator, decl.link.local_sym_index) catch {}; |
| 1763 | | self.offset_table_free_list.append(self.base.allocator, decl.link.offset_table_index) catch {}; |
| 1770 | self.freeTextBlock(&decl.link.elf); |
| 1771 | if (decl.link.elf.local_sym_index != 0) { |
| 1772 | self.local_symbol_free_list.append(self.base.allocator, decl.link.elf.local_sym_index) catch {}; |
| 1773 | self.offset_table_free_list.append(self.base.allocator, decl.link.elf.offset_table_index) catch {}; |
| 1764 | 1774 | |
| 1765 | | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; |
| 1775 | self.local_symbols.items[decl.link.elf.local_sym_index].st_info = 0; |
| 1766 | 1776 | |
| 1767 | | decl.link.local_sym_index = 0; |
| 1777 | decl.link.elf.local_sym_index = 0; |
| 1768 | 1778 | } |
| 1769 | 1779 | // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing |
| 1770 | 1780 | // is desired for both. |
| 1771 | | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link); |
| 1772 | | if (decl.fn_link.prev) |prev| { |
| 1781 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link.elf); |
| 1782 | if (decl.fn_link.elf.prev) |prev| { |
| 1773 | 1783 | _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {}; |
| 1774 | | prev.next = decl.fn_link.next; |
| 1775 | | if (decl.fn_link.next) |next| { |
| 1784 | prev.next = decl.fn_link.elf.next; |
| 1785 | if (decl.fn_link.elf.next) |next| { |
| 1776 | 1786 | next.prev = prev; |
| 1777 | 1787 | } else { |
| 1778 | 1788 | self.dbg_line_fn_last = prev; |
| 1779 | 1789 | } |
| 1780 | | } else if (decl.fn_link.next) |next| { |
| 1790 | } else if (decl.fn_link.elf.next) |next| { |
| 1781 | 1791 | self.dbg_line_fn_first = next; |
| 1782 | 1792 | next.prev = null; |
| 1783 | 1793 | } |
| 1784 | | if (self.dbg_line_fn_first == &decl.fn_link) { |
| 1794 | if (self.dbg_line_fn_first == &decl.fn_link.elf) { |
| 1785 | 1795 | self.dbg_line_fn_first = null; |
| 1786 | 1796 | } |
| 1787 | | if (self.dbg_line_fn_last == &decl.fn_link) { |
| 1797 | if (self.dbg_line_fn_last == &decl.fn_link.elf) { |
| 1788 | 1798 | self.dbg_line_fn_last = null; |
| 1789 | 1799 | } |
| 1790 | 1800 | } |
| ... | ... | @@ -1870,24 +1880,24 @@ pub const File = struct { |
| 1870 | 1880 | |
| 1871 | 1881 | const stt_bits: u8 = if (is_fn) elf.STT_FUNC else elf.STT_OBJECT; |
| 1872 | 1882 | |
| 1873 | | assert(decl.link.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() |
| 1874 | | const local_sym = &self.local_symbols.items[decl.link.local_sym_index]; |
| 1883 | assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes() |
| 1884 | const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index]; |
| 1875 | 1885 | if (local_sym.st_size != 0) { |
| 1876 | | const capacity = decl.link.capacity(self.*); |
| 1886 | const capacity = decl.link.elf.capacity(self.*); |
| 1877 | 1887 | const need_realloc = code.len > capacity or |
| 1878 | 1888 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); |
| 1879 | 1889 | if (need_realloc) { |
| 1880 | | const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment); |
| 1890 | const vaddr = try self.growTextBlock(&decl.link.elf, code.len, required_alignment); |
| 1881 | 1891 | log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr }); |
| 1882 | 1892 | if (vaddr != local_sym.st_value) { |
| 1883 | 1893 | local_sym.st_value = vaddr; |
| 1884 | 1894 | |
| 1885 | 1895 | log.debug(.link, " (writing new offset table entry)\n", .{}); |
| 1886 | | self.offset_table.items[decl.link.offset_table_index] = vaddr; |
| 1887 | | try self.writeOffsetTableEntry(decl.link.offset_table_index); |
| 1896 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; |
| 1897 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); |
| 1888 | 1898 | } |
| 1889 | 1899 | } else if (code.len < local_sym.st_size) { |
| 1890 | | self.shrinkTextBlock(&decl.link, code.len); |
| 1900 | self.shrinkTextBlock(&decl.link.elf, code.len); |
| 1891 | 1901 | } |
| 1892 | 1902 | local_sym.st_size = code.len; |
| 1893 | 1903 | local_sym.st_name = try self.updateString(local_sym.st_name, mem.spanZ(decl.name)); |
| ... | ... | @@ -1895,13 +1905,13 @@ pub const File = struct { |
| 1895 | 1905 | local_sym.st_other = 0; |
| 1896 | 1906 | local_sym.st_shndx = self.text_section_index.?; |
| 1897 | 1907 | // TODO this write could be avoided if no fields of the symbol were changed. |
| 1898 | | try self.writeSymbol(decl.link.local_sym_index); |
| 1908 | try self.writeSymbol(decl.link.elf.local_sym_index); |
| 1899 | 1909 | } else { |
| 1900 | 1910 | const decl_name = mem.spanZ(decl.name); |
| 1901 | 1911 | const name_str_index = try self.makeString(decl_name); |
| 1902 | | const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment); |
| 1912 | const vaddr = try self.allocateTextBlock(&decl.link.elf, code.len, required_alignment); |
| 1903 | 1913 | log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr }); |
| 1904 | | errdefer self.freeTextBlock(&decl.link); |
| 1914 | errdefer self.freeTextBlock(&decl.link.elf); |
| 1905 | 1915 | |
| 1906 | 1916 | local_sym.* = .{ |
| 1907 | 1917 | .st_name = name_str_index, |
| ... | ... | @@ -1911,10 +1921,10 @@ pub const File = struct { |
| 1911 | 1921 | .st_value = vaddr, |
| 1912 | 1922 | .st_size = code.len, |
| 1913 | 1923 | }; |
| 1914 | | self.offset_table.items[decl.link.offset_table_index] = vaddr; |
| 1924 | self.offset_table.items[decl.link.elf.offset_table_index] = vaddr; |
| 1915 | 1925 | |
| 1916 | | try self.writeSymbol(decl.link.local_sym_index); |
| 1917 | | try self.writeOffsetTableEntry(decl.link.offset_table_index); |
| 1926 | try self.writeSymbol(decl.link.elf.local_sym_index); |
| 1927 | try self.writeOffsetTableEntry(decl.link.elf.offset_table_index); |
| 1918 | 1928 | } |
| 1919 | 1929 | |
| 1920 | 1930 | const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr; |
| ... | ... | @@ -1941,7 +1951,7 @@ pub const File = struct { |
| 1941 | 1951 | // Now we have the full contents and may allocate a region to store it. |
| 1942 | 1952 | |
| 1943 | 1953 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; |
| 1944 | | const src_fn = &decl.fn_link; |
| 1954 | const src_fn = &decl.fn_link.elf; |
| 1945 | 1955 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| 1946 | 1956 | if (self.dbg_line_fn_last) |last| { |
| 1947 | 1957 | if (src_fn.next) |next| { |
| ... | ... | @@ -2026,8 +2036,8 @@ pub const File = struct { |
| 2026 | 2036 | |
| 2027 | 2037 | try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len); |
| 2028 | 2038 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 2029 | | if (decl.link.local_sym_index == 0) return; |
| 2030 | | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; |
| 2039 | if (decl.link.elf.local_sym_index == 0) return; |
| 2040 | const decl_sym = self.local_symbols.items[decl.link.elf.local_sym_index]; |
| 2031 | 2041 | |
| 2032 | 2042 | for (exports) |exp| { |
| 2033 | 2043 | if (exp.options.section) |section_name| { |
| ... | ... | @@ -2105,7 +2115,7 @@ pub const File = struct { |
| 2105 | 2115 | const casted_line_off = @intCast(u28, line_delta); |
| 2106 | 2116 | |
| 2107 | 2117 | const shdr = &self.sections.items[self.debug_line_section_index.?]; |
| 2108 | | const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff(); |
| 2118 | const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff(); |
| 2109 | 2119 | var data: [4]u8 = undefined; |
| 2110 | 2120 | leb128.writeUnsignedFixed(4, &data, casted_line_off); |
| 2111 | 2121 | try self.base.file.?.pwriteAll(&data, file_pos); |