| ... | ... | @@ -125,36 +125,34 @@ pub const File = struct { |
| 125 | 125 | } |
| 126 | 126 | |
| 127 | 127 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { |
| 128 | | try switch (base.tag) { |
| 129 | | .Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path), |
| 130 | | .C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path), |
| 128 | switch (base.tag) { |
| 129 | .Elf => return @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path), |
| 130 | .C => return @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path), |
| 131 | 131 | else => unreachable, |
| 132 | | }; |
| 132 | } |
| 133 | 133 | } |
| 134 | 134 | |
| 135 | 135 | pub fn makeExecutable(base: *File) !void { |
| 136 | | try switch (base.tag) { |
| 137 | | .Elf => @fieldParentPtr(Elf, "base", base).makeExecutable(), |
| 136 | switch (base.tag) { |
| 137 | .Elf => return @fieldParentPtr(Elf, "base", base).makeExecutable(), |
| 138 | 138 | else => unreachable, |
| 139 | | }; |
| 139 | } |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { |
| 143 | | try switch (base.tag) { |
| 144 | | .Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| 145 | | .C => @fieldParentPtr(C, "base", base).updateDecl(module, decl), |
| 143 | switch (base.tag) { |
| 144 | .Elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| 145 | .C => return @fieldParentPtr(C, "base", base).updateDecl(module, decl), |
| 146 | 146 | else => unreachable, |
| 147 | | }; |
| 147 | } |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | 150 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { |
| 151 | | try switch (base.tag) { |
| 152 | | .Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| 153 | | .C => { |
| 154 | | //TODO |
| 155 | | }, |
| 151 | switch (base.tag) { |
| 152 | .Elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| 153 | .C => {}, |
| 156 | 154 | else => unreachable, |
| 157 | | }; |
| 155 | } |
| 158 | 156 | } |
| 159 | 157 | |
| 160 | 158 | pub fn deinit(base: *File) void { |
| ... | ... | @@ -380,7 +378,7 @@ pub const File = struct { |
| 380 | 378 | /// Returns how much room there is to grow in virtual address space. |
| 381 | 379 | /// File offset relocation happens transparently, so it is not included in |
| 382 | 380 | /// this calculation. |
| 383 | | fn capacity(self: TextBlock, elf_file: File.Elf) u64 { |
| 381 | fn capacity(self: TextBlock, elf_file: Elf) u64 { |
| 384 | 382 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; |
| 385 | 383 | if (self.next) |next| { |
| 386 | 384 | const next_sym = elf_file.local_symbols.items[next.local_sym_index]; |
| ... | ... | @@ -391,7 +389,7 @@ pub const File = struct { |
| 391 | 389 | } |
| 392 | 390 | } |
| 393 | 391 | |
| 394 | | fn freeListEligible(self: TextBlock, elf_file: File.Elf) bool { |
| 392 | fn freeListEligible(self: TextBlock, elf_file: Elf) bool { |
| 395 | 393 | // No need to keep a free list node for the last block. |
| 396 | 394 | const next = self.next orelse return false; |
| 397 | 395 | const self_sym = elf_file.local_symbols.items[self.local_sym_index]; |
| ... | ... | @@ -408,7 +406,7 @@ pub const File = struct { |
| 408 | 406 | sym_index: ?u32 = null, |
| 409 | 407 | }; |
| 410 | 408 | |
| 411 | | pub fn deinit(self: *File.Elf) void { |
| 409 | pub fn deinit(self: *Elf) void { |
| 412 | 410 | self.sections.deinit(self.allocator); |
| 413 | 411 | self.program_headers.deinit(self.allocator); |
| 414 | 412 | self.shstrtab.deinit(self.allocator); |
| ... | ... | @@ -424,7 +422,7 @@ pub const File = struct { |
| 424 | 422 | } |
| 425 | 423 | } |
| 426 | 424 | |
| 427 | | pub fn makeExecutable(self: *File.Elf) !void { |
| 425 | pub fn makeExecutable(self: *Elf) !void { |
| 428 | 426 | assert(self.owns_file_handle); |
| 429 | 427 | if (self.file) |f| { |
| 430 | 428 | f.close(); |
| ... | ... | @@ -432,7 +430,7 @@ pub const File = struct { |
| 432 | 430 | } |
| 433 | 431 | } |
| 434 | 432 | |
| 435 | | pub fn makeWritable(self: *File.Elf, dir: fs.Dir, sub_path: []const u8) !void { |
| 433 | pub fn makeWritable(self: *Elf, dir: fs.Dir, sub_path: []const u8) !void { |
| 436 | 434 | assert(self.owns_file_handle); |
| 437 | 435 | if (self.file != null) return; |
| 438 | 436 | self.file = try dir.createFile(sub_path, .{ |
| ... | ... | @@ -443,7 +441,7 @@ pub const File = struct { |
| 443 | 441 | } |
| 444 | 442 | |
| 445 | 443 | /// Returns end pos of collision, if any. |
| 446 | | fn detectAllocCollision(self: *File.Elf, start: u64, size: u64) ?u64 { |
| 444 | fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 447 | 445 | const small_ptr = self.options.target.cpu.arch.ptrBitWidth() == 32; |
| 448 | 446 | const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); |
| 449 | 447 | if (start < ehdr_size) |
| ... | ... | @@ -488,7 +486,7 @@ pub const File = struct { |
| 488 | 486 | return null; |
| 489 | 487 | } |
| 490 | 488 | |
| 491 | | fn allocatedSize(self: *File.Elf, start: u64) u64 { |
| 489 | fn allocatedSize(self: *Elf, start: u64) u64 { |
| 492 | 490 | var min_pos: u64 = std.math.maxInt(u64); |
| 493 | 491 | if (self.shdr_table_offset) |off| { |
| 494 | 492 | if (off > start and off < min_pos) min_pos = off; |
| ... | ... | @@ -507,7 +505,7 @@ pub const File = struct { |
| 507 | 505 | return min_pos - start; |
| 508 | 506 | } |
| 509 | 507 | |
| 510 | | fn findFreeSpace(self: *File.Elf, object_size: u64, min_alignment: u16) u64 { |
| 508 | fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u16) u64 { |
| 511 | 509 | var start: u64 = 0; |
| 512 | 510 | while (self.detectAllocCollision(start, object_size)) |item_end| { |
| 513 | 511 | start = mem.alignForwardGeneric(u64, item_end, min_alignment); |
| ... | ... | @@ -515,7 +513,7 @@ pub const File = struct { |
| 515 | 513 | return start; |
| 516 | 514 | } |
| 517 | 515 | |
| 518 | | fn makeString(self: *File.Elf, bytes: []const u8) !u32 { |
| 516 | fn makeString(self: *Elf, bytes: []const u8) !u32 { |
| 519 | 517 | try self.shstrtab.ensureCapacity(self.allocator, self.shstrtab.items.len + bytes.len + 1); |
| 520 | 518 | const result = self.shstrtab.items.len; |
| 521 | 519 | self.shstrtab.appendSliceAssumeCapacity(bytes); |
| ... | ... | @@ -523,12 +521,12 @@ pub const File = struct { |
| 523 | 521 | return @intCast(u32, result); |
| 524 | 522 | } |
| 525 | 523 | |
| 526 | | fn getString(self: *File.Elf, str_off: u32) []const u8 { |
| 524 | fn getString(self: *Elf, str_off: u32) []const u8 { |
| 527 | 525 | assert(str_off < self.shstrtab.items.len); |
| 528 | 526 | return mem.spanZ(@ptrCast([*:0]const u8, self.shstrtab.items.ptr + str_off)); |
| 529 | 527 | } |
| 530 | 528 | |
| 531 | | fn updateString(self: *File.Elf, old_str_off: u32, new_name: []const u8) !u32 { |
| 529 | fn updateString(self: *Elf, old_str_off: u32, new_name: []const u8) !u32 { |
| 532 | 530 | const existing_name = self.getString(old_str_off); |
| 533 | 531 | if (mem.eql(u8, existing_name, new_name)) { |
| 534 | 532 | return old_str_off; |
| ... | ... | @@ -536,7 +534,7 @@ pub const File = struct { |
| 536 | 534 | return self.makeString(new_name); |
| 537 | 535 | } |
| 538 | 536 | |
| 539 | | pub fn populateMissingMetadata(self: *File.Elf) !void { |
| 537 | pub fn populateMissingMetadata(self: *Elf) !void { |
| 540 | 538 | const small_ptr = switch (self.ptr_width) { |
| 541 | 539 | .p32 => true, |
| 542 | 540 | .p64 => false, |
| ... | ... | @@ -703,7 +701,7 @@ pub const File = struct { |
| 703 | 701 | } |
| 704 | 702 | |
| 705 | 703 | /// Commit pending changes and write headers. |
| 706 | | pub fn flush(self: *File.Elf) !void { |
| 704 | pub fn flush(self: *Elf) !void { |
| 707 | 705 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 708 | 706 | |
| 709 | 707 | // Unfortunately these have to be buffered and done at the end because ELF does not allow |
| ... | ... | @@ -839,7 +837,7 @@ pub const File = struct { |
| 839 | 837 | assert(syms_sect.sh_info == self.local_symbols.items.len); |
| 840 | 838 | } |
| 841 | 839 | |
| 842 | | fn writeElfHeader(self: *File.Elf) !void { |
| 840 | fn writeElfHeader(self: *Elf) !void { |
| 843 | 841 | var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 = undefined; |
| 844 | 842 | |
| 845 | 843 | var index: usize = 0; |
| ... | ... | @@ -960,7 +958,7 @@ pub const File = struct { |
| 960 | 958 | try self.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 961 | 959 | } |
| 962 | 960 | |
| 963 | | fn freeTextBlock(self: *File.Elf, text_block: *TextBlock) void { |
| 961 | fn freeTextBlock(self: *Elf, text_block: *TextBlock) void { |
| 964 | 962 | var already_have_free_list_node = false; |
| 965 | 963 | { |
| 966 | 964 | var i: usize = 0; |
| ... | ... | @@ -1000,12 +998,12 @@ pub const File = struct { |
| 1000 | 998 | } |
| 1001 | 999 | } |
| 1002 | 1000 | |
| 1003 | | fn shrinkTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64) void { |
| 1001 | fn shrinkTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64) void { |
| 1004 | 1002 | // TODO check the new capacity, and if it crosses the size threshold into a big enough |
| 1005 | 1003 | // capacity, insert a free list node for it. |
| 1006 | 1004 | } |
| 1007 | 1005 | |
| 1008 | | fn growTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { |
| 1006 | fn growTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { |
| 1009 | 1007 | const sym = self.local_symbols.items[text_block.local_sym_index]; |
| 1010 | 1008 | const align_ok = mem.alignBackwardGeneric(u64, sym.st_value, alignment) == sym.st_value; |
| 1011 | 1009 | const need_realloc = !align_ok or new_block_size > text_block.capacity(self.*); |
| ... | ... | @@ -1013,7 +1011,7 @@ pub const File = struct { |
| 1013 | 1011 | return self.allocateTextBlock(text_block, new_block_size, alignment); |
| 1014 | 1012 | } |
| 1015 | 1013 | |
| 1016 | | fn allocateTextBlock(self: *File.Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { |
| 1014 | fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { |
| 1017 | 1015 | const phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1018 | 1016 | const shdr = &self.sections.items[self.text_section_index.?]; |
| 1019 | 1017 | const new_block_ideal_capacity = new_block_size * alloc_num / alloc_den; |
| ... | ... | @@ -1127,7 +1125,7 @@ pub const File = struct { |
| 1127 | 1125 | return vaddr; |
| 1128 | 1126 | } |
| 1129 | 1127 | |
| 1130 | | pub fn allocateDeclIndexes(self: *File.Elf, decl: *Module.Decl) !void { |
| 1128 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 1131 | 1129 | if (decl.link.local_sym_index != 0) return; |
| 1132 | 1130 | |
| 1133 | 1131 | // Here we also ensure capacity for the free lists so that they can be appended to without fail. |
| ... | ... | @@ -1166,7 +1164,7 @@ pub const File = struct { |
| 1166 | 1164 | self.offset_table.items[decl.link.offset_table_index] = 0; |
| 1167 | 1165 | } |
| 1168 | 1166 | |
| 1169 | | pub fn freeDecl(self: *File.Elf, decl: *Module.Decl) void { |
| 1167 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| 1170 | 1168 | self.freeTextBlock(&decl.link); |
| 1171 | 1169 | if (decl.link.local_sym_index != 0) { |
| 1172 | 1170 | self.local_symbol_free_list.appendAssumeCapacity(decl.link.local_sym_index); |
| ... | ... | @@ -1178,7 +1176,7 @@ pub const File = struct { |
| 1178 | 1176 | } |
| 1179 | 1177 | } |
| 1180 | 1178 | |
| 1181 | | pub fn updateDecl(self: *File.Elf, module: *Module, decl: *Module.Decl) !void { |
| 1179 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 1182 | 1180 | var code_buffer = std.ArrayList(u8).init(self.allocator); |
| 1183 | 1181 | defer code_buffer.deinit(); |
| 1184 | 1182 | |
| ... | ... | @@ -1258,7 +1256,7 @@ pub const File = struct { |
| 1258 | 1256 | |
| 1259 | 1257 | /// Must be called only after a successful call to `updateDecl`. |
| 1260 | 1258 | pub fn updateDeclExports( |
| 1261 | | self: *File.Elf, |
| 1259 | self: *Elf, |
| 1262 | 1260 | module: *Module, |
| 1263 | 1261 | decl: *const Module.Decl, |
| 1264 | 1262 | exports: []const *Module.Export, |
| ... | ... | @@ -1331,13 +1329,13 @@ pub const File = struct { |
| 1331 | 1329 | } |
| 1332 | 1330 | } |
| 1333 | 1331 | |
| 1334 | | pub fn deleteExport(self: *File.Elf, exp: Export) void { |
| 1332 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 1335 | 1333 | const sym_index = exp.sym_index orelse return; |
| 1336 | 1334 | self.global_symbol_free_list.appendAssumeCapacity(sym_index); |
| 1337 | 1335 | self.global_symbols.items[sym_index].st_info = 0; |
| 1338 | 1336 | } |
| 1339 | 1337 | |
| 1340 | | fn writeProgHeader(self: *File.Elf, index: usize) !void { |
| 1338 | fn writeProgHeader(self: *Elf, index: usize) !void { |
| 1341 | 1339 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 1342 | 1340 | const offset = self.program_headers.items[index].p_offset; |
| 1343 | 1341 | switch (self.options.target.cpu.arch.ptrBitWidth()) { |
| ... | ... | @@ -1359,7 +1357,7 @@ pub const File = struct { |
| 1359 | 1357 | } |
| 1360 | 1358 | } |
| 1361 | 1359 | |
| 1362 | | fn writeSectHeader(self: *File.Elf, index: usize) !void { |
| 1360 | fn writeSectHeader(self: *Elf, index: usize) !void { |
| 1363 | 1361 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 1364 | 1362 | const offset = self.sections.items[index].sh_offset; |
| 1365 | 1363 | switch (self.options.target.cpu.arch.ptrBitWidth()) { |
| ... | ... | @@ -1382,7 +1380,7 @@ pub const File = struct { |
| 1382 | 1380 | } |
| 1383 | 1381 | } |
| 1384 | 1382 | |
| 1385 | | fn writeOffsetTableEntry(self: *File.Elf, index: usize) !void { |
| 1383 | fn writeOffsetTableEntry(self: *Elf, index: usize) !void { |
| 1386 | 1384 | const shdr = &self.sections.items[self.got_section_index.?]; |
| 1387 | 1385 | const phdr = &self.program_headers.items[self.phdr_got_index.?]; |
| 1388 | 1386 | const entry_size: u16 = switch (self.ptr_width) { |
| ... | ... | @@ -1426,7 +1424,7 @@ pub const File = struct { |
| 1426 | 1424 | } |
| 1427 | 1425 | } |
| 1428 | 1426 | |
| 1429 | | fn writeSymbol(self: *File.Elf, index: usize) !void { |
| 1427 | fn writeSymbol(self: *Elf, index: usize) !void { |
| 1430 | 1428 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; |
| 1431 | 1429 | // Make sure we are not pointlessly writing symbol data that will have to get relocated |
| 1432 | 1430 | // due to running out of space. |
| ... | ... | @@ -1482,7 +1480,7 @@ pub const File = struct { |
| 1482 | 1480 | } |
| 1483 | 1481 | } |
| 1484 | 1482 | |
| 1485 | | fn writeAllGlobalSymbols(self: *File.Elf) !void { |
| 1483 | fn writeAllGlobalSymbols(self: *Elf) !void { |
| 1486 | 1484 | const syms_sect = &self.sections.items[self.symtab_section_index.?]; |
| 1487 | 1485 | const sym_size: u64 = switch (self.ptr_width) { |
| 1488 | 1486 | .p32 => @sizeOf(elf.Elf32_Sym), |