| ... | @@ -91,7 +91,7 @@ pub fn openBinFile(allocator: *Allocator, file: fs.File, options: Options) !ElfF | ... | @@ -91,7 +91,7 @@ pub fn openBinFile(allocator: *Allocator, file: fs.File, options: Options) !ElfF |
| 91 | | 91 | |
| 92 | pub const ElfFile = struct { | 92 | pub const ElfFile = struct { |
| 93 | allocator: *Allocator, | 93 | allocator: *Allocator, |
| 94 | file: fs.File, | 94 | file: ?fs.File, |
| 95 | owns_file_handle: bool, | 95 | owns_file_handle: bool, |
| 96 | options: Options, | 96 | options: Options, |
| 97 | ptr_width: enum { p32, p64 }, | 97 | ptr_width: enum { p32, p64 }, |
| ... | @@ -170,8 +170,27 @@ pub const ElfFile = struct { | ... | @@ -170,8 +170,27 @@ pub const ElfFile = struct { |
| 170 | self.local_symbols.deinit(self.allocator); | 170 | self.local_symbols.deinit(self.allocator); |
| 171 | self.global_symbols.deinit(self.allocator); | 171 | self.global_symbols.deinit(self.allocator); |
| 172 | self.offset_table.deinit(self.allocator); | 172 | self.offset_table.deinit(self.allocator); |
| 173 | if (self.owns_file_handle) | 173 | if (self.owns_file_handle) { |
| 174 | self.file.close(); | 174 | if (self.file) |f| f.close(); |
| | 175 | } |
| | 176 | } |
| | 177 | |
| | 178 | pub fn makeExecutable(self: *ElfFile) !void { |
| | 179 | assert(self.owns_file_handle); |
| | 180 | if (self.file) |f| { |
| | 181 | f.close(); |
| | 182 | self.file = null; |
| | 183 | } |
| | 184 | } |
| | 185 | |
| | 186 | pub fn makeWritable(self: *ElfFile, dir: fs.Dir, sub_path: []const u8) !void { |
| | 187 | assert(self.owns_file_handle); |
| | 188 | if (self.file != null) return; |
| | 189 | self.file = try dir.createFile(sub_path, .{ |
| | 190 | .truncate = false, |
| | 191 | .read = true, |
| | 192 | .mode = determineMode(self.options), |
| | 193 | }); |
| 175 | } | 194 | } |
| 176 | | 195 | |
| 177 | // `alloc_num / alloc_den` is the factor of padding when allocation | 196 | // `alloc_num / alloc_den` is the factor of padding when allocation |
| ... | @@ -467,7 +486,7 @@ pub const ElfFile = struct { | ... | @@ -467,7 +486,7 @@ pub const ElfFile = struct { |
| 467 | bswapAllFields(elf.Elf32_Phdr, phdr); | 486 | bswapAllFields(elf.Elf32_Phdr, phdr); |
| 468 | } | 487 | } |
| 469 | } | 488 | } |
| 470 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | 489 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); |
| 471 | }, | 490 | }, |
| 472 | .p64 => { | 491 | .p64 => { |
| 473 | const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); | 492 | const buf = try self.allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len); |
| ... | @@ -479,7 +498,7 @@ pub const ElfFile = struct { | ... | @@ -479,7 +498,7 @@ pub const ElfFile = struct { |
| 479 | bswapAllFields(elf.Elf64_Phdr, phdr); | 498 | bswapAllFields(elf.Elf64_Phdr, phdr); |
| 480 | } | 499 | } |
| 481 | } | 500 | } |
| 482 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); | 501 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?); |
| 483 | }, | 502 | }, |
| 484 | } | 503 | } |
| 485 | self.phdr_table_dirty = false; | 504 | self.phdr_table_dirty = false; |
| ... | @@ -498,7 +517,7 @@ pub const ElfFile = struct { | ... | @@ -498,7 +517,7 @@ pub const ElfFile = struct { |
| 498 | shstrtab_sect.sh_size = needed_size; | 517 | shstrtab_sect.sh_size = needed_size; |
| 499 | //std.debug.warn("shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); | 518 | //std.debug.warn("shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); |
| 500 | | 519 | |
| 501 | try self.file.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); | 520 | try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); |
| 502 | if (!self.shdr_table_dirty) { | 521 | if (!self.shdr_table_dirty) { |
| 503 | // Then it won't get written with the others and we need to do it. | 522 | // Then it won't get written with the others and we need to do it. |
| 504 | try self.writeSectHeader(self.shstrtab_index.?); | 523 | try self.writeSectHeader(self.shstrtab_index.?); |
| ... | @@ -534,7 +553,7 @@ pub const ElfFile = struct { | ... | @@ -534,7 +553,7 @@ pub const ElfFile = struct { |
| 534 | bswapAllFields(elf.Elf32_Shdr, shdr); | 553 | bswapAllFields(elf.Elf32_Shdr, shdr); |
| 535 | } | 554 | } |
| 536 | } | 555 | } |
| 537 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | 556 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 538 | }, | 557 | }, |
| 539 | .p64 => { | 558 | .p64 => { |
| 540 | const buf = try self.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); | 559 | const buf = try self.allocator.alloc(elf.Elf64_Shdr, self.sections.items.len); |
| ... | @@ -547,7 +566,7 @@ pub const ElfFile = struct { | ... | @@ -547,7 +566,7 @@ pub const ElfFile = struct { |
| 547 | bswapAllFields(elf.Elf64_Shdr, shdr); | 566 | bswapAllFields(elf.Elf64_Shdr, shdr); |
| 548 | } | 567 | } |
| 549 | } | 568 | } |
| 550 | try self.file.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | 569 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 551 | }, | 570 | }, |
| 552 | } | 571 | } |
| 553 | self.shdr_table_dirty = false; | 572 | self.shdr_table_dirty = false; |
| ... | @@ -687,7 +706,7 @@ pub const ElfFile = struct { | ... | @@ -687,7 +706,7 @@ pub const ElfFile = struct { |
| 687 | | 706 | |
| 688 | assert(index == e_ehsize); | 707 | assert(index == e_ehsize); |
| 689 | | 708 | |
| 690 | try self.file.pwriteAll(hdr_buf[0..index], 0); | 709 | try self.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 691 | } | 710 | } |
| 692 | | 711 | |
| 693 | const AllocatedBlock = struct { | 712 | const AllocatedBlock = struct { |
| ... | @@ -718,7 +737,7 @@ pub const ElfFile = struct { | ... | @@ -718,7 +737,7 @@ pub const ElfFile = struct { |
| 718 | // Must move the entire text section. | 737 | // Must move the entire text section. |
| 719 | const new_offset = self.findFreeSpace(needed_size, 0x1000); | 738 | const new_offset = self.findFreeSpace(needed_size, 0x1000); |
| 720 | const text_size = (last_start + last_size) - phdr.p_vaddr; | 739 | const text_size = (last_start + last_size) - phdr.p_vaddr; |
| 721 | const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, text_size); | 740 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, text_size); |
| 722 | if (amt != text_size) return error.InputOutput; | 741 | if (amt != text_size) return error.InputOutput; |
| 723 | shdr.sh_offset = new_offset; | 742 | shdr.sh_offset = new_offset; |
| 724 | } | 743 | } |
| ... | @@ -876,7 +895,7 @@ pub const ElfFile = struct { | ... | @@ -876,7 +895,7 @@ pub const ElfFile = struct { |
| 876 | } | 895 | } |
| 877 | }; | 896 | }; |
| 878 | | 897 | |
| 879 | try self.file.pwriteAll(code, file_offset); | 898 | try self.file.?.pwriteAll(code, file_offset); |
| 880 | | 899 | |
| 881 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. | 900 | // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated. |
| 882 | const decl_exports = module.decl_exports.getValue(decl) orelse &[0]*Module.Export{}; | 901 | const decl_exports = module.decl_exports.getValue(decl) orelse &[0]*Module.Export{}; |
| ... | @@ -962,14 +981,14 @@ pub const ElfFile = struct { | ... | @@ -962,14 +981,14 @@ pub const ElfFile = struct { |
| 962 | if (foreign_endian) { | 981 | if (foreign_endian) { |
| 963 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); | 982 | bswapAllFields(elf.Elf32_Phdr, &phdr[0]); |
| 964 | } | 983 | } |
| 965 | return self.file.pwriteAll(mem.sliceAsBytes(&phdr), offset); | 984 | return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); |
| 966 | }, | 985 | }, |
| 967 | 64 => { | 986 | 64 => { |
| 968 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; | 987 | var phdr = [1]elf.Elf64_Phdr{self.program_headers.items[index]}; |
| 969 | if (foreign_endian) { | 988 | if (foreign_endian) { |
| 970 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); | 989 | bswapAllFields(elf.Elf64_Phdr, &phdr[0]); |
| 971 | } | 990 | } |
| 972 | return self.file.pwriteAll(mem.sliceAsBytes(&phdr), offset); | 991 | return self.file.?.pwriteAll(mem.sliceAsBytes(&phdr), offset); |
| 973 | }, | 992 | }, |
| 974 | else => return error.UnsupportedArchitecture, | 993 | else => return error.UnsupportedArchitecture, |
| 975 | } | 994 | } |
| ... | @@ -985,14 +1004,14 @@ pub const ElfFile = struct { | ... | @@ -985,14 +1004,14 @@ pub const ElfFile = struct { |
| 985 | if (foreign_endian) { | 1004 | if (foreign_endian) { |
| 986 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); | 1005 | bswapAllFields(elf.Elf32_Shdr, &shdr[0]); |
| 987 | } | 1006 | } |
| 988 | return self.file.pwriteAll(mem.sliceAsBytes(&shdr), offset); | 1007 | return self.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); |
| 989 | }, | 1008 | }, |
| 990 | 64 => { | 1009 | 64 => { |
| 991 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; | 1010 | var shdr = [1]elf.Elf64_Shdr{self.sections.items[index]}; |
| 992 | if (foreign_endian) { | 1011 | if (foreign_endian) { |
| 993 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); | 1012 | bswapAllFields(elf.Elf64_Shdr, &shdr[0]); |
| 994 | } | 1013 | } |
| 995 | return self.file.pwriteAll(mem.sliceAsBytes(&shdr), offset); | 1014 | return self.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); |
| 996 | }, | 1015 | }, |
| 997 | else => return error.UnsupportedArchitecture, | 1016 | else => return error.UnsupportedArchitecture, |
| 998 | } | 1017 | } |
| ... | @@ -1012,7 +1031,7 @@ pub const ElfFile = struct { | ... | @@ -1012,7 +1031,7 @@ pub const ElfFile = struct { |
| 1012 | if (needed_size > allocated_size) { | 1031 | if (needed_size > allocated_size) { |
| 1013 | // Must move the entire got section. | 1032 | // Must move the entire got section. |
| 1014 | const new_offset = self.findFreeSpace(needed_size, entry_size); | 1033 | const new_offset = self.findFreeSpace(needed_size, entry_size); |
| 1015 | const amt = try self.file.copyRangeAll(shdr.sh_offset, self.file, new_offset, shdr.sh_size); | 1034 | const amt = try self.file.?.copyRangeAll(shdr.sh_offset, self.file.?, new_offset, shdr.sh_size); |
| 1016 | if (amt != shdr.sh_size) return error.InputOutput; | 1035 | if (amt != shdr.sh_size) return error.InputOutput; |
| 1017 | shdr.sh_offset = new_offset; | 1036 | shdr.sh_offset = new_offset; |
| 1018 | } | 1037 | } |
| ... | @@ -1031,12 +1050,12 @@ pub const ElfFile = struct { | ... | @@ -1031,12 +1050,12 @@ pub const ElfFile = struct { |
| 1031 | .p32 => { | 1050 | .p32 => { |
| 1032 | var buf: [4]u8 = undefined; | 1051 | var buf: [4]u8 = undefined; |
| 1033 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); | 1052 | mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian); |
| 1034 | try self.file.pwriteAll(&buf, off); | 1053 | try self.file.?.pwriteAll(&buf, off); |
| 1035 | }, | 1054 | }, |
| 1036 | .p64 => { | 1055 | .p64 => { |
| 1037 | var buf: [8]u8 = undefined; | 1056 | var buf: [8]u8 = undefined; |
| 1038 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); | 1057 | mem.writeInt(u64, &buf, self.offset_table.items[index], endian); |
| 1039 | try self.file.pwriteAll(&buf, off); | 1058 | try self.file.?.pwriteAll(&buf, off); |
| 1040 | }, | 1059 | }, |
| 1041 | } | 1060 | } |
| 1042 | } | 1061 | } |
| ... | @@ -1059,7 +1078,7 @@ pub const ElfFile = struct { | ... | @@ -1059,7 +1078,7 @@ pub const ElfFile = struct { |
| 1059 | // Move all the symbols to a new file location. | 1078 | // Move all the symbols to a new file location. |
| 1060 | const new_offset = self.findFreeSpace(needed_size, sym_align); | 1079 | const new_offset = self.findFreeSpace(needed_size, sym_align); |
| 1061 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; | 1080 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; |
| 1062 | const amt = try self.file.copyRangeAll(syms_sect.sh_offset, self.file, new_offset, existing_size); | 1081 | const amt = try self.file.?.copyRangeAll(syms_sect.sh_offset, self.file.?, new_offset, existing_size); |
| 1063 | if (amt != existing_size) return error.InputOutput; | 1082 | if (amt != existing_size) return error.InputOutput; |
| 1064 | syms_sect.sh_offset = new_offset; | 1083 | syms_sect.sh_offset = new_offset; |
| 1065 | } | 1084 | } |
| ... | @@ -1084,7 +1103,7 @@ pub const ElfFile = struct { | ... | @@ -1084,7 +1103,7 @@ pub const ElfFile = struct { |
| 1084 | bswapAllFields(elf.Elf32_Sym, &sym[0]); | 1103 | bswapAllFields(elf.Elf32_Sym, &sym[0]); |
| 1085 | } | 1104 | } |
| 1086 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index; | 1105 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf32_Sym) * index; |
| 1087 | try self.file.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | 1106 | try self.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); |
| 1088 | }, | 1107 | }, |
| 1089 | .p64 => { | 1108 | .p64 => { |
| 1090 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; | 1109 | var sym = [1]elf.Elf64_Sym{self.local_symbols.items[index]}; |
| ... | @@ -1092,7 +1111,7 @@ pub const ElfFile = struct { | ... | @@ -1092,7 +1111,7 @@ pub const ElfFile = struct { |
| 1092 | bswapAllFields(elf.Elf64_Sym, &sym[0]); | 1111 | bswapAllFields(elf.Elf64_Sym, &sym[0]); |
| 1093 | } | 1112 | } |
| 1094 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index; | 1113 | const off = syms_sect.sh_offset + @sizeOf(elf.Elf64_Sym) * index; |
| 1095 | try self.file.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); | 1114 | try self.file.?.pwriteAll(mem.sliceAsBytes(sym[0..1]), off); |
| 1096 | }, | 1115 | }, |
| 1097 | } | 1116 | } |
| 1098 | } | 1117 | } |
| ... | @@ -1124,7 +1143,7 @@ pub const ElfFile = struct { | ... | @@ -1124,7 +1143,7 @@ pub const ElfFile = struct { |
| 1124 | bswapAllFields(elf.Elf32_Sym, sym); | 1143 | bswapAllFields(elf.Elf32_Sym, sym); |
| 1125 | } | 1144 | } |
| 1126 | } | 1145 | } |
| 1127 | try self.file.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | 1146 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); |
| 1128 | }, | 1147 | }, |
| 1129 | .p64 => { | 1148 | .p64 => { |
| 1130 | const buf = try self.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); | 1149 | const buf = try self.allocator.alloc(elf.Elf64_Sym, self.global_symbols.items.len); |
| ... | @@ -1143,7 +1162,7 @@ pub const ElfFile = struct { | ... | @@ -1143,7 +1162,7 @@ pub const ElfFile = struct { |
| 1143 | bswapAllFields(elf.Elf64_Sym, sym); | 1162 | bswapAllFields(elf.Elf64_Sym, sym); |
| 1144 | } | 1163 | } |
| 1145 | } | 1164 | } |
| 1146 | try self.file.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); | 1165 | try self.file.?.pwriteAll(mem.sliceAsBytes(buf), global_syms_off); |
| 1147 | }, | 1166 | }, |
| 1148 | } | 1167 | } |
| 1149 | } | 1168 | } |