authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-08-02 20:46:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-05 11:25:08-07:00
loga5b76d2474c5d1cbbb1c08def6b30ad1836da3bc
tree8abd88d04d2393cefc77766a0992439d9572506d
parentcf4936bcb0d48df5578efe76156c5c7ffc0d7b1e

Stage2: minor File.ELF refactor


3 files changed, 130 insertions(+), 146 deletions(-)

src-self-hosted/codegen.zig+13-12
......@@ -134,7 +134,7 @@ pub fn generateSymbol(
134134 }
135135 return Result{
136136 .fail = try ErrorMsg.create(
137 bin_file.allocator,
137 bin_file.base.allocator,
138138 src,
139139 "TODO implement generateSymbol for more kinds of arrays",
140140 .{},
......@@ -150,21 +150,22 @@ pub fn generateSymbol(
150150 // If the decl changes vaddr, then this symbol needs to get regenerated.
151151 const vaddr = bin_file.local_symbols.items[decl.link.local_sym_index].st_value;
152152 const endian = bin_file.base.options.target.cpu.arch.endian();
153 switch (bin_file.ptr_width) {
154 .p32 => {
153 switch (bin_file.base.options.target.cpu.arch.ptrBitWidth()) {
154 32 => {
155155 try code.resize(4);
156156 mem.writeInt(u32, code.items[0..4], @intCast(u32, vaddr), endian);
157157 },
158 .p64 => {
158 64 => {
159159 try code.resize(8);
160160 mem.writeInt(u64, code.items[0..8], vaddr, endian);
161161 },
162 else => unreachable,
162163 }
163164 return Result{ .appended = {} };
164165 }
165166 return Result{
166167 .fail = try ErrorMsg.create(
167 bin_file.allocator,
168 bin_file.base.allocator,
168169 src,
169170 "TODO implement generateSymbol for pointer {}",
170171 .{typed_value.val},
......@@ -180,7 +181,7 @@ pub fn generateSymbol(
180181 }
181182 return Result{
182183 .fail = try ErrorMsg.create(
183 bin_file.allocator,
184 bin_file.base.allocator,
184185 src,
185186 "TODO implement generateSymbol for int type '{}'",
186187 .{typed_value.ty},
......@@ -190,7 +191,7 @@ pub fn generateSymbol(
190191 else => |t| {
191192 return Result{
192193 .fail = try ErrorMsg.create(
193 bin_file.allocator,
194 bin_file.base.allocator,
194195 src,
195196 "TODO implement generateSymbol for type '{}'",
196197 .{@tagName(t)},
......@@ -387,10 +388,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
387388
388389 const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty;
389390
390 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
391 var branch_stack = std.ArrayList(Branch).init(bin_file.base.allocator);
391392 defer {
392393 assert(branch_stack.items.len == 1);
393 branch_stack.items[0].deinit(bin_file.allocator);
394 branch_stack.items[0].deinit(bin_file.base.allocator);
394395 branch_stack.deinit();
395396 }
396397 const branch = try branch_stack.addOne();
......@@ -413,7 +414,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
413414 };
414415
415416 var function = Self{
416 .gpa = bin_file.allocator,
417 .gpa = bin_file.base.allocator,
417418 .target = &bin_file.base.options.target,
418419 .bin_file = bin_file,
419420 .mod_fn = module_fn,
......@@ -432,7 +433,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
432433 .rbrace_src = src_data.rbrace_src,
433434 .source = src_data.source,
434435 };
435 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
436 defer function.exitlude_jump_relocs.deinit(bin_file.base.allocator);
436437
437438 var call_info = function.resolveCallingConventionValues(src, fn_type) catch |err| switch (err) {
438439 error.CodegenFail => return Result{ .fail = function.err_msg.? },
......@@ -2054,7 +2055,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
20542055 fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) error{ CodegenFail, OutOfMemory } {
20552056 @setCold(true);
20562057 assert(self.err_msg == null);
2057 self.err_msg = try ErrorMsg.create(self.bin_file.allocator, src, format, args);
2058 self.err_msg = try ErrorMsg.create(self.bin_file.base.allocator, src, format, args);
20582059 return error.CodegenFail;
20592060 }
20602061
src-self-hosted/codegen/c.zig+4-4
......@@ -44,8 +44,8 @@ fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !
4444fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
4545 const tv = decl.typed_value.most_recent.typed_value;
4646 try renderType(file, writer, tv.ty.fnReturnType(), decl.src());
47 const name = try map(file.allocator, mem.spanZ(decl.name));
48 defer file.allocator.free(name);
47 const name = try map(file.base.allocator, mem.spanZ(decl.name));
48 defer file.base.allocator.free(name);
4949 try writer.print(" {}(", .{name});
5050 if (tv.ty.fnParamLen() == 0)
5151 try writer.writeAll("void)")
......@@ -64,8 +64,8 @@ pub fn generate(file: *C, decl: *Decl) !void {
6464fn genArray(file: *C, decl: *Decl) !void {
6565 const tv = decl.typed_value.most_recent.typed_value;
6666 // TODO: prevent inline asm constants from being emitted
67 const name = try map(file.allocator, mem.span(decl.name));
68 defer file.allocator.free(name);
67 const name = try map(file.base.allocator, mem.span(decl.name));
68 defer file.base.allocator.free(name);
6969 if (tv.val.cast(Value.Payload.Bytes)) |payload|
7070 if (tv.ty.arraySentinel()) |sentinel|
7171 if (sentinel.toUnsignedInt() == 0)
src-self-hosted/link.zig+113-130
......@@ -36,9 +36,12 @@ pub const Options = struct {
3636 program_code_size_hint: u64 = 256 * 1024,
3737};
3838
39
3940pub const File = struct {
4041 tag: Tag,
4142 options: Options,
43 file: ?fs.File,
44 allocator: *Allocator,
4245
4346 /// Attempts incremental linking, if the file already exists. If
4447 /// incremental linking fails, falls back to truncating the file and
......@@ -66,15 +69,23 @@ pub const File = struct {
6669
6770 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
6871 switch (base.tag) {
69 .elf => return @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
72 .elf => {
73 if (base.file != null) return;
74 base.file = try dir.createFile(sub_path, .{
75 .truncate = false,
76 .read = true,
77 .mode = determineMode(base.options),
78 });
79 },
7080 .c => {},
7181 }
7282 }
7383
7484 pub fn makeExecutable(base: *File) !void {
75 switch (base.tag) {
76 .elf => return @fieldParentPtr(Elf, "base", base).makeExecutable(),
77 .c => unreachable,
85 std.debug.assert(base.tag != .c);
86 if (base.file) |f| {
87 f.close();
88 base.file = null;
7889 }
7990 }
8091
......@@ -100,6 +111,7 @@ pub const File = struct {
100111 }
101112
102113 pub fn deinit(base: *File) void {
114 if (base.file) |f| f.close();
103115 switch (base.tag) {
104116 .elf => @fieldParentPtr(Elf, "base", base).deinit(),
105117 .c => @fieldParentPtr(C, "base", base).deinit(),
......@@ -111,12 +123,12 @@ pub const File = struct {
111123 .elf => {
112124 const parent = @fieldParentPtr(Elf, "base", base);
113125 parent.deinit();
114 parent.allocator.destroy(parent);
126 base.allocator.destroy(parent);
115127 },
116128 .c => {
117129 const parent = @fieldParentPtr(C, "base", base);
118130 parent.deinit();
119 parent.allocator.destroy(parent);
131 base.allocator.destroy(parent);
120132 },
121133 }
122134 }
......@@ -172,11 +184,10 @@ pub const File = struct {
172184
173185 base: File,
174186
175 allocator: *Allocator,
176187 header: std.ArrayList(u8),
177188 constants: std.ArrayList(u8),
178189 main: std.ArrayList(u8),
179 file: ?fs.File,
190
180191 called: std.StringHashMap(void),
181192 need_stddef: bool = false,
182193 need_stdint: bool = false,
......@@ -196,9 +207,9 @@ pub const File = struct {
196207 .base = .{
197208 .tag = .c,
198209 .options = options,
210 .file = file,
211 .allocator = allocator,
199212 },
200 .allocator = allocator,
201 .file = file,
202213 .main = std.ArrayList(u8).init(allocator),
203214 .header = std.ArrayList(u8).init(allocator),
204215 .constants = std.ArrayList(u8).init(allocator),
......@@ -209,7 +220,7 @@ pub const File = struct {
209220 }
210221
211222 pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) !void {
212 self.error_msg = try Module.ErrorMsg.create(self.allocator, src, format, args);
223 self.error_msg = try Module.ErrorMsg.create(self.base.allocator, src, format, args);
213224 return error.AnalysisFail;
214225 }
215226
......@@ -218,8 +229,6 @@ pub const File = struct {
218229 self.header.deinit();
219230 self.constants.deinit();
220231 self.called.deinit();
221 if (self.file) |f|
222 f.close();
223232 }
224233
225234 pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {
......@@ -232,7 +241,7 @@ pub const File = struct {
232241 }
233242
234243 pub fn flush(self: *File.C) !void {
235 const writer = self.file.?.writer();
244 const writer = self.base.file.?.writer();
236245 try writer.writeAll(@embedFile("cbe.h"));
237246 var includes = false;
238247 if (self.need_stddef) {
......@@ -259,8 +268,8 @@ pub const File = struct {
259268 }
260269 }
261270 try writer.writeAll(self.main.items);
262 self.file.?.close();
263 self.file = null;
271 self.base.file.?.close();
272 self.base.file = null;
264273 }
265274 };
266275
......@@ -269,9 +278,6 @@ pub const File = struct {
269278
270279 base: File,
271280
272 allocator: *Allocator,
273 file: ?fs.File,
274 owns_file_handle: bool,
275281 ptr_width: enum { p32, p64 },
276282
277283 /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
......@@ -454,7 +460,6 @@ pub const File = struct {
454460 else => |e| return e,
455461 };
456462
457 elf_file.owns_file_handle = true;
458463 return &elf_file.base;
459464 }
460465
......@@ -467,12 +472,11 @@ pub const File = struct {
467472 }
468473 var self: Elf = .{
469474 .base = .{
475 .file = file,
470476 .tag = .elf,
471477 .options = options,
478 .allocator = allocator,
472479 },
473 .allocator = allocator,
474 .file = file,
475 .owns_file_handle = false,
476480 .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
477481 32 => .p32,
478482 64 => .p64,
......@@ -499,16 +503,15 @@ pub const File = struct {
499503 .base = .{
500504 .tag = .elf,
501505 .options = options,
506 .allocator = allocator,
507 .file = file,
502508 },
503 .allocator = allocator,
504 .file = file,
505509 .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
506510 32 => .p32,
507511 64 => .p64,
508512 else => return error.UnsupportedELFArchitecture,
509513 },
510514 .shdr_table_dirty = true,
511 .owns_file_handle = false,
512515 };
513516 errdefer self.deinit();
514517
......@@ -542,39 +545,18 @@ pub const File = struct {
542545 }
543546
544547 pub fn deinit(self: *Elf) void {
545 self.sections.deinit(self.allocator);
546 self.program_headers.deinit(self.allocator);
547 self.shstrtab.deinit(self.allocator);
548 self.debug_strtab.deinit(self.allocator);
549 self.local_symbols.deinit(self.allocator);
550 self.global_symbols.deinit(self.allocator);
551 self.global_symbol_free_list.deinit(self.allocator);
552 self.local_symbol_free_list.deinit(self.allocator);
553 self.offset_table_free_list.deinit(self.allocator);
554 self.text_block_free_list.deinit(self.allocator);
555 self.dbg_line_fn_free_list.deinit(self.allocator);
556 self.offset_table.deinit(self.allocator);
557 if (self.owns_file_handle) {
558 if (self.file) |f| f.close();
559 }
560 }
561
562 pub fn makeExecutable(self: *Elf) !void {
563 assert(self.owns_file_handle);
564 if (self.file) |f| {
565 f.close();
566 self.file = null;
567 }
568 }
569
570 pub fn makeWritable(self: *Elf, dir: fs.Dir, sub_path: []const u8) !void {
571 assert(self.owns_file_handle);
572 if (self.file != null) return;
573 self.file = try dir.createFile(sub_path, .{
574 .truncate = false,
575 .read = true,
576 .mode = determineMode(self.base.options),
577 });
548 self.sections.deinit(self.base.allocator);
549 self.program_headers.deinit(self.base.allocator);
550 self.shstrtab.deinit(self.base.allocator);
551 self.debug_strtab.deinit(self.base.allocator);
552 self.local_symbols.deinit(self.base.allocator);
553 self.global_symbols.deinit(self.base.allocator);
554 self.global_symbol_free_list.deinit(self.base.allocator);
555 self.local_symbol_free_list.deinit(self.base.allocator);
556 self.offset_table_free_list.deinit(self.base.allocator);
557 self.text_block_free_list.deinit(self.base.allocator);
558 self.dbg_line_fn_free_list.deinit(self.base.allocator);
559 self.offset_table.deinit(self.base.allocator);
578560 }
579561
580562 fn getDebugLineProgramOff(self: Elf) u32 {
......@@ -662,7 +644,7 @@ pub const File = struct {
662644
663645 /// TODO Improve this to use a table.
664646 fn makeString(self: *Elf, bytes: []const u8) !u32 {
665 try self.shstrtab.ensureCapacity(self.allocator, self.shstrtab.items.len + bytes.len + 1);
647 try self.shstrtab.ensureCapacity(self.base.allocator, self.shstrtab.items.len + bytes.len + 1);
666648 const result = self.shstrtab.items.len;
667649 self.shstrtab.appendSliceAssumeCapacity(bytes);
668650 self.shstrtab.appendAssumeCapacity(0);
......@@ -671,7 +653,7 @@ pub const File = struct {
671653
672654 /// TODO Improve this to use a table.
673655 fn makeDebugString(self: *Elf, bytes: []const u8) !u32 {
674 try self.debug_strtab.ensureCapacity(self.allocator, self.debug_strtab.items.len + bytes.len + 1);
656 try self.debug_strtab.ensureCapacity(self.base.allocator, self.debug_strtab.items.len + bytes.len + 1);
675657 const result = self.debug_strtab.items.len;
676658 self.debug_strtab.appendSliceAssumeCapacity(bytes);
677659 self.debug_strtab.appendAssumeCapacity(0);
......@@ -703,7 +685,7 @@ pub const File = struct {
703685 const p_align = 0x1000;
704686 const off = self.findFreeSpace(file_size, p_align);
705687 log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
706 try self.program_headers.append(self.allocator, .{
688 try self.program_headers.append(self.base.allocator, .{
707689 .p_type = elf.PT_LOAD,
708690 .p_offset = off,
709691 .p_filesz = file_size,
......@@ -721,14 +703,14 @@ pub const File = struct {
721703 const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint;
722704 // We really only need ptr alignment but since we are using PROGBITS, linux requires
723705 // page align.
724 const p_align = 0x1000;
706 const p_align = if (self.base.options.target.os.tag == .linux) 0x1000 else @as(u16, ptr_size);
725707 const off = self.findFreeSpace(file_size, p_align);
726708 log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
727709 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
728710 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something
729711 // else in virtual memory.
730 const default_got_addr = 0x4000000;
731 try self.program_headers.append(self.allocator, .{
712 const default_got_addr = if (ptr_size == 2) @as(u32, 0x8000) else 0x4000000;
713 try self.program_headers.append(self.base.allocator, .{
732714 .p_type = elf.PT_LOAD,
733715 .p_offset = off,
734716 .p_filesz = file_size,
......@@ -743,10 +725,10 @@ pub const File = struct {
743725 if (self.shstrtab_index == null) {
744726 self.shstrtab_index = @intCast(u16, self.sections.items.len);
745727 assert(self.shstrtab.items.len == 0);
746 try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0
728 try self.shstrtab.append(self.base.allocator, 0); // need a 0 at position 0
747729 const off = self.findFreeSpace(self.shstrtab.items.len, 1);
748730 log.debug(.link, "found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
749 try self.sections.append(self.allocator, .{
731 try self.sections.append(self.base.allocator, .{
750732 .sh_name = try self.makeString(".shstrtab"),
751733 .sh_type = elf.SHT_STRTAB,
752734 .sh_flags = 0,
......@@ -765,7 +747,7 @@ pub const File = struct {
765747 self.text_section_index = @intCast(u16, self.sections.items.len);
766748 const phdr = &self.program_headers.items[self.phdr_load_re_index.?];
767749
768 try self.sections.append(self.allocator, .{
750 try self.sections.append(self.base.allocator, .{
769751 .sh_name = try self.makeString(".text"),
770752 .sh_type = elf.SHT_PROGBITS,
771753 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
......@@ -783,7 +765,7 @@ pub const File = struct {
783765 self.got_section_index = @intCast(u16, self.sections.items.len);
784766 const phdr = &self.program_headers.items[self.phdr_got_index.?];
785767
786 try self.sections.append(self.allocator, .{
768 try self.sections.append(self.base.allocator, .{
787769 .sh_name = try self.makeString(".got"),
788770 .sh_type = elf.SHT_PROGBITS,
789771 .sh_flags = elf.SHF_ALLOC,
......@@ -805,7 +787,7 @@ pub const File = struct {
805787 const off = self.findFreeSpace(file_size, min_align);
806788 log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
807789
808 try self.sections.append(self.allocator, .{
790 try self.sections.append(self.base.allocator, .{
809791 .sh_name = try self.makeString(".symtab"),
810792 .sh_type = elf.SHT_SYMTAB,
811793 .sh_flags = 0,
......@@ -824,7 +806,7 @@ pub const File = struct {
824806 if (self.debug_str_section_index == null) {
825807 self.debug_str_section_index = @intCast(u16, self.sections.items.len);
826808 assert(self.debug_strtab.items.len == 0);
827 try self.sections.append(self.allocator, .{
809 try self.sections.append(self.base.allocator, .{
828810 .sh_name = try self.makeString(".debug_str"),
829811 .sh_type = elf.SHT_PROGBITS,
830812 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
......@@ -849,7 +831,7 @@ pub const File = struct {
849831 off,
850832 off + file_size_hint,
851833 });
852 try self.sections.append(self.allocator, .{
834 try self.sections.append(self.base.allocator, .{
853835 .sh_name = try self.makeString(".debug_info"),
854836 .sh_type = elf.SHT_PROGBITS,
855837 .sh_flags = 0,
......@@ -874,7 +856,7 @@ pub const File = struct {
874856 off,
875857 off + file_size_hint,
876858 });
877 try self.sections.append(self.allocator, .{
859 try self.sections.append(self.base.allocator, .{
878860 .sh_name = try self.makeString(".debug_abbrev"),
879861 .sh_type = elf.SHT_PROGBITS,
880862 .sh_flags = 0,
......@@ -899,7 +881,7 @@ pub const File = struct {
899881 off,
900882 off + file_size_hint,
901883 });
902 try self.sections.append(self.allocator, .{
884 try self.sections.append(self.base.allocator, .{
903885 .sh_name = try self.makeString(".debug_aranges"),
904886 .sh_type = elf.SHT_PROGBITS,
905887 .sh_flags = 0,
......@@ -924,7 +906,7 @@ pub const File = struct {
924906 off,
925907 off + file_size_hint,
926908 });
927 try self.sections.append(self.allocator, .{
909 try self.sections.append(self.base.allocator, .{
928910 .sh_name = try self.makeString(".debug_line"),
929911 .sh_type = elf.SHT_PROGBITS,
930912 .sh_flags = 0,
......@@ -1019,7 +1001,7 @@ pub const File = struct {
10191001
10201002 const abbrev_offset = 0;
10211003 self.debug_abbrev_table_offset = abbrev_offset;
1022 try self.file.?.pwriteAll(&abbrev_buf, debug_abbrev_sect.sh_offset + abbrev_offset);
1004 try self.base.file.?.pwriteAll(&abbrev_buf, debug_abbrev_sect.sh_offset + abbrev_offset);
10231005 if (!self.shdr_table_dirty) {
10241006 // Then it won't get written with the others and we need to do it.
10251007 try self.writeSectHeader(self.debug_abbrev_section_index.?);
......@@ -1030,7 +1012,7 @@ pub const File = struct {
10301012 if (self.debug_info_section_dirty) {
10311013 const debug_info_sect = &self.sections.items[self.debug_info_section_index.?];
10321014
1033 var di_buf = std.ArrayList(u8).init(self.allocator);
1015 var di_buf = std.ArrayList(u8).init(self.base.allocator);
10341016 defer di_buf.deinit();
10351017
10361018 // Enough for a 64-bit header and main compilation unit without resizing.
......@@ -1101,7 +1083,7 @@ pub const File = struct {
11011083 debug_info_sect.sh_offset + needed_size,
11021084 });
11031085
1104 try self.file.?.pwriteAll(di_buf.items, debug_info_sect.sh_offset);
1086 try self.base.file.?.pwriteAll(di_buf.items, debug_info_sect.sh_offset);
11051087 if (!self.shdr_table_dirty) {
11061088 // Then it won't get written with the others and we need to do it.
11071089 try self.writeSectHeader(self.debug_info_section_index.?);
......@@ -1112,7 +1094,7 @@ pub const File = struct {
11121094 if (self.debug_aranges_section_dirty) {
11131095 const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?];
11141096
1115 var di_buf = std.ArrayList(u8).init(self.allocator);
1097 var di_buf = std.ArrayList(u8).init(self.base.allocator);
11161098 defer di_buf.deinit();
11171099
11181100 // Enough for all the data without resizing. When support for more compilation units
......@@ -1172,7 +1154,7 @@ pub const File = struct {
11721154 debug_aranges_sect.sh_offset + needed_size,
11731155 });
11741156
1175 try self.file.?.pwriteAll(di_buf.items, debug_aranges_sect.sh_offset);
1157 try self.base.file.?.pwriteAll(di_buf.items, debug_aranges_sect.sh_offset);
11761158 if (!self.shdr_table_dirty) {
11771159 // Then it won't get written with the others and we need to do it.
11781160 try self.writeSectHeader(self.debug_aranges_section_index.?);
......@@ -1187,7 +1169,7 @@ pub const File = struct {
11871169
11881170 const debug_line_sect = &self.sections.items[self.debug_line_section_index.?];
11891171
1190 var di_buf = std.ArrayList(u8).init(self.allocator);
1172 var di_buf = std.ArrayList(u8).init(self.base.allocator);
11911173 defer di_buf.deinit();
11921174
11931175 // The size of this header is variable, depending on the number of directories,
......@@ -1294,8 +1276,8 @@ pub const File = struct {
12941276
12951277 switch (self.ptr_width) {
12961278 .p32 => {
1297 const buf = try self.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
1298 defer self.allocator.free(buf);
1279 const buf = try self.base.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
1280 defer self.base.allocator.free(buf);
12991281
13001282 for (buf) |*phdr, i| {
13011283 phdr.* = progHeaderTo32(self.program_headers.items[i]);
......@@ -1303,11 +1285,11 @@ pub const File = struct {
13031285 bswapAllFields(elf.Elf32_Phdr, phdr);
13041286 }
13051287 }
1306 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
1288 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
13071289 },
13081290 .p64 => {
1309 const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
1310 defer self.allocator.free(buf);
1291 const buf = try self.base.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
1292 defer self.base.allocator.free(buf);
13111293
13121294 for (buf) |*phdr, i| {
13131295 phdr.* = self.program_headers.items[i];
......@@ -1315,7 +1297,7 @@ pub const File = struct {
13151297 bswapAllFields(elf.Elf64_Phdr, phdr);
13161298 }
13171299 }
1318 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
1300 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
13191301 },
13201302 }
13211303 self.phdr_table_dirty = false;
......@@ -1334,7 +1316,7 @@ pub const File = struct {
13341316 shstrtab_sect.sh_size = needed_size;
13351317 log.debug(.link, "writing shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
13361318
1337 try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
1319 try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
13381320 if (!self.shdr_table_dirty) {
13391321 // Then it won't get written with the others and we need to do it.
13401322 try self.writeSectHeader(self.shstrtab_index.?);
......@@ -1355,7 +1337,7 @@ pub const File = struct {
13551337 debug_strtab_sect.sh_size = needed_size;
13561338 log.debug(.link, "debug_strtab start=0x{x} end=0x{x}\n", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size });
13571339
1358 try self.file.?.pwriteAll(self.debug_strtab.items, debug_strtab_sect.sh_offset);
1340 try self.base.file.?.pwriteAll(self.debug_strtab.items, debug_strtab_sect.sh_offset);
13591341 if (!self.shdr_table_dirty) {
13601342 // Then it won't get written with the others and we need to do it.
13611343 try self.writeSectHeader(self.debug_str_section_index.?);
......@@ -1382,20 +1364,21 @@ pub const File = struct {
13821364
13831365 switch (self.ptr_width) {
13841366 .p32 => {
1385 const buf = try self.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len);
1386 defer self.allocator.free(buf);
1367 const buf = try self.base.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len);
1368 defer self.base.allocator.free(buf);
13871369
13881370 for (buf) |*shdr, i| {
13891371 shdr.* = sectHeaderTo32(self.sections.items[i]);
1372 std.log.debug(.link, "writing section {}\n", .{shdr.*});
13901373 if (foreign_endian) {
13911374 bswapAllFields(elf.Elf32_Shdr, shdr);
13921375 }
13931376 }
1394 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
1377 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
13951378 },
13961379 .p64 => {
1397 const buf = try self.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len);
1398 defer self.allocator.free(buf);
1380 const buf = try self.base.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len);
1381 defer self.base.allocator.free(buf);
13991382
14001383 for (buf) |*shdr, i| {
14011384 shdr.* = self.sections.items[i];
......@@ -1404,7 +1387,7 @@ pub const File = struct {
14041387 bswapAllFields(elf.Elf64_Shdr, shdr);
14051388 }
14061389 }
1407 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
1390 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?);
14081391 },
14091392 }
14101393 self.shdr_table_dirty = false;
......@@ -1557,7 +1540,7 @@ pub const File = struct {
15571540
15581541 assert(index == e_ehsize);
15591542
1560 try self.file.?.pwriteAll(hdr_buf[0..index], 0);
1543 try self.base.file.?.pwriteAll(hdr_buf[0..index], 0);
15611544 }
15621545
15631546 fn freeTextBlock(self: *Elf, text_block: *TextBlock) void {
......@@ -1587,7 +1570,7 @@ pub const File = struct {
15871570 if (!already_have_free_list_node and prev.freeListEligible(self.*)) {
15881571 // The free list is heuristics, it doesn't have to be perfect, so we can
15891572 // ignore the OOM here.
1590 self.text_block_free_list.append(self.allocator, prev) catch {};
1573 self.text_block_free_list.append(self.base.allocator, prev) catch {};
15911574 }
15921575 } else {
15931576 text_block.prev = null;
......@@ -1688,7 +1671,7 @@ pub const File = struct {
16881671 const sym = self.local_symbols.items[last.local_sym_index];
16891672 break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr;
16901673 } else 0;
1691 const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, text_size);
1674 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, text_size);
16921675 if (amt != text_size) return error.InputOutput;
16931676 shdr.sh_offset = new_offset;
16941677 phdr.p_offset = new_offset;
......@@ -1739,8 +1722,8 @@ pub const File = struct {
17391722 pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void {
17401723 if (decl.link.local_sym_index != 0) return;
17411724
1742 try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1);
1743 try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1);
1725 try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1);
1726 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
17441727
17451728 if (self.local_symbol_free_list.popOrNull()) |i| {
17461729 log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name });
......@@ -1776,8 +1759,8 @@ pub const File = struct {
17761759 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
17771760 self.freeTextBlock(&decl.link);
17781761 if (decl.link.local_sym_index != 0) {
1779 self.local_symbol_free_list.append(self.allocator, decl.link.local_sym_index) catch {};
1780 self.offset_table_free_list.append(self.allocator, decl.link.offset_table_index) catch {};
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 {};
17811764
17821765 self.local_symbols.items[decl.link.local_sym_index].st_info = 0;
17831766
......@@ -1787,7 +1770,7 @@ pub const File = struct {
17871770 // is desired for both.
17881771 _ = self.dbg_line_fn_free_list.remove(&decl.fn_link);
17891772 if (decl.fn_link.prev) |prev| {
1790 _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {};
1773 _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
17911774 prev.next = decl.fn_link.next;
17921775 if (decl.fn_link.next) |next| {
17931776 next.prev = prev;
......@@ -1810,10 +1793,10 @@ pub const File = struct {
18101793 const tracy = trace(@src());
18111794 defer tracy.end();
18121795
1813 var code_buffer = std.ArrayList(u8).init(self.allocator);
1796 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
18141797 defer code_buffer.deinit();
18151798
1816 var dbg_line_buffer = std.ArrayList(u8).init(self.allocator);
1799 var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator);
18171800 defer dbg_line_buffer.deinit();
18181801
18191802 const typed_value = decl.typed_value.most_recent.typed_value;
......@@ -1936,7 +1919,7 @@ pub const File = struct {
19361919
19371920 const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr;
19381921 const file_offset = self.sections.items[self.text_section_index.?].sh_offset + section_offset;
1939 try self.file.?.pwriteAll(code, file_offset);
1922 try self.base.file.?.pwriteAll(code, file_offset);
19401923
19411924 // If the Decl is a function, we need to update the .debug_line program.
19421925 if (is_fn) {
......@@ -1966,7 +1949,7 @@ pub const File = struct {
19661949 if (src_fn.off + src_fn.len + min_nop_size > next.off) {
19671950 // It grew too big, so we move it to a new location.
19681951 if (src_fn.prev) |prev| {
1969 _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {};
1952 _ = self.dbg_line_fn_free_list.put(self.base.allocator, prev, {}) catch {};
19701953 prev.next = src_fn.next;
19711954 }
19721955 next.prev = src_fn.prev;
......@@ -2009,7 +1992,7 @@ pub const File = struct {
20091992 debug_line_sect.sh_offset,
20101993 new_offset,
20111994 });
2012 const amt = try self.file.?.copyRangeAll(debug_line_sect.sh_offset, self.file.?, new_offset, existing_size);
1995 const amt = try self.base.file.?.copyRangeAll(debug_line_sect.sh_offset, self.base.file.?, new_offset, existing_size);
20131996 if (amt != existing_size) return error.InputOutput;
20141997 debug_line_sect.sh_offset = new_offset;
20151998 }
......@@ -2041,7 +2024,7 @@ pub const File = struct {
20412024 const tracy = trace(@src());
20422025 defer tracy.end();
20432026
2044 try self.global_symbols.ensureCapacity(self.allocator, self.global_symbols.items.len + exports.len);
2027 try self.global_symbols.ensureCapacity(self.base.allocator, self.global_symbols.items.len + exports.len);
20452028 const typed_value = decl.typed_value.most_recent.typed_value;
20462029 if (decl.link.local_sym_index == 0) return;
20472030 const decl_sym = self.local_symbols.items[decl.link.local_sym_index];
......@@ -2052,7 +2035,7 @@ pub const File = struct {
20522035 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
20532036 module.failed_exports.putAssumeCapacityNoClobber(
20542037 exp,
2055 try Module.ErrorMsg.create(self.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
2038 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
20562039 );
20572040 continue;
20582041 }
......@@ -2070,7 +2053,7 @@ pub const File = struct {
20702053 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
20712054 module.failed_exports.putAssumeCapacityNoClobber(
20722055 exp,
2073 try Module.ErrorMsg.create(self.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
2056 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}),
20742057 );
20752058 continue;
20762059 },
......@@ -2125,12 +2108,12 @@ pub const File = struct {
21252108 const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff();
21262109 var data: [4]u8 = undefined;
21272110 leb128.writeUnsignedFixed(4, &data, casted_line_off);
2128 try self.file.?.pwriteAll(&data, file_pos);
2111 try self.base.file.?.pwriteAll(&data, file_pos);
21292112 }
21302113
21312114 pub fn deleteExport(self: *Elf, exp: Export) void {
21322115 const sym_index = exp.sym_index orelse return;
2133 self.global_symbol_free_list.append(self.allocator, sym_index) catch {};
2116 self.global_symbol_free_list.append(self.base.allocator, sym_index) catch {};
21342117 self.global_symbols.items[sym_index].st_info = 0;
21352118 }
21362119
......@@ -2143,14 +2126,14 @@ pub const File = struct {
21432126 if (foreign_endian) {
21442127 bswapAllFields(elf.Elf32_Phdr, &phdr[0]);
21452128 }
2146 return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
2129 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
21472130 },
21482131 64 => {
21492132 var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]};
21502133 if (foreign_endian) {
21512134 bswapAllFields(elf.Elf64_Phdr, &phdr[0]);
21522135 }
2153 return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
2136 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset);
21542137 },
21552138 else => return error.UnsupportedArchitecture,
21562139 }
......@@ -2166,7 +2149,7 @@ pub const File = struct {
21662149 bswapAllFields(elf.Elf32_Shdr, &shdr[0]);
21672150 }
21682151 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr);
2169 return self.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
2152 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
21702153 },
21712154 64 => {
21722155 var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]};
......@@ -2174,7 +2157,7 @@ pub const File = struct {
21742157 bswapAllFields(elf.Elf64_Shdr, &shdr[0]);
21752158 }
21762159 const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr);
2177 return self.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
2160 return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset);
21782161 },
21792162 else => return error.UnsupportedArchitecture,
21802163 }
......@@ -2191,7 +2174,7 @@ pub const File = struct {
21912174 if (needed_size > allocated_size) {
21922175 // Must move the entire got section.
21932176 const new_offset = self.findFreeSpace(needed_size, entry_size);
2194 const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size);
2177 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, shdr.sh_size);
21952178 if (amt != shdr.sh_size) return error.InputOutput;
21962179 shdr.sh_offset = new_offset;
21972180 phdr.p_offset = new_offset;
......@@ -2211,12 +2194,12 @@ pub const File = struct {
22112194 .p32 => {
22122195 var buf: [4]u8 = undefined;
22132196 mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);
2214 try self.file.?.pwriteAll(&buf, off);
2197 try self.base.file.?.pwriteAll(&buf, off);
22152198 },
22162199 .p64 => {
22172200 var buf: [8]u8 = undefined;
22182201 mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
2219 try self.file.?.pwriteAll(&buf, off);
2202 try self.base.file.?.pwriteAll(&buf, off);
22202203 },
22212204 }
22222205 }
......@@ -2239,7 +2222,7 @@ pub const File = struct {
22392222 // Move all the symbols to a new file location.
22402223 const new_offset = self.findFreeSpace(needed_size, sym_align);
22412224 const existing_size = @as(u64, syms_sect.sh_info) * sym_size;
2242 const amt = try self.file.?.copyRangeAll(syms_sect.sh_offset, self.file.?, new_offset, existing_size);
2225 const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size);
22432226 if (amt != existing_size) return error.InputOutput;
22442227 syms_sect.sh_offset = new_offset;
22452228 }
......@@ -2264,7 +2247,7 @@ pub const File = struct {
22642247 bswapAllFields(elf.Elf32_Sym, &sym[0]);
22652248 }
22662249 const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index;
2267 try self.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
2250 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
22682251 },
22692252 .p64 => {
22702253 var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]};
......@@ -2272,7 +2255,7 @@ pub const File = struct {
22722255 bswapAllFields(elf.Elf64_Sym, &sym[0]);
22732256 }
22742257 const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index;
2275 try self.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
2258 try self.base.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off);
22762259 },
22772260 }
22782261 }
......@@ -2287,8 +2270,8 @@ pub const File = struct {
22872270 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
22882271 switch (self.ptr_width) {
22892272 .p32 => {
2290 const buf = try self.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len);
2291 defer self.allocator.free(buf);
2273 const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len);
2274 defer self.base.allocator.free(buf);
22922275
22932276 for (buf) |*sym, i| {
22942277 sym.* = .{
......@@ -2303,11 +2286,11 @@ pub const File = struct {
23032286 bswapAllFields(elf.Elf32_Sym, sym);
23042287 }
23052288 }
2306 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
2289 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
23072290 },
23082291 .p64 => {
2309 const buf = try self.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len);
2310 defer self.allocator.free(buf);
2292 const buf = try self.base.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len);
2293 defer self.base.allocator.free(buf);
23112294
23122295 for (buf) |*sym, i| {
23132296 sym.* = .{
......@@ -2322,7 +2305,7 @@ pub const File = struct {
23222305 bswapAllFields(elf.Elf64_Sym, sym);
23232306 }
23242307 }
2325 try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
2308 try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off);
23262309 },
23272310 }
23282311 }
......@@ -2437,7 +2420,7 @@ pub const File = struct {
24372420 vec_index += 1;
24382421 }
24392422 }
2440 try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
2423 try self.base.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
24412424 }
24422425
24432426 const min_nop_size = 2;