| ... | @@ -36,9 +36,12 @@ pub const Options = struct { | ... | @@ -36,9 +36,12 @@ pub const Options = struct { |
| 36 | program_code_size_hint: u64 = 256 * 1024, | 36 | program_code_size_hint: u64 = 256 * 1024, |
| 37 | }; | 37 | }; |
| 38 | | 38 | |
| | 39 | |
| 39 | pub const File = struct { | 40 | pub const File = struct { |
| 40 | tag: Tag, | 41 | tag: Tag, |
| 41 | options: Options, | 42 | options: Options, |
| | 43 | file: ?fs.File, |
| | 44 | allocator: *Allocator, |
| 42 | | 45 | |
| 43 | /// Attempts incremental linking, if the file already exists. If | 46 | /// Attempts incremental linking, if the file already exists. If |
| 44 | /// incremental linking fails, falls back to truncating the file and | 47 | /// incremental linking fails, falls back to truncating the file and |
| ... | @@ -66,15 +69,23 @@ pub const File = struct { | ... | @@ -66,15 +69,23 @@ pub const File = struct { |
| 66 | | 69 | |
| 67 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { | 70 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { |
| 68 | switch (base.tag) { | 71 | 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 | }, |
| 70 | .c => {}, | 80 | .c => {}, |
| 71 | } | 81 | } |
| 72 | } | 82 | } |
| 73 | | 83 | |
| 74 | pub fn makeExecutable(base: *File) !void { | 84 | pub fn makeExecutable(base: *File) !void { |
| 75 | switch (base.tag) { | 85 | std.debug.assert(base.tag != .c); |
| 76 | .elf => return @fieldParentPtr(Elf, "base", base).makeExecutable(), | 86 | if (base.file) |f| { |
| 77 | .c => unreachable, | 87 | f.close(); |
| | 88 | base.file = null; |
| 78 | } | 89 | } |
| 79 | } | 90 | } |
| 80 | | 91 | |
| ... | @@ -100,6 +111,7 @@ pub const File = struct { | ... | @@ -100,6 +111,7 @@ pub const File = struct { |
| 100 | } | 111 | } |
| 101 | | 112 | |
| 102 | pub fn deinit(base: *File) void { | 113 | pub fn deinit(base: *File) void { |
| | 114 | if (base.file) |f| f.close(); |
| 103 | switch (base.tag) { | 115 | switch (base.tag) { |
| 104 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), | 116 | .elf => @fieldParentPtr(Elf, "base", base).deinit(), |
| 105 | .c => @fieldParentPtr(C, "base", base).deinit(), | 117 | .c => @fieldParentPtr(C, "base", base).deinit(), |
| ... | @@ -111,12 +123,12 @@ pub const File = struct { | ... | @@ -111,12 +123,12 @@ pub const File = struct { |
| 111 | .elf => { | 123 | .elf => { |
| 112 | const parent = @fieldParentPtr(Elf, "base", base); | 124 | const parent = @fieldParentPtr(Elf, "base", base); |
| 113 | parent.deinit(); | 125 | parent.deinit(); |
| 114 | parent.allocator.destroy(parent); | 126 | base.allocator.destroy(parent); |
| 115 | }, | 127 | }, |
| 116 | .c => { | 128 | .c => { |
| 117 | const parent = @fieldParentPtr(C, "base", base); | 129 | const parent = @fieldParentPtr(C, "base", base); |
| 118 | parent.deinit(); | 130 | parent.deinit(); |
| 119 | parent.allocator.destroy(parent); | 131 | base.allocator.destroy(parent); |
| 120 | }, | 132 | }, |
| 121 | } | 133 | } |
| 122 | } | 134 | } |
| ... | @@ -172,11 +184,10 @@ pub const File = struct { | ... | @@ -172,11 +184,10 @@ pub const File = struct { |
| 172 | | 184 | |
| 173 | base: File, | 185 | base: File, |
| 174 | | 186 | |
| 175 | allocator: *Allocator, | | |
| 176 | header: std.ArrayList(u8), | 187 | header: std.ArrayList(u8), |
| 177 | constants: std.ArrayList(u8), | 188 | constants: std.ArrayList(u8), |
| 178 | main: std.ArrayList(u8), | 189 | main: std.ArrayList(u8), |
| 179 | file: ?fs.File, | 190 | |
| 180 | called: std.StringHashMap(void), | 191 | called: std.StringHashMap(void), |
| 181 | need_stddef: bool = false, | 192 | need_stddef: bool = false, |
| 182 | need_stdint: bool = false, | 193 | need_stdint: bool = false, |
| ... | @@ -196,9 +207,9 @@ pub const File = struct { | ... | @@ -196,9 +207,9 @@ pub const File = struct { |
| 196 | .base = .{ | 207 | .base = .{ |
| 197 | .tag = .c, | 208 | .tag = .c, |
| 198 | .options = options, | 209 | .options = options, |
| | 210 | .file = file, |
| | 211 | .allocator = allocator, |
| 199 | }, | 212 | }, |
| 200 | .allocator = allocator, | | |
| 201 | .file = file, | | |
| 202 | .main = std.ArrayList(u8).init(allocator), | 213 | .main = std.ArrayList(u8).init(allocator), |
| 203 | .header = std.ArrayList(u8).init(allocator), | 214 | .header = std.ArrayList(u8).init(allocator), |
| 204 | .constants = std.ArrayList(u8).init(allocator), | 215 | .constants = std.ArrayList(u8).init(allocator), |
| ... | @@ -209,7 +220,7 @@ pub const File = struct { | ... | @@ -209,7 +220,7 @@ pub const File = struct { |
| 209 | } | 220 | } |
| 210 | | 221 | |
| 211 | pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) !void { | 222 | 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); |
| 213 | return error.AnalysisFail; | 224 | return error.AnalysisFail; |
| 214 | } | 225 | } |
| 215 | | 226 | |
| ... | @@ -218,8 +229,6 @@ pub const File = struct { | ... | @@ -218,8 +229,6 @@ pub const File = struct { |
| 218 | self.header.deinit(); | 229 | self.header.deinit(); |
| 219 | self.constants.deinit(); | 230 | self.constants.deinit(); |
| 220 | self.called.deinit(); | 231 | self.called.deinit(); |
| 221 | if (self.file) |f| | | |
| 222 | f.close(); | | |
| 223 | } | 232 | } |
| 224 | | 233 | |
| 225 | pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { | 234 | pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { |
| ... | @@ -232,7 +241,7 @@ pub const File = struct { | ... | @@ -232,7 +241,7 @@ pub const File = struct { |
| 232 | } | 241 | } |
| 233 | | 242 | |
| 234 | pub fn flush(self: *File.C) !void { | 243 | pub fn flush(self: *File.C) !void { |
| 235 | const writer = self.file.?.writer(); | 244 | const writer = self.base.file.?.writer(); |
| 236 | try writer.writeAll(@embedFile("cbe.h")); | 245 | try writer.writeAll(@embedFile("cbe.h")); |
| 237 | var includes = false; | 246 | var includes = false; |
| 238 | if (self.need_stddef) { | 247 | if (self.need_stddef) { |
| ... | @@ -259,8 +268,8 @@ pub const File = struct { | ... | @@ -259,8 +268,8 @@ pub const File = struct { |
| 259 | } | 268 | } |
| 260 | } | 269 | } |
| 261 | try writer.writeAll(self.main.items); | 270 | try writer.writeAll(self.main.items); |
| 262 | self.file.?.close(); | 271 | self.base.file.?.close(); |
| 263 | self.file = null; | 272 | self.base.file = null; |
| 264 | } | 273 | } |
| 265 | }; | 274 | }; |
| 266 | | 275 | |
| ... | @@ -269,9 +278,6 @@ pub const File = struct { | ... | @@ -269,9 +278,6 @@ pub const File = struct { |
| 269 | | 278 | |
| 270 | base: File, | 279 | base: File, |
| 271 | | 280 | |
| 272 | allocator: *Allocator, | | |
| 273 | file: ?fs.File, | | |
| 274 | owns_file_handle: bool, | | |
| 275 | ptr_width: enum { p32, p64 }, | 281 | ptr_width: enum { p32, p64 }, |
| 276 | | 282 | |
| 277 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 283 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| ... | @@ -454,7 +460,6 @@ pub const File = struct { | ... | @@ -454,7 +460,6 @@ pub const File = struct { |
| 454 | else => |e| return e, | 460 | else => |e| return e, |
| 455 | }; | 461 | }; |
| 456 | | 462 | |
| 457 | elf_file.owns_file_handle = true; | | |
| 458 | return &elf_file.base; | 463 | return &elf_file.base; |
| 459 | } | 464 | } |
| 460 | | 465 | |
| ... | @@ -467,12 +472,11 @@ pub const File = struct { | ... | @@ -467,12 +472,11 @@ pub const File = struct { |
| 467 | } | 472 | } |
| 468 | var self: Elf = .{ | 473 | var self: Elf = .{ |
| 469 | .base = .{ | 474 | .base = .{ |
| | 475 | .file = file, |
| 470 | .tag = .elf, | 476 | .tag = .elf, |
| 471 | .options = options, | 477 | .options = options, |
| | 478 | .allocator = allocator, |
| 472 | }, | 479 | }, |
| 473 | .allocator = allocator, | | |
| 474 | .file = file, | | |
| 475 | .owns_file_handle = false, | | |
| 476 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | 480 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 477 | 32 => .p32, | 481 | 32 => .p32, |
| 478 | 64 => .p64, | 482 | 64 => .p64, |
| ... | @@ -499,16 +503,15 @@ pub const File = struct { | ... | @@ -499,16 +503,15 @@ pub const File = struct { |
| 499 | .base = .{ | 503 | .base = .{ |
| 500 | .tag = .elf, | 504 | .tag = .elf, |
| 501 | .options = options, | 505 | .options = options, |
| | 506 | .allocator = allocator, |
| | 507 | .file = file, |
| 502 | }, | 508 | }, |
| 503 | .allocator = allocator, | | |
| 504 | .file = file, | | |
| 505 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { | 509 | .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) { |
| 506 | 32 => .p32, | 510 | 32 => .p32, |
| 507 | 64 => .p64, | 511 | 64 => .p64, |
| 508 | else => return error.UnsupportedELFArchitecture, | 512 | else => return error.UnsupportedELFArchitecture, |
| 509 | }, | 513 | }, |
| 510 | .shdr_table_dirty = true, | 514 | .shdr_table_dirty = true, |
| 511 | .owns_file_handle = false, | | |
| 512 | }; | 515 | }; |
| 513 | errdefer self.deinit(); | 516 | errdefer self.deinit(); |
| 514 | | 517 | |
| ... | @@ -542,39 +545,18 @@ pub const File = struct { | ... | @@ -542,39 +545,18 @@ pub const File = struct { |
| 542 | } | 545 | } |
| 543 | | 546 | |
| 544 | pub fn deinit(self: *Elf) void { | 547 | pub fn deinit(self: *Elf) void { |
| 545 | self.sections.deinit(self.allocator); | 548 | self.sections.deinit(self.base.allocator); |
| 546 | self.program_headers.deinit(self.allocator); | 549 | self.program_headers.deinit(self.base.allocator); |
| 547 | self.shstrtab.deinit(self.allocator); | 550 | self.shstrtab.deinit(self.base.allocator); |
| 548 | self.debug_strtab.deinit(self.allocator); | 551 | self.debug_strtab.deinit(self.base.allocator); |
| 549 | self.local_symbols.deinit(self.allocator); | 552 | self.local_symbols.deinit(self.base.allocator); |
| 550 | self.global_symbols.deinit(self.allocator); | 553 | self.global_symbols.deinit(self.base.allocator); |
| 551 | self.global_symbol_free_list.deinit(self.allocator); | 554 | self.global_symbol_free_list.deinit(self.base.allocator); |
| 552 | self.local_symbol_free_list.deinit(self.allocator); | 555 | self.local_symbol_free_list.deinit(self.base.allocator); |
| 553 | self.offset_table_free_list.deinit(self.allocator); | 556 | self.offset_table_free_list.deinit(self.base.allocator); |
| 554 | self.text_block_free_list.deinit(self.allocator); | 557 | self.text_block_free_list.deinit(self.base.allocator); |
| 555 | self.dbg_line_fn_free_list.deinit(self.allocator); | 558 | self.dbg_line_fn_free_list.deinit(self.base.allocator); |
| 556 | self.offset_table.deinit(self.allocator); | 559 | self.offset_table.deinit(self.base.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 | }); | | |
| 578 | } | 560 | } |
| 579 | | 561 | |
| 580 | fn getDebugLineProgramOff(self: Elf) u32 { | 562 | fn getDebugLineProgramOff(self: Elf) u32 { |
| ... | @@ -662,7 +644,7 @@ pub const File = struct { | ... | @@ -662,7 +644,7 @@ pub const File = struct { |
| 662 | | 644 | |
| 663 | /// TODO Improve this to use a table. | 645 | /// TODO Improve this to use a table. |
| 664 | fn makeString(self: *Elf, bytes: []const u8) !u32 { | 646 | 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); |
| 666 | const result = self.shstrtab.items.len; | 648 | const result = self.shstrtab.items.len; |
| 667 | self.shstrtab.appendSliceAssumeCapacity(bytes); | 649 | self.shstrtab.appendSliceAssumeCapacity(bytes); |
| 668 | self.shstrtab.appendAssumeCapacity(0); | 650 | self.shstrtab.appendAssumeCapacity(0); |
| ... | @@ -671,7 +653,7 @@ pub const File = struct { | ... | @@ -671,7 +653,7 @@ pub const File = struct { |
| 671 | | 653 | |
| 672 | /// TODO Improve this to use a table. | 654 | /// TODO Improve this to use a table. |
| 673 | fn makeDebugString(self: *Elf, bytes: []const u8) !u32 { | 655 | 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); |
| 675 | const result = self.debug_strtab.items.len; | 657 | const result = self.debug_strtab.items.len; |
| 676 | self.debug_strtab.appendSliceAssumeCapacity(bytes); | 658 | self.debug_strtab.appendSliceAssumeCapacity(bytes); |
| 677 | self.debug_strtab.appendAssumeCapacity(0); | 659 | self.debug_strtab.appendAssumeCapacity(0); |
| ... | @@ -703,7 +685,7 @@ pub const File = struct { | ... | @@ -703,7 +685,7 @@ pub const File = struct { |
| 703 | const p_align = 0x1000; | 685 | const p_align = 0x1000; |
| 704 | const off = self.findFreeSpace(file_size, p_align); | 686 | const off = self.findFreeSpace(file_size, p_align); |
| 705 | log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 687 | 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, .{ |
| 707 | .p_type = elf.PT_LOAD, | 689 | .p_type = elf.PT_LOAD, |
| 708 | .p_offset = off, | 690 | .p_offset = off, |
| 709 | .p_filesz = file_size, | 691 | .p_filesz = file_size, |
| ... | @@ -721,14 +703,14 @@ pub const File = struct { | ... | @@ -721,14 +703,14 @@ pub const File = struct { |
| 721 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; | 703 | const file_size = @as(u64, ptr_size) * self.base.options.symbol_count_hint; |
| 722 | // We really only need ptr alignment but since we are using PROGBITS, linux requires | 704 | // We really only need ptr alignment but since we are using PROGBITS, linux requires |
| 723 | // page align. | 705 | // 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); |
| 725 | const off = self.findFreeSpace(file_size, p_align); | 707 | const off = self.findFreeSpace(file_size, p_align); |
| 726 | log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 708 | log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 727 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. | 709 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| 728 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something | 710 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something |
| 729 | // else in virtual memory. | 711 | // else in virtual memory. |
| 730 | const default_got_addr = 0x4000000; | 712 | const default_got_addr = if (ptr_size == 2) @as(u32, 0x8000) else 0x4000000; |
| 731 | try self.program_headers.append(self.allocator, .{ | 713 | try self.program_headers.append(self.base.allocator, .{ |
| 732 | .p_type = elf.PT_LOAD, | 714 | .p_type = elf.PT_LOAD, |
| 733 | .p_offset = off, | 715 | .p_offset = off, |
| 734 | .p_filesz = file_size, | 716 | .p_filesz = file_size, |
| ... | @@ -743,10 +725,10 @@ pub const File = struct { | ... | @@ -743,10 +725,10 @@ pub const File = struct { |
| 743 | if (self.shstrtab_index == null) { | 725 | if (self.shstrtab_index == null) { |
| 744 | self.shstrtab_index = @intCast(u16, self.sections.items.len); | 726 | self.shstrtab_index = @intCast(u16, self.sections.items.len); |
| 745 | assert(self.shstrtab.items.len == 0); | 727 | 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 |
| 747 | const off = self.findFreeSpace(self.shstrtab.items.len, 1); | 729 | const off = self.findFreeSpace(self.shstrtab.items.len, 1); |
| 748 | log.debug(.link, "found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len }); | 730 | 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, .{ |
| 750 | .sh_name = try self.makeString(".shstrtab"), | 732 | .sh_name = try self.makeString(".shstrtab"), |
| 751 | .sh_type = elf.SHT_STRTAB, | 733 | .sh_type = elf.SHT_STRTAB, |
| 752 | .sh_flags = 0, | 734 | .sh_flags = 0, |
| ... | @@ -765,7 +747,7 @@ pub const File = struct { | ... | @@ -765,7 +747,7 @@ pub const File = struct { |
| 765 | self.text_section_index = @intCast(u16, self.sections.items.len); | 747 | self.text_section_index = @intCast(u16, self.sections.items.len); |
| 766 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | 748 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 767 | | 749 | |
| 768 | try self.sections.append(self.allocator, .{ | 750 | try self.sections.append(self.base.allocator, .{ |
| 769 | .sh_name = try self.makeString(".text"), | 751 | .sh_name = try self.makeString(".text"), |
| 770 | .sh_type = elf.SHT_PROGBITS, | 752 | .sh_type = elf.SHT_PROGBITS, |
| 771 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | 753 | .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, |
| ... | @@ -783,7 +765,7 @@ pub const File = struct { | ... | @@ -783,7 +765,7 @@ pub const File = struct { |
| 783 | self.got_section_index = @intCast(u16, self.sections.items.len); | 765 | self.got_section_index = @intCast(u16, self.sections.items.len); |
| 784 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; | 766 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| 785 | | 767 | |
| 786 | try self.sections.append(self.allocator, .{ | 768 | try self.sections.append(self.base.allocator, .{ |
| 787 | .sh_name = try self.makeString(".got"), | 769 | .sh_name = try self.makeString(".got"), |
| 788 | .sh_type = elf.SHT_PROGBITS, | 770 | .sh_type = elf.SHT_PROGBITS, |
| 789 | .sh_flags = elf.SHF_ALLOC, | 771 | .sh_flags = elf.SHF_ALLOC, |
| ... | @@ -805,7 +787,7 @@ pub const File = struct { | ... | @@ -805,7 +787,7 @@ pub const File = struct { |
| 805 | const off = self.findFreeSpace(file_size, min_align); | 787 | const off = self.findFreeSpace(file_size, min_align); |
| 806 | log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); | 788 | log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size }); |
| 807 | | 789 | |
| 808 | try self.sections.append(self.allocator, .{ | 790 | try self.sections.append(self.base.allocator, .{ |
| 809 | .sh_name = try self.makeString(".symtab"), | 791 | .sh_name = try self.makeString(".symtab"), |
| 810 | .sh_type = elf.SHT_SYMTAB, | 792 | .sh_type = elf.SHT_SYMTAB, |
| 811 | .sh_flags = 0, | 793 | .sh_flags = 0, |
| ... | @@ -824,7 +806,7 @@ pub const File = struct { | ... | @@ -824,7 +806,7 @@ pub const File = struct { |
| 824 | if (self.debug_str_section_index == null) { | 806 | if (self.debug_str_section_index == null) { |
| 825 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); | 807 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); |
| 826 | assert(self.debug_strtab.items.len == 0); | 808 | assert(self.debug_strtab.items.len == 0); |
| 827 | try self.sections.append(self.allocator, .{ | 809 | try self.sections.append(self.base.allocator, .{ |
| 828 | .sh_name = try self.makeString(".debug_str"), | 810 | .sh_name = try self.makeString(".debug_str"), |
| 829 | .sh_type = elf.SHT_PROGBITS, | 811 | .sh_type = elf.SHT_PROGBITS, |
| 830 | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, | 812 | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| ... | @@ -849,7 +831,7 @@ pub const File = struct { | ... | @@ -849,7 +831,7 @@ pub const File = struct { |
| 849 | off, | 831 | off, |
| 850 | off + file_size_hint, | 832 | off + file_size_hint, |
| 851 | }); | 833 | }); |
| 852 | try self.sections.append(self.allocator, .{ | 834 | try self.sections.append(self.base.allocator, .{ |
| 853 | .sh_name = try self.makeString(".debug_info"), | 835 | .sh_name = try self.makeString(".debug_info"), |
| 854 | .sh_type = elf.SHT_PROGBITS, | 836 | .sh_type = elf.SHT_PROGBITS, |
| 855 | .sh_flags = 0, | 837 | .sh_flags = 0, |
| ... | @@ -874,7 +856,7 @@ pub const File = struct { | ... | @@ -874,7 +856,7 @@ pub const File = struct { |
| 874 | off, | 856 | off, |
| 875 | off + file_size_hint, | 857 | off + file_size_hint, |
| 876 | }); | 858 | }); |
| 877 | try self.sections.append(self.allocator, .{ | 859 | try self.sections.append(self.base.allocator, .{ |
| 878 | .sh_name = try self.makeString(".debug_abbrev"), | 860 | .sh_name = try self.makeString(".debug_abbrev"), |
| 879 | .sh_type = elf.SHT_PROGBITS, | 861 | .sh_type = elf.SHT_PROGBITS, |
| 880 | .sh_flags = 0, | 862 | .sh_flags = 0, |
| ... | @@ -899,7 +881,7 @@ pub const File = struct { | ... | @@ -899,7 +881,7 @@ pub const File = struct { |
| 899 | off, | 881 | off, |
| 900 | off + file_size_hint, | 882 | off + file_size_hint, |
| 901 | }); | 883 | }); |
| 902 | try self.sections.append(self.allocator, .{ | 884 | try self.sections.append(self.base.allocator, .{ |
| 903 | .sh_name = try self.makeString(".debug_aranges"), | 885 | .sh_name = try self.makeString(".debug_aranges"), |
| 904 | .sh_type = elf.SHT_PROGBITS, | 886 | .sh_type = elf.SHT_PROGBITS, |
| 905 | .sh_flags = 0, | 887 | .sh_flags = 0, |
| ... | @@ -924,7 +906,7 @@ pub const File = struct { | ... | @@ -924,7 +906,7 @@ pub const File = struct { |
| 924 | off, | 906 | off, |
| 925 | off + file_size_hint, | 907 | off + file_size_hint, |
| 926 | }); | 908 | }); |
| 927 | try self.sections.append(self.allocator, .{ | 909 | try self.sections.append(self.base.allocator, .{ |
| 928 | .sh_name = try self.makeString(".debug_line"), | 910 | .sh_name = try self.makeString(".debug_line"), |
| 929 | .sh_type = elf.SHT_PROGBITS, | 911 | .sh_type = elf.SHT_PROGBITS, |
| 930 | .sh_flags = 0, | 912 | .sh_flags = 0, |
| ... | @@ -1019,7 +1001,7 @@ pub const File = struct { | ... | @@ -1019,7 +1001,7 @@ pub const File = struct { |
| 1019 | | 1001 | |
| 1020 | const abbrev_offset = 0; | 1002 | const abbrev_offset = 0; |
| 1021 | self.debug_abbrev_table_offset = abbrev_offset; | 1003 | 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); |
| 1023 | if (!self.shdr_table_dirty) { | 1005 | if (!self.shdr_table_dirty) { |
| 1024 | // Then it won't get written with the others and we need to do it. | 1006 | // Then it won't get written with the others and we need to do it. |
| 1025 | try self.writeSectHeader(self.debug_abbrev_section_index.?); | 1007 | try self.writeSectHeader(self.debug_abbrev_section_index.?); |
| ... | @@ -1030,7 +1012,7 @@ pub const File = struct { | ... | @@ -1030,7 +1012,7 @@ pub const File = struct { |
| 1030 | if (self.debug_info_section_dirty) { | 1012 | if (self.debug_info_section_dirty) { |
| 1031 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; | 1013 | const debug_info_sect = &self.sections.items[self.debug_info_section_index.?]; |
| 1032 | | 1014 | |
| 1033 | var di_buf = std.ArrayList(u8).init(self.allocator); | 1015 | var di_buf = std.ArrayList(u8).init(self.base.allocator); |
| 1034 | defer di_buf.deinit(); | 1016 | defer di_buf.deinit(); |
| 1035 | | 1017 | |
| 1036 | // Enough for a 64-bit header and main compilation unit without resizing. | 1018 | // Enough for a 64-bit header and main compilation unit without resizing. |
| ... | @@ -1101,7 +1083,7 @@ pub const File = struct { | ... | @@ -1101,7 +1083,7 @@ pub const File = struct { |
| 1101 | debug_info_sect.sh_offset + needed_size, | 1083 | debug_info_sect.sh_offset + needed_size, |
| 1102 | }); | 1084 | }); |
| 1103 | | 1085 | |
| 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); |
| 1105 | if (!self.shdr_table_dirty) { | 1087 | if (!self.shdr_table_dirty) { |
| 1106 | // Then it won't get written with the others and we need to do it. | 1088 | // Then it won't get written with the others and we need to do it. |
| 1107 | try self.writeSectHeader(self.debug_info_section_index.?); | 1089 | try self.writeSectHeader(self.debug_info_section_index.?); |
| ... | @@ -1112,7 +1094,7 @@ pub const File = struct { | ... | @@ -1112,7 +1094,7 @@ pub const File = struct { |
| 1112 | if (self.debug_aranges_section_dirty) { | 1094 | if (self.debug_aranges_section_dirty) { |
| 1113 | const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?]; | 1095 | const debug_aranges_sect = &self.sections.items[self.debug_aranges_section_index.?]; |
| 1114 | | 1096 | |
| 1115 | var di_buf = std.ArrayList(u8).init(self.allocator); | 1097 | var di_buf = std.ArrayList(u8).init(self.base.allocator); |
| 1116 | defer di_buf.deinit(); | 1098 | defer di_buf.deinit(); |
| 1117 | | 1099 | |
| 1118 | // Enough for all the data without resizing. When support for more compilation units | 1100 | // Enough for all the data without resizing. When support for more compilation units |
| ... | @@ -1172,7 +1154,7 @@ pub const File = struct { | ... | @@ -1172,7 +1154,7 @@ pub const File = struct { |
| 1172 | debug_aranges_sect.sh_offset + needed_size, | 1154 | debug_aranges_sect.sh_offset + needed_size, |
| 1173 | }); | 1155 | }); |
| 1174 | | 1156 | |
| 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); |
| 1176 | if (!self.shdr_table_dirty) { | 1158 | if (!self.shdr_table_dirty) { |
| 1177 | // Then it won't get written with the others and we need to do it. | 1159 | // Then it won't get written with the others and we need to do it. |
| 1178 | try self.writeSectHeader(self.debug_aranges_section_index.?); | 1160 | try self.writeSectHeader(self.debug_aranges_section_index.?); |
| ... | @@ -1187,7 +1169,7 @@ pub const File = struct { | ... | @@ -1187,7 +1169,7 @@ pub const File = struct { |
| 1187 | | 1169 | |
| 1188 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | 1170 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; |
| 1189 | | 1171 | |
| 1190 | var di_buf = std.ArrayList(u8).init(self.allocator); | 1172 | var di_buf = std.ArrayList(u8).init(self.base.allocator); |
| 1191 | defer di_buf.deinit(); | 1173 | defer di_buf.deinit(); |
| 1192 | | 1174 | |
| 1193 | // The size of this header is variable, depending on the number of directories, | 1175 | // The size of this header is variable, depending on the number of directories, |
| ... | @@ -1294,8 +1276,8 @@ pub const File = struct { | ... | @@ -1294,8 +1276,8 @@ pub const File = struct { |
| 1294 | | 1276 | |
| 1295 | switch (self.ptr_width) { | 1277 | switch (self.ptr_width) { |
| 1296 | .p32 => { | 1278 | .p32 => { |
| 1297 | const buf = try self.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len); | 1279 | const buf = try self.base.allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len); |
| 1298 | defer self.allocator.free(buf); | 1280 | defer self.base.allocator.free(buf); |
| 1299 | | 1281 | |
| 1300 | for (buf) |*phdr, i| { | 1282 | for (buf) |*phdr, i| { |
| 1301 | phdr.* = progHeaderTo32(self.program_headers.items[i]); | 1283 | phdr.* = progHeaderTo32(self.program_headers.items[i]); |
| ... | @@ -1303,11 +1285,11 @@ pub const File = struct { | ... | @@ -1303,11 +1285,11 @@ pub const File = struct { |
| 1303 | bswapAllFields(elf.Elf32_Phdr, phdr); | 1285 | bswapAllFields(elf.Elf32_Phdr, phdr); |
| 1304 | } | 1286 | } |
| 1305 | } | 1287 | } |
| 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.?); |
| 1307 | }, | 1289 | }, |
| 1308 | .p64 => { | 1290 | .p64 => { |
| 1309 | const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); | 1291 | const buf = try self.base.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); |
| 1310 | defer self.allocator.free(buf); | 1292 | defer self.base.allocator.free(buf); |
| 1311 | | 1293 | |
| 1312 | for (buf) |*phdr, i| { | 1294 | for (buf) |*phdr, i| { |
| 1313 | phdr.* = self.program_headers.items[i]; | 1295 | phdr.* = self.program_headers.items[i]; |
| ... | @@ -1315,7 +1297,7 @@ pub const File = struct { | ... | @@ -1315,7 +1297,7 @@ pub const File = struct { |
| 1315 | bswapAllFields(elf.Elf64_Phdr, phdr); | 1297 | bswapAllFields(elf.Elf64_Phdr, phdr); |
| 1316 | } | 1298 | } |
| 1317 | } | 1299 | } |
| 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.?); |
| 1319 | }, | 1301 | }, |
| 1320 | } | 1302 | } |
| 1321 | self.phdr_table_dirty = false; | 1303 | self.phdr_table_dirty = false; |
| ... | @@ -1334,7 +1316,7 @@ pub const File = struct { | ... | @@ -1334,7 +1316,7 @@ pub const File = struct { |
| 1334 | shstrtab_sect.sh_size = needed_size; | 1316 | shstrtab_sect.sh_size = needed_size; |
| 1335 | log.debug(.link, "writing shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); | 1317 | log.debug(.link, "writing shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); |
| 1336 | | 1318 | |
| 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); |
| 1338 | if (!self.shdr_table_dirty) { | 1320 | if (!self.shdr_table_dirty) { |
| 1339 | // Then it won't get written with the others and we need to do it. | 1321 | // Then it won't get written with the others and we need to do it. |
| 1340 | try self.writeSectHeader(self.shstrtab_index.?); | 1322 | try self.writeSectHeader(self.shstrtab_index.?); |
| ... | @@ -1355,7 +1337,7 @@ pub const File = struct { | ... | @@ -1355,7 +1337,7 @@ pub const File = struct { |
| 1355 | debug_strtab_sect.sh_size = needed_size; | 1337 | debug_strtab_sect.sh_size = needed_size; |
| 1356 | log.debug(.link, "debug_strtab start=0x{x} end=0x{x}\n", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); | 1338 | log.debug(.link, "debug_strtab start=0x{x} end=0x{x}\n", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); |
| 1357 | | 1339 | |
| 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); |
| 1359 | if (!self.shdr_table_dirty) { | 1341 | if (!self.shdr_table_dirty) { |
| 1360 | // Then it won't get written with the others and we need to do it. | 1342 | // Then it won't get written with the others and we need to do it. |
| 1361 | try self.writeSectHeader(self.debug_str_section_index.?); | 1343 | try self.writeSectHeader(self.debug_str_section_index.?); |
| ... | @@ -1382,20 +1364,21 @@ pub const File = struct { | ... | @@ -1382,20 +1364,21 @@ pub const File = struct { |
| 1382 | | 1364 | |
| 1383 | switch (self.ptr_width) { | 1365 | switch (self.ptr_width) { |
| 1384 | .p32 => { | 1366 | .p32 => { |
| 1385 | const buf = try self.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); | 1367 | const buf = try self.base.allocator.alloc(elf.Elf32_Shdr, self.sections.items.len); |
| 1386 | defer self.allocator.free(buf); | 1368 | defer self.base.allocator.free(buf); |
| 1387 | | 1369 | |
| 1388 | for (buf) |*shdr, i| { | 1370 | for (buf) |*shdr, i| { |
| 1389 | shdr.* = sectHeaderTo32(self.sections.items[i]); | 1371 | shdr.* = sectHeaderTo32(self.sections.items[i]); |
| | 1372 | std.log.debug(.link, "writing section {}\n", .{shdr.*}); |
| 1390 | if (foreign_endian) { | 1373 | if (foreign_endian) { |
| 1391 | bswapAllFields(elf.Elf32_Shdr, shdr); | 1374 | bswapAllFields(elf.Elf32_Shdr, shdr); |
| 1392 | } | 1375 | } |
| 1393 | } | 1376 | } |
| 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.?); |
| 1395 | }, | 1378 | }, |
| 1396 | .p64 => { | 1379 | .p64 => { |
| 1397 | const buf = try self.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); | 1380 | const buf = try self.base.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); |
| 1398 | defer self.allocator.free(buf); | 1381 | defer self.base.allocator.free(buf); |
| 1399 | | 1382 | |
| 1400 | for (buf) |*shdr, i| { | 1383 | for (buf) |*shdr, i| { |
| 1401 | shdr.* = self.sections.items[i]; | 1384 | shdr.* = self.sections.items[i]; |
| ... | @@ -1404,7 +1387,7 @@ pub const File = struct { | ... | @@ -1404,7 +1387,7 @@ pub const File = struct { |
| 1404 | bswapAllFields(elf.Elf64_Shdr, shdr); | 1387 | bswapAllFields(elf.Elf64_Shdr, shdr); |
| 1405 | } | 1388 | } |
| 1406 | } | 1389 | } |
| 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.?); |
| 1408 | }, | 1391 | }, |
| 1409 | } | 1392 | } |
| 1410 | self.shdr_table_dirty = false; | 1393 | self.shdr_table_dirty = false; |
| ... | @@ -1557,7 +1540,7 @@ pub const File = struct { | ... | @@ -1557,7 +1540,7 @@ pub const File = struct { |
| 1557 | | 1540 | |
| 1558 | assert(index == e_ehsize); | 1541 | assert(index == e_ehsize); |
| 1559 | | 1542 | |
| 1560 | try self.file.?.pwriteAll(hdr_buf[0..index], 0); | 1543 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 1561 | } | 1544 | } |
| 1562 | | 1545 | |
| 1563 | fn freeTextBlock(self: *Elf, text_block: *TextBlock) void { | 1546 | fn freeTextBlock(self: *Elf, text_block: *TextBlock) void { |
| ... | @@ -1587,7 +1570,7 @@ pub const File = struct { | ... | @@ -1587,7 +1570,7 @@ pub const File = struct { |
| 1587 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { | 1570 | if (!already_have_free_list_node and prev.freeListEligible(self.*)) { |
| 1588 | // The free list is heuristics, it doesn't have to be perfect, so we can | 1571 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 1589 | // ignore the OOM here. | 1572 | // 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 {}; |
| 1591 | } | 1574 | } |
| 1592 | } else { | 1575 | } else { |
| 1593 | text_block.prev = null; | 1576 | text_block.prev = null; |
| ... | @@ -1688,7 +1671,7 @@ pub const File = struct { | ... | @@ -1688,7 +1671,7 @@ pub const File = struct { |
| 1688 | const sym = self.local_symbols.items[last.local_sym_index]; | 1671 | const sym = self.local_symbols.items[last.local_sym_index]; |
| 1689 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; | 1672 | break :blk (sym.st_value + sym.st_size) - phdr.p_vaddr; |
| 1690 | } else 0; | 1673 | } 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); |
| 1692 | if (amt != text_size) return error.InputOutput; | 1675 | if (amt != text_size) return error.InputOutput; |
| 1693 | shdr.sh_offset = new_offset; | 1676 | shdr.sh_offset = new_offset; |
| 1694 | phdr.p_offset = new_offset; | 1677 | phdr.p_offset = new_offset; |
| ... | @@ -1739,8 +1722,8 @@ pub const File = struct { | ... | @@ -1739,8 +1722,8 @@ pub const File = struct { |
| 1739 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | 1722 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 1740 | if (decl.link.local_sym_index != 0) return; | 1723 | if (decl.link.local_sym_index != 0) return; |
| 1741 | | 1724 | |
| 1742 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); | 1725 | try self.local_symbols.ensureCapacity(self.base.allocator, self.local_symbols.items.len + 1); |
| 1743 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); | 1726 | try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1); |
| 1744 | | 1727 | |
| 1745 | if (self.local_symbol_free_list.popOrNull()) |i| { | 1728 | if (self.local_symbol_free_list.popOrNull()) |i| { |
| 1746 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); | 1729 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); |
| ... | @@ -1776,8 +1759,8 @@ pub const File = struct { | ... | @@ -1776,8 +1759,8 @@ pub const File = struct { |
| 1776 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. | 1759 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 1777 | self.freeTextBlock(&decl.link); | 1760 | self.freeTextBlock(&decl.link); |
| 1778 | if (decl.link.local_sym_index != 0) { | 1761 | if (decl.link.local_sym_index != 0) { |
| 1779 | self.local_symbol_free_list.append(self.allocator, decl.link.local_sym_index) catch {}; | 1762 | self.local_symbol_free_list.append(self.base.allocator, decl.link.local_sym_index) catch {}; |
| 1780 | self.offset_table_free_list.append(self.allocator, decl.link.offset_table_index) catch {}; | 1763 | self.offset_table_free_list.append(self.base.allocator, decl.link.offset_table_index) catch {}; |
| 1781 | | 1764 | |
| 1782 | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; | 1765 | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; |
| 1783 | | 1766 | |
| ... | @@ -1787,7 +1770,7 @@ pub const File = struct { | ... | @@ -1787,7 +1770,7 @@ pub const File = struct { |
| 1787 | // is desired for both. | 1770 | // is desired for both. |
| 1788 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link); | 1771 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link); |
| 1789 | if (decl.fn_link.prev) |prev| { | 1772 | 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 {}; |
| 1791 | prev.next = decl.fn_link.next; | 1774 | prev.next = decl.fn_link.next; |
| 1792 | if (decl.fn_link.next) |next| { | 1775 | if (decl.fn_link.next) |next| { |
| 1793 | next.prev = prev; | 1776 | next.prev = prev; |
| ... | @@ -1810,10 +1793,10 @@ pub const File = struct { | ... | @@ -1810,10 +1793,10 @@ pub const File = struct { |
| 1810 | const tracy = trace(@src()); | 1793 | const tracy = trace(@src()); |
| 1811 | defer tracy.end(); | 1794 | defer tracy.end(); |
| 1812 | | 1795 | |
| 1813 | var code_buffer = std.ArrayList(u8).init(self.allocator); | 1796 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1814 | defer code_buffer.deinit(); | 1797 | defer code_buffer.deinit(); |
| 1815 | | 1798 | |
| 1816 | var dbg_line_buffer = std.ArrayList(u8).init(self.allocator); | 1799 | var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1817 | defer dbg_line_buffer.deinit(); | 1800 | defer dbg_line_buffer.deinit(); |
| 1818 | | 1801 | |
| 1819 | const typed_value = decl.typed_value.most_recent.typed_value; | 1802 | const typed_value = decl.typed_value.most_recent.typed_value; |
| ... | @@ -1936,7 +1919,7 @@ pub const File = struct { | ... | @@ -1936,7 +1919,7 @@ pub const File = struct { |
| 1936 | | 1919 | |
| 1937 | const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr; | 1920 | const section_offset = local_sym.st_value - self.program_headers.items[self.phdr_load_re_index.?].p_vaddr; |
| 1938 | const file_offset = self.sections.items[self.text_section_index.?].sh_offset + section_offset; | 1921 | 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); |
| 1940 | | 1923 | |
| 1941 | // If the Decl is a function, we need to update the .debug_line program. | 1924 | // If the Decl is a function, we need to update the .debug_line program. |
| 1942 | if (is_fn) { | 1925 | if (is_fn) { |
| ... | @@ -1966,7 +1949,7 @@ pub const File = struct { | ... | @@ -1966,7 +1949,7 @@ pub const File = struct { |
| 1966 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { | 1949 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { |
| 1967 | // It grew too big, so we move it to a new location. | 1950 | // It grew too big, so we move it to a new location. |
| 1968 | if (src_fn.prev) |prev| { | 1951 | 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 {}; |
| 1970 | prev.next = src_fn.next; | 1953 | prev.next = src_fn.next; |
| 1971 | } | 1954 | } |
| 1972 | next.prev = src_fn.prev; | 1955 | next.prev = src_fn.prev; |
| ... | @@ -2009,7 +1992,7 @@ pub const File = struct { | ... | @@ -2009,7 +1992,7 @@ pub const File = struct { |
| 2009 | debug_line_sect.sh_offset, | 1992 | debug_line_sect.sh_offset, |
| 2010 | new_offset, | 1993 | new_offset, |
| 2011 | }); | 1994 | }); |
| 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); |
| 2013 | if (amt != existing_size) return error.InputOutput; | 1996 | if (amt != existing_size) return error.InputOutput; |
| 2014 | debug_line_sect.sh_offset = new_offset; | 1997 | debug_line_sect.sh_offset = new_offset; |
| 2015 | } | 1998 | } |
| ... | @@ -2041,7 +2024,7 @@ pub const File = struct { | ... | @@ -2041,7 +2024,7 @@ pub const File = struct { |
| 2041 | const tracy = trace(@src()); | 2024 | const tracy = trace(@src()); |
| 2042 | defer tracy.end(); | 2025 | defer tracy.end(); |
| 2043 | | 2026 | |
| 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); |
| 2045 | const typed_value = decl.typed_value.most_recent.typed_value; | 2028 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 2046 | if (decl.link.local_sym_index == 0) return; | 2029 | if (decl.link.local_sym_index == 0) return; |
| 2047 | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; | 2030 | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; |
| ... | @@ -2052,7 +2035,7 @@ pub const File = struct { | ... | @@ -2052,7 +2035,7 @@ pub const File = struct { |
| 2052 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | 2035 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 2053 | module.failed_exports.putAssumeCapacityNoClobber( | 2036 | module.failed_exports.putAssumeCapacityNoClobber( |
| 2054 | exp, | 2037 | exp, |
| 2055 | try Module.ErrorMsg.create(self.allocator, 0, "Unimplemented: ExportOptions.section", .{}), | 2038 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}), |
| 2056 | ); | 2039 | ); |
| 2057 | continue; | 2040 | continue; |
| 2058 | } | 2041 | } |
| ... | @@ -2070,7 +2053,7 @@ pub const File = struct { | ... | @@ -2070,7 +2053,7 @@ pub const File = struct { |
| 2070 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); | 2053 | try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1); |
| 2071 | module.failed_exports.putAssumeCapacityNoClobber( | 2054 | module.failed_exports.putAssumeCapacityNoClobber( |
| 2072 | exp, | 2055 | exp, |
| 2073 | try Module.ErrorMsg.create(self.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), | 2056 | try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: GlobalLinkage.LinkOnce", .{}), |
| 2074 | ); | 2057 | ); |
| 2075 | continue; | 2058 | continue; |
| 2076 | }, | 2059 | }, |
| ... | @@ -2125,12 +2108,12 @@ pub const File = struct { | ... | @@ -2125,12 +2108,12 @@ pub const File = struct { |
| 2125 | const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff(); | 2108 | const file_pos = shdr.sh_offset + decl.fn_link.off + self.getRelocDbgLineOff(); |
| 2126 | var data: [4]u8 = undefined; | 2109 | var data: [4]u8 = undefined; |
| 2127 | leb128.writeUnsignedFixed(4, &data, casted_line_off); | 2110 | leb128.writeUnsignedFixed(4, &data, casted_line_off); |
| 2128 | try self.file.?.pwriteAll(&data, file_pos); | 2111 | try self.base.file.?.pwriteAll(&data, file_pos); |
| 2129 | } | 2112 | } |
| 2130 | | 2113 | |
| 2131 | pub fn deleteExport(self: *Elf, exp: Export) void { | 2114 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 2132 | const sym_index = exp.sym_index orelse return; | 2115 | 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 {}; |
| 2134 | self.global_symbols.items[sym_index].st_info = 0; | 2117 | self.global_symbols.items[sym_index].st_info = 0; |
| 2135 | } | 2118 | } |
| 2136 | | 2119 | |
| ... | @@ -2143,14 +2126,14 @@ pub const File = struct { | ... | @@ -2143,14 +2126,14 @@ pub const File = struct { |
| 2143 | if (foreign_endian) { | 2126 | if (foreign_endian) { |
| 2144 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); | 2127 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); |
| 2145 | } | 2128 | } |
| 2146 | return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | 2129 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); |
| 2147 | }, | 2130 | }, |
| 2148 | 64 => { | 2131 | 64 => { |
| 2149 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; | 2132 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; |
| 2150 | if (foreign_endian) { | 2133 | if (foreign_endian) { |
| 2151 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); | 2134 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); |
| 2152 | } | 2135 | } |
| 2153 | return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); | 2136 | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); |
| 2154 | }, | 2137 | }, |
| 2155 | else => return error.UnsupportedArchitecture, | 2138 | else => return error.UnsupportedArchitecture, |
| 2156 | } | 2139 | } |
| ... | @@ -2166,7 +2149,7 @@ pub const File = struct { | ... | @@ -2166,7 +2149,7 @@ pub const File = struct { |
| 2166 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); | 2149 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); |
| 2167 | } | 2150 | } |
| 2168 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr); | 2151 | 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); |
| 2170 | }, | 2153 | }, |
| 2171 | 64 => { | 2154 | 64 => { |
| 2172 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; | 2155 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; |
| ... | @@ -2174,7 +2157,7 @@ pub const File = struct { | ... | @@ -2174,7 +2157,7 @@ pub const File = struct { |
| 2174 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); | 2157 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); |
| 2175 | } | 2158 | } |
| 2176 | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr); | 2159 | 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); |
| 2178 | }, | 2161 | }, |
| 2179 | else => return error.UnsupportedArchitecture, | 2162 | else => return error.UnsupportedArchitecture, |
| 2180 | } | 2163 | } |
| ... | @@ -2191,7 +2174,7 @@ pub const File = struct { | ... | @@ -2191,7 +2174,7 @@ pub const File = struct { |
| 2191 | if (needed_size > allocated_size) { | 2174 | if (needed_size > allocated_size) { |
| 2192 | // Must move the entire got section. | 2175 | // Must move the entire got section. |
| 2193 | const new_offset = self.findFreeSpace(needed_size, entry_size); | 2176 | 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); |
| 2195 | if (amt != shdr.sh_size) return error.InputOutput; | 2178 | if (amt != shdr.sh_size) return error.InputOutput; |
| 2196 | shdr.sh_offset = new_offset; | 2179 | shdr.sh_offset = new_offset; |
| 2197 | phdr.p_offset = new_offset; | 2180 | phdr.p_offset = new_offset; |
| ... | @@ -2211,12 +2194,12 @@ pub const File = struct { | ... | @@ -2211,12 +2194,12 @@ pub const File = struct { |
| 2211 | .p32 => { | 2194 | .p32 => { |
| 2212 | var buf: [4]u8 = undefined; | 2195 | var buf: [4]u8 = undefined; |
| 2213 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); | 2196 | 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); |
| 2215 | }, | 2198 | }, |
| 2216 | .p64 => { | 2199 | .p64 => { |
| 2217 | var buf: [8]u8 = undefined; | 2200 | var buf: [8]u8 = undefined; |
| 2218 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); | 2201 | 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); |
| 2220 | }, | 2203 | }, |
| 2221 | } | 2204 | } |
| 2222 | } | 2205 | } |
| ... | @@ -2239,7 +2222,7 @@ pub const File = struct { | ... | @@ -2239,7 +2222,7 @@ pub const File = struct { |
| 2239 | // Move all the symbols to a new file location. | 2222 | // Move all the symbols to a new file location. |
| 2240 | const new_offset = self.findFreeSpace(needed_size, sym_align); | 2223 | const new_offset = self.findFreeSpace(needed_size, sym_align); |
| 2241 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; | 2224 | 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); |
| 2243 | if (amt != existing_size) return error.InputOutput; | 2226 | if (amt != existing_size) return error.InputOutput; |
| 2244 | syms_sect.sh_offset = new_offset; | 2227 | syms_sect.sh_offset = new_offset; |
| 2245 | } | 2228 | } |
| ... | @@ -2264,7 +2247,7 @@ pub const File = struct { | ... | @@ -2264,7 +2247,7 @@ pub const File = struct { |
| 2264 | bswapAllFields(elf.Elf32_Sym, &sym[0]); | 2247 | bswapAllFields(elf.Elf32_Sym, &sym[0]); |
| 2265 | } | 2248 | } |
| 2266 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index; | 2249 | 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); |
| 2268 | }, | 2251 | }, |
| 2269 | .p64 => { | 2252 | .p64 => { |
| 2270 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; | 2253 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; |
| ... | @@ -2272,7 +2255,7 @@ pub const File = struct { | ... | @@ -2272,7 +2255,7 @@ pub const File = struct { |
| 2272 | bswapAllFields(elf.Elf64_Sym, &sym[0]); | 2255 | bswapAllFields(elf.Elf64_Sym, &sym[0]); |
| 2273 | } | 2256 | } |
| 2274 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index; | 2257 | 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); |
| 2276 | }, | 2259 | }, |
| 2277 | } | 2260 | } |
| 2278 | } | 2261 | } |
| ... | @@ -2287,8 +2270,8 @@ pub const File = struct { | ... | @@ -2287,8 +2270,8 @@ pub const File = struct { |
| 2287 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; | 2270 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; |
| 2288 | switch (self.ptr_width) { | 2271 | switch (self.ptr_width) { |
| 2289 | .p32 => { | 2272 | .p32 => { |
| 2290 | const buf = try self.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len); | 2273 | const buf = try self.base.allocator.alloc(elf.Elf32_Sym, self.global_symbols.items.len); |
| 2291 | defer self.allocator.free(buf); | 2274 | defer self.base.allocator.free(buf); |
| 2292 | | 2275 | |
| 2293 | for (buf) |*sym, i| { | 2276 | for (buf) |*sym, i| { |
| 2294 | sym.* = .{ | 2277 | sym.* = .{ |
| ... | @@ -2303,11 +2286,11 @@ pub const File = struct { | ... | @@ -2303,11 +2286,11 @@ pub const File = struct { |
| 2303 | bswapAllFields(elf.Elf32_Sym, sym); | 2286 | bswapAllFields(elf.Elf32_Sym, sym); |
| 2304 | } | 2287 | } |
| 2305 | } | 2288 | } |
| 2306 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | 2289 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); |
| 2307 | }, | 2290 | }, |
| 2308 | .p64 => { | 2291 | .p64 => { |
| 2309 | const buf = try self.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); | 2292 | const buf = try self.base.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); |
| 2310 | defer self.allocator.free(buf); | 2293 | defer self.base.allocator.free(buf); |
| 2311 | | 2294 | |
| 2312 | for (buf) |*sym, i| { | 2295 | for (buf) |*sym, i| { |
| 2313 | sym.* = .{ | 2296 | sym.* = .{ |
| ... | @@ -2322,7 +2305,7 @@ pub const File = struct { | ... | @@ -2322,7 +2305,7 @@ pub const File = struct { |
| 2322 | bswapAllFields(elf.Elf64_Sym, sym); | 2305 | bswapAllFields(elf.Elf64_Sym, sym); |
| 2323 | } | 2306 | } |
| 2324 | } | 2307 | } |
| 2325 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | 2308 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); |
| 2326 | }, | 2309 | }, |
| 2327 | } | 2310 | } |
| 2328 | } | 2311 | } |
| ... | @@ -2437,7 +2420,7 @@ pub const File = struct { | ... | @@ -2437,7 +2420,7 @@ pub const File = struct { |
| 2437 | vec_index += 1; | 2420 | vec_index += 1; |
| 2438 | } | 2421 | } |
| 2439 | } | 2422 | } |
| 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); |
| 2441 | } | 2424 | } |
| 2442 | | 2425 | |
| 2443 | const min_nop_size = 2; | 2426 | const min_nop_size = 2; |