| ... | ... | @@ -1731,11 +1731,8 @@ pub const File = struct { |
| 1731 | 1731 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 1732 | 1732 | if (decl.link.local_sym_index != 0) return; |
| 1733 | 1733 | |
| 1734 | | // Here we also ensure capacity for the free lists so that they can be appended to without fail. |
| 1735 | 1734 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); |
| 1736 | | try self.local_symbol_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len); |
| 1737 | 1735 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); |
| 1738 | | try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len); |
| 1739 | 1736 | |
| 1740 | 1737 | if (self.local_symbol_free_list.popOrNull()) |i| { |
| 1741 | 1738 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); |
| ... | ... | @@ -1768,15 +1765,37 @@ pub const File = struct { |
| 1768 | 1765 | } |
| 1769 | 1766 | |
| 1770 | 1767 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 1768 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 1771 | 1769 | self.freeTextBlock(&decl.link); |
| 1772 | 1770 | if (decl.link.local_sym_index != 0) { |
| 1773 | | self.local_symbol_free_list.appendAssumeCapacity(decl.link.local_sym_index); |
| 1774 | | self.offset_table_free_list.appendAssumeCapacity(decl.link.offset_table_index); |
| 1771 | self.local_symbol_free_list.append(self.allocator, decl.link.local_sym_index) catch {}; |
| 1772 | self.offset_table_free_list.append(self.allocator, decl.link.offset_table_index) catch {}; |
| 1775 | 1773 | |
| 1776 | 1774 | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; |
| 1777 | 1775 | |
| 1778 | 1776 | decl.link.local_sym_index = 0; |
| 1779 | 1777 | } |
| 1778 | // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing |
| 1779 | // is desired for both. |
| 1780 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link); |
| 1781 | if (decl.fn_link.prev) |prev| { |
| 1782 | _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {}; |
| 1783 | prev.next = decl.fn_link.next; |
| 1784 | if (decl.fn_link.next) |next| { |
| 1785 | next.prev = prev; |
| 1786 | } else { |
| 1787 | self.dbg_line_fn_last = prev; |
| 1788 | } |
| 1789 | } else if (decl.fn_link.next) |next| { |
| 1790 | self.dbg_line_fn_first = next; |
| 1791 | next.prev = null; |
| 1792 | } |
| 1793 | if (self.dbg_line_fn_first == &decl.fn_link) { |
| 1794 | self.dbg_line_fn_first = null; |
| 1795 | } |
| 1796 | if (self.dbg_line_fn_last == &decl.fn_link) { |
| 1797 | self.dbg_line_fn_last = null; |
| 1798 | } |
| 1780 | 1799 | } |
| 1781 | 1800 | |
| 1782 | 1801 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| ... | ... | @@ -1923,18 +1942,35 @@ pub const File = struct { |
| 1923 | 1942 | |
| 1924 | 1943 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; |
| 1925 | 1944 | const src_fn = &decl.fn_link; |
| 1945 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| 1926 | 1946 | if (self.dbg_line_fn_last) |last| { |
| 1927 | | if (src_fn.prev == null and src_fn.next == null) { |
| 1947 | if (src_fn.next) |next| { |
| 1948 | // Update existing function - non-last item. |
| 1949 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { |
| 1950 | // It grew too big, so we move it to a new location. |
| 1951 | if (src_fn.prev) |prev| { |
| 1952 | _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {}; |
| 1953 | prev.next = src_fn.next; |
| 1954 | } |
| 1955 | next.prev = src_fn.prev; |
| 1956 | // Populate where it used to be with NOPs. |
| 1957 | const file_pos = debug_line_sect.sh_offset + src_fn.off; |
| 1958 | try self.pwriteWithNops(0, &[0]u8{}, src_fn.len, file_pos); |
| 1959 | // TODO Look at the free list before appending at the end. |
| 1960 | src_fn.prev = last; |
| 1961 | last.next = src_fn; |
| 1962 | self.dbg_line_fn_last = src_fn; |
| 1963 | |
| 1964 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); |
| 1965 | } |
| 1966 | } else if (src_fn.prev == null) { |
| 1928 | 1967 | // Append new function. |
| 1968 | // TODO Look at the free list before appending at the end. |
| 1929 | 1969 | src_fn.prev = last; |
| 1930 | 1970 | last.next = src_fn; |
| 1931 | 1971 | self.dbg_line_fn_last = src_fn; |
| 1932 | 1972 | |
| 1933 | 1973 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); |
| 1934 | | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| 1935 | | } else { |
| 1936 | | // Update existing function. |
| 1937 | | @panic("TODO updateDecl for .debug_line: add new SrcFn: update"); |
| 1938 | 1974 | } |
| 1939 | 1975 | } else { |
| 1940 | 1976 | // This is the first function of the Line Number Program. |
| ... | ... | @@ -1942,7 +1978,6 @@ pub const File = struct { |
| 1942 | 1978 | self.dbg_line_fn_last = src_fn; |
| 1943 | 1979 | |
| 1944 | 1980 | src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den; |
| 1945 | | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| 1946 | 1981 | } |
| 1947 | 1982 | |
| 1948 | 1983 | const needed_size = src_fn.off + src_fn.len; |
| ... | ... | @@ -1982,10 +2017,7 @@ pub const File = struct { |
| 1982 | 2017 | const tracy = trace(@src()); |
| 1983 | 2018 | defer tracy.end(); |
| 1984 | 2019 | |
| 1985 | | // In addition to ensuring capacity for global_symbols, we also ensure capacity for freeing all of |
| 1986 | | // them, so that deleting exports is guaranteed to succeed. |
| 1987 | 2020 | try self.global_symbols.ensureCapacity(self.allocator, self.global_symbols.items.len + exports.len); |
| 1988 | | try self.global_symbol_free_list.ensureCapacity(self.allocator, self.global_symbols.items.len); |
| 1989 | 2021 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 1990 | 2022 | if (decl.link.local_sym_index == 0) return; |
| 1991 | 2023 | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; |
| ... | ... | @@ -2052,7 +2084,7 @@ pub const File = struct { |
| 2052 | 2084 | |
| 2053 | 2085 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 2054 | 2086 | const sym_index = exp.sym_index orelse return; |
| 2055 | | self.global_symbol_free_list.appendAssumeCapacity(sym_index); |
| 2087 | self.global_symbol_free_list.append(self.allocator, sym_index) catch {}; |
| 2056 | 2088 | self.global_symbols.items[sym_index].st_info = 0; |
| 2057 | 2089 | } |
| 2058 | 2090 | |
| ... | ... | @@ -2284,7 +2316,7 @@ pub const File = struct { |
| 2284 | 2316 | } |
| 2285 | 2317 | |
| 2286 | 2318 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of |
| 2287 | | /// bytes of NOPs. Asserts each padding size is at least two bytes and total padding bytes |
| 2319 | /// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes |
| 2288 | 2320 | /// are less than 126,976 bytes (if this limit is ever reached, this function can be |
| 2289 | 2321 | /// improved to make more than one pwritev call, or the limit can be raised by a fixed |
| 2290 | 2322 | /// amount by increasing the length of `vecs`). |
| ... | ... | @@ -2361,6 +2393,8 @@ pub const File = struct { |
| 2361 | 2393 | try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); |
| 2362 | 2394 | } |
| 2363 | 2395 | |
| 2396 | const min_nop_size = 2; |
| 2397 | |
| 2364 | 2398 | }; |
| 2365 | 2399 | }; |
| 2366 | 2400 | |