authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 20:36:34+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-30 20:36:34+01:00
logea95c74948b6cbc615452c661180874213cb5f9c
tree1132796c12795cea08af7fd88a9cbdc99099b1f8
parentb1a735ac65126c9fb383ae894e31fb53b94ce0b8

elf: encapsulate ZigObject-specific logic in flushModule hook


3 files changed, 153 insertions(+), 140 deletions(-)

src/link/Elf.zig+37-136
...@@ -113,14 +113,6 @@ debug_str_section_index: ?u16 = null,...@@ -113,14 +113,6 @@ debug_str_section_index: ?u16 = null,
113debug_aranges_section_index: ?u16 = null,113debug_aranges_section_index: ?u16 = null,
114debug_line_section_index: ?u16 = null,114debug_line_section_index: ?u16 = null,
115115
116/// Size contribution of Zig's metadata to each debug section.
117/// Used to track start of metadata from input object files.
118debug_info_section_zig_size: u64 = 0,
119debug_abbrev_section_zig_size: u64 = 0,
120debug_str_section_zig_size: u64 = 0,
121debug_aranges_section_zig_size: u64 = 0,
122debug_line_section_zig_size: u64 = 0,
123
124copy_rel_section_index: ?u16 = null,116copy_rel_section_index: ?u16 = null,
125dynamic_section_index: ?u16 = null,117dynamic_section_index: ?u16 = null,
126dynstrtab_section_index: ?u16 = null,118dynstrtab_section_index: ?u16 = null,
...@@ -170,12 +162,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},...@@ -170,12 +162,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
170has_text_reloc: bool = false,162has_text_reloc: bool = false,
171num_ifunc_dynrelocs: usize = 0,163num_ifunc_dynrelocs: usize = 0,
172164
173debug_strtab_dirty: bool = false,
174debug_abbrev_section_dirty: bool = false,
175debug_aranges_section_dirty: bool = false,
176debug_info_header_dirty: bool = false,
177debug_line_header_dirty: bool = false,
178
179error_flags: link.File.ErrorFlags = link.File.ErrorFlags{},165error_flags: link.File.ErrorFlags = link.File.ErrorFlags{},
180misc_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},166misc_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},
181167
...@@ -696,7 +682,8 @@ pub fn initMetadata(self: *Elf) !void {...@@ -696,7 +682,8 @@ pub fn initMetadata(self: *Elf) !void {
696 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});682 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
697 }683 }
698684
699 if (self.zigObjectPtr().?.dwarf) |*dw| {685 const zig_object = self.zigObjectPtr().?;
686 if (zig_object.dwarf) |*dw| {
700 if (self.debug_str_section_index == null) {687 if (self.debug_str_section_index == null) {
701 assert(dw.strtab.buffer.items.len == 0);688 assert(dw.strtab.buffer.items.len == 0);
702 try dw.strtab.buffer.append(gpa, 0);689 try dw.strtab.buffer.append(gpa, 0);
...@@ -706,7 +693,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -706,7 +693,7 @@ pub fn initMetadata(self: *Elf) !void {
706 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,693 .flags = elf.SHF_MERGE | elf.SHF_STRINGS,
707 .entsize = 1,694 .entsize = 1,
708 });695 });
709 self.debug_strtab_dirty = true;696 zig_object.debug_strtab_dirty = true;
710 }697 }
711698
712 if (self.debug_info_section_index == null) {699 if (self.debug_info_section_index == null) {
...@@ -715,7 +702,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -715,7 +702,7 @@ pub fn initMetadata(self: *Elf) !void {
715 .size = 200,702 .size = 200,
716 .alignment = 1,703 .alignment = 1,
717 });704 });
718 self.debug_info_header_dirty = true;705 zig_object.debug_info_header_dirty = true;
719 }706 }
720707
721 if (self.debug_abbrev_section_index == null) {708 if (self.debug_abbrev_section_index == null) {
...@@ -724,7 +711,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -724,7 +711,7 @@ pub fn initMetadata(self: *Elf) !void {
724 .size = 128,711 .size = 128,
725 .alignment = 1,712 .alignment = 1,
726 });713 });
727 self.debug_abbrev_section_dirty = true;714 zig_object.debug_abbrev_section_dirty = true;
728 }715 }
729716
730 if (self.debug_aranges_section_index == null) {717 if (self.debug_aranges_section_index == null) {
...@@ -733,7 +720,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -733,7 +720,7 @@ pub fn initMetadata(self: *Elf) !void {
733 .size = 160,720 .size = 160,
734 .alignment = 16,721 .alignment = 16,
735 });722 });
736 self.debug_aranges_section_dirty = true;723 zig_object.debug_aranges_section_dirty = true;
737 }724 }
738725
739 if (self.debug_line_section_index == null) {726 if (self.debug_line_section_index == null) {
...@@ -742,7 +729,7 @@ pub fn initMetadata(self: *Elf) !void {...@@ -742,7 +729,7 @@ pub fn initMetadata(self: *Elf) !void {
742 .size = 250,729 .size = 250,
743 .alignment = 1,730 .alignment = 1,
744 });731 });
745 self.debug_line_header_dirty = true;732 zig_object.debug_line_header_dirty = true;
746 }733 }
747 }734 }
748}735}
...@@ -833,17 +820,18 @@ pub fn growNonAllocSection(...@@ -833,17 +820,18 @@ pub fn growNonAllocSection(
833}820}
834821
835pub fn markDirty(self: *Elf, shdr_index: u16) void {822pub fn markDirty(self: *Elf, shdr_index: u16) void {
836 if (self.zigObjectPtr().?.dwarf) |_| {823 const zig_object = self.zigObjectPtr().?;
824 if (zig_object.dwarf) |_| {
837 if (self.debug_info_section_index.? == shdr_index) {825 if (self.debug_info_section_index.? == shdr_index) {
838 self.debug_info_header_dirty = true;826 zig_object.debug_info_header_dirty = true;
839 } else if (self.debug_line_section_index.? == shdr_index) {827 } else if (self.debug_line_section_index.? == shdr_index) {
840 self.debug_line_header_dirty = true;828 zig_object.debug_line_header_dirty = true;
841 } else if (self.debug_abbrev_section_index.? == shdr_index) {829 } else if (self.debug_abbrev_section_index.? == shdr_index) {
842 self.debug_abbrev_section_dirty = true;830 zig_object.debug_abbrev_section_dirty = true;
843 } else if (self.debug_str_section_index.? == shdr_index) {831 } else if (self.debug_str_section_index.? == shdr_index) {
844 self.debug_strtab_dirty = true;832 zig_object.debug_strtab_dirty = true;
845 } else if (self.debug_aranges_section_index.? == shdr_index) {833 } else if (self.debug_aranges_section_index.? == shdr_index) {
846 self.debug_aranges_section_dirty = true;834 zig_object.debug_aranges_section_dirty = true;
847 }835 }
848 }836 }
849}837}
...@@ -1343,39 +1331,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1343,39 +1331,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1343 try self.handleAndReportParseError(obj.path, err, &parse_ctx);1331 try self.handleAndReportParseError(obj.path, err, &parse_ctx);
1344 }1332 }
13451333
1346 if (self.zigObjectPtr()) |zig_object| {1334 if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self);
1347 // Handle any lazy symbols that were emitted by incremental compilation.
1348 if (zig_object.lazy_syms.getPtr(.none)) |metadata| {
1349 const module = self.base.options.module.?;
1350
1351 // Most lazy symbols can be updated on first use, but
1352 // anyerror needs to wait for everything to be flushed.
1353 if (metadata.text_state != .unused) zig_object.updateLazySymbol(
1354 self,
1355 link.File.LazySymbol.initDecl(.code, null, module),
1356 metadata.text_symbol_index,
1357 ) catch |err| return switch (err) {
1358 error.CodegenFail => error.FlushFailure,
1359 else => |e| e,
1360 };
1361 if (metadata.rodata_state != .unused) zig_object.updateLazySymbol(
1362 self,
1363 link.File.LazySymbol.initDecl(.const_data, null, module),
1364 metadata.rodata_symbol_index,
1365 ) catch |err| return switch (err) {
1366 error.CodegenFail => error.FlushFailure,
1367 else => |e| e,
1368 };
1369 }
1370 for (zig_object.lazy_syms.values()) |*metadata| {
1371 if (metadata.text_state != .unused) metadata.text_state = .flushed;
1372 if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
1373 }
1374
1375 if (zig_object.dwarf) |*dw| {
1376 try dw.flushModule(self.base.options.module.?);
1377 }
1378 }
13791335
1380 // Dedup shared objects1336 // Dedup shared objects
1381 {1337 {
...@@ -1437,47 +1393,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1437,47 +1393,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1437 // Scan and create missing synthetic entries such as GOT indirection.1393 // Scan and create missing synthetic entries such as GOT indirection.
1438 try self.scanRelocs();1394 try self.scanRelocs();
14391395
1440 if (self.zigObjectPtr()) |zig_object| {
1441 // TODO I need to re-think how to handle ZigObject's debug sections AND debug sections
1442 // extracted from input object files correctly.
1443 if (zig_object.dwarf) |*dw| {
1444 if (self.debug_abbrev_section_dirty) {
1445 try dw.writeDbgAbbrev();
1446 self.debug_abbrev_section_dirty = false;
1447 }
1448
1449 if (self.debug_info_header_dirty) {
1450 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1451 const low_pc = text_phdr.p_vaddr;
1452 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
1453 try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc);
1454 self.debug_info_header_dirty = false;
1455 }
1456
1457 if (self.debug_aranges_section_dirty) {
1458 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1459 try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
1460 self.debug_aranges_section_dirty = false;
1461 }
1462
1463 if (self.debug_line_header_dirty) {
1464 try dw.writeDbgLineHeader();
1465 self.debug_line_header_dirty = false;
1466 }
1467
1468 if (self.debug_str_section_index) |shndx| {
1469 if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != self.shdrs.items[shndx].sh_size) {
1470 try self.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
1471 const shdr = self.shdrs.items[shndx];
1472 try self.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
1473 self.debug_strtab_dirty = false;
1474 }
1475 }
1476
1477 self.saveDebugSectionsSizes();
1478 }
1479 }
1480
1481 // Generate and emit non-incremental sections.1396 // Generate and emit non-incremental sections.
1482 try self.initSections();1397 try self.initSections();
1483 try self.initSpecialPhdrs();1398 try self.initSpecialPhdrs();
...@@ -1542,14 +1457,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1542,14 +1457,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1542 self.error_flags.no_entry_point_found = false;1457 self.error_flags.no_entry_point_found = false;
1543 try self.writeHeader();1458 try self.writeHeader();
1544 }1459 }
1545
1546 // The point of flush() is to commit changes, so in theory, nothing should
1547 // be dirty after this. However, it is possible for some things to remain
1548 // dirty because they fail to be written in the event of compile errors,
1549 // such as debug_line_header_dirty and debug_info_header_dirty.
1550 assert(!self.debug_abbrev_section_dirty);
1551 assert(!self.debug_aranges_section_dirty);
1552 assert(!self.debug_strtab_dirty);
1553}1460}
15541461
1555const ParseError = error{1462const ParseError = error{
...@@ -3815,24 +3722,6 @@ fn sortShdrs(self: *Elf) !void {...@@ -3815,24 +3722,6 @@ fn sortShdrs(self: *Elf) !void {
3815 }3722 }
3816}3723}
38173724
3818fn saveDebugSectionsSizes(self: *Elf) void {
3819 if (self.debug_info_section_index) |shndx| {
3820 self.debug_info_section_zig_size = self.shdrs.items[shndx].sh_size;
3821 }
3822 if (self.debug_abbrev_section_index) |shndx| {
3823 self.debug_abbrev_section_zig_size = self.shdrs.items[shndx].sh_size;
3824 }
3825 if (self.debug_str_section_index) |shndx| {
3826 self.debug_str_section_zig_size = self.shdrs.items[shndx].sh_size;
3827 }
3828 if (self.debug_aranges_section_index) |shndx| {
3829 self.debug_aranges_section_zig_size = self.shdrs.items[shndx].sh_size;
3830 }
3831 if (self.debug_line_section_index) |shndx| {
3832 self.debug_line_section_zig_size = self.shdrs.items[shndx].sh_size;
3833 }
3834}
3835
3836fn updateSectionSizes(self: *Elf) !void {3725fn updateSectionSizes(self: *Elf) !void {
3837 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {3726 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
3838 if (atom_list.items.len == 0) continue;3727 if (atom_list.items.len == 0) continue;
...@@ -4189,12 +4078,18 @@ fn allocateNonAllocSections(self: *Elf) !void {...@@ -4189,12 +4078,18 @@ fn allocateNonAllocSections(self: *Elf) !void {
4189 shdr.sh_offset,4078 shdr.sh_offset,
4190 new_offset,4079 new_offset,
4191 });4080 });
4081 const zig_object = self.zigObjectPtr().?;
4192 const existing_size = blk: {4082 const existing_size = blk: {
4193 if (shndx == self.debug_info_section_index.?) break :blk self.debug_info_section_zig_size;4083 if (shndx == self.debug_info_section_index.?)
4194 if (shndx == self.debug_abbrev_section_index.?) break :blk self.debug_abbrev_section_zig_size;4084 break :blk zig_object.debug_info_section_zig_size;
4195 if (shndx == self.debug_str_section_index.?) break :blk self.debug_str_section_zig_size;4085 if (shndx == self.debug_abbrev_section_index.?)
4196 if (shndx == self.debug_aranges_section_index.?) break :blk self.debug_aranges_section_zig_size;4086 break :blk zig_object.debug_abbrev_section_zig_size;
4197 if (shndx == self.debug_line_section_index.?) break :blk self.debug_line_section_zig_size;4087 if (shndx == self.debug_str_section_index.?)
4088 break :blk zig_object.debug_str_section_zig_size;
4089 if (shndx == self.debug_aranges_section_index.?)
4090 break :blk zig_object.debug_aranges_section_zig_size;
4091 if (shndx == self.debug_line_section_index.?)
4092 break :blk zig_object.debug_line_section_zig_size;
4198 unreachable;4093 unreachable;
4199 };4094 };
4200 const amt = try self.base.file.?.copyRangeAll(4095 const amt = try self.base.file.?.copyRangeAll(
...@@ -4296,11 +4191,17 @@ fn writeAtoms(self: *Elf) !void {...@@ -4296,11 +4191,17 @@ fn writeAtoms(self: *Elf) !void {
42964191
4297 // TODO really, really handle debug section separately4192 // TODO really, really handle debug section separately
4298 const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: {4193 const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: {
4299 if (shndx == self.debug_info_section_index.?) break :blk self.debug_info_section_zig_size;4194 const zig_object = self.zigObjectPtr().?;
4300 if (shndx == self.debug_abbrev_section_index.?) break :blk self.debug_abbrev_section_zig_size;4195 if (shndx == self.debug_info_section_index.?)
4301 if (shndx == self.debug_str_section_index.?) break :blk self.debug_str_section_zig_size;4196 break :blk zig_object.debug_info_section_zig_size;
4302 if (shndx == self.debug_aranges_section_index.?) break :blk self.debug_aranges_section_zig_size;4197 if (shndx == self.debug_abbrev_section_index.?)
4303 if (shndx == self.debug_line_section_index.?) break :blk self.debug_line_section_zig_size;4198 break :blk zig_object.debug_abbrev_section_zig_size;
4199 if (shndx == self.debug_str_section_index.?)
4200 break :blk zig_object.debug_str_section_zig_size;
4201 if (shndx == self.debug_aranges_section_index.?)
4202 break :blk zig_object.debug_aranges_section_zig_size;
4203 if (shndx == self.debug_line_section_index.?)
4204 break :blk zig_object.debug_line_section_zig_size;
4304 unreachable;4205 unreachable;
4305 } else 0;4206 } else 0;
4306 const sh_offset = shdr.sh_offset + base_offset;4207 const sh_offset = shdr.sh_offset + base_offset;
src/link/Elf/Atom.zig+4-3
...@@ -166,15 +166,16 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {...@@ -166,15 +166,16 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
166 try elf_file.growAllocSection(self.outputShndx().?, needed_size);166 try elf_file.growAllocSection(self.outputShndx().?, needed_size);
167 last_atom_index.* = self.atom_index;167 last_atom_index.* = self.atom_index;
168168
169 if (elf_file.zigObjectPtr().?.dwarf) |_| {169 const zig_object = elf_file.zigObjectPtr().?;
170 if (zig_object.dwarf) |_| {
170 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address171 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address
171 // range of the compilation unit. When we expand the text section, this range changes,172 // range of the compilation unit. When we expand the text section, this range changes,
172 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.173 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.
173 elf_file.debug_info_header_dirty = true;174 zig_object.debug_info_header_dirty = true;
174 // This becomes dirty for the same reason. We could potentially make this more175 // This becomes dirty for the same reason. We could potentially make this more
175 // fine-grained with the addition of support for more compilation units. It is planned to176 // fine-grained with the addition of support for more compilation units. It is planned to
176 // model each package as a different compilation unit.177 // model each package as a different compilation unit.
177 elf_file.debug_aranges_section_dirty = true;178 zig_object.debug_aranges_section_dirty = true;
178 }179 }
179 }180 }
180 shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnitsOptional().?);181 shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnitsOptional().?);
src/link/Elf/ZigObject.zig+112-1
...@@ -52,6 +52,20 @@ unnamed_consts: UnnamedConstTable = .{},...@@ -52,6 +52,20 @@ unnamed_consts: UnnamedConstTable = .{},
52/// Table of tracked AnonDecls.52/// Table of tracked AnonDecls.
53anon_decls: AnonDeclTable = .{},53anon_decls: AnonDeclTable = .{},
5454
55debug_strtab_dirty: bool = false,
56debug_abbrev_section_dirty: bool = false,
57debug_aranges_section_dirty: bool = false,
58debug_info_header_dirty: bool = false,
59debug_line_header_dirty: bool = false,
60
61/// Size contribution of Zig's metadata to each debug section.
62/// Used to track start of metadata from input object files.
63debug_info_section_zig_size: u64 = 0,
64debug_abbrev_section_zig_size: u64 = 0,
65debug_str_section_zig_size: u64 = 0,
66debug_aranges_section_zig_size: u64 = 0,
67debug_line_section_zig_size: u64 = 0,
68
55pub const global_symbol_bit: u32 = 0x80000000;69pub const global_symbol_bit: u32 = 0x80000000;
56pub const symbol_mask: u32 = 0x7fffffff;70pub const symbol_mask: u32 = 0x7fffffff;
57pub const SHN_ATOM: u16 = 0x100;71pub const SHN_ATOM: u16 = 0x100;
...@@ -123,6 +137,103 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {...@@ -123,6 +137,103 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
123 }137 }
124}138}
125139
140pub fn flushModule(self: *ZigObject, elf_file: *Elf) !void {
141 // Handle any lazy symbols that were emitted by incremental compilation.
142 if (self.lazy_syms.getPtr(.none)) |metadata| {
143 const module = elf_file.base.options.module.?;
144
145 // Most lazy symbols can be updated on first use, but
146 // anyerror needs to wait for everything to be flushed.
147 if (metadata.text_state != .unused) self.updateLazySymbol(
148 elf_file,
149 link.File.LazySymbol.initDecl(.code, null, module),
150 metadata.text_symbol_index,
151 ) catch |err| return switch (err) {
152 error.CodegenFail => error.FlushFailure,
153 else => |e| e,
154 };
155 if (metadata.rodata_state != .unused) self.updateLazySymbol(
156 elf_file,
157 link.File.LazySymbol.initDecl(.const_data, null, module),
158 metadata.rodata_symbol_index,
159 ) catch |err| return switch (err) {
160 error.CodegenFail => error.FlushFailure,
161 else => |e| e,
162 };
163 }
164 for (self.lazy_syms.values()) |*metadata| {
165 if (metadata.text_state != .unused) metadata.text_state = .flushed;
166 if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
167 }
168
169 if (self.dwarf) |*dw| {
170 try dw.flushModule(elf_file.base.options.module.?);
171
172 // TODO I need to re-think how to handle ZigObject's debug sections AND debug sections
173 // extracted from input object files correctly.
174 if (self.debug_abbrev_section_dirty) {
175 try dw.writeDbgAbbrev();
176 self.debug_abbrev_section_dirty = false;
177 }
178
179 if (self.debug_info_header_dirty) {
180 const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?];
181 const low_pc = text_phdr.p_vaddr;
182 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
183 try dw.writeDbgInfoHeader(elf_file.base.options.module.?, low_pc, high_pc);
184 self.debug_info_header_dirty = false;
185 }
186
187 if (self.debug_aranges_section_dirty) {
188 const text_phdr = &elf_file.phdrs.items[elf_file.phdr_zig_load_re_index.?];
189 try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
190 self.debug_aranges_section_dirty = false;
191 }
192
193 if (self.debug_line_header_dirty) {
194 try dw.writeDbgLineHeader();
195 self.debug_line_header_dirty = false;
196 }
197
198 if (elf_file.debug_str_section_index) |shndx| {
199 if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != elf_file.shdrs.items[shndx].sh_size) {
200 try elf_file.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
201 const shdr = elf_file.shdrs.items[shndx];
202 try elf_file.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
203 self.debug_strtab_dirty = false;
204 }
205 }
206
207 self.saveDebugSectionsSizes(elf_file);
208 }
209
210 // The point of flushModule() is to commit changes, so in theory, nothing should
211 // be dirty after this. However, it is possible for some things to remain
212 // dirty because they fail to be written in the event of compile errors,
213 // such as debug_line_header_dirty and debug_info_header_dirty.
214 assert(!self.debug_abbrev_section_dirty);
215 assert(!self.debug_aranges_section_dirty);
216 assert(!self.debug_strtab_dirty);
217}
218
219fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void {
220 if (elf_file.debug_info_section_index) |shndx| {
221 self.debug_info_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
222 }
223 if (elf_file.debug_abbrev_section_index) |shndx| {
224 self.debug_abbrev_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
225 }
226 if (elf_file.debug_str_section_index) |shndx| {
227 self.debug_str_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
228 }
229 if (elf_file.debug_aranges_section_index) |shndx| {
230 self.debug_aranges_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
231 }
232 if (elf_file.debug_line_section_index) |shndx| {
233 self.debug_line_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
234 }
235}
236
126pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {237pub fn addLocalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
127 try self.local_esyms.ensureUnusedCapacity(allocator, 1);238 try self.local_esyms.ensureUnusedCapacity(allocator, 1);
128 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));239 const index = @as(Symbol.Index, @intCast(self.local_esyms.addOneAssumeCapacity()));
...@@ -837,7 +948,7 @@ pub fn updateDecl(...@@ -837,7 +948,7 @@ pub fn updateDecl(
837 return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));948 return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
838}949}
839950
840pub fn updateLazySymbol(951fn updateLazySymbol(
841 self: *ZigObject,952 self: *ZigObject,
842 elf_file: *Elf,953 elf_file: *Elf,
843 sym: link.File.LazySymbol,954 sym: link.File.LazySymbol,