| ... | @@ -6,6 +6,10 @@ ptr_width: PtrWidth, | ... | @@ -6,6 +6,10 @@ ptr_width: PtrWidth, |
| 6 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. | 6 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. |
| 7 | llvm_object: ?*LlvmObject = null, | 7 | llvm_object: ?*LlvmObject = null, |
| 8 | | 8 | |
| | 9 | files: std.MutliArrayList(File.Entry) = .{}, |
| | 10 | zig_module_index: ?File.Index = null, |
| | 11 | linker_defined_index: ?File.Index = null, |
| | 12 | |
| 9 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 13 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 10 | /// Same order as in the file. | 14 | /// Same order as in the file. |
| 11 | sections: std.MultiArrayList(Section) = .{}, | 15 | sections: std.MultiArrayList(Section) = .{}, |
| ... | @@ -51,16 +55,12 @@ debug_line_section_index: ?u16 = null, | ... | @@ -51,16 +55,12 @@ debug_line_section_index: ?u16 = null, |
| 51 | shstrtab_section_index: ?u16 = null, | 55 | shstrtab_section_index: ?u16 = null, |
| 52 | strtab_section_index: ?u16 = null, | 56 | strtab_section_index: ?u16 = null, |
| 53 | | 57 | |
| 54 | /// The same order as in the file. ELF requires global symbols to all be after the | 58 | symbols: std.ArrayListUnmanaged(Symbol) = .{}, |
| 55 | /// local symbols, they cannot be mixed. So we must buffer all the global symbols and | 59 | globals: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 56 | /// write them at the end. These are only the local symbols. The length of this array | | |
| 57 | /// is the value used for sh_info in the .symtab section. | | |
| 58 | locals: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{}, | | |
| 59 | globals: std.ArrayListUnmanaged(u32) = .{}, | | |
| 60 | resolver: std.StringHashMapUnmanaged(u32) = .{}, | 60 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| 61 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, | 61 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 62 | | 62 | |
| 63 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 63 | symbols_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 64 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 64 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 65 | | 65 | |
| 66 | got_table: TableSection(u32) = .{}, | 66 | got_table: TableSection(u32) = .{}, |
| ... | @@ -77,7 +77,7 @@ debug_aranges_section_dirty: bool = false, | ... | @@ -77,7 +77,7 @@ debug_aranges_section_dirty: bool = false, |
| 77 | debug_info_header_dirty: bool = false, | 77 | debug_info_header_dirty: bool = false, |
| 78 | debug_line_header_dirty: bool = false, | 78 | debug_line_header_dirty: bool = false, |
| 79 | | 79 | |
| 80 | error_flags: File.ErrorFlags = File.ErrorFlags{}, | 80 | error_flags: link.File.ErrorFlags = link.File.ErrorFlags{}, |
| 81 | | 81 | |
| 82 | /// Table of tracked LazySymbols. | 82 | /// Table of tracked LazySymbols. |
| 83 | lazy_syms: LazySymbolTable = .{}, | 83 | lazy_syms: LazySymbolTable = .{}, |
| ... | @@ -153,9 +153,11 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option | ... | @@ -153,9 +153,11 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 153 | self.shdr_table_dirty = true; | 153 | self.shdr_table_dirty = true; |
| 154 | | 154 | |
| 155 | // Index 0 is always a null symbol. | 155 | // Index 0 is always a null symbol. |
| 156 | try self.locals.append(allocator, null_sym); | 156 | try self.symbols.append(allocator, .{}); |
| 157 | // Allocate atom index 0 to null atom | 157 | // Allocate atom index 0 to null atom |
| 158 | try self.atoms.append(allocator, .{}); | 158 | try self.atoms.append(allocator, .{}); |
| | 159 | // Append null file at index 0 |
| | 160 | try self.files.append(allocator, .null); |
| 159 | // There must always be a null section in index 0 | 161 | // There must always be a null section in index 0 |
| 160 | try self.sections.append(allocator, .{ | 162 | try self.sections.append(allocator, .{ |
| 161 | .shdr = .{ | 163 | .shdr = .{ |
| ... | @@ -222,6 +224,15 @@ pub fn deinit(self: *Elf) void { | ... | @@ -222,6 +224,15 @@ pub fn deinit(self: *Elf) void { |
| 222 | | 224 | |
| 223 | if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); | 225 | if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa); |
| 224 | | 226 | |
| | 227 | for (self.files.items(.tags), self.files.items(.data)) |tag, *data| switch (tag) { |
| | 228 | .null => {}, |
| | 229 | .zig_module => data.zig_module.deinit(gpa), |
| | 230 | .linker_defined => data.linker_defined.deinit(gpa), |
| | 231 | // .object => data.object.deinit(gpa), |
| | 232 | // .shared_object => data.shared_object.deinit(gpa), |
| | 233 | }; |
| | 234 | self.files.deinit(gpa); |
| | 235 | |
| 225 | for (self.sections.items(.free_list)) |*free_list| { | 236 | for (self.sections.items(.free_list)) |*free_list| { |
| 226 | free_list.deinit(gpa); | 237 | free_list.deinit(gpa); |
| 227 | } | 238 | } |
| ... | @@ -230,10 +241,10 @@ pub fn deinit(self: *Elf) void { | ... | @@ -230,10 +241,10 @@ pub fn deinit(self: *Elf) void { |
| 230 | self.program_headers.deinit(gpa); | 241 | self.program_headers.deinit(gpa); |
| 231 | self.shstrtab.deinit(gpa); | 242 | self.shstrtab.deinit(gpa); |
| 232 | self.strtab.deinit(gpa); | 243 | self.strtab.deinit(gpa); |
| 233 | self.locals.deinit(gpa); | 244 | self.symbols.deinit(gpa); |
| | 245 | self.symbols_free_list.deinit(gpa); |
| 234 | self.globals.deinit(gpa); | 246 | self.globals.deinit(gpa); |
| 235 | self.globals_free_list.deinit(gpa); | 247 | self.globals_free_list.deinit(gpa); |
| 236 | self.locals_free_list.deinit(gpa); | | |
| 237 | self.got_table.deinit(gpa); | 248 | self.got_table.deinit(gpa); |
| 238 | self.unresolved.deinit(gpa); | 249 | self.unresolved.deinit(gpa); |
| 239 | | 250 | |
| ... | @@ -278,7 +289,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -278,7 +289,7 @@ pub fn deinit(self: *Elf) void { |
| 278 | } | 289 | } |
| 279 | } | 290 | } |
| 280 | | 291 | |
| 281 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: File.RelocInfo) !u64 { | 292 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { |
| 282 | assert(self.llvm_object == null); | 293 | assert(self.llvm_object == null); |
| 283 | | 294 | |
| 284 | const this_atom_index = try self.getOrCreateAtomForDecl(decl_index); | 295 | const this_atom_index = try self.getOrCreateAtomForDecl(decl_index); |
| ... | @@ -653,7 +664,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -653,7 +664,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 653 | .sh_size = file_size, | 664 | .sh_size = file_size, |
| 654 | // The section header index of the associated string table. | 665 | // The section header index of the associated string table. |
| 655 | .sh_link = self.strtab_section_index.?, | 666 | .sh_link = self.strtab_section_index.?, |
| 656 | .sh_info = @as(u32, @intCast(self.locals.items.len)), | 667 | .sh_info = @as(u32, @intCast(self.symbols.items.len)), |
| 657 | .sh_addralign = min_align, | 668 | .sh_addralign = min_align, |
| 658 | .sh_entsize = each_size, | 669 | .sh_entsize = each_size, |
| 659 | }, | 670 | }, |
| ... | @@ -818,7 +829,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -818,7 +829,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 818 | | 829 | |
| 819 | { | 830 | { |
| 820 | // Iterate over symbols, populating free_list and last_text_block. | 831 | // Iterate over symbols, populating free_list and last_text_block. |
| 821 | if (self.locals.items.len != 1) { | 832 | if (self.symbols.items.len != 1) { |
| 822 | @panic("TODO implement setting up free_list and last_text_block from existing ELF file"); | 833 | @panic("TODO implement setting up free_list and last_text_block from existing ELF file"); |
| 823 | } | 834 | } |
| 824 | // We are starting with an empty file. The default values are correct, null and empty list. | 835 | // We are starting with an empty file. The default values are correct, null and empty list. |
| ... | @@ -975,280 +986,294 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -975,280 +986,294 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 975 | // corresponds to the Zig source code. | 986 | // corresponds to the Zig source code. |
| 976 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 987 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 977 | | 988 | |
| 978 | if (self.lazy_syms.getPtr(.none)) |metadata| { | 989 | self.zig_module_index = blk: { |
| 979 | // Most lazy symbols can be updated on first use, but | 990 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 980 | // anyerror needs to wait for everything to be flushed. | 991 | self.files.set(index, .{ .zig_module = .{ .index = index } }); |
| 981 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( | 992 | break :blk index; |
| 982 | File.LazySymbol.initDecl(.code, null, module), | 993 | }; |
| 983 | metadata.text_atom, | | |
| 984 | self.text_section_index.?, | | |
| 985 | ) catch |err| return switch (err) { | | |
| 986 | error.CodegenFail => error.FlushFailure, | | |
| 987 | else => |e| e, | | |
| 988 | }; | | |
| 989 | if (metadata.rodata_state != .unused) self.updateLazySymbolAtom( | | |
| 990 | File.LazySymbol.initDecl(.const_data, null, module), | | |
| 991 | metadata.rodata_atom, | | |
| 992 | self.rodata_section_index.?, | | |
| 993 | ) catch |err| return switch (err) { | | |
| 994 | error.CodegenFail => error.FlushFailure, | | |
| 995 | else => |e| e, | | |
| 996 | }; | | |
| 997 | } | | |
| 998 | for (self.lazy_syms.values()) |*metadata| { | | |
| 999 | if (metadata.text_state != .unused) metadata.text_state = .flushed; | | |
| 1000 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; | | |
| 1001 | } | | |
| 1002 | | | |
| 1003 | const target_endian = self.base.options.target.cpu.arch.endian(); | | |
| 1004 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); | | |
| 1005 | | | |
| 1006 | if (self.dwarf) |*dw| { | | |
| 1007 | try dw.flushModule(module); | | |
| 1008 | } | | |
| 1009 | | | |
| 1010 | { | | |
| 1011 | var it = self.relocs.iterator(); | | |
| 1012 | while (it.next()) |entry| { | | |
| 1013 | const atom_index = entry.key_ptr.*; | | |
| 1014 | const relocs = entry.value_ptr.*; | | |
| 1015 | const atom_ptr = self.atom(atom_index); | | |
| 1016 | const source_sym = atom_ptr.symbol(self); | | |
| 1017 | const source_shdr = self.sections.items(.shdr)[source_sym.st_shndx]; | | |
| 1018 | | | |
| 1019 | log.debug("relocating '{?s}'", .{self.strtab.get(source_sym.st_name)}); | | |
| 1020 | | | |
| 1021 | for (relocs.items) |*reloc| { | | |
| 1022 | const target_sym = self.locals.items[reloc.target]; | | |
| 1023 | const target_vaddr = target_sym.st_value + reloc.addend; | | |
| 1024 | | | |
| 1025 | if (target_vaddr == reloc.prev_vaddr) continue; | | |
| 1026 | | | |
| 1027 | const section_offset = (source_sym.st_value + reloc.offset) - source_shdr.sh_addr; | | |
| 1028 | const file_offset = source_shdr.sh_offset + section_offset; | | |
| 1029 | | | |
| 1030 | log.debug(" ({x}: [() => 0x{x}] ({?s}))", .{ | | |
| 1031 | reloc.offset, | | |
| 1032 | target_vaddr, | | |
| 1033 | self.strtab.get(target_sym.st_name), | | |
| 1034 | }); | | |
| 1035 | | | |
| 1036 | switch (self.ptr_width) { | | |
| 1037 | .p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@as(u32, @intCast(target_vaddr))), file_offset), | | |
| 1038 | .p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset), | | |
| 1039 | } | | |
| 1040 | | | |
| 1041 | reloc.prev_vaddr = target_vaddr; | | |
| 1042 | } | | |
| 1043 | } | | |
| 1044 | } | | |
| 1045 | | | |
| 1046 | try self.writeSymbols(); | | |
| 1047 | | | |
| 1048 | if (build_options.enable_logging) { | | |
| 1049 | self.logSymtab(); | | |
| 1050 | } | | |
| 1051 | | | |
| 1052 | if (self.dwarf) |*dw| { | | |
| 1053 | if (self.debug_abbrev_section_dirty) { | | |
| 1054 | try dw.writeDbgAbbrev(); | | |
| 1055 | if (!self.shdr_table_dirty) { | | |
| 1056 | // Then it won't get written with the others and we need to do it. | | |
| 1057 | try self.writeSectHeader(self.debug_abbrev_section_index.?); | | |
| 1058 | } | | |
| 1059 | self.debug_abbrev_section_dirty = false; | | |
| 1060 | } | | |
| 1061 | | | |
| 1062 | if (self.debug_info_header_dirty) { | | |
| 1063 | // Currently only one compilation unit is supported, so the address range is simply | | |
| 1064 | // identical to the main program header virtual address and memory size. | | |
| 1065 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | | |
| 1066 | const low_pc = text_phdr.p_vaddr; | | |
| 1067 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; | | |
| 1068 | try dw.writeDbgInfoHeader(module, low_pc, high_pc); | | |
| 1069 | self.debug_info_header_dirty = false; | | |
| 1070 | } | | |
| 1071 | | | |
| 1072 | if (self.debug_aranges_section_dirty) { | | |
| 1073 | // Currently only one compilation unit is supported, so the address range is simply | | |
| 1074 | // identical to the main program header virtual address and memory size. | | |
| 1075 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; | | |
| 1076 | try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); | | |
| 1077 | if (!self.shdr_table_dirty) { | | |
| 1078 | // Then it won't get written with the others and we need to do it. | | |
| 1079 | try self.writeSectHeader(self.debug_aranges_section_index.?); | | |
| 1080 | } | | |
| 1081 | self.debug_aranges_section_dirty = false; | | |
| 1082 | } | | |
| 1083 | | | |
| 1084 | if (self.debug_line_header_dirty) { | | |
| 1085 | try dw.writeDbgLineHeader(); | | |
| 1086 | self.debug_line_header_dirty = false; | | |
| 1087 | } | | |
| 1088 | } | | |
| 1089 | | | |
| 1090 | if (self.phdr_table_dirty) { | | |
| 1091 | const phsize: u64 = switch (self.ptr_width) { | | |
| 1092 | .p32 => @sizeOf(elf.Elf32_Phdr), | | |
| 1093 | .p64 => @sizeOf(elf.Elf64_Phdr), | | |
| 1094 | }; | | |
| 1095 | | | |
| 1096 | const phdr_table_index = self.phdr_table_index.?; | | |
| 1097 | const phdr_table = &self.program_headers.items[phdr_table_index]; | | |
| 1098 | const phdr_table_load = &self.program_headers.items[self.phdr_table_load_index.?]; | | |
| 1099 | | | |
| 1100 | const allocated_size = self.allocatedSize(phdr_table.p_offset); | | |
| 1101 | const needed_size = self.program_headers.items.len * phsize; | | |
| 1102 | | | |
| 1103 | if (needed_size > allocated_size) { | | |
| 1104 | phdr_table.p_offset = 0; // free the space | | |
| 1105 | phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align))); | | |
| 1106 | } | | |
| 1107 | | | |
| 1108 | phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align); | | |
| 1109 | const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset; | | |
| 1110 | phdr_table_load.p_filesz = load_align_offset + needed_size; | | |
| 1111 | phdr_table_load.p_memsz = load_align_offset + needed_size; | | |
| 1112 | | | |
| 1113 | phdr_table.p_filesz = needed_size; | | |
| 1114 | phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset; | | |
| 1115 | phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset; | | |
| 1116 | phdr_table.p_memsz = needed_size; | | |
| 1117 | | | |
| 1118 | switch (self.ptr_width) { | | |
| 1119 | .p32 => { | | |
| 1120 | const buf = try gpa.alloc(elf.Elf32_Phdr, self.program_headers.items.len); | | |
| 1121 | defer gpa.free(buf); | | |
| 1122 | | | |
| 1123 | for (buf, 0..) |*phdr, i| { | | |
| 1124 | phdr.* = progHeaderTo32(self.program_headers.items[i]); | | |
| 1125 | if (foreign_endian) { | | |
| 1126 | mem.byteSwapAllFields(elf.Elf32_Phdr, phdr); | | |
| 1127 | } | | |
| 1128 | } | | |
| 1129 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset); | | |
| 1130 | }, | | |
| 1131 | .p64 => { | | |
| 1132 | const buf = try gpa.alloc(elf.Elf64_Phdr, self.program_headers.items.len); | | |
| 1133 | defer gpa.free(buf); | | |
| 1134 | | | |
| 1135 | for (buf, 0..) |*phdr, i| { | | |
| 1136 | phdr.* = self.program_headers.items[i]; | | |
| 1137 | if (foreign_endian) { | | |
| 1138 | mem.byteSwapAllFields(elf.Elf64_Phdr, phdr); | | |
| 1139 | } | | |
| 1140 | } | | |
| 1141 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset); | | |
| 1142 | }, | | |
| 1143 | } | | |
| 1144 | | | |
| 1145 | // We don't actually care if the phdr load section overlaps, only the phdr section matters. | | |
| 1146 | phdr_table_load.p_offset = 0; | | |
| 1147 | phdr_table_load.p_filesz = 0; | | |
| 1148 | | | |
| 1149 | self.phdr_table_dirty = false; | | |
| 1150 | } | | |
| 1151 | | | |
| 1152 | { | | |
| 1153 | const shdr_index = self.shstrtab_section_index.?; | | |
| 1154 | if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { | | |
| 1155 | try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false); | | |
| 1156 | const shstrtab_sect = self.sections.items(.shdr)[shdr_index]; | | |
| 1157 | try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset); | | |
| 1158 | self.shstrtab_dirty = false; | | |
| 1159 | } | | |
| 1160 | } | | |
| 1161 | | | |
| 1162 | { | | |
| 1163 | const shdr_index = self.strtab_section_index.?; | | |
| 1164 | if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { | | |
| 1165 | try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false); | | |
| 1166 | const strtab_sect = self.sections.items(.shdr)[shdr_index]; | | |
| 1167 | try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset); | | |
| 1168 | self.strtab_dirty = false; | | |
| 1169 | } | | |
| 1170 | } | | |
| 1171 | | | |
| 1172 | if (self.dwarf) |dwarf| { | | |
| 1173 | const shdr_index = self.debug_str_section_index.?; | | |
| 1174 | if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { | | |
| 1175 | try self.growNonAllocSection(shdr_index, dwarf.strtab.buffer.items.len, 1, false); | | |
| 1176 | const debug_strtab_sect = self.sections.items(.shdr)[shdr_index]; | | |
| 1177 | try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset); | | |
| 1178 | self.debug_strtab_dirty = false; | | |
| 1179 | } | | |
| 1180 | } | | |
| 1181 | | | |
| 1182 | if (self.shdr_table_dirty) { | | |
| 1183 | const shsize: u64 = switch (self.ptr_width) { | | |
| 1184 | .p32 => @sizeOf(elf.Elf32_Shdr), | | |
| 1185 | .p64 => @sizeOf(elf.Elf64_Shdr), | | |
| 1186 | }; | | |
| 1187 | const shalign: u16 = switch (self.ptr_width) { | | |
| 1188 | .p32 => @alignOf(elf.Elf32_Shdr), | | |
| 1189 | .p64 => @alignOf(elf.Elf64_Shdr), | | |
| 1190 | }; | | |
| 1191 | const allocated_size = self.allocatedSize(self.shdr_table_offset.?); | | |
| 1192 | const needed_size = self.sections.slice().len * shsize; | | |
| 1193 | | | |
| 1194 | if (needed_size > allocated_size) { | | |
| 1195 | self.shdr_table_offset = null; // free the space | | |
| 1196 | self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); | | |
| 1197 | } | | |
| 1198 | | 994 | |
| 1199 | switch (self.ptr_width) { | 995 | self.linker_defined = blk: { |
| 1200 | .p32 => { | 996 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1201 | const slice = self.sections.slice(); | 997 | self.files.set(index, .{ .linker_defined = .{} }); |
| 1202 | const buf = try gpa.alloc(elf.Elf32_Shdr, slice.len); | 998 | break :blk index; |
| 1203 | defer gpa.free(buf); | 999 | }; |
| 1204 | | 1000 | |
| 1205 | for (buf, 0..) |*shdr, i| { | 1001 | std.debug.print("{}\n", .{self.dumpState()}); |
| 1206 | shdr.* = sectHeaderTo32(slice.items(.shdr)[i]); | 1002 | |
| 1207 | log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); | 1003 | // if (self.lazy_syms.getPtr(.none)) |metadata| { |
| 1208 | if (foreign_endian) { | 1004 | // // Most lazy symbols can be updated on first use, but |
| 1209 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); | 1005 | // // anyerror needs to wait for everything to be flushed. |
| 1210 | } | 1006 | // if (metadata.text_state != .unused) self.updateLazySymbolAtom( |
| 1211 | } | 1007 | // link.File.LazySymbol.initDecl(.code, null, module), |
| 1212 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | 1008 | // metadata.text_atom, |
| 1213 | }, | 1009 | // self.text_section_index.?, |
| 1214 | .p64 => { | 1010 | // ) catch |err| return switch (err) { |
| 1215 | const slice = self.sections.slice(); | 1011 | // error.CodegenFail => error.FlushFailure, |
| 1216 | const buf = try gpa.alloc(elf.Elf64_Shdr, slice.len); | 1012 | // else => |e| e, |
| 1217 | defer gpa.free(buf); | 1013 | // }; |
| 1218 | | 1014 | // if (metadata.rodata_state != .unused) self.updateLazySymbolAtom( |
| 1219 | for (buf, 0..) |*shdr, i| { | 1015 | // link.File.LazySymbol.initDecl(.const_data, null, module), |
| 1220 | shdr.* = slice.items(.shdr)[i]; | 1016 | // metadata.rodata_atom, |
| 1221 | log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); | 1017 | // self.rodata_section_index.?, |
| 1222 | if (foreign_endian) { | 1018 | // ) catch |err| return switch (err) { |
| 1223 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); | 1019 | // error.CodegenFail => error.FlushFailure, |
| 1224 | } | 1020 | // else => |e| e, |
| 1225 | } | 1021 | // }; |
| 1226 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | 1022 | // } |
| 1227 | }, | 1023 | // for (self.lazy_syms.values()) |*metadata| { |
| 1228 | } | 1024 | // if (metadata.text_state != .unused) metadata.text_state = .flushed; |
| 1229 | self.shdr_table_dirty = false; | 1025 | // if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; |
| 1230 | } | 1026 | // } |
| 1231 | if (self.entry_addr == null and self.base.options.effectiveOutputMode() == .Exe) { | 1027 | |
| 1232 | log.debug("flushing. no_entry_point_found = true", .{}); | 1028 | // const target_endian = self.base.options.target.cpu.arch.endian(); |
| 1233 | self.error_flags.no_entry_point_found = true; | 1029 | // const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 1234 | } else { | 1030 | |
| 1235 | log.debug("flushing. no_entry_point_found = false", .{}); | 1031 | // if (self.dwarf) |*dw| { |
| 1236 | self.error_flags.no_entry_point_found = false; | 1032 | // try dw.flushModule(module); |
| 1237 | try self.writeElfHeader(); | 1033 | // } |
| 1238 | } | 1034 | |
| 1239 | | 1035 | // { |
| 1240 | // The point of flush() is to commit changes, so in theory, nothing should | 1036 | // var it = self.relocs.iterator(); |
| 1241 | // be dirty after this. However, it is possible for some things to remain | 1037 | // while (it.next()) |entry| { |
| 1242 | // dirty because they fail to be written in the event of compile errors, | 1038 | // const atom_index = entry.key_ptr.*; |
| 1243 | // such as debug_line_header_dirty and debug_info_header_dirty. | 1039 | // const relocs = entry.value_ptr.*; |
| 1244 | assert(!self.debug_abbrev_section_dirty); | 1040 | // const atom_ptr = self.atom(atom_index); |
| 1245 | assert(!self.debug_aranges_section_dirty); | 1041 | // const source_sym = atom_ptr.symbol(self); |
| 1246 | assert(!self.phdr_table_dirty); | 1042 | // const source_shdr = self.sections.items(.shdr)[source_sym.st_shndx]; |
| 1247 | assert(!self.shdr_table_dirty); | 1043 | |
| 1248 | assert(!self.shstrtab_dirty); | 1044 | // log.debug("relocating '{?s}'", .{self.strtab.get(source_sym.st_name)}); |
| 1249 | assert(!self.strtab_dirty); | 1045 | |
| 1250 | assert(!self.debug_strtab_dirty); | 1046 | // for (relocs.items) |*reloc| { |
| 1251 | assert(!self.got_table_count_dirty); | 1047 | // const target_sym = self.locals.items[reloc.target]; |
| | 1048 | // const target_vaddr = target_sym.st_value + reloc.addend; |
| | 1049 | |
| | 1050 | // if (target_vaddr == reloc.prev_vaddr) continue; |
| | 1051 | |
| | 1052 | // const section_offset = (source_sym.st_value + reloc.offset) - source_shdr.sh_addr; |
| | 1053 | // const file_offset = source_shdr.sh_offset + section_offset; |
| | 1054 | |
| | 1055 | // log.debug(" ({x}: [() => 0x{x}] ({?s}))", .{ |
| | 1056 | // reloc.offset, |
| | 1057 | // target_vaddr, |
| | 1058 | // self.strtab.get(target_sym.st_name), |
| | 1059 | // }); |
| | 1060 | |
| | 1061 | // switch (self.ptr_width) { |
| | 1062 | // .p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@as(u32, @intCast(target_vaddr))), file_offset), |
| | 1063 | // .p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset), |
| | 1064 | // } |
| | 1065 | |
| | 1066 | // reloc.prev_vaddr = target_vaddr; |
| | 1067 | // } |
| | 1068 | // } |
| | 1069 | // } |
| | 1070 | |
| | 1071 | // try self.writeSymbols(); |
| | 1072 | |
| | 1073 | // if (build_options.enable_logging) { |
| | 1074 | // self.logSymtab(); |
| | 1075 | // } |
| | 1076 | |
| | 1077 | // if (self.dwarf) |*dw| { |
| | 1078 | // if (self.debug_abbrev_section_dirty) { |
| | 1079 | // try dw.writeDbgAbbrev(); |
| | 1080 | // if (!self.shdr_table_dirty) { |
| | 1081 | // // Then it won't get written with the others and we need to do it. |
| | 1082 | // try self.writeSectHeader(self.debug_abbrev_section_index.?); |
| | 1083 | // } |
| | 1084 | // self.debug_abbrev_section_dirty = false; |
| | 1085 | // } |
| | 1086 | |
| | 1087 | // if (self.debug_info_header_dirty) { |
| | 1088 | // // Currently only one compilation unit is supported, so the address range is simply |
| | 1089 | // // identical to the main program header virtual address and memory size. |
| | 1090 | // const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| | 1091 | // const low_pc = text_phdr.p_vaddr; |
| | 1092 | // const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| | 1093 | // try dw.writeDbgInfoHeader(module, low_pc, high_pc); |
| | 1094 | // self.debug_info_header_dirty = false; |
| | 1095 | // } |
| | 1096 | |
| | 1097 | // if (self.debug_aranges_section_dirty) { |
| | 1098 | // // Currently only one compilation unit is supported, so the address range is simply |
| | 1099 | // // identical to the main program header virtual address and memory size. |
| | 1100 | // const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| | 1101 | // try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); |
| | 1102 | // if (!self.shdr_table_dirty) { |
| | 1103 | // // Then it won't get written with the others and we need to do it. |
| | 1104 | // try self.writeSectHeader(self.debug_aranges_section_index.?); |
| | 1105 | // } |
| | 1106 | // self.debug_aranges_section_dirty = false; |
| | 1107 | // } |
| | 1108 | |
| | 1109 | // if (self.debug_line_header_dirty) { |
| | 1110 | // try dw.writeDbgLineHeader(); |
| | 1111 | // self.debug_line_header_dirty = false; |
| | 1112 | // } |
| | 1113 | // } |
| | 1114 | |
| | 1115 | // if (self.phdr_table_dirty) { |
| | 1116 | // const phsize: u64 = switch (self.ptr_width) { |
| | 1117 | // .p32 => @sizeOf(elf.Elf32_Phdr), |
| | 1118 | // .p64 => @sizeOf(elf.Elf64_Phdr), |
| | 1119 | // }; |
| | 1120 | |
| | 1121 | // const phdr_table_index = self.phdr_table_index.?; |
| | 1122 | // const phdr_table = &self.program_headers.items[phdr_table_index]; |
| | 1123 | // const phdr_table_load = &self.program_headers.items[self.phdr_table_load_index.?]; |
| | 1124 | |
| | 1125 | // const allocated_size = self.allocatedSize(phdr_table.p_offset); |
| | 1126 | // const needed_size = self.program_headers.items.len * phsize; |
| | 1127 | |
| | 1128 | // if (needed_size > allocated_size) { |
| | 1129 | // phdr_table.p_offset = 0; // free the space |
| | 1130 | // phdr_table.p_offset = self.findFreeSpace(needed_size, @as(u32, @intCast(phdr_table.p_align))); |
| | 1131 | // } |
| | 1132 | |
| | 1133 | // phdr_table_load.p_offset = mem.alignBackward(u64, phdr_table.p_offset, phdr_table_load.p_align); |
| | 1134 | // const load_align_offset = phdr_table.p_offset - phdr_table_load.p_offset; |
| | 1135 | // phdr_table_load.p_filesz = load_align_offset + needed_size; |
| | 1136 | // phdr_table_load.p_memsz = load_align_offset + needed_size; |
| | 1137 | |
| | 1138 | // phdr_table.p_filesz = needed_size; |
| | 1139 | // phdr_table.p_vaddr = phdr_table_load.p_vaddr + load_align_offset; |
| | 1140 | // phdr_table.p_paddr = phdr_table_load.p_paddr + load_align_offset; |
| | 1141 | // phdr_table.p_memsz = needed_size; |
| | 1142 | |
| | 1143 | // switch (self.ptr_width) { |
| | 1144 | // .p32 => { |
| | 1145 | // const buf = try gpa.alloc(elf.Elf32_Phdr, self.program_headers.items.len); |
| | 1146 | // defer gpa.free(buf); |
| | 1147 | |
| | 1148 | // for (buf, 0..) |*phdr, i| { |
| | 1149 | // phdr.* = progHeaderTo32(self.program_headers.items[i]); |
| | 1150 | // if (foreign_endian) { |
| | 1151 | // mem.byteSwapAllFields(elf.Elf32_Phdr, phdr); |
| | 1152 | // } |
| | 1153 | // } |
| | 1154 | // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset); |
| | 1155 | // }, |
| | 1156 | // .p64 => { |
| | 1157 | // const buf = try gpa.alloc(elf.Elf64_Phdr, self.program_headers.items.len); |
| | 1158 | // defer gpa.free(buf); |
| | 1159 | |
| | 1160 | // for (buf, 0..) |*phdr, i| { |
| | 1161 | // phdr.* = self.program_headers.items[i]; |
| | 1162 | // if (foreign_endian) { |
| | 1163 | // mem.byteSwapAllFields(elf.Elf64_Phdr, phdr); |
| | 1164 | // } |
| | 1165 | // } |
| | 1166 | // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), phdr_table.p_offset); |
| | 1167 | // }, |
| | 1168 | // } |
| | 1169 | |
| | 1170 | // // We don't actually care if the phdr load section overlaps, only the phdr section matters. |
| | 1171 | // phdr_table_load.p_offset = 0; |
| | 1172 | // phdr_table_load.p_filesz = 0; |
| | 1173 | |
| | 1174 | // self.phdr_table_dirty = false; |
| | 1175 | // } |
| | 1176 | |
| | 1177 | // { |
| | 1178 | // const shdr_index = self.shstrtab_section_index.?; |
| | 1179 | // if (self.shstrtab_dirty or self.shstrtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { |
| | 1180 | // try self.growNonAllocSection(shdr_index, self.shstrtab.buffer.items.len, 1, false); |
| | 1181 | // const shstrtab_sect = self.sections.items(.shdr)[shdr_index]; |
| | 1182 | // try self.base.file.?.pwriteAll(self.shstrtab.buffer.items, shstrtab_sect.sh_offset); |
| | 1183 | // self.shstrtab_dirty = false; |
| | 1184 | // } |
| | 1185 | // } |
| | 1186 | |
| | 1187 | // { |
| | 1188 | // const shdr_index = self.strtab_section_index.?; |
| | 1189 | // if (self.strtab_dirty or self.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { |
| | 1190 | // try self.growNonAllocSection(shdr_index, self.strtab.buffer.items.len, 1, false); |
| | 1191 | // const strtab_sect = self.sections.items(.shdr)[shdr_index]; |
| | 1192 | // try self.base.file.?.pwriteAll(self.strtab.buffer.items, strtab_sect.sh_offset); |
| | 1193 | // self.strtab_dirty = false; |
| | 1194 | // } |
| | 1195 | // } |
| | 1196 | |
| | 1197 | // if (self.dwarf) |dwarf| { |
| | 1198 | // const shdr_index = self.debug_str_section_index.?; |
| | 1199 | // if (self.debug_strtab_dirty or dwarf.strtab.buffer.items.len != self.sections.items(.shdr)[shdr_index].sh_size) { |
| | 1200 | // try self.growNonAllocSection(shdr_index, dwarf.strtab.buffer.items.len, 1, false); |
| | 1201 | // const debug_strtab_sect = self.sections.items(.shdr)[shdr_index]; |
| | 1202 | // try self.base.file.?.pwriteAll(dwarf.strtab.buffer.items, debug_strtab_sect.sh_offset); |
| | 1203 | // self.debug_strtab_dirty = false; |
| | 1204 | // } |
| | 1205 | // } |
| | 1206 | |
| | 1207 | // if (self.shdr_table_dirty) { |
| | 1208 | // const shsize: u64 = switch (self.ptr_width) { |
| | 1209 | // .p32 => @sizeOf(elf.Elf32_Shdr), |
| | 1210 | // .p64 => @sizeOf(elf.Elf64_Shdr), |
| | 1211 | // }; |
| | 1212 | // const shalign: u16 = switch (self.ptr_width) { |
| | 1213 | // .p32 => @alignOf(elf.Elf32_Shdr), |
| | 1214 | // .p64 => @alignOf(elf.Elf64_Shdr), |
| | 1215 | // }; |
| | 1216 | // const allocated_size = self.allocatedSize(self.shdr_table_offset.?); |
| | 1217 | // const needed_size = self.sections.slice().len * shsize; |
| | 1218 | |
| | 1219 | // if (needed_size > allocated_size) { |
| | 1220 | // self.shdr_table_offset = null; // free the space |
| | 1221 | // self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); |
| | 1222 | // } |
| | 1223 | |
| | 1224 | // switch (self.ptr_width) { |
| | 1225 | // .p32 => { |
| | 1226 | // const slice = self.sections.slice(); |
| | 1227 | // const buf = try gpa.alloc(elf.Elf32_Shdr, slice.len); |
| | 1228 | // defer gpa.free(buf); |
| | 1229 | |
| | 1230 | // for (buf, 0..) |*shdr, i| { |
| | 1231 | // shdr.* = sectHeaderTo32(slice.items(.shdr)[i]); |
| | 1232 | // log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); |
| | 1233 | // if (foreign_endian) { |
| | 1234 | // mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); |
| | 1235 | // } |
| | 1236 | // } |
| | 1237 | // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| | 1238 | // }, |
| | 1239 | // .p64 => { |
| | 1240 | // const slice = self.sections.slice(); |
| | 1241 | // const buf = try gpa.alloc(elf.Elf64_Shdr, slice.len); |
| | 1242 | // defer gpa.free(buf); |
| | 1243 | |
| | 1244 | // for (buf, 0..) |*shdr, i| { |
| | 1245 | // shdr.* = slice.items(.shdr)[i]; |
| | 1246 | // log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); |
| | 1247 | // if (foreign_endian) { |
| | 1248 | // mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); |
| | 1249 | // } |
| | 1250 | // } |
| | 1251 | // try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| | 1252 | // }, |
| | 1253 | // } |
| | 1254 | // self.shdr_table_dirty = false; |
| | 1255 | // } |
| | 1256 | // if (self.entry_addr == null and self.base.options.effectiveOutputMode() == .Exe) { |
| | 1257 | // log.debug("flushing. no_entry_point_found = true", .{}); |
| | 1258 | // self.error_flags.no_entry_point_found = true; |
| | 1259 | // } else { |
| | 1260 | // log.debug("flushing. no_entry_point_found = false", .{}); |
| | 1261 | // self.error_flags.no_entry_point_found = false; |
| | 1262 | // try self.writeElfHeader(); |
| | 1263 | // } |
| | 1264 | |
| | 1265 | // // The point of flush() is to commit changes, so in theory, nothing should |
| | 1266 | // // be dirty after this. However, it is possible for some things to remain |
| | 1267 | // // dirty because they fail to be written in the event of compile errors, |
| | 1268 | // // such as debug_line_header_dirty and debug_info_header_dirty. |
| | 1269 | // assert(!self.debug_abbrev_section_dirty); |
| | 1270 | // assert(!self.debug_aranges_section_dirty); |
| | 1271 | // assert(!self.phdr_table_dirty); |
| | 1272 | // assert(!self.shdr_table_dirty); |
| | 1273 | // assert(!self.shstrtab_dirty); |
| | 1274 | // assert(!self.strtab_dirty); |
| | 1275 | // assert(!self.debug_strtab_dirty); |
| | 1276 | // assert(!self.got_table_count_dirty); |
| 1252 | } | 1277 | } |
| 1253 | | 1278 | |
| 1254 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1279 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| ... | @@ -2347,7 +2372,7 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { | ... | @@ -2347,7 +2372,7 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2347 | } | 2372 | } |
| 2348 | } | 2373 | } |
| 2349 | | 2374 | |
| 2350 | pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index { | 2375 | pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !Atom.Index { |
| 2351 | const mod = self.base.options.module.?; | 2376 | const mod = self.base.options.module.?; |
| 2352 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod)); | 2377 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod)); |
| 2353 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); | 2378 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| ... | @@ -2559,7 +2584,7 @@ pub fn updateDecl( | ... | @@ -2559,7 +2584,7 @@ pub fn updateDecl( |
| 2559 | self: *Elf, | 2584 | self: *Elf, |
| 2560 | mod: *Module, | 2585 | mod: *Module, |
| 2561 | decl_index: Module.Decl.Index, | 2586 | decl_index: Module.Decl.Index, |
| 2562 | ) File.UpdateDeclError!void { | 2587 | ) link.File.UpdateDeclError!void { |
| 2563 | if (build_options.skip_non_native and builtin.object_format != .elf) { | 2588 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2564 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 2589 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2565 | } | 2590 | } |
| ... | @@ -2634,7 +2659,7 @@ pub fn updateDecl( | ... | @@ -2634,7 +2659,7 @@ pub fn updateDecl( |
| 2634 | | 2659 | |
| 2635 | fn updateLazySymbolAtom( | 2660 | fn updateLazySymbolAtom( |
| 2636 | self: *Elf, | 2661 | self: *Elf, |
| 2637 | sym: File.LazySymbol, | 2662 | sym: link.File.LazySymbol, |
| 2638 | atom_index: Atom.Index, | 2663 | atom_index: Atom.Index, |
| 2639 | shdr_index: u16, | 2664 | shdr_index: u16, |
| 2640 | ) !void { | 2665 | ) !void { |
| ... | @@ -2776,7 +2801,7 @@ pub fn updateDeclExports( | ... | @@ -2776,7 +2801,7 @@ pub fn updateDeclExports( |
| 2776 | mod: *Module, | 2801 | mod: *Module, |
| 2777 | decl_index: Module.Decl.Index, | 2802 | decl_index: Module.Decl.Index, |
| 2778 | exports: []const *Module.Export, | 2803 | exports: []const *Module.Export, |
| 2779 | ) File.UpdateDeclExportsError!void { | 2804 | ) link.File.UpdateDeclExportsError!void { |
| 2780 | if (build_options.skip_non_native and builtin.object_format != .elf) { | 2805 | if (build_options.skip_non_native and builtin.object_format != .elf) { |
| 2781 | @panic("Attempted to compile for object format that was disabled by build configuration"); | 2806 | @panic("Attempted to compile for object format that was disabled by build configuration"); |
| 2782 | } | 2807 | } |
| ... | @@ -3420,6 +3445,18 @@ pub fn atomIndexForSymbol(self: *Elf, sym_index: u32) ?Atom.Index { | ... | @@ -3420,6 +3445,18 @@ pub fn atomIndexForSymbol(self: *Elf, sym_index: u32) ?Atom.Index { |
| 3420 | return self.atom_by_index_table.get(sym_index); | 3445 | return self.atom_by_index_table.get(sym_index); |
| 3421 | } | 3446 | } |
| 3422 | | 3447 | |
| | 3448 | fn dumpState(self: *Elf ) std.fmt.Formatter(fmtDumpState) { |
| | 3449 | return .{ .data = self }; |
| | 3450 | } |
| | 3451 | |
| | 3452 | fn fmtDumpState(self: *Elf, |
| | 3453 | comptime unused_fmt_string: []const u8, |
| | 3454 | options: std.fmt.FormatOptions, |
| | 3455 | writer: anytype, |
| | 3456 | ) !void { |
| | 3457 | |
| | 3458 | } |
| | 3459 | |
| 3423 | pub const null_sym = elf.Elf64_Sym{ | 3460 | pub const null_sym = elf.Elf64_Sym{ |
| 3424 | .st_name = 0, | 3461 | .st_name = 0, |
| 3425 | .st_info = 0, | 3462 | .st_info = 0, |
| ... | @@ -3431,7 +3468,7 @@ pub const null_sym = elf.Elf64_Sym{ | ... | @@ -3431,7 +3468,7 @@ pub const null_sym = elf.Elf64_Sym{ |
| 3431 | | 3468 | |
| 3432 | const default_entry_addr = 0x8000000; | 3469 | const default_entry_addr = 0x8000000; |
| 3433 | | 3470 | |
| 3434 | pub const base_tag: File.Tag = .elf; | 3471 | pub const base_tag: link.File.Tag = .elf; |
| 3435 | | 3472 | |
| 3436 | const Section = struct { | 3473 | const Section = struct { |
| 3437 | shdr: elf.Elf64_Shdr, | 3474 | shdr: elf.Elf64_Shdr, |
| ... | @@ -3506,7 +3543,8 @@ pub const Atom = @import("Elf/Atom.zig"); | ... | @@ -3506,7 +3543,8 @@ pub const Atom = @import("Elf/Atom.zig"); |
| 3506 | const Cache = std.Build.Cache; | 3543 | const Cache = std.Build.Cache; |
| 3507 | const Compilation = @import("../Compilation.zig"); | 3544 | const Compilation = @import("../Compilation.zig"); |
| 3508 | const Dwarf = @import("Dwarf.zig"); | 3545 | const Dwarf = @import("Dwarf.zig"); |
| 3509 | const File = link.File; | 3546 | const File = @import("Elf/File.zig"); |
| | 3547 | const LinkerDefined = @import("Elf/LinkerDefined.zig"); |
| 3510 | const Liveness = @import("../Liveness.zig"); | 3548 | const Liveness = @import("../Liveness.zig"); |
| 3511 | const LlvmObject = @import("../codegen/llvm.zig").Object; | 3549 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 3512 | const Module = @import("../Module.zig"); | 3550 | const Module = @import("../Module.zig"); |
| ... | @@ -3517,3 +3555,4 @@ const TableSection = @import("table_section.zig").TableSection; | ... | @@ -3517,3 +3555,4 @@ const TableSection = @import("table_section.zig").TableSection; |
| 3517 | const Type = @import("../type.zig").Type; | 3555 | const Type = @import("../type.zig").Type; |
| 3518 | const TypedValue = @import("../TypedValue.zig"); | 3556 | const TypedValue = @import("../TypedValue.zig"); |
| 3519 | const Value = @import("../value.zig").Value; | 3557 | const Value = @import("../value.zig").Value; |
| | 3558 | const ZigModule = @import("Elf/ZigModule.zig"); |