diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-27 15:07:05 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-09-27 15:07:05 +0200 |
| commit | 09863fc97043f3aadcad476c3eda8f3e3dde18dd (patch) | |
| tree | 9c991287ed9fb02d66e3450d6cefb047fc426c37 /src | |
| parent | e178580d864407864ebb4d95bb28b041b7b0870a (diff) | |
| download | zig-09863fc97043f3aadcad476c3eda8f3e3dde18dd.tar.gz zig-09863fc97043f3aadcad476c3eda8f3e3dde18dd.zip | |
elf: emit fatal linker error if we run out of VM space with self-hosted backends
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index aefac433f7..430adeb527 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -857,6 +857,17 @@ pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { // TODO mark relocs dirty } try self.growSegment(shdr_index, needed_size); + + if (self.zig_module_index != null) { + // TODO self-hosted backends cannot yet handle this condition correctly as the linker + // cannot update emitted virtual addresses of symbols already committed to the final file. + var err = try self.addErrorWithNotes(2); + try err.addMsg(self, "fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{ + phdr_index, + }); + try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); + try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); + } } shdr.sh_size = needed_size; @@ -3972,6 +3983,46 @@ pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupO return &self.comdat_groups_owners.items[index]; } +const ErrorWithNotes = struct { + /// Allocated index in misc_errors array. + index: usize, + + /// Next available note slot. + note_slot: usize = 0, + + pub fn addMsg( + err: ErrorWithNotes, + elf_file: *Elf, + comptime format: []const u8, + args: anytype, + ) error{OutOfMemory}!void { + const gpa = elf_file.base.allocator; + const err_msg = &elf_file.misc_errors.items[err.index]; + err_msg.msg = try std.fmt.allocPrint(gpa, format, args); + } + + pub fn addNote( + err: *ErrorWithNotes, + elf_file: *Elf, + comptime format: []const u8, + args: anytype, + ) error{OutOfMemory}!void { + const gpa = elf_file.base.allocator; + const err_msg = &elf_file.misc_errors.items[err.index]; + assert(err.note_slot < err_msg.notes.len); + err_msg.notes[err.note_slot] = .{ .msg = try std.fmt.allocPrint(gpa, format, args) }; + err.note_slot += 1; + } +}; + +fn addErrorWithNotes(self: *Elf, note_count: usize) error{OutOfMemory}!ErrorWithNotes { + const gpa = self.base.allocator; + const index = self.misc_errors.items.len; + const err = try self.misc_errors.addOne(gpa); + err.* = .{ .msg = undefined, .notes = try gpa.alloc(link.File.ErrorMsg, note_count) }; + return .{ .index = index }; +} + fn reportUndefined(self: *Elf, undefs: anytype) !void { const gpa = self.base.allocator; const max_notes = 4; |
