authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-03 23:13:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-03 23:13:54-07:00
logcb25d8e4bc78d6fe21e0cb0b979aa8250a086c2e
treed176142591c260654533586f314ecfc04409b15e
parent9b3a70c8aab74b804cac0d7c15e4e7518a88c868

stage2 .debug_line: handle Decl deletes and updates


1 files changed, 50 insertions(+), 16 deletions(-)

src-self-hosted/link.zig+50-16
......@@ -1731,11 +1731,8 @@ pub const File = struct {
17311731 pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
17321732 if (decl.link.local_sym_index != 0) return;
17331733
1734 // Here we also ensure capacity for the free lists so that they can be appended to without fail.
17351734 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);
17371735 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);
17391736
17401737 if (self.local_symbol_free_list.popOrNull()) |i| {
17411738 log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name });
......@@ -1768,15 +1765,37 @@ pub const File = struct {
17681765 }
17691766
17701767 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.
17711769 self.freeTextBlock(&decl.link);
17721770 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 {};
17751773
17761774 self.local_symbols.items[decl.link.local_sym_index].st_info = 0;
17771775
17781776 decl.link.local_sym_index = 0;
17791777 }
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 }
17801799 }
17811800
17821801 pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
......@@ -1923,18 +1942,35 @@ pub const File = struct {
19231942
19241943 const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];
19251944 const src_fn = &decl.fn_link;
1945 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
19261946 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) {
19281967 // Append new function.
1968 // TODO Look at the free list before appending at the end.
19291969 src_fn.prev = last;
19301970 last.next = src_fn;
19311971 self.dbg_line_fn_last = src_fn;
19321972
19331973 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");
19381974 }
19391975 } else {
19401976 // This is the first function of the Line Number Program.
......@@ -1942,7 +1978,6 @@ pub const File = struct {
19421978 self.dbg_line_fn_last = src_fn;
19431979
19441980 src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den;
1945 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
19461981 }
19471982
19481983 const needed_size = src_fn.off + src_fn.len;
......@@ -1982,10 +2017,7 @@ pub const File = struct {
19822017 const tracy = trace(@src());
19832018 defer tracy.end();
19842019
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.
19872020 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);
19892021 const typed_value = decl.typed_value.most_recent.typed_value;
19902022 if (decl.link.local_sym_index == 0) return;
19912023 const decl_sym = self.local_symbols.items[decl.link.local_sym_index];
......@@ -2052,7 +2084,7 @@ pub const File = struct {
20522084
20532085 pub fn deleteExport(self: *Elf, exp: Export) void {
20542086 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 {};
20562088 self.global_symbols.items[sym_index].st_info = 0;
20572089 }
20582090
......@@ -2284,7 +2316,7 @@ pub const File = struct {
22842316 }
22852317
22862318 /// 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
22882320 /// are less than 126,976 bytes (if this limit is ever reached, this function can be
22892321 /// improved to make more than one pwritev call, or the limit can be raised by a fixed
22902322 /// amount by increasing the length of `vecs`).
......@@ -2361,6 +2393,8 @@ pub const File = struct {
23612393 try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
23622394 }
23632395
2396 const min_nop_size = 2;
2397
23642398 };
23652399};
23662400