| author | |
| committer | |
| log | 9e0bca73e2ae8c29873c7280f28ce58502e6abab |
| tree | 3fd87d1fd8eca202b357d134327f90dbd1aa177e |
| parent | 09820a96b691f79403291d9b2179adbae50fc33b |
14 files changed, 711 insertions(+), 226 deletions(-)
src/link/Elf.zig+242-32| ... | @@ -210,6 +210,14 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .{}, | ... | @@ -210,6 +210,14 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 210 | /// List of range extension thunks. | 210 | /// List of range extension thunks. |
| 211 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, | 211 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| 212 | 212 | ||
| 213 | /// List of output merge sections with deduped contents. | ||
| 214 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, | ||
| 215 | /// List of output merge subsections. | ||
| 216 | /// Each subsection is akin to Atom but belongs to a MergeSection. | ||
| 217 | merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, | ||
| 218 | /// List of input merge sections as parsed from input relocatables. | ||
| 219 | merge_input_sections: std.ArrayListUnmanaged(InputMergeSection) = .{}, | ||
| 220 | |||
| 213 | /// Table of last atom index in a section and matching atom free list if any. | 221 | /// Table of last atom index in a section and matching atom free list if any. |
| 214 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, | 222 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 215 | 223 | ||
| ... | @@ -380,6 +388,8 @@ pub fn createEmpty( | ... | @@ -380,6 +388,8 @@ pub fn createEmpty( |
| 380 | _ = try self.addSection(.{ .name = "" }); | 388 | _ = try self.addSection(.{ .name = "" }); |
| 381 | // Append null symbol in output symtab | 389 | // Append null symbol in output symtab |
| 382 | try self.symtab.append(gpa, null_sym); | 390 | try self.symtab.append(gpa, null_sym); |
| 391 | // Append null input merge section. | ||
| 392 | try self.merge_input_sections.append(gpa, .{}); | ||
| 383 | 393 | ||
| 384 | if (!is_obj_or_ar) { | 394 | if (!is_obj_or_ar) { |
| 385 | try self.dynstrtab.append(gpa, 0); | 395 | try self.dynstrtab.append(gpa, 0); |
| ... | @@ -498,6 +508,15 @@ pub fn deinit(self: *Elf) void { | ... | @@ -498,6 +508,15 @@ pub fn deinit(self: *Elf) void { |
| 498 | th.deinit(gpa); | 508 | th.deinit(gpa); |
| 499 | } | 509 | } |
| 500 | self.thunks.deinit(gpa); | 510 | self.thunks.deinit(gpa); |
| 511 | for (self.merge_sections.items) |*sect| { | ||
| 512 | sect.deinit(gpa); | ||
| 513 | } | ||
| 514 | self.merge_sections.deinit(gpa); | ||
| 515 | self.merge_subsections.deinit(gpa); | ||
| 516 | for (self.merge_input_sections.items) |*sect| { | ||
| 517 | sect.deinit(gpa); | ||
| 518 | } | ||
| 519 | self.merge_input_sections.deinit(gpa); | ||
| 501 | for (self.last_atom_and_free_list_table.values()) |*value| { | 520 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 502 | value.free_list.deinit(gpa); | 521 | value.free_list.deinit(gpa); |
| 503 | } | 522 | } |
| ... | @@ -1295,6 +1314,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1295,6 +1314,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1295 | // symbol for potential resolution at load-time. | 1314 | // symbol for potential resolution at load-time. |
| 1296 | self.resolveSymbols(); | 1315 | self.resolveSymbols(); |
| 1297 | self.markEhFrameAtomsDead(); | 1316 | self.markEhFrameAtomsDead(); |
| 1317 | try self.resolveMergeSections(); | ||
| 1298 | 1318 | ||
| 1299 | try self.convertCommonSymbols(); | 1319 | try self.convertCommonSymbols(); |
| 1300 | self.markImportsExports(); | 1320 | self.markImportsExports(); |
| ... | @@ -1319,6 +1339,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1319,6 +1339,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1319 | else => |e| return e, | 1339 | else => |e| return e, |
| 1320 | }; | 1340 | }; |
| 1321 | 1341 | ||
| 1342 | try self.addCommentString(); | ||
| 1343 | try self.sortMergeSections(); | ||
| 1322 | try self.initOutputSections(); | 1344 | try self.initOutputSections(); |
| 1323 | try self.addLinkerDefinedSymbols(); | 1345 | try self.addLinkerDefinedSymbols(); |
| 1324 | self.claimUnresolved(); | 1346 | self.claimUnresolved(); |
| ... | @@ -1338,6 +1360,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1338,6 +1360,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1338 | self.sortDynamicSymtab(); | 1360 | self.sortDynamicSymtab(); |
| 1339 | try self.setHashSections(); | 1361 | try self.setHashSections(); |
| 1340 | try self.setVersionSymtab(); | 1362 | try self.setVersionSymtab(); |
| 1363 | try self.updateMergeSectionSizes(); | ||
| 1341 | try self.updateSectionSizes(); | 1364 | try self.updateSectionSizes(); |
| 1342 | 1365 | ||
| 1343 | try self.allocatePhdrTable(); | 1366 | try self.allocatePhdrTable(); |
| ... | @@ -1365,7 +1388,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1365,7 +1388,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1365 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 1388 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1366 | const code = try zig_object.codeAlloc(self, atom_index); | 1389 | const code = try zig_object.codeAlloc(self, atom_index); |
| 1367 | defer gpa.free(code); | 1390 | defer gpa.free(code); |
| 1368 | const file_offset = shdr.sh_offset + atom_ptr.value; | 1391 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1369 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { | 1392 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { |
| 1370 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, | 1393 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 1371 | error.UnsupportedCpuArch => { | 1394 | error.UnsupportedCpuArch => { |
| ... | @@ -1383,6 +1406,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) | ... | @@ -1383,6 +1406,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1383 | try self.writePhdrTable(); | 1406 | try self.writePhdrTable(); |
| 1384 | try self.writeShdrTable(); | 1407 | try self.writeShdrTable(); |
| 1385 | try self.writeAtoms(); | 1408 | try self.writeAtoms(); |
| 1409 | try self.writeMergeSections(); | ||
| 1386 | self.writeSyntheticSections() catch |err| switch (err) { | 1410 | self.writeSyntheticSections() catch |err| switch (err) { |
| 1387 | error.RelocFailure => return error.FlushFailure, | 1411 | error.RelocFailure => return error.FlushFailure, |
| 1388 | error.UnsupportedCpuArch => { | 1412 | error.UnsupportedCpuArch => { |
| ... | @@ -2952,7 +2976,10 @@ pub fn writeElfHeader(self: *Elf) !void { | ... | @@ -2952,7 +2976,10 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2952 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); | 2976 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); |
| 2953 | index += 4; | 2977 | index += 4; |
| 2954 | 2978 | ||
| 2955 | const e_entry = if (self.entry_index) |entry_index| self.symbol(entry_index).address(.{}, self) else 0; | 2979 | const e_entry = if (self.entry_index) |entry_index| |
| 2980 | @as(u64, @intCast(self.symbol(entry_index).address(.{}, self))) | ||
| 2981 | else | ||
| 2982 | 0; | ||
| 2956 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; | 2983 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; |
| 2957 | switch (self.ptr_width) { | 2984 | switch (self.ptr_width) { |
| 2958 | .p32 => { | 2985 | .p32 => { |
| ... | @@ -3138,14 +3165,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3138,14 +3165,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3138 | if (self.dynamic_section_index) |shndx| { | 3165 | if (self.dynamic_section_index) |shndx| { |
| 3139 | const shdr = &self.shdrs.items[shndx]; | 3166 | const shdr = &self.shdrs.items[shndx]; |
| 3140 | const symbol_ptr = self.symbol(self.dynamic_index.?); | 3167 | const symbol_ptr = self.symbol(self.dynamic_index.?); |
| 3141 | symbol_ptr.value = shdr.sh_addr; | 3168 | symbol_ptr.value = @intCast(shdr.sh_addr); |
| 3142 | symbol_ptr.output_section_index = shndx; | 3169 | symbol_ptr.output_section_index = shndx; |
| 3143 | } | 3170 | } |
| 3144 | 3171 | ||
| 3145 | // __ehdr_start | 3172 | // __ehdr_start |
| 3146 | { | 3173 | { |
| 3147 | const symbol_ptr = self.symbol(self.ehdr_start_index.?); | 3174 | const symbol_ptr = self.symbol(self.ehdr_start_index.?); |
| 3148 | symbol_ptr.value = self.image_base; | 3175 | symbol_ptr.value = @intCast(self.image_base); |
| 3149 | symbol_ptr.output_section_index = 1; | 3176 | symbol_ptr.output_section_index = 1; |
| 3150 | } | 3177 | } |
| 3151 | 3178 | ||
| ... | @@ -3155,9 +3182,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3155,9 +3182,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3155 | const end_sym = self.symbol(self.init_array_end_index.?); | 3182 | const end_sym = self.symbol(self.init_array_end_index.?); |
| 3156 | const shdr = &self.shdrs.items[shndx]; | 3183 | const shdr = &self.shdrs.items[shndx]; |
| 3157 | start_sym.output_section_index = shndx; | 3184 | start_sym.output_section_index = shndx; |
| 3158 | start_sym.value = shdr.sh_addr; | 3185 | start_sym.value = @intCast(shdr.sh_addr); |
| 3159 | end_sym.output_section_index = shndx; | 3186 | end_sym.output_section_index = shndx; |
| 3160 | end_sym.value = shdr.sh_addr + shdr.sh_size; | 3187 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); |
| 3161 | } | 3188 | } |
| 3162 | 3189 | ||
| 3163 | // __fini_array_start, __fini_array_end | 3190 | // __fini_array_start, __fini_array_end |
| ... | @@ -3166,9 +3193,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3166,9 +3193,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3166 | const end_sym = self.symbol(self.fini_array_end_index.?); | 3193 | const end_sym = self.symbol(self.fini_array_end_index.?); |
| 3167 | const shdr = &self.shdrs.items[shndx]; | 3194 | const shdr = &self.shdrs.items[shndx]; |
| 3168 | start_sym.output_section_index = shndx; | 3195 | start_sym.output_section_index = shndx; |
| 3169 | start_sym.value = shdr.sh_addr; | 3196 | start_sym.value = @intCast(shdr.sh_addr); |
| 3170 | end_sym.output_section_index = shndx; | 3197 | end_sym.output_section_index = shndx; |
| 3171 | end_sym.value = shdr.sh_addr + shdr.sh_size; | 3198 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); |
| 3172 | } | 3199 | } |
| 3173 | 3200 | ||
| 3174 | // __preinit_array_start, __preinit_array_end | 3201 | // __preinit_array_start, __preinit_array_end |
| ... | @@ -3177,9 +3204,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3177,9 +3204,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3177 | const end_sym = self.symbol(self.preinit_array_end_index.?); | 3204 | const end_sym = self.symbol(self.preinit_array_end_index.?); |
| 3178 | const shdr = &self.shdrs.items[shndx]; | 3205 | const shdr = &self.shdrs.items[shndx]; |
| 3179 | start_sym.output_section_index = shndx; | 3206 | start_sym.output_section_index = shndx; |
| 3180 | start_sym.value = shdr.sh_addr; | 3207 | start_sym.value = @intCast(shdr.sh_addr); |
| 3181 | end_sym.output_section_index = shndx; | 3208 | end_sym.output_section_index = shndx; |
| 3182 | end_sym.value = shdr.sh_addr + shdr.sh_size; | 3209 | end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size); |
| 3183 | } | 3210 | } |
| 3184 | 3211 | ||
| 3185 | // _GLOBAL_OFFSET_TABLE_ | 3212 | // _GLOBAL_OFFSET_TABLE_ |
| ... | @@ -3187,14 +3214,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3187,14 +3214,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3187 | if (self.got_plt_section_index) |shndx| { | 3214 | if (self.got_plt_section_index) |shndx| { |
| 3188 | const shdr = self.shdrs.items[shndx]; | 3215 | const shdr = self.shdrs.items[shndx]; |
| 3189 | const sym = self.symbol(self.got_index.?); | 3216 | const sym = self.symbol(self.got_index.?); |
| 3190 | sym.value = shdr.sh_addr; | 3217 | sym.value = @intCast(shdr.sh_addr); |
| 3191 | sym.output_section_index = shndx; | 3218 | sym.output_section_index = shndx; |
| 3192 | } | 3219 | } |
| 3193 | } else { | 3220 | } else { |
| 3194 | if (self.got_section_index) |shndx| { | 3221 | if (self.got_section_index) |shndx| { |
| 3195 | const shdr = self.shdrs.items[shndx]; | 3222 | const shdr = self.shdrs.items[shndx]; |
| 3196 | const sym = self.symbol(self.got_index.?); | 3223 | const sym = self.symbol(self.got_index.?); |
| 3197 | sym.value = shdr.sh_addr; | 3224 | sym.value = @intCast(shdr.sh_addr); |
| 3198 | sym.output_section_index = shndx; | 3225 | sym.output_section_index = shndx; |
| 3199 | } | 3226 | } |
| 3200 | } | 3227 | } |
| ... | @@ -3203,7 +3230,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3203,7 +3230,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3203 | if (self.plt_section_index) |shndx| { | 3230 | if (self.plt_section_index) |shndx| { |
| 3204 | const shdr = &self.shdrs.items[shndx]; | 3231 | const shdr = &self.shdrs.items[shndx]; |
| 3205 | const symbol_ptr = self.symbol(self.plt_index.?); | 3232 | const symbol_ptr = self.symbol(self.plt_index.?); |
| 3206 | symbol_ptr.value = shdr.sh_addr; | 3233 | symbol_ptr.value = @intCast(shdr.sh_addr); |
| 3207 | symbol_ptr.output_section_index = shndx; | 3234 | symbol_ptr.output_section_index = shndx; |
| 3208 | } | 3235 | } |
| 3209 | 3236 | ||
| ... | @@ -3211,7 +3238,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3211,7 +3238,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3211 | if (self.dso_handle_index) |index| { | 3238 | if (self.dso_handle_index) |index| { |
| 3212 | const shdr = &self.shdrs.items[1]; | 3239 | const shdr = &self.shdrs.items[1]; |
| 3213 | const symbol_ptr = self.symbol(index); | 3240 | const symbol_ptr = self.symbol(index); |
| 3214 | symbol_ptr.value = shdr.sh_addr; | 3241 | symbol_ptr.value = @intCast(shdr.sh_addr); |
| 3215 | symbol_ptr.output_section_index = 0; | 3242 | symbol_ptr.output_section_index = 0; |
| 3216 | } | 3243 | } |
| 3217 | 3244 | ||
| ... | @@ -3219,7 +3246,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3219,7 +3246,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3219 | if (self.eh_frame_hdr_section_index) |shndx| { | 3246 | if (self.eh_frame_hdr_section_index) |shndx| { |
| 3220 | const shdr = &self.shdrs.items[shndx]; | 3247 | const shdr = &self.shdrs.items[shndx]; |
| 3221 | const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?); | 3248 | const symbol_ptr = self.symbol(self.gnu_eh_frame_hdr_index.?); |
| 3222 | symbol_ptr.value = shdr.sh_addr; | 3249 | symbol_ptr.value = @intCast(shdr.sh_addr); |
| 3223 | symbol_ptr.output_section_index = shndx; | 3250 | symbol_ptr.output_section_index = shndx; |
| 3224 | } | 3251 | } |
| 3225 | 3252 | ||
| ... | @@ -3231,9 +3258,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3231,9 +3258,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3231 | const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); | 3258 | const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); |
| 3232 | const start_sym = self.symbol(self.rela_iplt_start_index.?); | 3259 | const start_sym = self.symbol(self.rela_iplt_start_index.?); |
| 3233 | const end_sym = self.symbol(self.rela_iplt_end_index.?); | 3260 | const end_sym = self.symbol(self.rela_iplt_end_index.?); |
| 3234 | start_sym.value = start_addr; | 3261 | start_sym.value = @intCast(start_addr); |
| 3235 | start_sym.output_section_index = shndx; | 3262 | start_sym.output_section_index = shndx; |
| 3236 | end_sym.value = end_addr; | 3263 | end_sym.value = @intCast(end_addr); |
| 3237 | end_sym.output_section_index = shndx; | 3264 | end_sym.output_section_index = shndx; |
| 3238 | } | 3265 | } |
| 3239 | 3266 | ||
| ... | @@ -3242,7 +3269,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3242,7 +3269,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3242 | const end_symbol = self.symbol(self.end_index.?); | 3269 | const end_symbol = self.symbol(self.end_index.?); |
| 3243 | for (self.shdrs.items, 0..) |shdr, shndx| { | 3270 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 3244 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { | 3271 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { |
| 3245 | end_symbol.value = shdr.sh_addr + shdr.sh_size; | 3272 | end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size); |
| 3246 | end_symbol.output_section_index = @intCast(shndx); | 3273 | end_symbol.output_section_index = @intCast(shndx); |
| 3247 | } | 3274 | } |
| 3248 | } | 3275 | } |
| ... | @@ -3257,9 +3284,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3257,9 +3284,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3257 | const stop = self.symbol(self.start_stop_indexes.items[index + 1]); | 3284 | const stop = self.symbol(self.start_stop_indexes.items[index + 1]); |
| 3258 | const shndx = self.sectionByName(name["__start_".len..]).?; | 3285 | const shndx = self.sectionByName(name["__start_".len..]).?; |
| 3259 | const shdr = &self.shdrs.items[shndx]; | 3286 | const shdr = &self.shdrs.items[shndx]; |
| 3260 | start.value = shdr.sh_addr; | 3287 | start.value = @intCast(shdr.sh_addr); |
| 3261 | start.output_section_index = shndx; | 3288 | start.output_section_index = shndx; |
| 3262 | stop.value = shdr.sh_addr + shdr.sh_size; | 3289 | stop.value = @intCast(shdr.sh_addr + shdr.sh_size); |
| 3263 | stop.output_section_index = shndx; | 3290 | stop.output_section_index = shndx; |
| 3264 | } | 3291 | } |
| 3265 | } | 3292 | } |
| ... | @@ -3269,7 +3296,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { | ... | @@ -3269,7 +3296,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3269 | const sym = self.symbol(index); | 3296 | const sym = self.symbol(index); |
| 3270 | if (self.sectionByName(".sdata")) |shndx| { | 3297 | if (self.sectionByName(".sdata")) |shndx| { |
| 3271 | const shdr = self.shdrs.items[shndx]; | 3298 | const shdr = self.shdrs.items[shndx]; |
| 3272 | sym.value = shdr.sh_addr + 0x800; | 3299 | sym.value = @intCast(shdr.sh_addr + 0x800); |
| 3273 | sym.output_section_index = shndx; | 3300 | sym.output_section_index = shndx; |
| 3274 | } else { | 3301 | } else { |
| 3275 | sym.value = 0; | 3302 | sym.value = 0; |
| ... | @@ -3299,10 +3326,109 @@ fn checkDuplicates(self: *Elf) !void { | ... | @@ -3299,10 +3326,109 @@ fn checkDuplicates(self: *Elf) !void { |
| 3299 | try self.reportDuplicates(dupes); | 3326 | try self.reportDuplicates(dupes); |
| 3300 | } | 3327 | } |
| 3301 | 3328 | ||
| 3329 | pub fn addCommentString(self: *Elf) !void { | ||
| 3330 | const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS); | ||
| 3331 | const msec = self.mergeSection(msec_index); | ||
| 3332 | const res = try msec.insertZ(self.base.comp.gpa, "zig version x.x.x"); // TODO get actual version | ||
| 3333 | if (res.found_existing) return; | ||
| 3334 | const msub_index = try self.addMergeSubsection(); | ||
| 3335 | const msub = self.mergeSubsection(msub_index); | ||
| 3336 | msub.merge_section_index = msec_index; | ||
| 3337 | msub.string_index = res.key.pos; | ||
| 3338 | msub.alignment = .@"1"; | ||
| 3339 | msub.size = res.key.len; | ||
| 3340 | msub.alive = true; | ||
| 3341 | res.sub.* = msub_index; | ||
| 3342 | } | ||
| 3343 | |||
| 3344 | fn resolveMergeSections(self: *Elf) !void { | ||
| 3345 | const tracy = trace(@src()); | ||
| 3346 | defer tracy.end(); | ||
| 3347 | |||
| 3348 | var has_errors = false; | ||
| 3349 | for (self.objects.items) |index| { | ||
| 3350 | const file_ptr = self.file(index).?; | ||
| 3351 | if (!file_ptr.isAlive()) continue; | ||
| 3352 | file_ptr.object.initMergeSections(self) catch |err| switch (err) { | ||
| 3353 | error.MalformedObject => has_errors = true, | ||
| 3354 | else => |e| return e, | ||
| 3355 | }; | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | if (has_errors) return error.FlushFailure; | ||
| 3359 | |||
| 3360 | for (self.objects.items) |index| { | ||
| 3361 | const file_ptr = self.file(index).?; | ||
| 3362 | if (!file_ptr.isAlive()) continue; | ||
| 3363 | file_ptr.object.resolveMergeSubsections(self) catch |err| switch (err) { | ||
| 3364 | error.MalformedObject => has_errors = true, | ||
| 3365 | else => |e| return e, | ||
| 3366 | }; | ||
| 3367 | } | ||
| 3368 | |||
| 3369 | if (has_errors) return error.FlushFailure; | ||
| 3370 | } | ||
| 3371 | |||
| 3372 | pub fn sortMergeSections(self: *Elf) !void { | ||
| 3373 | for (self.merge_sections.items) |*msec| { | ||
| 3374 | try msec.sort(self); | ||
| 3375 | } | ||
| 3376 | } | ||
| 3377 | |||
| 3378 | pub fn updateMergeSectionSizes(self: *Elf) !void { | ||
| 3379 | for (self.merge_sections.items) |*msec| { | ||
| 3380 | const shdr = &self.shdrs.items[msec.output_section_index]; | ||
| 3381 | for (msec.subsections.items) |msub_index| { | ||
| 3382 | const msub = self.mergeSubsection(msub_index); | ||
| 3383 | assert(msub.alive); | ||
| 3384 | const offset = msub.alignment.forward(shdr.sh_size); | ||
| 3385 | const padding = offset - shdr.sh_size; | ||
| 3386 | msub.value = @intCast(offset); | ||
| 3387 | shdr.sh_size += padding + msub.size; | ||
| 3388 | shdr.sh_addralign = @max(shdr.sh_addralign, msub.alignment.toByteUnits() orelse 1); | ||
| 3389 | } | ||
| 3390 | } | ||
| 3391 | } | ||
| 3392 | |||
| 3393 | pub fn writeMergeSections(self: *Elf) !void { | ||
| 3394 | const gpa = self.base.comp.gpa; | ||
| 3395 | var buffer = std.ArrayList(u8).init(gpa); | ||
| 3396 | defer buffer.deinit(); | ||
| 3397 | |||
| 3398 | for (self.merge_sections.items) |msec| { | ||
| 3399 | const shdr = self.shdrs.items[msec.output_section_index]; | ||
| 3400 | |||
| 3401 | try buffer.ensureTotalCapacity(shdr.sh_size); | ||
| 3402 | buffer.appendNTimesAssumeCapacity(0, shdr.sh_size); | ||
| 3403 | |||
| 3404 | for (msec.subsections.items) |msub_index| { | ||
| 3405 | const msub = self.mergeSubsection(msub_index); | ||
| 3406 | assert(msub.alive); | ||
| 3407 | const string = msub.getString(self); | ||
| 3408 | const off: u64 = @intCast(msub.value); | ||
| 3409 | @memcpy(buffer.items[off..][0..string.len], string); | ||
| 3410 | } | ||
| 3411 | |||
| 3412 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | ||
| 3413 | buffer.clearRetainingCapacity(); | ||
| 3414 | } | ||
| 3415 | } | ||
| 3416 | |||
| 3302 | fn initOutputSections(self: *Elf) !void { | 3417 | fn initOutputSections(self: *Elf) !void { |
| 3303 | for (self.objects.items) |index| { | 3418 | for (self.objects.items) |index| { |
| 3304 | try self.file(index).?.object.initOutputSections(self); | 3419 | try self.file(index).?.object.initOutputSections(self); |
| 3305 | } | 3420 | } |
| 3421 | |||
| 3422 | for (self.merge_sections.items) |*msec| { | ||
| 3423 | if (msec.subsections.items.len == 0) continue; | ||
| 3424 | const name = msec.name(self); | ||
| 3425 | const shndx = self.sectionByName(name) orelse try self.addSection(.{ | ||
| 3426 | .name = name, | ||
| 3427 | .type = msec.type, | ||
| 3428 | .flags = msec.flags, | ||
| 3429 | }); | ||
| 3430 | msec.output_section_index = shndx; | ||
| 3431 | } | ||
| 3306 | } | 3432 | } |
| 3307 | 3433 | ||
| 3308 | fn initSyntheticSections(self: *Elf) !void { | 3434 | fn initSyntheticSections(self: *Elf) !void { |
| ... | @@ -3971,6 +4097,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { | ... | @@ -3971,6 +4097,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { |
| 3971 | } | 4097 | } |
| 3972 | } | 4098 | } |
| 3973 | 4099 | ||
| 4100 | for (self.merge_sections.items) |*msec| { | ||
| 4101 | msec.output_section_index = backlinks[msec.output_section_index]; | ||
| 4102 | } | ||
| 4103 | |||
| 3974 | { | 4104 | { |
| 3975 | var output_rela_sections = try self.output_rela_sections.clone(gpa); | 4105 | var output_rela_sections = try self.output_rela_sections.clone(gpa); |
| 3976 | defer output_rela_sections.deinit(gpa); | 4106 | defer output_rela_sections.deinit(gpa); |
| ... | @@ -4058,7 +4188,7 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4058,7 +4188,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4058 | if (!atom_ptr.flags.alive) continue; | 4188 | if (!atom_ptr.flags.alive) continue; |
| 4059 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | 4189 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 4060 | const padding = offset - shdr.sh_size; | 4190 | const padding = offset - shdr.sh_size; |
| 4061 | atom_ptr.value = offset; | 4191 | atom_ptr.value = @intCast(offset); |
| 4062 | shdr.sh_size += padding + atom_ptr.size; | 4192 | shdr.sh_size += padding + atom_ptr.size; |
| 4063 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); | 4193 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 4064 | } | 4194 | } |
| ... | @@ -4541,7 +4671,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4541,7 +4671,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4541 | const atom_ptr = self.atom(atom_index).?; | 4671 | const atom_ptr = self.atom(atom_index).?; |
| 4542 | assert(atom_ptr.flags.alive); | 4672 | assert(atom_ptr.flags.alive); |
| 4543 | 4673 | ||
| 4544 | const offset = math.cast(usize, atom_ptr.value - base_offset) orelse | 4674 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse |
| 4545 | return error.Overflow; | 4675 | return error.Overflow; |
| 4546 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | 4676 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 4547 | 4677 | ||
| ... | @@ -4582,7 +4712,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4582,7 +4712,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4582 | const thunk_size = th.size(self); | 4712 | const thunk_size = th.size(self); |
| 4583 | try buffer.ensureUnusedCapacity(thunk_size); | 4713 | try buffer.ensureUnusedCapacity(thunk_size); |
| 4584 | const shdr = self.shdrs.items[th.output_section_index]; | 4714 | const shdr = self.shdrs.items[th.output_section_index]; |
| 4585 | const offset = th.value + shdr.sh_offset; | 4715 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; |
| 4586 | try th.write(self, buffer.writer()); | 4716 | try th.write(self, buffer.writer()); |
| 4587 | assert(buffer.items.len == thunk_size); | 4717 | assert(buffer.items.len == thunk_size); |
| 4588 | try self.base.file.?.pwriteAll(buffer.items, offset); | 4718 | try self.base.file.?.pwriteAll(buffer.items, offset); |
| ... | @@ -4617,6 +4747,7 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4617,6 +4747,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4617 | if (self.eh_frame_section_index) |_| { | 4747 | if (self.eh_frame_section_index) |_| { |
| 4618 | nlocals += 1; | 4748 | nlocals += 1; |
| 4619 | } | 4749 | } |
| 4750 | nlocals += @intCast(self.merge_sections.items.len); | ||
| 4620 | 4751 | ||
| 4621 | if (self.requiresThunks()) for (self.thunks.items) |*th| { | 4752 | if (self.requiresThunks()) for (self.thunks.items) |*th| { |
| 4622 | th.output_symtab_ctx.ilocal = nlocals + 1; | 4753 | th.output_symtab_ctx.ilocal = nlocals + 1; |
| ... | @@ -4953,12 +5084,29 @@ fn writeSectionSymbols(self: *Elf) void { | ... | @@ -4953,12 +5084,29 @@ fn writeSectionSymbols(self: *Elf) void { |
| 4953 | }; | 5084 | }; |
| 4954 | ilocal += 1; | 5085 | ilocal += 1; |
| 4955 | } | 5086 | } |
| 5087 | |||
| 5088 | for (self.merge_sections.items) |msec| { | ||
| 5089 | const shdr = self.shdrs.items[msec.output_section_index]; | ||
| 5090 | const out_sym = &self.symtab.items[ilocal]; | ||
| 5091 | out_sym.* = .{ | ||
| 5092 | .st_name = 0, | ||
| 5093 | .st_value = shdr.sh_addr, | ||
| 5094 | .st_info = elf.STT_SECTION, | ||
| 5095 | .st_shndx = @intCast(msec.output_section_index), | ||
| 5096 | .st_size = 0, | ||
| 5097 | .st_other = 0, | ||
| 5098 | }; | ||
| 5099 | ilocal += 1; | ||
| 5100 | } | ||
| 4956 | } | 5101 | } |
| 4957 | 5102 | ||
| 4958 | pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { | 5103 | pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { |
| 4959 | if (self.eh_frame_section_index) |index| { | 5104 | if (self.eh_frame_section_index) |index| { |
| 4960 | if (index == shndx) return @intCast(self.output_sections.keys().len + 1); | 5105 | if (index == shndx) return @intCast(self.output_sections.keys().len + 1); |
| 4961 | } | 5106 | } |
| 5107 | for (self.merge_sections.items, 1..) |msec, index| { | ||
| 5108 | if (msec.output_section_index == shndx) return @intCast(self.output_sections.keys().len + 1 + index); | ||
| 5109 | } | ||
| 4962 | return @intCast(self.output_sections.getIndex(shndx).? + 1); | 5110 | return @intCast(self.output_sections.getIndex(shndx).? + 1); |
| 4963 | } | 5111 | } |
| 4964 | 5112 | ||
| ... | @@ -5687,35 +5835,88 @@ pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupO | ... | @@ -5687,35 +5835,88 @@ pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupO |
| 5687 | return &self.comdat_groups_owners.items[index]; | 5835 | return &self.comdat_groups_owners.items[index]; |
| 5688 | } | 5836 | } |
| 5689 | 5837 | ||
| 5690 | pub fn gotAddress(self: *Elf) u64 { | 5838 | pub fn addInputMergeSection(self: *Elf) !InputMergeSection.Index { |
| 5839 | const index: InputMergeSection.Index = @intCast(self.merge_input_sections.items.len); | ||
| 5840 | const msec = try self.merge_input_sections.addOne(self.base.comp.gpa); | ||
| 5841 | msec.* = .{}; | ||
| 5842 | return index; | ||
| 5843 | } | ||
| 5844 | |||
| 5845 | pub fn inputMergeSection(self: *Elf, index: InputMergeSection.Index) ?*InputMergeSection { | ||
| 5846 | if (index == 0) return null; | ||
| 5847 | return &self.merge_input_sections.items[index]; | ||
| 5848 | } | ||
| 5849 | |||
| 5850 | pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index { | ||
| 5851 | const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len); | ||
| 5852 | const msec = try self.merge_subsections.addOne(self.base.comp.gpa); | ||
| 5853 | msec.* = .{}; | ||
| 5854 | return index; | ||
| 5855 | } | ||
| 5856 | |||
| 5857 | pub fn mergeSubsection(self: *Elf, index: MergeSubsection.Index) *MergeSubsection { | ||
| 5858 | assert(index < self.merge_subsections.items.len); | ||
| 5859 | return &self.merge_subsections.items[index]; | ||
| 5860 | } | ||
| 5861 | |||
| 5862 | pub fn getOrCreateMergeSection(self: *Elf, name: []const u8, flags: u64, @"type": u32) !MergeSection.Index { | ||
| 5863 | const gpa = self.base.comp.gpa; | ||
| 5864 | const out_name = name: { | ||
| 5865 | if (self.base.isRelocatable()) break :name name; | ||
| 5866 | if (mem.eql(u8, name, ".rodata") or mem.startsWith(u8, name, ".rodata")) | ||
| 5867 | break :name if (flags & elf.SHF_STRINGS != 0) ".rodata.str" else ".rodata.cst"; | ||
| 5868 | break :name name; | ||
| 5869 | }; | ||
| 5870 | const out_off = try self.strings.insert(gpa, out_name); | ||
| 5871 | const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP); | ||
| 5872 | for (self.merge_sections.items, 0..) |msec, index| { | ||
| 5873 | if (msec.name_offset == out_off) return @intCast(index); | ||
| 5874 | } | ||
| 5875 | const index = @as(MergeSection.Index, @intCast(self.merge_sections.items.len)); | ||
| 5876 | const msec = try self.merge_sections.addOne(gpa); | ||
| 5877 | msec.* = .{ | ||
| 5878 | .name_offset = out_off, | ||
| 5879 | .flags = out_flags, | ||
| 5880 | .type = @"type", | ||
| 5881 | }; | ||
| 5882 | return index; | ||
| 5883 | } | ||
| 5884 | |||
| 5885 | pub fn mergeSection(self: *Elf, index: MergeSection.Index) *MergeSection { | ||
| 5886 | assert(index < self.merge_sections.items.len); | ||
| 5887 | return &self.merge_sections.items[index]; | ||
| 5888 | } | ||
| 5889 | |||
| 5890 | pub fn gotAddress(self: *Elf) i64 { | ||
| 5691 | const shndx = blk: { | 5891 | const shndx = blk: { |
| 5692 | if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null) | 5892 | if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null) |
| 5693 | break :blk self.got_plt_section_index.?; | 5893 | break :blk self.got_plt_section_index.?; |
| 5694 | break :blk if (self.got_section_index) |shndx| shndx else null; | 5894 | break :blk if (self.got_section_index) |shndx| shndx else null; |
| 5695 | }; | 5895 | }; |
| 5696 | return if (shndx) |index| self.shdrs.items[index].sh_addr else 0; | 5896 | return if (shndx) |index| @intCast(self.shdrs.items[index].sh_addr) else 0; |
| 5697 | } | 5897 | } |
| 5698 | 5898 | ||
| 5699 | pub fn tpAddress(self: *Elf) u64 { | 5899 | pub fn tpAddress(self: *Elf) i64 { |
| 5700 | const index = self.phdr_tls_index orelse return 0; | 5900 | const index = self.phdr_tls_index orelse return 0; |
| 5701 | const phdr = self.phdrs.items[index]; | 5901 | const phdr = self.phdrs.items[index]; |
| 5702 | return switch (self.getTarget().cpu.arch) { | 5902 | const addr = switch (self.getTarget().cpu.arch) { |
| 5703 | .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), | 5903 | .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), |
| 5704 | .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), | 5904 | .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), |
| 5705 | else => @panic("TODO implement getTpAddress for this arch"), | 5905 | else => @panic("TODO implement getTpAddress for this arch"), |
| 5706 | }; | 5906 | }; |
| 5907 | return @intCast(addr); | ||
| 5707 | } | 5908 | } |
| 5708 | 5909 | ||
| 5709 | pub fn dtpAddress(self: *Elf) u64 { | 5910 | pub fn dtpAddress(self: *Elf) i64 { |
| 5710 | const index = self.phdr_tls_index orelse return 0; | 5911 | const index = self.phdr_tls_index orelse return 0; |
| 5711 | const phdr = self.phdrs.items[index]; | 5912 | const phdr = self.phdrs.items[index]; |
| 5712 | return phdr.p_vaddr; | 5913 | return @intCast(phdr.p_vaddr); |
| 5713 | } | 5914 | } |
| 5714 | 5915 | ||
| 5715 | pub fn tlsAddress(self: *Elf) u64 { | 5916 | pub fn tlsAddress(self: *Elf) i64 { |
| 5716 | const index = self.phdr_tls_index orelse return 0; | 5917 | const index = self.phdr_tls_index orelse return 0; |
| 5717 | const phdr = self.phdrs.items[index]; | 5918 | const phdr = self.phdrs.items[index]; |
| 5718 | return phdr.p_vaddr; | 5919 | return @intCast(phdr.p_vaddr); |
| 5719 | } | 5920 | } |
| 5720 | 5921 | ||
| 5721 | const ErrorWithNotes = struct { | 5922 | const ErrorWithNotes = struct { |
| ... | @@ -6093,6 +6294,11 @@ fn fmtDumpState( | ... | @@ -6093,6 +6294,11 @@ fn fmtDumpState( |
| 6093 | try writer.print(" shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index }); | 6294 | try writer.print(" shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index }); |
| 6094 | } | 6295 | } |
| 6095 | 6296 | ||
| 6297 | try writer.writeAll("\nOutput merge sections\n"); | ||
| 6298 | for (self.merge_sections.items) |msec| { | ||
| 6299 | try writer.print(" shdr({d}) : {}\n", .{ msec.output_section_index, msec.fmt(self) }); | ||
| 6300 | } | ||
| 6301 | |||
| 6096 | try writer.writeAll("\nOutput shdrs\n"); | 6302 | try writer.writeAll("\nOutput shdrs\n"); |
| 6097 | for (self.shdrs.items, 0..) |shdr, shndx| { | 6303 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 6098 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ | 6304 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| ... | @@ -6285,6 +6491,7 @@ const gc = @import("Elf/gc.zig"); | ... | @@ -6285,6 +6491,7 @@ const gc = @import("Elf/gc.zig"); |
| 6285 | const glibc = @import("../glibc.zig"); | 6491 | const glibc = @import("../glibc.zig"); |
| 6286 | const link = @import("../link.zig"); | 6492 | const link = @import("../link.zig"); |
| 6287 | const lldMain = @import("../main.zig").lldMain; | 6493 | const lldMain = @import("../main.zig").lldMain; |
| 6494 | const merge_section = @import("Elf/merge_section.zig"); | ||
| 6288 | const musl = @import("../musl.zig"); | 6495 | const musl = @import("../musl.zig"); |
| 6289 | const relocatable = @import("Elf/relocatable.zig"); | 6496 | const relocatable = @import("Elf/relocatable.zig"); |
| 6290 | const relocation = @import("Elf/relocation.zig"); | 6497 | const relocation = @import("Elf/relocation.zig"); |
| ... | @@ -6310,10 +6517,13 @@ const GnuHashSection = synthetic_sections.GnuHashSection; | ... | @@ -6310,10 +6517,13 @@ const GnuHashSection = synthetic_sections.GnuHashSection; |
| 6310 | const GotSection = synthetic_sections.GotSection; | 6517 | const GotSection = synthetic_sections.GotSection; |
| 6311 | const GotPltSection = synthetic_sections.GotPltSection; | 6518 | const GotPltSection = synthetic_sections.GotPltSection; |
| 6312 | const HashSection = synthetic_sections.HashSection; | 6519 | const HashSection = synthetic_sections.HashSection; |
| 6520 | const InputMergeSection = merge_section.InputMergeSection; | ||
| 6313 | const LdScript = @import("Elf/LdScript.zig"); | 6521 | const LdScript = @import("Elf/LdScript.zig"); |
| 6314 | const LinkerDefined = @import("Elf/LinkerDefined.zig"); | 6522 | const LinkerDefined = @import("Elf/LinkerDefined.zig"); |
| 6315 | const Liveness = @import("../Liveness.zig"); | 6523 | const Liveness = @import("../Liveness.zig"); |
| 6316 | const LlvmObject = @import("../codegen/llvm.zig").Object; | 6524 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 6525 | const MergeSection = merge_section.MergeSection; | ||
| 6526 | const MergeSubsection = merge_section.MergeSubsection; | ||
| 6317 | const Module = @import("../Module.zig"); | 6527 | const Module = @import("../Module.zig"); |
| 6318 | const Object = @import("Elf/Object.zig"); | 6528 | const Object = @import("Elf/Object.zig"); |
| 6319 | const InternPool = @import("../InternPool.zig"); | 6529 | const InternPool = @import("../InternPool.zig"); |
src/link/Elf/Atom.zig+113-86| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | /// Address allocated for this Atom. | 1 | /// Address allocated for this Atom. |
| 2 | value: u64 = 0, | 2 | value: i64 = 0, |
| 3 | 3 | ||
| 4 | /// Name of this Atom. | 4 | /// Name of this Atom. |
| 5 | name_offset: u32 = 0, | 5 | name_offset: u32 = 0, |
| ... | @@ -44,10 +44,22 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 { | ... | @@ -44,10 +44,22 @@ pub fn name(self: Atom, elf_file: *Elf) []const u8 { |
| 44 | }; | 44 | }; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | pub fn address(self: Atom, elf_file: *Elf) u64 { | 47 | pub fn address(self: Atom, elf_file: *Elf) i64 { |
| 48 | const shndx = self.outputShndx() orelse return self.value; | 48 | const shndx = self.outputShndx() orelse return self.value; |
| 49 | const shdr = elf_file.shdrs.items[shndx]; | 49 | const shdr = elf_file.shdrs.items[shndx]; |
| 50 | return shdr.sh_addr + self.value; | 50 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; |
| 51 | } | ||
| 52 | |||
| 53 | pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 { | ||
| 54 | if (target.mergeSubsection(elf_file)) |msub| { | ||
| 55 | if (msub.alive) return null; | ||
| 56 | } | ||
| 57 | if (target.atom(elf_file)) |atom_ptr| { | ||
| 58 | if (atom_ptr.flags.alive) return null; | ||
| 59 | } | ||
| 60 | const atom_name = self.name(elf_file); | ||
| 61 | if (!mem.startsWith(u8, atom_name, ".debug")) return null; | ||
| 62 | return if (mem.eql(u8, atom_name, ".debug_loc") or mem.eql(u8, atom_name, ".debug_ranges")) 1 else 0; | ||
| 51 | } | 63 | } |
| 52 | 64 | ||
| 53 | pub fn file(self: Atom, elf_file: *Elf) ?File { | 65 | pub fn file(self: Atom, elf_file: *Elf) ?File { |
| ... | @@ -91,13 +103,13 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 { | ... | @@ -91,13 +103,13 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 91 | next.address(elf_file) | 103 | next.address(elf_file) |
| 92 | else | 104 | else |
| 93 | std.math.maxInt(u32); | 105 | std.math.maxInt(u32); |
| 94 | return next_addr - self.address(elf_file); | 106 | return @intCast(next_addr - self.address(elf_file)); |
| 95 | } | 107 | } |
| 96 | 108 | ||
| 97 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { | 109 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 98 | // No need to keep a free list node for the last block. | 110 | // No need to keep a free list node for the last block. |
| 99 | const next = elf_file.atom(self.next_index) orelse return false; | 111 | const next = elf_file.atom(self.next_index) orelse return false; |
| 100 | const cap = next.address(elf_file) - self.address(elf_file); | 112 | const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file)); |
| 101 | const ideal_cap = Elf.padToIdeal(self.size); | 113 | const ideal_cap = Elf.padToIdeal(self.size); |
| 102 | if (cap <= ideal_cap) return false; | 114 | if (cap <= ideal_cap) return false; |
| 103 | const surplus = cap - ideal_cap; | 115 | const surplus = cap - ideal_cap; |
| ... | @@ -130,8 +142,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -130,8 +142,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 130 | // Is it enough that we could fit this new atom? | 142 | // Is it enough that we could fit this new atom? |
| 131 | const cap = big_atom.capacity(elf_file); | 143 | const cap = big_atom.capacity(elf_file); |
| 132 | const ideal_capacity = Elf.padToIdeal(cap); | 144 | const ideal_capacity = Elf.padToIdeal(cap); |
| 133 | const ideal_capacity_end_vaddr = std.math.add(u64, big_atom.value, ideal_capacity) catch ideal_capacity; | 145 | const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity; |
| 134 | const capacity_end_vaddr = big_atom.value + cap; | 146 | const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap; |
| 135 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; | 147 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; |
| 136 | const new_start_vaddr = self.alignment.backward(new_start_vaddr_unaligned); | 148 | const new_start_vaddr = self.alignment.backward(new_start_vaddr_unaligned); |
| 137 | if (new_start_vaddr < ideal_capacity_end_vaddr) { | 149 | if (new_start_vaddr < ideal_capacity_end_vaddr) { |
| ... | @@ -156,14 +168,14 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -156,14 +168,14 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 156 | if (!keep_free_list_node) { | 168 | if (!keep_free_list_node) { |
| 157 | free_list_removal = i; | 169 | free_list_removal = i; |
| 158 | } | 170 | } |
| 159 | break :blk new_start_vaddr; | 171 | break :blk @intCast(new_start_vaddr); |
| 160 | } else if (elf_file.atom(last_atom_index.*)) |last| { | 172 | } else if (elf_file.atom(last_atom_index.*)) |last| { |
| 161 | const ideal_capacity = Elf.padToIdeal(last.size); | 173 | const ideal_capacity = Elf.padToIdeal(last.size); |
| 162 | const ideal_capacity_end_vaddr = last.value + ideal_capacity; | 174 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity; |
| 163 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); | 175 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); |
| 164 | // Set up the metadata to be updated, after errors are no longer possible. | 176 | // Set up the metadata to be updated, after errors are no longer possible. |
| 165 | atom_placement = last.atom_index; | 177 | atom_placement = last.atom_index; |
| 166 | break :blk new_start_vaddr; | 178 | break :blk @intCast(new_start_vaddr); |
| 167 | } else { | 179 | } else { |
| 168 | break :blk 0; | 180 | break :blk 0; |
| 169 | } | 181 | } |
| ... | @@ -173,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -173,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 173 | self.atom_index, | 185 | self.atom_index, |
| 174 | self.name(elf_file), | 186 | self.name(elf_file), |
| 175 | self.address(elf_file), | 187 | self.address(elf_file), |
| 176 | self.address(elf_file) + self.size, | 188 | self.address(elf_file) + @as(i64, @intCast(self.size)), |
| 177 | }); | 189 | }); |
| 178 | 190 | ||
| 179 | const expand_section = if (atom_placement) |placement_index| | 191 | const expand_section = if (atom_placement) |placement_index| |
| ... | @@ -181,7 +193,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -181,7 +193,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 181 | else | 193 | else |
| 182 | true; | 194 | true; |
| 183 | if (expand_section) { | 195 | if (expand_section) { |
| 184 | const needed_size = self.value + self.size; | 196 | const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); |
| 185 | try elf_file.growAllocSection(self.outputShndx().?, needed_size); | 197 | try elf_file.growAllocSection(self.outputShndx().?, needed_size); |
| 186 | last_atom_index.* = self.atom_index; | 198 | last_atom_index.* = self.atom_index; |
| 187 | 199 | ||
| ... | @@ -231,7 +243,7 @@ pub fn shrink(self: *Atom, elf_file: *Elf) void { | ... | @@ -231,7 +243,7 @@ pub fn shrink(self: *Atom, elf_file: *Elf) void { |
| 231 | } | 243 | } |
| 232 | 244 | ||
| 233 | pub fn grow(self: *Atom, elf_file: *Elf) !void { | 245 | pub fn grow(self: *Atom, elf_file: *Elf) !void { |
| 234 | if (!self.alignment.check(self.value) or self.size > self.capacity(elf_file)) | 246 | if (!self.alignment.check(@intCast(self.value)) or self.size > self.capacity(elf_file)) |
| 235 | try self.allocate(elf_file); | 247 | try self.allocate(elf_file); |
| 236 | } | 248 | } |
| 237 | 249 | ||
| ... | @@ -321,11 +333,14 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El | ... | @@ -321,11 +333,14 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 321 | }; | 333 | }; |
| 322 | const target = elf_file.symbol(target_index); | 334 | const target = elf_file.symbol(target_index); |
| 323 | const r_type = rel.r_type(); | 335 | const r_type = rel.r_type(); |
| 324 | const r_offset = self.value + rel.r_offset; | 336 | const r_offset: u64 = @intCast(self.value + @as(i64, @intCast(rel.r_offset))); |
| 325 | var r_addend = rel.r_addend; | 337 | var r_addend = rel.r_addend; |
| 326 | var r_sym: u32 = 0; | 338 | var r_sym: u32 = 0; |
| 327 | switch (target.type(elf_file)) { | 339 | switch (target.type(elf_file)) { |
| 328 | elf.STT_SECTION => { | 340 | elf.STT_SECTION => if (target.mergeSubsection(elf_file)) |msub| { |
| 341 | r_addend += @intCast(target.address(.{}, elf_file)); | ||
| 342 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(msub.mergeSection(elf_file).output_section_index); | ||
| 343 | } else { | ||
| 329 | r_addend += @intCast(target.address(.{}, elf_file)); | 344 | r_addend += @intCast(target.address(.{}, elf_file)); |
| 330 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?); | 345 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?); |
| 331 | }, | 346 | }, |
| ... | @@ -412,6 +427,12 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype | ... | @@ -412,6 +427,12 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 412 | }; | 427 | }; |
| 413 | const symbol = elf_file.symbol(symbol_index); | 428 | const symbol = elf_file.symbol(symbol_index); |
| 414 | 429 | ||
| 430 | const is_synthetic_symbol = switch (file_ptr) { | ||
| 431 | .zig_object => false, // TODO: implement this once we support merge sections in ZigObject | ||
| 432 | .object => |x| rel.r_sym() >= x.symtab.items.len, | ||
| 433 | else => unreachable, | ||
| 434 | }; | ||
| 435 | |||
| 415 | // Check for violation of One Definition Rule for COMDATs. | 436 | // Check for violation of One Definition Rule for COMDATs. |
| 416 | if (symbol.file(elf_file) == null) { | 437 | if (symbol.file(elf_file) == null) { |
| 417 | // TODO convert into an error | 438 | // TODO convert into an error |
| ... | @@ -424,7 +445,8 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype | ... | @@ -424,7 +445,8 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 424 | } | 445 | } |
| 425 | 446 | ||
| 426 | // Report an undefined symbol. | 447 | // Report an undefined symbol. |
| 427 | if (try self.reportUndefined(elf_file, symbol, symbol_index, rel, undefs)) continue; | 448 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, symbol, symbol_index, rel, undefs))) |
| 449 | continue; | ||
| 428 | 450 | ||
| 429 | if (symbol.isIFunc(elf_file)) { | 451 | if (symbol.isIFunc(elf_file)) { |
| 430 | symbol.flags.needs_got = true; | 452 | symbol.flags.needs_got = true; |
| ... | @@ -733,21 +755,21 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi | ... | @@ -733,21 +755,21 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 733 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ | 755 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ |
| 734 | // | 756 | // |
| 735 | // Address of the source atom. | 757 | // Address of the source atom. |
| 736 | const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset)); | 758 | const P = self.address(elf_file) + @as(i64, @intCast(rel.r_offset)); |
| 737 | // Addend from the relocation. | 759 | // Addend from the relocation. |
| 738 | const A = rel.r_addend; | 760 | const A = rel.r_addend; |
| 739 | // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. | 761 | // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. |
| 740 | const S = @as(i64, @intCast(target.address(.{}, elf_file))); | 762 | const S = target.address(.{}, elf_file); |
| 741 | // Address of the global offset table. | 763 | // Address of the global offset table. |
| 742 | const GOT = @as(i64, @intCast(elf_file.gotAddress())); | 764 | const GOT = elf_file.gotAddress(); |
| 743 | // Address of the .zig.got table entry if any. | 765 | // Address of the .zig.got table entry if any. |
| 744 | const ZIG_GOT = @as(i64, @intCast(target.zigGotAddress(elf_file))); | 766 | const ZIG_GOT = target.zigGotAddress(elf_file); |
| 745 | // Relative offset to the start of the global offset table. | 767 | // Relative offset to the start of the global offset table. |
| 746 | const G = @as(i64, @intCast(target.gotAddress(elf_file))) - GOT; | 768 | const G = target.gotAddress(elf_file) - GOT; |
| 747 | // // Address of the thread pointer. | 769 | // // Address of the thread pointer. |
| 748 | const TP = @as(i64, @intCast(elf_file.tpAddress())); | 770 | const TP = elf_file.tpAddress(); |
| 749 | // Address of the dynamic thread pointer. | 771 | // Address of the dynamic thread pointer. |
| 750 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); | 772 | const DTP = elf_file.dtpAddress(); |
| 751 | 773 | ||
| 752 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ | 774 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ |
| 753 | relocation.fmtRelocType(rel.r_type(), cpu_arch), | 775 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| ... | @@ -804,9 +826,9 @@ fn resolveDynAbsReloc( | ... | @@ -804,9 +826,9 @@ fn resolveDynAbsReloc( |
| 804 | const comp = elf_file.base.comp; | 826 | const comp = elf_file.base.comp; |
| 805 | const gpa = comp.gpa; | 827 | const gpa = comp.gpa; |
| 806 | const cpu_arch = elf_file.getTarget().cpu.arch; | 828 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 807 | const P = self.address(elf_file) + rel.r_offset; | 829 | const P: u64 = @intCast(self.address(elf_file) + @as(i64, @intCast(rel.r_offset))); |
| 808 | const A = rel.r_addend; | 830 | const A = rel.r_addend; |
| 809 | const S = @as(i64, @intCast(target.address(.{}, elf_file))); | 831 | const S = target.address(.{}, elf_file); |
| 810 | const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; | 832 | const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; |
| 811 | 833 | ||
| 812 | const num_dynrelocs = switch (self.file(elf_file).?) { | 834 | const num_dynrelocs = switch (self.file(elf_file).?) { |
| ... | @@ -874,7 +896,7 @@ fn resolveDynAbsReloc( | ... | @@ -874,7 +896,7 @@ fn resolveDynAbsReloc( |
| 874 | }, | 896 | }, |
| 875 | 897 | ||
| 876 | .ifunc => { | 898 | .ifunc => { |
| 877 | const S_ = @as(i64, @intCast(target.address(.{ .plt = false }, elf_file))); | 899 | const S_ = target.address(.{ .plt = false }, elf_file); |
| 878 | elf_file.addRelaDynAssumeCapacity(.{ | 900 | elf_file.addRelaDynAssumeCapacity(.{ |
| 879 | .offset = P, | 901 | .offset = P, |
| 880 | .type = relocation.encode(.irel, cpu_arch), | 902 | .type = relocation.encode(.irel, cpu_arch), |
| ... | @@ -914,6 +936,11 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any | ... | @@ -914,6 +936,11 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 914 | else => unreachable, | 936 | else => unreachable, |
| 915 | }; | 937 | }; |
| 916 | const target = elf_file.symbol(target_index); | 938 | const target = elf_file.symbol(target_index); |
| 939 | const is_synthetic_symbol = switch (file_ptr) { | ||
| 940 | .zig_object => false, // TODO: implement this once we support merge sections in ZigObject | ||
| 941 | .object => |x| rel.r_sym() >= x.symtab.items.len, | ||
| 942 | else => unreachable, | ||
| 943 | }; | ||
| 917 | 944 | ||
| 918 | // Check for violation of One Definition Rule for COMDATs. | 945 | // Check for violation of One Definition Rule for COMDATs. |
| 919 | if (target.file(elf_file) == null) { | 946 | if (target.file(elf_file) == null) { |
| ... | @@ -927,20 +954,21 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any | ... | @@ -927,20 +954,21 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 927 | } | 954 | } |
| 928 | 955 | ||
| 929 | // Report an undefined symbol. | 956 | // Report an undefined symbol. |
| 930 | if (try self.reportUndefined(elf_file, target, target_index, rel, undefs)) continue; | 957 | if (!is_synthetic_symbol and (try self.reportUndefined(elf_file, target, target_index, rel, undefs))) |
| 958 | continue; | ||
| 931 | 959 | ||
| 932 | // We will use equation format to resolve relocations: | 960 | // We will use equation format to resolve relocations: |
| 933 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ | 961 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ |
| 934 | // | 962 | // |
| 935 | const P = @as(i64, @intCast(self.address(elf_file) + rel.r_offset)); | 963 | const P = self.address(elf_file) + @as(i64, @intCast(rel.r_offset)); |
| 936 | // Addend from the relocation. | 964 | // Addend from the relocation. |
| 937 | const A = rel.r_addend; | 965 | const A = rel.r_addend; |
| 938 | // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. | 966 | // Address of the target symbol - can be address of the symbol within an atom or address of PLT stub. |
| 939 | const S = @as(i64, @intCast(target.address(.{}, elf_file))); | 967 | const S = target.address(.{}, elf_file); |
| 940 | // Address of the global offset table. | 968 | // Address of the global offset table. |
| 941 | const GOT = @as(i64, @intCast(elf_file.gotAddress())); | 969 | const GOT = elf_file.gotAddress(); |
| 942 | // Address of the dynamic thread pointer. | 970 | // Address of the dynamic thread pointer. |
| 943 | const DTP = @as(i64, @intCast(elf_file.dtpAddress())); | 971 | const DTP = elf_file.dtpAddress(); |
| 944 | 972 | ||
| 945 | const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP, 0 }; | 973 | const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP, 0 }; |
| 946 | 974 | ||
| ... | @@ -1261,10 +1289,10 @@ const x86_64 = struct { | ... | @@ -1261,10 +1289,10 @@ const x86_64 = struct { |
| 1261 | 1289 | ||
| 1262 | .TLSGD => { | 1290 | .TLSGD => { |
| 1263 | if (target.flags.has_tlsgd) { | 1291 | if (target.flags.has_tlsgd) { |
| 1264 | const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); | 1292 | const S_ = target.tlsGdAddress(elf_file); |
| 1265 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1293 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1266 | } else if (target.flags.has_gottp) { | 1294 | } else if (target.flags.has_gottp) { |
| 1267 | const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); | 1295 | const S_ = target.gotTpAddress(elf_file); |
| 1268 | try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream); | 1296 | try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream); |
| 1269 | } else { | 1297 | } else { |
| 1270 | try x86_64.relaxTlsGdToLe( | 1298 | try x86_64.relaxTlsGdToLe( |
| ... | @@ -1280,13 +1308,13 @@ const x86_64 = struct { | ... | @@ -1280,13 +1308,13 @@ const x86_64 = struct { |
| 1280 | .TLSLD => { | 1308 | .TLSLD => { |
| 1281 | if (elf_file.got.tlsld_index) |entry_index| { | 1309 | if (elf_file.got.tlsld_index) |entry_index| { |
| 1282 | const tlsld_entry = elf_file.got.entries.items[entry_index]; | 1310 | const tlsld_entry = elf_file.got.entries.items[entry_index]; |
| 1283 | const S_ = @as(i64, @intCast(tlsld_entry.address(elf_file))); | 1311 | const S_ = tlsld_entry.address(elf_file); |
| 1284 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1312 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1285 | } else { | 1313 | } else { |
| 1286 | try x86_64.relaxTlsLdToLe( | 1314 | try x86_64.relaxTlsLdToLe( |
| 1287 | atom, | 1315 | atom, |
| 1288 | &.{ rel, it.next().? }, | 1316 | &.{ rel, it.next().? }, |
| 1289 | @as(i32, @intCast(TP - @as(i64, @intCast(elf_file.tlsAddress())))), | 1317 | @as(i32, @intCast(TP - elf_file.tlsAddress())), |
| 1290 | elf_file, | 1318 | elf_file, |
| 1291 | stream, | 1319 | stream, |
| 1292 | ); | 1320 | ); |
| ... | @@ -1295,7 +1323,7 @@ const x86_64 = struct { | ... | @@ -1295,7 +1323,7 @@ const x86_64 = struct { |
| 1295 | 1323 | ||
| 1296 | .GOTPC32_TLSDESC => { | 1324 | .GOTPC32_TLSDESC => { |
| 1297 | if (target.flags.has_tlsdesc) { | 1325 | if (target.flags.has_tlsdesc) { |
| 1298 | const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file))); | 1326 | const S_ = target.tlsDescAddress(elf_file); |
| 1299 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1327 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1300 | } else { | 1328 | } else { |
| 1301 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch { | 1329 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch { |
| ... | @@ -1319,7 +1347,7 @@ const x86_64 = struct { | ... | @@ -1319,7 +1347,7 @@ const x86_64 = struct { |
| 1319 | 1347 | ||
| 1320 | .GOTTPOFF => { | 1348 | .GOTTPOFF => { |
| 1321 | if (target.flags.has_gottp) { | 1349 | if (target.flags.has_gottp) { |
| 1322 | const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); | 1350 | const S_ = target.gotTpAddress(elf_file); |
| 1323 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); | 1351 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1324 | } else { | 1352 | } else { |
| 1325 | x86_64.relaxGotTpOff(code[r_offset - 3 ..]); | 1353 | x86_64.relaxGotTpOff(code[r_offset - 3 ..]); |
| ... | @@ -1362,9 +1390,18 @@ const x86_64 = struct { | ... | @@ -1362,9 +1390,18 @@ const x86_64 = struct { |
| 1362 | .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), | 1390 | .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), |
| 1363 | .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), | 1391 | .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), |
| 1364 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | 1392 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), |
| 1365 | .@"64" => try cwriter.writeInt(i64, S + A, .little), | 1393 | .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1366 | .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | 1394 | try cwriter.writeInt(u64, value, .little) |
| 1367 | .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), | 1395 | else |
| 1396 | try cwriter.writeInt(i64, S + A, .little), | ||
| 1397 | .DTPOFF32 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| | ||
| 1398 | try cwriter.writeInt(u64, value, .little) | ||
| 1399 | else | ||
| 1400 | try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | ||
| 1401 | .DTPOFF64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| | ||
| 1402 | try cwriter.writeInt(u64, value, .little) | ||
| 1403 | else | ||
| 1404 | try cwriter.writeInt(i64, S + A - DTP, .little), | ||
| 1368 | .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), | 1405 | .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), |
| 1369 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), | 1406 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), |
| 1370 | .SIZE32 => { | 1407 | .SIZE32 => { |
| ... | @@ -1746,7 +1783,7 @@ const aarch64 = struct { | ... | @@ -1746,7 +1783,7 @@ const aarch64 = struct { |
| 1746 | .object => |x| x.symbols.items[rel.r_sym()], | 1783 | .object => |x| x.symbols.items[rel.r_sym()], |
| 1747 | else => unreachable, | 1784 | else => unreachable, |
| 1748 | }; | 1785 | }; |
| 1749 | const S_: i64 = @intCast(th.targetAddress(target_index, elf_file)); | 1786 | const S_ = th.targetAddress(target_index, elf_file); |
| 1750 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; | 1787 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; |
| 1751 | }; | 1788 | }; |
| 1752 | aarch64_util.writeBranchImm(disp, code); | 1789 | aarch64_util.writeBranchImm(disp, code); |
| ... | @@ -1764,16 +1801,12 @@ const aarch64 = struct { | ... | @@ -1764,16 +1801,12 @@ const aarch64 = struct { |
| 1764 | 1801 | ||
| 1765 | .ADR_PREL_PG_HI21 => { | 1802 | .ADR_PREL_PG_HI21 => { |
| 1766 | // TODO: check for relaxation of ADRP+ADD | 1803 | // TODO: check for relaxation of ADRP+ADD |
| 1767 | const saddr = @as(u64, @intCast(P)); | 1804 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, S + A))); |
| 1768 | const taddr = @as(u64, @intCast(S + A)); | ||
| 1769 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr))); | ||
| 1770 | aarch64_util.writeAdrpInst(pages, code); | 1805 | aarch64_util.writeAdrpInst(pages, code); |
| 1771 | }, | 1806 | }, |
| 1772 | 1807 | ||
| 1773 | .ADR_GOT_PAGE => if (target.flags.has_got) { | 1808 | .ADR_GOT_PAGE => if (target.flags.has_got) { |
| 1774 | const saddr = @as(u64, @intCast(P)); | 1809 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, G + GOT + A))); |
| 1775 | const taddr = @as(u64, @intCast(G + GOT + A)); | ||
| 1776 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr))); | ||
| 1777 | aarch64_util.writeAdrpInst(pages, code); | 1810 | aarch64_util.writeAdrpInst(pages, code); |
| 1778 | } else { | 1811 | } else { |
| 1779 | // TODO: relax | 1812 | // TODO: relax |
| ... | @@ -1828,46 +1861,38 @@ const aarch64 = struct { | ... | @@ -1828,46 +1861,38 @@ const aarch64 = struct { |
| 1828 | }, | 1861 | }, |
| 1829 | 1862 | ||
| 1830 | .TLSIE_ADR_GOTTPREL_PAGE21 => { | 1863 | .TLSIE_ADR_GOTTPREL_PAGE21 => { |
| 1831 | const S_: i64 = @intCast(target.gotTpAddress(elf_file)); | 1864 | const S_ = target.gotTpAddress(elf_file); |
| 1832 | const saddr: u64 = @intCast(P); | 1865 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1833 | const taddr: u64 = @intCast(S_ + A); | 1866 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); |
| 1834 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | ||
| 1835 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | ||
| 1836 | aarch64_util.writeAdrpInst(pages, code); | 1867 | aarch64_util.writeAdrpInst(pages, code); |
| 1837 | }, | 1868 | }, |
| 1838 | 1869 | ||
| 1839 | .TLSIE_LD64_GOTTPREL_LO12_NC => { | 1870 | .TLSIE_LD64_GOTTPREL_LO12_NC => { |
| 1840 | const S_: i64 = @intCast(target.gotTpAddress(elf_file)); | 1871 | const S_ = target.gotTpAddress(elf_file); |
| 1841 | const taddr: u64 = @intCast(S_ + A); | 1872 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1842 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | 1873 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); |
| 1843 | const offset: u12 = try math.divExact(u12, @truncate(taddr), 8); | ||
| 1844 | aarch64_util.writeLoadStoreRegInst(offset, code); | 1874 | aarch64_util.writeLoadStoreRegInst(offset, code); |
| 1845 | }, | 1875 | }, |
| 1846 | 1876 | ||
| 1847 | .TLSGD_ADR_PAGE21 => { | 1877 | .TLSGD_ADR_PAGE21 => { |
| 1848 | const S_: i64 = @intCast(target.tlsGdAddress(elf_file)); | 1878 | const S_ = target.tlsGdAddress(elf_file); |
| 1849 | const saddr: u64 = @intCast(P); | 1879 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1850 | const taddr: u64 = @intCast(S_ + A); | 1880 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); |
| 1851 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | ||
| 1852 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | ||
| 1853 | aarch64_util.writeAdrpInst(pages, code); | 1881 | aarch64_util.writeAdrpInst(pages, code); |
| 1854 | }, | 1882 | }, |
| 1855 | 1883 | ||
| 1856 | .TLSGD_ADD_LO12_NC => { | 1884 | .TLSGD_ADD_LO12_NC => { |
| 1857 | const S_: i64 = @intCast(target.tlsGdAddress(elf_file)); | 1885 | const S_ = target.tlsGdAddress(elf_file); |
| 1858 | const taddr: u64 = @intCast(S_ + A); | 1886 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1859 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | 1887 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); |
| 1860 | const offset: u12 = @truncate(taddr); | ||
| 1861 | aarch64_util.writeAddImmInst(offset, code); | 1888 | aarch64_util.writeAddImmInst(offset, code); |
| 1862 | }, | 1889 | }, |
| 1863 | 1890 | ||
| 1864 | .TLSDESC_ADR_PAGE21 => { | 1891 | .TLSDESC_ADR_PAGE21 => { |
| 1865 | if (target.flags.has_tlsdesc) { | 1892 | if (target.flags.has_tlsdesc) { |
| 1866 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | 1893 | const S_ = target.tlsDescAddress(elf_file); |
| 1867 | const saddr: u64 = @intCast(P); | 1894 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1868 | const taddr: u64 = @intCast(S_ + A); | 1895 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); |
| 1869 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | ||
| 1870 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | ||
| 1871 | aarch64_util.writeAdrpInst(pages, code); | 1896 | aarch64_util.writeAdrpInst(pages, code); |
| 1872 | } else { | 1897 | } else { |
| 1873 | relocs_log.debug(" relaxing adrp => nop", .{}); | 1898 | relocs_log.debug(" relaxing adrp => nop", .{}); |
| ... | @@ -1877,10 +1902,9 @@ const aarch64 = struct { | ... | @@ -1877,10 +1902,9 @@ const aarch64 = struct { |
| 1877 | 1902 | ||
| 1878 | .TLSDESC_LD64_LO12 => { | 1903 | .TLSDESC_LD64_LO12 => { |
| 1879 | if (target.flags.has_tlsdesc) { | 1904 | if (target.flags.has_tlsdesc) { |
| 1880 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | 1905 | const S_ = target.tlsDescAddress(elf_file); |
| 1881 | const taddr: u64 = @intCast(S_ + A); | 1906 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1882 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | 1907 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); |
| 1883 | const offset: u12 = try math.divExact(u12, @truncate(taddr), 8); | ||
| 1884 | aarch64_util.writeLoadStoreRegInst(offset, code); | 1908 | aarch64_util.writeLoadStoreRegInst(offset, code); |
| 1885 | } else { | 1909 | } else { |
| 1886 | relocs_log.debug(" relaxing ldr => nop", .{}); | 1910 | relocs_log.debug(" relaxing ldr => nop", .{}); |
| ... | @@ -1890,10 +1914,9 @@ const aarch64 = struct { | ... | @@ -1890,10 +1914,9 @@ const aarch64 = struct { |
| 1890 | 1914 | ||
| 1891 | .TLSDESC_ADD_LO12 => { | 1915 | .TLSDESC_ADD_LO12 => { |
| 1892 | if (target.flags.has_tlsdesc) { | 1916 | if (target.flags.has_tlsdesc) { |
| 1893 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | 1917 | const S_ = target.tlsDescAddress(elf_file); |
| 1894 | const taddr: u64 = @intCast(S_ + A); | 1918 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); |
| 1895 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | 1919 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); |
| 1896 | const offset: u12 = @truncate(taddr); | ||
| 1897 | aarch64_util.writeAddImmInst(offset, code); | 1920 | aarch64_util.writeAddImmInst(offset, code); |
| 1898 | } else { | 1921 | } else { |
| 1899 | const old_inst = Instruction{ | 1922 | const old_inst = Instruction{ |
| ... | @@ -1938,7 +1961,6 @@ const aarch64 = struct { | ... | @@ -1938,7 +1961,6 @@ const aarch64 = struct { |
| 1938 | ) !void { | 1961 | ) !void { |
| 1939 | _ = it; | 1962 | _ = it; |
| 1940 | _ = code; | 1963 | _ = code; |
| 1941 | _ = target; | ||
| 1942 | 1964 | ||
| 1943 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); | 1965 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1944 | const cwriter = stream.writer(); | 1966 | const cwriter = stream.writer(); |
| ... | @@ -1948,7 +1970,10 @@ const aarch64 = struct { | ... | @@ -1948,7 +1970,10 @@ const aarch64 = struct { |
| 1948 | switch (r_type) { | 1970 | switch (r_type) { |
| 1949 | .NONE => unreachable, | 1971 | .NONE => unreachable, |
| 1950 | .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | 1972 | .ABS32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), |
| 1951 | .ABS64 => try cwriter.writeInt(i64, S + A, .little), | 1973 | .ABS64 => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 1974 | try cwriter.writeInt(u64, value, .little) | ||
| 1975 | else | ||
| 1976 | try cwriter.writeInt(i64, S + A, .little), | ||
| 1952 | else => try atom.reportUnhandledRelocError(rel, elf_file), | 1977 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1953 | } | 1978 | } |
| 1954 | } | 1979 | } |
| ... | @@ -2073,7 +2098,7 @@ const riscv = struct { | ... | @@ -2073,7 +2098,7 @@ const riscv = struct { |
| 2073 | const atom_addr = atom.address(elf_file); | 2098 | const atom_addr = atom.address(elf_file); |
| 2074 | const pos = it.pos; | 2099 | const pos = it.pos; |
| 2075 | const pair = while (it.prev()) |pair| { | 2100 | const pair = while (it.prev()) |pair| { |
| 2076 | if (S == atom_addr + pair.r_offset) break pair; | 2101 | if (S == atom_addr + @as(i64, @intCast(pair.r_offset))) break pair; |
| 2077 | } else { | 2102 | } else { |
| 2078 | // TODO: implement searching forward | 2103 | // TODO: implement searching forward |
| 2079 | var err = try elf_file.addErrorWithNotes(1); | 2104 | var err = try elf_file.addErrorWithNotes(1); |
| ... | @@ -2091,10 +2116,10 @@ const riscv = struct { | ... | @@ -2091,10 +2116,10 @@ const riscv = struct { |
| 2091 | .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]), | 2116 | .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]), |
| 2092 | else => unreachable, | 2117 | else => unreachable, |
| 2093 | }; | 2118 | }; |
| 2094 | const S_ = @as(i64, @intCast(target_.address(.{}, elf_file))); | 2119 | const S_ = target_.address(.{}, elf_file); |
| 2095 | const A_ = pair.r_addend; | 2120 | const A_ = pair.r_addend; |
| 2096 | const P_ = @as(i64, @intCast(atom_addr + pair.r_offset)); | 2121 | const P_ = atom_addr + @as(i64, @intCast(pair.r_offset)); |
| 2097 | const G_ = @as(i64, @intCast(target_.gotAddress(elf_file))) - GOT; | 2122 | const G_ = target_.gotAddress(elf_file) - GOT; |
| 2098 | const disp = switch (@as(elf.R_RISCV, @enumFromInt(pair.r_type()))) { | 2123 | const disp = switch (@as(elf.R_RISCV, @enumFromInt(pair.r_type()))) { |
| 2099 | .PCREL_HI20 => math.cast(i32, S_ + A_ - P_) orelse return error.Overflow, | 2124 | .PCREL_HI20 => math.cast(i32, S_ + A_ - P_) orelse return error.Overflow, |
| 2100 | .GOT_HI20 => math.cast(i32, G_ + GOT + A_ - P_) orelse return error.Overflow, | 2125 | .GOT_HI20 => math.cast(i32, G_ + GOT + A_ - P_) orelse return error.Overflow, |
| ... | @@ -2122,7 +2147,6 @@ const riscv = struct { | ... | @@ -2122,7 +2147,6 @@ const riscv = struct { |
| 2122 | code: []u8, | 2147 | code: []u8, |
| 2123 | stream: anytype, | 2148 | stream: anytype, |
| 2124 | ) !void { | 2149 | ) !void { |
| 2125 | _ = target; | ||
| 2126 | _ = it; | 2150 | _ = it; |
| 2127 | 2151 | ||
| 2128 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); | 2152 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); |
| ... | @@ -2137,7 +2161,10 @@ const riscv = struct { | ... | @@ -2137,7 +2161,10 @@ const riscv = struct { |
| 2137 | .NONE => unreachable, | 2161 | .NONE => unreachable, |
| 2138 | 2162 | ||
| 2139 | .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), | 2163 | .@"32" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), |
| 2140 | .@"64" => try cwriter.writeInt(i64, S + A, .little), | 2164 | .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| |
| 2165 | try cwriter.writeInt(u64, value, .little) | ||
| 2166 | else | ||
| 2167 | try cwriter.writeInt(i64, S + A, .little), | ||
| 2141 | 2168 | ||
| 2142 | .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A), | 2169 | .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A), |
| 2143 | .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A), | 2170 | .SUB8 => riscv_util.writeAddend(i8, .sub, code[r_offset..][0..1], S + A), |
src/link/Elf/Object.zig+214-11| ... | @@ -15,6 +15,8 @@ comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{}, | ... | @@ -15,6 +15,8 @@ comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup.Index) = .{}, |
| 15 | comdat_group_data: std.ArrayListUnmanaged(u32) = .{}, | 15 | comdat_group_data: std.ArrayListUnmanaged(u32) = .{}, |
| 16 | relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, | 16 | relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 17 | 17 | ||
| 18 | merge_sections: std.ArrayListUnmanaged(InputMergeSection.Index) = .{}, | ||
| 19 | |||
| 18 | fdes: std.ArrayListUnmanaged(Fde) = .{}, | 20 | fdes: std.ArrayListUnmanaged(Fde) = .{}, |
| 19 | cies: std.ArrayListUnmanaged(Cie) = .{}, | 21 | cies: std.ArrayListUnmanaged(Cie) = .{}, |
| 20 | eh_frame_data: std.ArrayListUnmanaged(u8) = .{}, | 22 | eh_frame_data: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -51,6 +53,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { | ... | @@ -51,6 +53,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 51 | self.fdes.deinit(allocator); | 53 | self.fdes.deinit(allocator); |
| 52 | self.cies.deinit(allocator); | 54 | self.cies.deinit(allocator); |
| 53 | self.eh_frame_data.deinit(allocator); | 55 | self.eh_frame_data.deinit(allocator); |
| 56 | self.merge_sections.deinit(allocator); | ||
| 54 | } | 57 | } |
| 55 | 58 | ||
| 56 | pub fn parse(self: *Object, elf_file: *Elf) !void { | 59 | pub fn parse(self: *Object, elf_file: *Elf) !void { |
| ... | @@ -280,8 +283,6 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O | ... | @@ -280,8 +283,6 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O |
| 280 | const name = blk: { | 283 | const name = blk: { |
| 281 | const name = self.getString(shdr.sh_name); | 284 | const name = self.getString(shdr.sh_name); |
| 282 | if (elf_file.base.isRelocatable()) break :blk name; | 285 | if (elf_file.base.isRelocatable()) break :blk name; |
| 283 | if (shdr.sh_flags & elf.SHF_MERGE != 0 and shdr.sh_flags & elf.SHF_STRINGS == 0) | ||
| 284 | break :blk name; // TODO: consider dropping SHF_STRINGS once ICF is implemented | ||
| 285 | const sh_name_prefixes: []const [:0]const u8 = &.{ | 286 | const sh_name_prefixes: []const [:0]const u8 = &.{ |
| 286 | ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", | 287 | ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", |
| 287 | ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", | 288 | ".init_array", ".fini_array", ".tbss", ".tdata", ".gcc_except_table", ".ctors", |
| ... | @@ -335,7 +336,6 @@ fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { | ... | @@ -335,7 +336,6 @@ fn skipShdr(self: *Object, index: u32, elf_file: *Elf) bool { |
| 335 | const name = self.getString(shdr.sh_name); | 336 | const name = self.getString(shdr.sh_name); |
| 336 | const ignore = blk: { | 337 | const ignore = blk: { |
| 337 | if (mem.startsWith(u8, name, ".note")) break :blk true; | 338 | if (mem.startsWith(u8, name, ".note")) break :blk true; |
| 338 | if (mem.startsWith(u8, name, ".comment")) break :blk true; | ||
| 339 | if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; | 339 | if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; |
| 340 | if (mem.startsWith(u8, name, ".riscv.attributes")) break :blk true; // TODO: riscv attributes | 340 | if (mem.startsWith(u8, name, ".riscv.attributes")) break :blk true; // TODO: riscv attributes |
| 341 | if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and | 341 | if (comp.config.debug_format == .strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and |
| ... | @@ -354,7 +354,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void { | ... | @@ -354,7 +354,7 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void { |
| 354 | const index = try elf_file.addSymbol(); | 354 | const index = try elf_file.addSymbol(); |
| 355 | self.symbols.appendAssumeCapacity(index); | 355 | self.symbols.appendAssumeCapacity(index); |
| 356 | const sym_ptr = elf_file.symbol(index); | 356 | const sym_ptr = elf_file.symbol(index); |
| 357 | sym_ptr.value = sym.st_value; | 357 | sym_ptr.value = @intCast(sym.st_value); |
| 358 | sym_ptr.name_offset = sym.st_name; | 358 | sym_ptr.name_offset = sym.st_name; |
| 359 | sym_ptr.esym_index = @as(u32, @intCast(i)); | 359 | sym_ptr.esym_index = @as(u32, @intCast(i)); |
| 360 | sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx]; | 360 | sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx]; |
| ... | @@ -547,7 +547,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { | ... | @@ -547,7 +547,7 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { |
| 547 | elf.SHN_ABS, elf.SHN_COMMON => 0, | 547 | elf.SHN_ABS, elf.SHN_COMMON => 0, |
| 548 | else => self.atoms.items[esym.st_shndx], | 548 | else => self.atoms.items[esym.st_shndx], |
| 549 | }; | 549 | }; |
| 550 | global.value = esym.st_value; | 550 | global.value = @intCast(esym.st_value); |
| 551 | global.atom_index = atom_index; | 551 | global.atom_index = atom_index; |
| 552 | global.esym_index = esym_index; | 552 | global.esym_index = esym_index; |
| 553 | global.file_index = self.index; | 553 | global.file_index = self.index; |
| ... | @@ -659,6 +659,173 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO | ... | @@ -659,6 +659,173 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO |
| 659 | } | 659 | } |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | pub fn initMergeSections(self: *Object, elf_file: *Elf) !void { | ||
| 663 | const gpa = elf_file.base.comp.gpa; | ||
| 664 | |||
| 665 | try self.merge_sections.resize(gpa, self.shdrs.items.len); | ||
| 666 | @memset(self.merge_sections.items, 0); | ||
| 667 | |||
| 668 | for (self.shdrs.items, 0..) |shdr, shndx| { | ||
| 669 | if (shdr.sh_flags & elf.SHF_MERGE == 0) continue; | ||
| 670 | |||
| 671 | const atom_index = self.atoms.items[shndx]; | ||
| 672 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | ||
| 673 | if (!atom_ptr.flags.alive) continue; | ||
| 674 | if (atom_ptr.relocs(elf_file).len > 0) continue; | ||
| 675 | |||
| 676 | const imsec_idx = try elf_file.addInputMergeSection(); | ||
| 677 | const imsec = elf_file.inputMergeSection(imsec_idx).?; | ||
| 678 | self.merge_sections.items[shndx] = imsec_idx; | ||
| 679 | |||
| 680 | imsec.merge_section_index = try elf_file.getOrCreateMergeSection(atom_ptr.name(elf_file), shdr.sh_flags, shdr.sh_type); | ||
| 681 | imsec.atom_index = atom_index; | ||
| 682 | |||
| 683 | const data = try self.codeDecompressAlloc(elf_file, atom_index); | ||
| 684 | defer gpa.free(data); | ||
| 685 | const sh_entsize: u32 = @intCast(shdr.sh_entsize); | ||
| 686 | |||
| 687 | if (shdr.sh_flags & elf.SHF_STRINGS != 0) { | ||
| 688 | var pos: u32 = 0; | ||
| 689 | while (pos < data.len) switch (sh_entsize) { | ||
| 690 | 0, 1 => { | ||
| 691 | // According to mold's source code, GHC emits MS sections with sh_entsize = 0. | ||
| 692 | // This actually can also happen for output created with `-r` mode. | ||
| 693 | const string = mem.sliceTo(@as([*:0]const u8, @ptrCast(data.ptr + pos)), 0); | ||
| 694 | if (pos + string.len == data.len) { | ||
| 695 | var err = try elf_file.addErrorWithNotes(1); | ||
| 696 | try err.addMsg(elf_file, "string not null terminated", .{}); | ||
| 697 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 698 | return error.MalformedObject; | ||
| 699 | } | ||
| 700 | try imsec.insertZ(gpa, string); | ||
| 701 | try imsec.offsets.append(gpa, pos); | ||
| 702 | pos += @as(u32, @intCast(string.len)) + 1; // account for null | ||
| 703 | }, | ||
| 704 | else => |entsize| { | ||
| 705 | const string = data.ptr[pos..][0..entsize]; | ||
| 706 | if (string[string.len - 1] != 0) { | ||
| 707 | var err = try elf_file.addErrorWithNotes(1); | ||
| 708 | try err.addMsg(elf_file, "string not null terminated", .{}); | ||
| 709 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 710 | return error.MalformedObject; | ||
| 711 | } | ||
| 712 | try imsec.insert(gpa, string); | ||
| 713 | try imsec.offsets.append(gpa, pos); | ||
| 714 | pos += @as(u32, @intCast(string.len)); | ||
| 715 | }, | ||
| 716 | }; | ||
| 717 | } else { | ||
| 718 | if (sh_entsize == 0) continue; // Malformed, don't split but don't error out | ||
| 719 | if (shdr.sh_size % sh_entsize != 0) { | ||
| 720 | var err = try elf_file.addErrorWithNotes(1); | ||
| 721 | try err.addMsg(elf_file, "size not a multiple of sh_entsize", .{}); | ||
| 722 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 723 | return error.MalformedObject; | ||
| 724 | } | ||
| 725 | |||
| 726 | var pos: u32 = 0; | ||
| 727 | while (pos < data.len) : (pos += sh_entsize) { | ||
| 728 | const string = data.ptr[pos..][0..sh_entsize]; | ||
| 729 | try imsec.insert(gpa, string); | ||
| 730 | try imsec.offsets.append(gpa, pos); | ||
| 731 | } | ||
| 732 | } | ||
| 733 | |||
| 734 | atom_ptr.flags.alive = false; | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { | ||
| 739 | const gpa = elf_file.base.comp.gpa; | ||
| 740 | |||
| 741 | for (self.merge_sections.items) |index| { | ||
| 742 | const imsec = elf_file.inputMergeSection(index) orelse continue; | ||
| 743 | const msec = elf_file.mergeSection(imsec.merge_section_index); | ||
| 744 | const atom_ptr = elf_file.atom(imsec.atom_index).?; | ||
| 745 | const isec = atom_ptr.inputShdr(elf_file); | ||
| 746 | |||
| 747 | try imsec.subsections.resize(gpa, imsec.strings.items.len); | ||
| 748 | |||
| 749 | for (imsec.strings.items, imsec.subsections.items) |str, *imsec_msub| { | ||
| 750 | const string = imsec.bytes.items[str.pos..][0..str.len]; | ||
| 751 | const res = try msec.insert(gpa, string); | ||
| 752 | if (!res.found_existing) { | ||
| 753 | const msub_index = try elf_file.addMergeSubsection(); | ||
| 754 | const msub = elf_file.mergeSubsection(msub_index); | ||
| 755 | msub.merge_section_index = imsec.merge_section_index; | ||
| 756 | msub.string_index = res.key.pos; | ||
| 757 | msub.alignment = atom_ptr.alignment; | ||
| 758 | msub.size = res.key.len; | ||
| 759 | msub.alive = !elf_file.base.gc_sections or isec.sh_flags & elf.SHF_ALLOC == 0; | ||
| 760 | res.sub.* = msub_index; | ||
| 761 | } | ||
| 762 | imsec_msub.* = res.sub.*; | ||
| 763 | } | ||
| 764 | |||
| 765 | imsec.clearAndFree(gpa); | ||
| 766 | } | ||
| 767 | |||
| 768 | for (self.symtab.items, 0..) |*esym, idx| { | ||
| 769 | const sym_index = self.symbols.items[idx]; | ||
| 770 | const sym = elf_file.symbol(sym_index); | ||
| 771 | |||
| 772 | if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue; | ||
| 773 | |||
| 774 | const imsec_index = self.merge_sections.items[esym.st_shndx]; | ||
| 775 | const imsec = elf_file.inputMergeSection(imsec_index) orelse continue; | ||
| 776 | const msub_index, const offset = imsec.findSubsection(@intCast(esym.st_value)) orelse { | ||
| 777 | var err = try elf_file.addErrorWithNotes(2); | ||
| 778 | try err.addMsg(elf_file, "invalid symbol value: {x}", .{esym.st_value}); | ||
| 779 | try err.addNote(elf_file, "for symbol {s}", .{sym.name(elf_file)}); | ||
| 780 | try err.addNote(elf_file, "in {}", .{self.fmtPath()}); | ||
| 781 | return error.MalformedObject; | ||
| 782 | }; | ||
| 783 | |||
| 784 | try sym.addExtra(.{ .subsection = msub_index }, elf_file); | ||
| 785 | sym.flags.merge_subsection = true; | ||
| 786 | sym.value = offset; | ||
| 787 | } | ||
| 788 | |||
| 789 | for (self.atoms.items) |atom_index| { | ||
| 790 | const atom_ptr = elf_file.atom(atom_index) orelse continue; | ||
| 791 | if (!atom_ptr.flags.alive) continue; | ||
| 792 | const extras = atom_ptr.extra(elf_file) orelse continue; | ||
| 793 | const relocs = self.relocs.items[extras.rel_index..][0..extras.rel_count]; | ||
| 794 | for (relocs) |*rel| { | ||
| 795 | const esym = self.symtab.items[rel.r_sym()]; | ||
| 796 | if (esym.st_type() != elf.STT_SECTION) continue; | ||
| 797 | |||
| 798 | const imsec_index = self.merge_sections.items[esym.st_shndx]; | ||
| 799 | const imsec = elf_file.inputMergeSection(imsec_index) orelse continue; | ||
| 800 | const msub_index, const offset = imsec.findSubsection(@intCast(@as(i64, @intCast(esym.st_value)) + rel.r_addend)) orelse { | ||
| 801 | var err = try elf_file.addErrorWithNotes(1); | ||
| 802 | try err.addMsg(elf_file, "invalid relocation at offset 0x{x}", .{rel.r_offset}); | ||
| 803 | try err.addNote(elf_file, "in {}:{s}", .{ self.fmtPath(), atom_ptr.name(elf_file) }); | ||
| 804 | return error.MalformedObject; | ||
| 805 | }; | ||
| 806 | const msub = elf_file.mergeSubsection(msub_index); | ||
| 807 | const msec = msub.mergeSection(elf_file); | ||
| 808 | |||
| 809 | const out_sym_idx: u64 = @intCast(self.symbols.items.len); | ||
| 810 | try self.symbols.ensureUnusedCapacity(gpa, 1); | ||
| 811 | const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), msub_index }); | ||
| 812 | defer gpa.free(name); | ||
| 813 | const sym_index = try elf_file.addSymbol(); | ||
| 814 | const sym = elf_file.symbol(sym_index); | ||
| 815 | sym.* = .{ | ||
| 816 | .value = @bitCast(@as(i64, @intCast(offset)) - rel.r_addend), | ||
| 817 | .name_offset = try self.addString(gpa, name), | ||
| 818 | .esym_index = rel.r_sym(), | ||
| 819 | .file_index = self.index, | ||
| 820 | }; | ||
| 821 | try sym.addExtra(.{ .subsection = msub_index }, elf_file); | ||
| 822 | sym.flags.merge_subsection = true; | ||
| 823 | self.symbols.addOneAssumeCapacity().* = sym_index; | ||
| 824 | rel.r_info = (out_sym_idx << 32) | rel.r_type(); | ||
| 825 | } | ||
| 826 | } | ||
| 827 | } | ||
| 828 | |||
| 662 | /// We will create dummy shdrs per each resolved common symbols to make it | 829 | /// We will create dummy shdrs per each resolved common symbols to make it |
| 663 | /// play nicely with the rest of the system. | 830 | /// play nicely with the rest of the system. |
| 664 | pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { | 831 | pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| ... | @@ -749,6 +916,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -749,6 +916,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 749 | 916 | ||
| 750 | for (self.locals()) |local_index| { | 917 | for (self.locals()) |local_index| { |
| 751 | const local = elf_file.symbol(local_index); | 918 | const local = elf_file.symbol(local_index); |
| 919 | if (local.mergeSubsection(elf_file)) |msub| { | ||
| 920 | if (!msub.alive) continue; | ||
| 921 | local.output_section_index = msub.mergeSection(elf_file).output_section_index; | ||
| 922 | continue; | ||
| 923 | } | ||
| 752 | const atom = local.atom(elf_file) orelse continue; | 924 | const atom = local.atom(elf_file) orelse continue; |
| 753 | if (!atom.flags.alive) continue; | 925 | if (!atom.flags.alive) continue; |
| 754 | local.output_section_index = atom.output_section_index; | 926 | local.output_section_index = atom.output_section_index; |
| ... | @@ -756,11 +928,23 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -756,11 +928,23 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 756 | 928 | ||
| 757 | for (self.globals()) |global_index| { | 929 | for (self.globals()) |global_index| { |
| 758 | const global = elf_file.symbol(global_index); | 930 | const global = elf_file.symbol(global_index); |
| 931 | if (global.file(elf_file).?.index() != self.index) continue; | ||
| 932 | if (global.mergeSubsection(elf_file)) |msub| { | ||
| 933 | if (!msub.alive) continue; | ||
| 934 | global.output_section_index = msub.mergeSection(elf_file).output_section_index; | ||
| 935 | continue; | ||
| 936 | } | ||
| 759 | const atom = global.atom(elf_file) orelse continue; | 937 | const atom = global.atom(elf_file) orelse continue; |
| 760 | if (!atom.flags.alive) continue; | 938 | if (!atom.flags.alive) continue; |
| 761 | if (global.file(elf_file).?.index() != self.index) continue; | ||
| 762 | global.output_section_index = atom.output_section_index; | 939 | global.output_section_index = atom.output_section_index; |
| 763 | } | 940 | } |
| 941 | |||
| 942 | for (self.symbols.items[self.symtab.items.len..]) |local_index| { | ||
| 943 | const local = elf_file.symbol(local_index); | ||
| 944 | const msub = local.mergeSubsection(elf_file).?; | ||
| 945 | if (!msub.alive) continue; | ||
| 946 | local.output_section_index = msub.mergeSection(elf_file).output_section_index; | ||
| 947 | } | ||
| 764 | } | 948 | } |
| 765 | 949 | ||
| 766 | pub fn initRelaSections(self: Object, elf_file: *Elf) !void { | 950 | pub fn initRelaSections(self: Object, elf_file: *Elf) !void { |
| ... | @@ -845,9 +1029,17 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { | ... | @@ -845,9 +1029,17 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { |
| 845 | } | 1029 | } |
| 846 | 1030 | ||
| 847 | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { | 1031 | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1032 | const isAlive = struct { | ||
| 1033 | fn isAlive(sym: *const Symbol, ctx: *Elf) bool { | ||
| 1034 | if (sym.mergeSubsection(ctx)) |msub| return msub.alive; | ||
| 1035 | if (sym.atom(ctx)) |atom_ptr| return atom_ptr.flags.alive; | ||
| 1036 | return true; | ||
| 1037 | } | ||
| 1038 | }.isAlive; | ||
| 1039 | |||
| 848 | for (self.locals()) |local_index| { | 1040 | for (self.locals()) |local_index| { |
| 849 | const local = elf_file.symbol(local_index); | 1041 | const local = elf_file.symbol(local_index); |
| 850 | if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue; | 1042 | if (!isAlive(local, elf_file)) continue; |
| 851 | const esym = local.elfSym(elf_file); | 1043 | const esym = local.elfSym(elf_file); |
| 852 | switch (esym.st_type()) { | 1044 | switch (esym.st_type()) { |
| 853 | elf.STT_SECTION => continue, | 1045 | elf.STT_SECTION => continue, |
| ... | @@ -864,7 +1056,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { | ... | @@ -864,7 +1056,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 864 | const global = elf_file.symbol(global_index); | 1056 | const global = elf_file.symbol(global_index); |
| 865 | const file_ptr = global.file(elf_file) orelse continue; | 1057 | const file_ptr = global.file(elf_file) orelse continue; |
| 866 | if (file_ptr.index() != self.index) continue; | 1058 | if (file_ptr.index() != self.index) continue; |
| 867 | if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue; | 1059 | if (!isAlive(global, elf_file)) continue; |
| 868 | global.flags.output_symtab = true; | 1060 | global.flags.output_symtab = true; |
| 869 | if (global.isLocal(elf_file)) { | 1061 | if (global.isLocal(elf_file)) { |
| 870 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); | 1062 | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| ... | @@ -904,14 +1096,16 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { | ... | @@ -904,14 +1096,16 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 904 | 1096 | ||
| 905 | pub fn locals(self: Object) []const Symbol.Index { | 1097 | pub fn locals(self: Object) []const Symbol.Index { |
| 906 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; | 1098 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; |
| 907 | const end = self.first_global orelse self.symbols.items.len; | 1099 | assert(self.symbols.items.len >= self.symtab.items.len); |
| 1100 | const end = self.first_global orelse self.symtab.items.len; | ||
| 908 | return self.symbols.items[0..end]; | 1101 | return self.symbols.items[0..end]; |
| 909 | } | 1102 | } |
| 910 | 1103 | ||
| 911 | pub fn globals(self: Object) []const Symbol.Index { | 1104 | pub fn globals(self: Object) []const Symbol.Index { |
| 912 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; | 1105 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; |
| 913 | const start = self.first_global orelse self.symbols.items.len; | 1106 | assert(self.symbols.items.len >= self.symtab.items.len); |
| 914 | return self.symbols.items[start..]; | 1107 | const start = self.first_global orelse self.symtab.items.len; |
| 1108 | return self.symbols.items[start..self.symtab.items.len]; | ||
| 915 | } | 1109 | } |
| 916 | 1110 | ||
| 917 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). | 1111 | /// Returns atom's code and optionally uncompresses data if required (for compressed sections). |
| ... | @@ -956,6 +1150,14 @@ pub fn getString(self: Object, off: u32) [:0]const u8 { | ... | @@ -956,6 +1150,14 @@ pub fn getString(self: Object, off: u32) [:0]const u8 { |
| 956 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); | 1150 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0); |
| 957 | } | 1151 | } |
| 958 | 1152 | ||
| 1153 | fn addString(self: *Object, allocator: Allocator, str: []const u8) !u32 { | ||
| 1154 | const off: u32 = @intCast(self.strtab.items.len); | ||
| 1155 | try self.strtab.ensureUnusedCapacity(allocator, str.len + 1); | ||
| 1156 | self.strtab.appendSliceAssumeCapacity(str); | ||
| 1157 | self.strtab.appendAssumeCapacity(0); | ||
| 1158 | return off; | ||
| 1159 | } | ||
| 1160 | |||
| 959 | /// Caller owns the memory. | 1161 | /// Caller owns the memory. |
| 960 | fn preadShdrContentsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, index: u32) ![]u8 { | 1162 | fn preadShdrContentsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, index: u32) ![]u8 { |
| 961 | assert(index < self.shdrs.items.len); | 1163 | assert(index < self.shdrs.items.len); |
| ... | @@ -1161,5 +1363,6 @@ const Cie = eh_frame.Cie; | ... | @@ -1161,5 +1363,6 @@ const Cie = eh_frame.Cie; |
| 1161 | const Elf = @import("../Elf.zig"); | 1363 | const Elf = @import("../Elf.zig"); |
| 1162 | const Fde = eh_frame.Fde; | 1364 | const Fde = eh_frame.Fde; |
| 1163 | const File = @import("file.zig").File; | 1365 | const File = @import("file.zig").File; |
| 1366 | const InputMergeSection = @import("merge_section.zig").InputMergeSection; | ||
| 1164 | const Symbol = @import("Symbol.zig"); | 1367 | const Symbol = @import("Symbol.zig"); |
| 1165 | const Alignment = Atom.Alignment; | 1368 | const Alignment = Atom.Alignment; |
src/link/Elf/SharedObject.zig+1-1| ... | @@ -231,7 +231,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void { | ... | @@ -231,7 +231,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void { |
| 231 | 231 | ||
| 232 | const global = elf_file.symbol(index); | 232 | const global = elf_file.symbol(index); |
| 233 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { | 233 | if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) { |
| 234 | global.value = this_sym.st_value; | 234 | global.value = @intCast(this_sym.st_value); |
| 235 | global.atom_index = 0; | 235 | global.atom_index = 0; |
| 236 | global.esym_index = esym_index; | 236 | global.esym_index = esym_index; |
| 237 | global.version_index = self.versyms.items[esym_index]; | 237 | global.version_index = self.versyms.items[esym_index]; |
src/link/Elf/Symbol.zig+43-21| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | //! Represents a defined symbol. | 1 | //! Represents a defined symbol. |
| 2 | 2 | ||
| 3 | /// Allocated address value of this symbol. | 3 | /// Allocated address value of this symbol. |
| 4 | value: u64 = 0, | 4 | value: i64 = 0, |
| 5 | 5 | ||
| 6 | /// Offset into the linker's string table. | 6 | /// Offset into the linker's string table. |
| 7 | name_offset: u32 = 0, | 7 | name_offset: u32 = 0, |
| ... | @@ -14,7 +14,7 @@ file_index: File.Index = 0, | ... | @@ -14,7 +14,7 @@ file_index: File.Index = 0, |
| 14 | /// Use `atom` to get the pointer to the atom. | 14 | /// Use `atom` to get the pointer to the atom. |
| 15 | atom_index: Atom.Index = 0, | 15 | atom_index: Atom.Index = 0, |
| 16 | 16 | ||
| 17 | /// Assigned output section index for this atom. | 17 | /// Assigned output section index for this symbol. |
| 18 | output_section_index: u32 = 0, | 18 | output_section_index: u32 = 0, |
| 19 | 19 | ||
| 20 | /// Index of the source symbol this symbol references. | 20 | /// Index of the source symbol this symbol references. |
| ... | @@ -33,7 +33,8 @@ extra_index: u32 = 0, | ... | @@ -33,7 +33,8 @@ extra_index: u32 = 0, |
| 33 | pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool { | 33 | pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool { |
| 34 | const file_ptr = symbol.file(elf_file).?; | 34 | const file_ptr = symbol.file(elf_file).?; |
| 35 | if (file_ptr == .shared_object) return symbol.elfSym(elf_file).st_shndx == elf.SHN_ABS; | 35 | if (file_ptr == .shared_object) return symbol.elfSym(elf_file).st_shndx == elf.SHN_ABS; |
| 36 | return !symbol.flags.import and symbol.atom(elf_file) == null and symbol.outputShndx() == null and | 36 | return !symbol.flags.import and symbol.atom(elf_file) == null and |
| 37 | symbol.mergeSubsection(elf_file) == null and symbol.outputShndx() == null and | ||
| 37 | file_ptr != .linker_defined; | 38 | file_ptr != .linker_defined; |
| 38 | } | 39 | } |
| 39 | 40 | ||
| ... | @@ -70,6 +71,12 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { | ... | @@ -70,6 +71,12 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { |
| 70 | return elf_file.atom(symbol.atom_index); | 71 | return elf_file.atom(symbol.atom_index); |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection { | ||
| 75 | if (!symbol.flags.merge_subsection) return null; | ||
| 76 | const extras = symbol.extra(elf_file).?; | ||
| 77 | return elf_file.mergeSubsection(extras.subsection); | ||
| 78 | } | ||
| 79 | |||
| 73 | pub fn file(symbol: Symbol, elf_file: *Elf) ?File { | 80 | pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| 74 | return elf_file.file(symbol.file_index); | 81 | return elf_file.file(symbol.file_index); |
| 75 | } | 82 | } |
| ... | @@ -92,7 +99,11 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { | ... | @@ -92,7 +99,11 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { |
| 92 | return file_ptr.symbolRank(sym, in_archive); | 99 | return file_ptr.symbolRank(sym, in_archive); |
| 93 | } | 100 | } |
| 94 | 101 | ||
| 95 | pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf) u64 { | 102 | pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf) i64 { |
| 103 | if (symbol.mergeSubsection(elf_file)) |msub| { | ||
| 104 | if (!msub.alive) return 0; | ||
| 105 | return msub.address(elf_file) + symbol.value; | ||
| 106 | } | ||
| 96 | if (symbol.flags.has_copy_rel) { | 107 | if (symbol.flags.has_copy_rel) { |
| 97 | return symbol.copyRelAddress(elf_file); | 108 | return symbol.copyRelAddress(elf_file); |
| 98 | } | 109 | } |
| ... | @@ -108,19 +119,23 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf | ... | @@ -108,19 +119,23 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf |
| 108 | if (!atom_ptr.flags.alive) { | 119 | if (!atom_ptr.flags.alive) { |
| 109 | if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) { | 120 | if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) { |
| 110 | const sym_name = symbol.name(elf_file); | 121 | const sym_name = symbol.name(elf_file); |
| 122 | const sh_addr, const sh_size = blk: { | ||
| 123 | const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 }; | ||
| 124 | const shdr = elf_file.shdrs.items[shndx]; | ||
| 125 | break :blk .{ shdr.sh_addr, shdr.sh_size }; | ||
| 126 | }; | ||
| 111 | if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or | 127 | if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or |
| 112 | mem.startsWith(u8, sym_name, "__EH_FRAME_LIST__") or | 128 | mem.startsWith(u8, sym_name, "__EH_FRAME_LIST__") or |
| 113 | mem.startsWith(u8, sym_name, ".eh_frame_seg") or | 129 | mem.startsWith(u8, sym_name, ".eh_frame_seg") or |
| 114 | symbol.elfSym(elf_file).st_type() == elf.STT_SECTION) | 130 | symbol.elfSym(elf_file).st_type() == elf.STT_SECTION) |
| 115 | { | 131 | { |
| 116 | return elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr; | 132 | return @intCast(sh_addr); |
| 117 | } | 133 | } |
| 118 | 134 | ||
| 119 | if (mem.startsWith(u8, sym_name, "__FRAME_END__") or | 135 | if (mem.startsWith(u8, sym_name, "__FRAME_END__") or |
| 120 | mem.startsWith(u8, sym_name, "__EH_FRAME_LIST_END__")) | 136 | mem.startsWith(u8, sym_name, "__EH_FRAME_LIST_END__")) |
| 121 | { | 137 | { |
| 122 | const shdr = elf_file.shdrs.items[elf_file.eh_frame_section_index.?]; | 138 | return @intCast(sh_addr + sh_size); |
| 123 | return shdr.sh_addr + shdr.sh_size; | ||
| 124 | } | 139 | } |
| 125 | 140 | ||
| 126 | // TODO I think we potentially should error here | 141 | // TODO I think we potentially should error here |
| ... | @@ -143,57 +158,57 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 { | ... | @@ -143,57 +158,57 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 { |
| 143 | return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal; | 158 | return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal; |
| 144 | } | 159 | } |
| 145 | 160 | ||
| 146 | pub fn gotAddress(symbol: Symbol, elf_file: *Elf) u64 { | 161 | pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 147 | if (!symbol.flags.has_got) return 0; | 162 | if (!symbol.flags.has_got) return 0; |
| 148 | const extras = symbol.extra(elf_file).?; | 163 | const extras = symbol.extra(elf_file).?; |
| 149 | const entry = elf_file.got.entries.items[extras.got]; | 164 | const entry = elf_file.got.entries.items[extras.got]; |
| 150 | return entry.address(elf_file); | 165 | return entry.address(elf_file); |
| 151 | } | 166 | } |
| 152 | 167 | ||
| 153 | pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) u64 { | 168 | pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 154 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; | 169 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; |
| 155 | const extras = symbol.extra(elf_file).?; | 170 | const extras = symbol.extra(elf_file).?; |
| 156 | const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?]; | 171 | const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?]; |
| 157 | const cpu_arch = elf_file.getTarget().cpu.arch; | 172 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 158 | return shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch); | 173 | return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); |
| 159 | } | 174 | } |
| 160 | 175 | ||
| 161 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 { | 176 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 162 | if (!symbol.flags.has_plt) return 0; | 177 | if (!symbol.flags.has_plt) return 0; |
| 163 | const extras = symbol.extra(elf_file).?; | 178 | const extras = symbol.extra(elf_file).?; |
| 164 | const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?]; | 179 | const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?]; |
| 165 | const cpu_arch = elf_file.getTarget().cpu.arch; | 180 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 166 | return shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch); | 181 | return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); |
| 167 | } | 182 | } |
| 168 | 183 | ||
| 169 | pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) u64 { | 184 | pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 170 | if (!symbol.flags.has_plt) return 0; | 185 | if (!symbol.flags.has_plt) return 0; |
| 171 | const extras = symbol.extra(elf_file).?; | 186 | const extras = symbol.extra(elf_file).?; |
| 172 | const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?]; | 187 | const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?]; |
| 173 | return shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size; | 188 | return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); |
| 174 | } | 189 | } |
| 175 | 190 | ||
| 176 | pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) u64 { | 191 | pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 177 | if (!symbol.flags.has_copy_rel) return 0; | 192 | if (!symbol.flags.has_copy_rel) return 0; |
| 178 | const shdr = elf_file.shdrs.items[elf_file.copy_rel_section_index.?]; | 193 | const shdr = elf_file.shdrs.items[elf_file.copy_rel_section_index.?]; |
| 179 | return shdr.sh_addr + symbol.value; | 194 | return @as(i64, @intCast(shdr.sh_addr)) + symbol.value; |
| 180 | } | 195 | } |
| 181 | 196 | ||
| 182 | pub fn tlsGdAddress(symbol: Symbol, elf_file: *Elf) u64 { | 197 | pub fn tlsGdAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 183 | if (!symbol.flags.has_tlsgd) return 0; | 198 | if (!symbol.flags.has_tlsgd) return 0; |
| 184 | const extras = symbol.extra(elf_file).?; | 199 | const extras = symbol.extra(elf_file).?; |
| 185 | const entry = elf_file.got.entries.items[extras.tlsgd]; | 200 | const entry = elf_file.got.entries.items[extras.tlsgd]; |
| 186 | return entry.address(elf_file); | 201 | return entry.address(elf_file); |
| 187 | } | 202 | } |
| 188 | 203 | ||
| 189 | pub fn gotTpAddress(symbol: Symbol, elf_file: *Elf) u64 { | 204 | pub fn gotTpAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 190 | if (!symbol.flags.has_gottp) return 0; | 205 | if (!symbol.flags.has_gottp) return 0; |
| 191 | const extras = symbol.extra(elf_file).?; | 206 | const extras = symbol.extra(elf_file).?; |
| 192 | const entry = elf_file.got.entries.items[extras.gottp]; | 207 | const entry = elf_file.got.entries.items[extras.gottp]; |
| 193 | return entry.address(elf_file); | 208 | return entry.address(elf_file); |
| 194 | } | 209 | } |
| 195 | 210 | ||
| 196 | pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) u64 { | 211 | pub fn tlsDescAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 197 | if (!symbol.flags.has_tlsdesc) return 0; | 212 | if (!symbol.flags.has_tlsdesc) return 0; |
| 198 | const extras = symbol.extra(elf_file).?; | 213 | const extras = symbol.extra(elf_file).?; |
| 199 | const entry = elf_file.got.entries.items[extras.tlsdesc]; | 214 | const entry = elf_file.got.entries.items[extras.tlsdesc]; |
| ... | @@ -213,7 +228,7 @@ pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *E | ... | @@ -213,7 +228,7 @@ pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *E |
| 213 | return .{ .found_existing = false, .index = index }; | 228 | return .{ .found_existing = false, .index = index }; |
| 214 | } | 229 | } |
| 215 | 230 | ||
| 216 | pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) u64 { | 231 | pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 217 | if (!symbol.flags.has_zig_got) return 0; | 232 | if (!symbol.flags.has_zig_got) return 0; |
| 218 | const extras = symbol.extra(elf_file).?; | 233 | const extras = symbol.extra(elf_file).?; |
| 219 | return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); | 234 | return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); |
| ... | @@ -243,6 +258,7 @@ const AddExtraOpts = struct { | ... | @@ -243,6 +258,7 @@ const AddExtraOpts = struct { |
| 243 | gottp: ?u32 = null, | 258 | gottp: ?u32 = null, |
| 244 | tlsdesc: ?u32 = null, | 259 | tlsdesc: ?u32 = null, |
| 245 | zig_got: ?u32 = null, | 260 | zig_got: ?u32 = null, |
| 261 | subsection: ?u32 = null, | ||
| 246 | }; | 262 | }; |
| 247 | 263 | ||
| 248 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { | 264 | pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) !void { |
| ... | @@ -280,6 +296,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { | ... | @@ -280,6 +296,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
| 280 | if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?); | 296 | if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?); |
| 281 | if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; | 297 | if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; |
| 282 | if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; | 298 | if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; |
| 299 | if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index); | ||
| 283 | if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; | 300 | if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; |
| 284 | break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF); | 301 | break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF); |
| 285 | }; | 302 | }; |
| ... | @@ -298,7 +315,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { | ... | @@ -298,7 +315,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
| 298 | out.st_info = (st_bind << 4) | st_type; | 315 | out.st_info = (st_bind << 4) | st_type; |
| 299 | out.st_other = esym.st_other; | 316 | out.st_other = esym.st_other; |
| 300 | out.st_shndx = st_shndx; | 317 | out.st_shndx = st_shndx; |
| 301 | out.st_value = st_value; | 318 | out.st_value = @intCast(st_value); |
| 302 | out.st_size = esym.st_size; | 319 | out.st_size = esym.st_size; |
| 303 | } | 320 | } |
| 304 | 321 | ||
| ... | @@ -450,6 +467,9 @@ pub const Flags = packed struct { | ... | @@ -450,6 +467,9 @@ pub const Flags = packed struct { |
| 450 | /// TODO this is really not needed if only we operated on esyms between | 467 | /// TODO this is really not needed if only we operated on esyms between |
| 451 | /// codegen and ZigObject. | 468 | /// codegen and ZigObject. |
| 452 | is_tls: bool = false, | 469 | is_tls: bool = false, |
| 470 | |||
| 471 | /// Whether the symbol is a merge subsection. | ||
| 472 | merge_subsection: bool = false, | ||
| 453 | }; | 473 | }; |
| 454 | 474 | ||
| 455 | pub const Extra = struct { | 475 | pub const Extra = struct { |
| ... | @@ -463,6 +483,7 @@ pub const Extra = struct { | ... | @@ -463,6 +483,7 @@ pub const Extra = struct { |
| 463 | gottp: u32 = 0, | 483 | gottp: u32 = 0, |
| 464 | tlsdesc: u32 = 0, | 484 | tlsdesc: u32 = 0, |
| 465 | zig_got: u32 = 0, | 485 | zig_got: u32 = 0, |
| 486 | subsection: u32 = 0, | ||
| 466 | }; | 487 | }; |
| 467 | 488 | ||
| 468 | pub const Index = u32; | 489 | pub const Index = u32; |
| ... | @@ -479,6 +500,7 @@ const File = @import("file.zig").File; | ... | @@ -479,6 +500,7 @@ const File = @import("file.zig").File; |
| 479 | const GotSection = synthetic_sections.GotSection; | 500 | const GotSection = synthetic_sections.GotSection; |
| 480 | const GotPltSection = synthetic_sections.GotPltSection; | 501 | const GotPltSection = synthetic_sections.GotPltSection; |
| 481 | const LinkerDefined = @import("LinkerDefined.zig"); | 502 | const LinkerDefined = @import("LinkerDefined.zig"); |
| 503 | const MergeSubsection = @import("merge_section.zig").MergeSubsection; | ||
| 482 | const Object = @import("Object.zig"); | 504 | const Object = @import("Object.zig"); |
| 483 | const PltSection = synthetic_sections.PltSection; | 505 | const PltSection = synthetic_sections.PltSection; |
| 484 | const PltGotSection = synthetic_sections.PltGotSection; | 506 | const PltGotSection = synthetic_sections.PltGotSection; |
src/link/Elf/ZigObject.zig+11-11| ... | @@ -343,7 +343,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { | ... | @@ -343,7 +343,7 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void { |
| 343 | atom.outputShndx().? | 343 | atom.outputShndx().? |
| 344 | else | 344 | else |
| 345 | elf.SHN_UNDEF; | 345 | elf.SHN_UNDEF; |
| 346 | global.value = esym.st_value; | 346 | global.value = @intCast(esym.st_value); |
| 347 | global.atom_index = atom_index; | 347 | global.atom_index = atom_index; |
| 348 | global.esym_index = esym_index; | 348 | global.esym_index = esym_index; |
| 349 | global.file_index = self.index; | 349 | global.file_index = self.index; |
| ... | @@ -631,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 | ... | @@ -631,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 |
| 631 | return code; | 631 | return code; |
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | const file_offset = shdr.sh_offset + atom.value; | 634 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom.value)); |
| 635 | const size = std.math.cast(usize, atom.size) orelse return error.Overflow; | 635 | const size = std.math.cast(usize, atom.size) orelse return error.Overflow; |
| 636 | const code = try gpa.alloc(u8, size); | 636 | const code = try gpa.alloc(u8, size); |
| 637 | errdefer gpa.free(code); | 637 | errdefer gpa.free(code); |
| ... | @@ -659,7 +659,7 @@ pub fn getDeclVAddr( | ... | @@ -659,7 +659,7 @@ pub fn getDeclVAddr( |
| 659 | .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type, | 659 | .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type, |
| 660 | .r_addend = reloc_info.addend, | 660 | .r_addend = reloc_info.addend, |
| 661 | }); | 661 | }); |
| 662 | return vaddr; | 662 | return @intCast(vaddr); |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | pub fn getAnonDeclVAddr( | 665 | pub fn getAnonDeclVAddr( |
| ... | @@ -678,7 +678,7 @@ pub fn getAnonDeclVAddr( | ... | @@ -678,7 +678,7 @@ pub fn getAnonDeclVAddr( |
| 678 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type, | 678 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type, |
| 679 | .r_addend = reloc_info.addend, | 679 | .r_addend = reloc_info.addend, |
| 680 | }); | 680 | }); |
| 681 | return vaddr; | 681 | return @intCast(vaddr); |
| 682 | } | 682 | } |
| 683 | 683 | ||
| 684 | pub fn lowerAnonDecl( | 684 | pub fn lowerAnonDecl( |
| ... | @@ -929,7 +929,7 @@ fn updateDeclCode( | ... | @@ -929,7 +929,7 @@ fn updateDeclCode( |
| 929 | 929 | ||
| 930 | if (old_size > 0 and elf_file.base.child_pid == null) { | 930 | if (old_size > 0 and elf_file.base.child_pid == null) { |
| 931 | const capacity = atom_ptr.capacity(elf_file); | 931 | const capacity = atom_ptr.capacity(elf_file); |
| 932 | const need_realloc = code.len > capacity or !required_alignment.check(atom_ptr.value); | 932 | const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value)); |
| 933 | if (need_realloc) { | 933 | if (need_realloc) { |
| 934 | try atom_ptr.grow(elf_file); | 934 | try atom_ptr.grow(elf_file); |
| 935 | log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom_ptr.value }); | 935 | log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom_ptr.value }); |
| ... | @@ -984,7 +984,7 @@ fn updateDeclCode( | ... | @@ -984,7 +984,7 @@ fn updateDeclCode( |
| 984 | 984 | ||
| 985 | const shdr = elf_file.shdrs.items[shdr_index]; | 985 | const shdr = elf_file.shdrs.items[shdr_index]; |
| 986 | if (shdr.sh_type != elf.SHT_NOBITS) { | 986 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 987 | const file_offset = shdr.sh_offset + atom_ptr.value; | 987 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 988 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 988 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 989 | } | 989 | } |
| 990 | } | 990 | } |
| ... | @@ -1107,7 +1107,7 @@ pub fn updateFunc( | ... | @@ -1107,7 +1107,7 @@ pub fn updateFunc( |
| 1107 | try self.dwarf.?.commitDeclState( | 1107 | try self.dwarf.?.commitDeclState( |
| 1108 | mod, | 1108 | mod, |
| 1109 | decl_index, | 1109 | decl_index, |
| 1110 | sym.address(.{}, elf_file), | 1110 | @intCast(sym.address(.{}, elf_file)), |
| 1111 | sym.atom(elf_file).?.size, | 1111 | sym.atom(elf_file).?.size, |
| 1112 | ds, | 1112 | ds, |
| 1113 | ); | 1113 | ); |
| ... | @@ -1186,7 +1186,7 @@ pub fn updateDecl( | ... | @@ -1186,7 +1186,7 @@ pub fn updateDecl( |
| 1186 | try self.dwarf.?.commitDeclState( | 1186 | try self.dwarf.?.commitDeclState( |
| 1187 | mod, | 1187 | mod, |
| 1188 | decl_index, | 1188 | decl_index, |
| 1189 | sym.address(.{}, elf_file), | 1189 | @intCast(sym.address(.{}, elf_file)), |
| 1190 | sym.atom(elf_file).?.size, | 1190 | sym.atom(elf_file).?.size, |
| 1191 | ds, | 1191 | ds, |
| 1192 | ); | 1192 | ); |
| ... | @@ -1275,7 +1275,7 @@ fn updateLazySymbol( | ... | @@ -1275,7 +1275,7 @@ fn updateLazySymbol( |
| 1275 | } | 1275 | } |
| 1276 | 1276 | ||
| 1277 | const shdr = elf_file.shdrs.items[output_section_index]; | 1277 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1278 | const file_offset = shdr.sh_offset + atom_ptr.value; | 1278 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1279 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1279 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| ... | @@ -1373,7 +1373,7 @@ fn lowerConst( | ... | @@ -1373,7 +1373,7 @@ fn lowerConst( |
| 1373 | local_esym.st_value = 0; | 1373 | local_esym.st_value = 0; |
| 1374 | 1374 | ||
| 1375 | const shdr = elf_file.shdrs.items[output_section_index]; | 1375 | const shdr = elf_file.shdrs.items[output_section_index]; |
| 1376 | const file_offset = shdr.sh_offset + atom_ptr.value; | 1376 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1377 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1377 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1378 | 1378 | ||
| 1379 | return .{ .ok = sym_index }; | 1379 | return .{ .ok = sym_index }; |
| ... | @@ -1457,7 +1457,7 @@ pub fn updateExports( | ... | @@ -1457,7 +1457,7 @@ pub fn updateExports( |
| 1457 | 1457 | ||
| 1458 | const actual_esym_index = global_esym_index & symbol_mask; | 1458 | const actual_esym_index = global_esym_index & symbol_mask; |
| 1459 | const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index]; | 1459 | const global_esym = &self.global_esyms.items(.elf_sym)[actual_esym_index]; |
| 1460 | global_esym.st_value = elf_file.symbol(sym_index).value; | 1460 | global_esym.st_value = @intCast(elf_file.symbol(sym_index).value); |
| 1461 | global_esym.st_shndx = esym.st_shndx; | 1461 | global_esym.st_shndx = esym.st_shndx; |
| 1462 | global_esym.st_info = (stb_bits << 4) | stt_bits; | 1462 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| 1463 | global_esym.st_name = name_off; | 1463 | global_esym.st_name = name_off; |
src/link/Elf/gc.zig+8| ... | @@ -68,6 +68,10 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil | ... | @@ -68,6 +68,10 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), elf_file: *Elf) !void { | 70 | fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), elf_file: *Elf) !void { |
| 71 | if (sym.mergeSubsection(elf_file)) |msub| { | ||
| 72 | msub.alive = true; | ||
| 73 | return; | ||
| 74 | } | ||
| 71 | const atom = sym.atom(elf_file) orelse return; | 75 | const atom = sym.atom(elf_file) orelse return; |
| 72 | if (markAtom(atom)) try roots.append(atom); | 76 | if (markAtom(atom)) try roots.append(atom); |
| 73 | } | 77 | } |
| ... | @@ -96,6 +100,10 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { | ... | @@ -96,6 +100,10 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 96 | 100 | ||
| 97 | for (atom.relocs(elf_file)) |rel| { | 101 | for (atom.relocs(elf_file)) |rel| { |
| 98 | const target_sym = elf_file.symbol(file.symbol(rel.r_sym())); | 102 | const target_sym = elf_file.symbol(file.symbol(rel.r_sym())); |
| 103 | if (target_sym.mergeSubsection(elf_file)) |msub| { | ||
| 104 | msub.alive = true; | ||
| 105 | continue; | ||
| 106 | } | ||
| 99 | const target_atom = target_sym.atom(elf_file) orelse continue; | 107 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 100 | target_atom.flags.alive = true; | 108 | target_atom.flags.alive = true; |
| 101 | gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index }); | 109 | gc_track_live_log.debug("{}marking live atom({d})", .{ track_live_level, target_atom.atom_index }); |
src/link/Elf/relocatable.zig+17-2| ... | @@ -181,6 +181,8 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -181,6 +181,8 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 181 | elf_file.markEhFrameAtomsDead(); | 181 | elf_file.markEhFrameAtomsDead(); |
| 182 | claimUnresolved(elf_file); | 182 | claimUnresolved(elf_file); |
| 183 | 183 | ||
| 184 | try elf_file.addCommentString(); | ||
| 185 | try elf_file.sortMergeSections(); | ||
| 184 | try initSections(elf_file); | 186 | try initSections(elf_file); |
| 185 | try elf_file.sortShdrs(); | 187 | try elf_file.sortShdrs(); |
| 186 | if (elf_file.zigObjectPtr()) |zig_object| { | 188 | if (elf_file.zigObjectPtr()) |zig_object| { |
| ... | @@ -191,6 +193,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -191,6 +193,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 191 | try object.addAtomsToOutputSections(elf_file); | 193 | try object.addAtomsToOutputSections(elf_file); |
| 192 | try object.addAtomsToRelaSections(elf_file); | 194 | try object.addAtomsToRelaSections(elf_file); |
| 193 | } | 195 | } |
| 196 | try elf_file.updateMergeSectionSizes(); | ||
| 194 | try updateSectionSizes(elf_file); | 197 | try updateSectionSizes(elf_file); |
| 195 | 198 | ||
| 196 | try allocateAllocSections(elf_file); | 199 | try allocateAllocSections(elf_file); |
| ... | @@ -201,6 +204,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -201,6 +204,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 201 | } | 204 | } |
| 202 | 205 | ||
| 203 | try writeAtoms(elf_file); | 206 | try writeAtoms(elf_file); |
| 207 | try elf_file.writeMergeSections(); | ||
| 204 | try writeSyntheticSections(elf_file); | 208 | try writeSyntheticSections(elf_file); |
| 205 | try elf_file.writeShdrTable(); | 209 | try elf_file.writeShdrTable(); |
| 206 | try elf_file.writeElfHeader(); | 210 | try elf_file.writeElfHeader(); |
| ... | @@ -275,6 +279,17 @@ fn initSections(elf_file: *Elf) !void { | ... | @@ -275,6 +279,17 @@ fn initSections(elf_file: *Elf) !void { |
| 275 | try object.initRelaSections(elf_file); | 279 | try object.initRelaSections(elf_file); |
| 276 | } | 280 | } |
| 277 | 281 | ||
| 282 | for (elf_file.merge_sections.items) |*msec| { | ||
| 283 | if (msec.subsections.items.len == 0) continue; | ||
| 284 | const name = msec.name(elf_file); | ||
| 285 | const shndx = elf_file.sectionByName(name) orelse try elf_file.addSection(.{ | ||
| 286 | .name = name, | ||
| 287 | .type = msec.type, | ||
| 288 | .flags = msec.flags, | ||
| 289 | }); | ||
| 290 | msec.output_section_index = shndx; | ||
| 291 | } | ||
| 292 | |||
| 278 | const needs_eh_frame = for (elf_file.objects.items) |index| { | 293 | const needs_eh_frame = for (elf_file.objects.items) |index| { |
| 279 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; | 294 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; |
| 280 | } else false; | 295 | } else false; |
| ... | @@ -328,7 +343,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { | ... | @@ -328,7 +343,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 328 | if (!atom_ptr.flags.alive) continue; | 343 | if (!atom_ptr.flags.alive) continue; |
| 329 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | 344 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 330 | const padding = offset - shdr.sh_size; | 345 | const padding = offset - shdr.sh_size; |
| 331 | atom_ptr.value = offset; | 346 | atom_ptr.value = @intCast(offset); |
| 332 | shdr.sh_size += padding + atom_ptr.size; | 347 | shdr.sh_size += padding + atom_ptr.size; |
| 333 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); | 348 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 334 | } | 349 | } |
| ... | @@ -434,7 +449,7 @@ fn writeAtoms(elf_file: *Elf) !void { | ... | @@ -434,7 +449,7 @@ fn writeAtoms(elf_file: *Elf) !void { |
| 434 | const atom_ptr = elf_file.atom(atom_index).?; | 449 | const atom_ptr = elf_file.atom(atom_index).?; |
| 435 | assert(atom_ptr.flags.alive); | 450 | assert(atom_ptr.flags.alive); |
| 436 | 451 | ||
| 437 | const offset = math.cast(usize, atom_ptr.value - shdr.sh_addr - base_offset) orelse | 452 | const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse |
| 438 | return error.Overflow; | 453 | return error.Overflow; |
| 439 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; | 454 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| 440 | 455 |
src/link/Elf/synthetic_sections.zig+38-39| ... | @@ -270,11 +270,11 @@ pub const ZigGotSection = struct { | ... | @@ -270,11 +270,11 @@ pub const ZigGotSection = struct { |
| 270 | return shdr.sh_offset + @as(u64, entry_size) * index; | 270 | return shdr.sh_offset + @as(u64, entry_size) * index; |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | pub fn entryAddress(zig_got: ZigGotSection, index: Index, elf_file: *Elf) u64 { | 273 | pub fn entryAddress(zig_got: ZigGotSection, index: Index, elf_file: *Elf) i64 { |
| 274 | _ = zig_got; | 274 | _ = zig_got; |
| 275 | const entry_size = elf_file.archPtrWidthBytes(); | 275 | const entry_size = elf_file.archPtrWidthBytes(); |
| 276 | const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?]; | 276 | const shdr = elf_file.shdrs.items[elf_file.zig_got_section_index.?]; |
| 277 | return shdr.sh_addr + @as(u64, entry_size) * index; | 277 | return @as(i64, @intCast(shdr.sh_addr)) + entry_size * index; |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | pub fn size(zig_got: ZigGotSection, elf_file: *Elf) usize { | 280 | pub fn size(zig_got: ZigGotSection, elf_file: *Elf) usize { |
| ... | @@ -291,23 +291,23 @@ pub const ZigGotSection = struct { | ... | @@ -291,23 +291,23 @@ pub const ZigGotSection = struct { |
| 291 | const target = elf_file.getTarget(); | 291 | const target = elf_file.getTarget(); |
| 292 | const endian = target.cpu.arch.endian(); | 292 | const endian = target.cpu.arch.endian(); |
| 293 | const off = zig_got.entryOffset(index, elf_file); | 293 | const off = zig_got.entryOffset(index, elf_file); |
| 294 | const vaddr = zig_got.entryAddress(index, elf_file); | 294 | const vaddr: u64 = @intCast(zig_got.entryAddress(index, elf_file)); |
| 295 | const entry = zig_got.entries.items[index]; | 295 | const entry = zig_got.entries.items[index]; |
| 296 | const value = elf_file.symbol(entry).address(.{}, elf_file); | 296 | const value = elf_file.symbol(entry).address(.{}, elf_file); |
| 297 | switch (entry_size) { | 297 | switch (entry_size) { |
| 298 | 2 => { | 298 | 2 => { |
| 299 | var buf: [2]u8 = undefined; | 299 | var buf: [2]u8 = undefined; |
| 300 | std.mem.writeInt(u16, &buf, @as(u16, @intCast(value)), endian); | 300 | std.mem.writeInt(u16, &buf, @intCast(value), endian); |
| 301 | try elf_file.base.file.?.pwriteAll(&buf, off); | 301 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 302 | }, | 302 | }, |
| 303 | 4 => { | 303 | 4 => { |
| 304 | var buf: [4]u8 = undefined; | 304 | var buf: [4]u8 = undefined; |
| 305 | std.mem.writeInt(u32, &buf, @as(u32, @intCast(value)), endian); | 305 | std.mem.writeInt(u32, &buf, @intCast(value), endian); |
| 306 | try elf_file.base.file.?.pwriteAll(&buf, off); | 306 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 307 | }, | 307 | }, |
| 308 | 8 => { | 308 | 8 => { |
| 309 | var buf: [8]u8 = undefined; | 309 | var buf: [8]u8 = undefined; |
| 310 | std.mem.writeInt(u64, &buf, value, endian); | 310 | std.mem.writeInt(u64, &buf, @intCast(value), endian); |
| 311 | try elf_file.base.file.?.pwriteAll(&buf, off); | 311 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 312 | 312 | ||
| 313 | if (elf_file.base.child_pid) |pid| { | 313 | if (elf_file.base.child_pid) |pid| { |
| ... | @@ -356,9 +356,9 @@ pub const ZigGotSection = struct { | ... | @@ -356,9 +356,9 @@ pub const ZigGotSection = struct { |
| 356 | const symbol = elf_file.symbol(entry); | 356 | const symbol = elf_file.symbol(entry); |
| 357 | const offset = symbol.zigGotAddress(elf_file); | 357 | const offset = symbol.zigGotAddress(elf_file); |
| 358 | elf_file.addRelaDynAssumeCapacity(.{ | 358 | elf_file.addRelaDynAssumeCapacity(.{ |
| 359 | .offset = offset, | 359 | .offset = @intCast(offset), |
| 360 | .type = relocation.encode(.rel, cpu_arch), | 360 | .type = relocation.encode(.rel, cpu_arch), |
| 361 | .addend = @intCast(symbol.address(.{ .plt = false }, elf_file)), | 361 | .addend = symbol.address(.{ .plt = false }, elf_file), |
| 362 | }); | 362 | }); |
| 363 | } | 363 | } |
| 364 | } | 364 | } |
| ... | @@ -386,7 +386,7 @@ pub const ZigGotSection = struct { | ... | @@ -386,7 +386,7 @@ pub const ZigGotSection = struct { |
| 386 | .st_info = elf.STT_OBJECT, | 386 | .st_info = elf.STT_OBJECT, |
| 387 | .st_other = 0, | 387 | .st_other = 0, |
| 388 | .st_shndx = @intCast(elf_file.zig_got_section_index.?), | 388 | .st_shndx = @intCast(elf_file.zig_got_section_index.?), |
| 389 | .st_value = st_value, | 389 | .st_value = @intCast(st_value), |
| 390 | .st_size = st_size, | 390 | .st_size = st_size, |
| 391 | }; | 391 | }; |
| 392 | } | 392 | } |
| ... | @@ -457,10 +457,10 @@ pub const GotSection = struct { | ... | @@ -457,10 +457,10 @@ pub const GotSection = struct { |
| 457 | }; | 457 | }; |
| 458 | } | 458 | } |
| 459 | 459 | ||
| 460 | pub fn address(entry: Entry, elf_file: *Elf) u64 { | 460 | pub fn address(entry: Entry, elf_file: *Elf) i64 { |
| 461 | const ptr_bytes = @as(u64, elf_file.archPtrWidthBytes()); | 461 | const ptr_bytes = elf_file.archPtrWidthBytes(); |
| 462 | const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?]; | 462 | const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?]; |
| 463 | return shdr.sh_addr + @as(u64, entry.cell_index) * ptr_bytes; | 463 | return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes; |
| 464 | } | 464 | } |
| 465 | }; | 465 | }; |
| 466 | 466 | ||
| ... | @@ -608,8 +608,7 @@ pub const GotSection = struct { | ... | @@ -608,8 +608,7 @@ pub const GotSection = struct { |
| 608 | 0; | 608 | 0; |
| 609 | try writeInt(offset, elf_file, writer); | 609 | try writeInt(offset, elf_file, writer); |
| 610 | } else { | 610 | } else { |
| 611 | const offset = @as(i64, @intCast(symbol.?.address(.{}, elf_file))) - | 611 | const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress(); |
| 612 | @as(i64, @intCast(elf_file.tpAddress())); | ||
| 613 | try writeInt(offset, elf_file, writer); | 612 | try writeInt(offset, elf_file, writer); |
| 614 | } | 613 | } |
| 615 | }, | 614 | }, |
| ... | @@ -620,7 +619,7 @@ pub const GotSection = struct { | ... | @@ -620,7 +619,7 @@ pub const GotSection = struct { |
| 620 | } else { | 619 | } else { |
| 621 | try writeInt(0, elf_file, writer); | 620 | try writeInt(0, elf_file, writer); |
| 622 | const offset = if (apply_relocs) | 621 | const offset = if (apply_relocs) |
| 623 | @as(i64, @intCast(symbol.?.address(.{}, elf_file))) - @as(i64, @intCast(elf_file.tlsAddress())) | 622 | symbol.?.address(.{}, elf_file) - elf_file.tlsAddress() |
| 624 | else | 623 | else |
| 625 | 0; | 624 | 0; |
| 626 | try writeInt(offset, elf_file, writer); | 625 | try writeInt(offset, elf_file, writer); |
| ... | @@ -646,7 +645,7 @@ pub const GotSection = struct { | ... | @@ -646,7 +645,7 @@ pub const GotSection = struct { |
| 646 | 645 | ||
| 647 | switch (entry.tag) { | 646 | switch (entry.tag) { |
| 648 | .got => { | 647 | .got => { |
| 649 | const offset = symbol.?.gotAddress(elf_file); | 648 | const offset: u64 = @intCast(symbol.?.gotAddress(elf_file)); |
| 650 | if (symbol.?.flags.import) { | 649 | if (symbol.?.flags.import) { |
| 651 | elf_file.addRelaDynAssumeCapacity(.{ | 650 | elf_file.addRelaDynAssumeCapacity(.{ |
| 652 | .offset = offset, | 651 | .offset = offset, |
| ... | @@ -659,7 +658,7 @@ pub const GotSection = struct { | ... | @@ -659,7 +658,7 @@ pub const GotSection = struct { |
| 659 | elf_file.addRelaDynAssumeCapacity(.{ | 658 | elf_file.addRelaDynAssumeCapacity(.{ |
| 660 | .offset = offset, | 659 | .offset = offset, |
| 661 | .type = relocation.encode(.irel, cpu_arch), | 660 | .type = relocation.encode(.irel, cpu_arch), |
| 662 | .addend = @intCast(symbol.?.address(.{ .plt = false }, elf_file)), | 661 | .addend = symbol.?.address(.{ .plt = false }, elf_file), |
| 663 | }); | 662 | }); |
| 664 | continue; | 663 | continue; |
| 665 | } | 664 | } |
| ... | @@ -669,14 +668,14 @@ pub const GotSection = struct { | ... | @@ -669,14 +668,14 @@ pub const GotSection = struct { |
| 669 | elf_file.addRelaDynAssumeCapacity(.{ | 668 | elf_file.addRelaDynAssumeCapacity(.{ |
| 670 | .offset = offset, | 669 | .offset = offset, |
| 671 | .type = relocation.encode(.rel, cpu_arch), | 670 | .type = relocation.encode(.rel, cpu_arch), |
| 672 | .addend = @intCast(symbol.?.address(.{ .plt = false }, elf_file)), | 671 | .addend = symbol.?.address(.{ .plt = false }, elf_file), |
| 673 | }); | 672 | }); |
| 674 | } | 673 | } |
| 675 | }, | 674 | }, |
| 676 | 675 | ||
| 677 | .tlsld => { | 676 | .tlsld => { |
| 678 | if (is_dyn_lib) { | 677 | if (is_dyn_lib) { |
| 679 | const offset = entry.address(elf_file); | 678 | const offset: u64 = @intCast(entry.address(elf_file)); |
| 680 | elf_file.addRelaDynAssumeCapacity(.{ | 679 | elf_file.addRelaDynAssumeCapacity(.{ |
| 681 | .offset = offset, | 680 | .offset = offset, |
| 682 | .type = relocation.encode(.dtpmod, cpu_arch), | 681 | .type = relocation.encode(.dtpmod, cpu_arch), |
| ... | @@ -685,7 +684,7 @@ pub const GotSection = struct { | ... | @@ -685,7 +684,7 @@ pub const GotSection = struct { |
| 685 | }, | 684 | }, |
| 686 | 685 | ||
| 687 | .tlsgd => { | 686 | .tlsgd => { |
| 688 | const offset = symbol.?.tlsGdAddress(elf_file); | 687 | const offset: u64 = @intCast(symbol.?.tlsGdAddress(elf_file)); |
| 689 | if (symbol.?.flags.import) { | 688 | if (symbol.?.flags.import) { |
| 690 | elf_file.addRelaDynAssumeCapacity(.{ | 689 | elf_file.addRelaDynAssumeCapacity(.{ |
| 691 | .offset = offset, | 690 | .offset = offset, |
| ... | @@ -707,7 +706,7 @@ pub const GotSection = struct { | ... | @@ -707,7 +706,7 @@ pub const GotSection = struct { |
| 707 | }, | 706 | }, |
| 708 | 707 | ||
| 709 | .gottp => { | 708 | .gottp => { |
| 710 | const offset = symbol.?.gotTpAddress(elf_file); | 709 | const offset: u64 = @intCast(symbol.?.gotTpAddress(elf_file)); |
| 711 | if (symbol.?.flags.import) { | 710 | if (symbol.?.flags.import) { |
| 712 | elf_file.addRelaDynAssumeCapacity(.{ | 711 | elf_file.addRelaDynAssumeCapacity(.{ |
| 713 | .offset = offset, | 712 | .offset = offset, |
| ... | @@ -718,18 +717,18 @@ pub const GotSection = struct { | ... | @@ -718,18 +717,18 @@ pub const GotSection = struct { |
| 718 | elf_file.addRelaDynAssumeCapacity(.{ | 717 | elf_file.addRelaDynAssumeCapacity(.{ |
| 719 | .offset = offset, | 718 | .offset = offset, |
| 720 | .type = relocation.encode(.tpoff, cpu_arch), | 719 | .type = relocation.encode(.tpoff, cpu_arch), |
| 721 | .addend = @intCast(symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()), | 720 | .addend = symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(), |
| 722 | }); | 721 | }); |
| 723 | } | 722 | } |
| 724 | }, | 723 | }, |
| 725 | 724 | ||
| 726 | .tlsdesc => { | 725 | .tlsdesc => { |
| 727 | const offset = symbol.?.tlsDescAddress(elf_file); | 726 | const offset: u64 = @intCast(symbol.?.tlsDescAddress(elf_file)); |
| 728 | elf_file.addRelaDynAssumeCapacity(.{ | 727 | elf_file.addRelaDynAssumeCapacity(.{ |
| 729 | .offset = offset, | 728 | .offset = offset, |
| 730 | .sym = if (symbol.?.flags.import) extra.?.dynamic else 0, | 729 | .sym = if (symbol.?.flags.import) extra.?.dynamic else 0, |
| 731 | .type = relocation.encode(.tlsdesc, cpu_arch), | 730 | .type = relocation.encode(.tlsdesc, cpu_arch), |
| 732 | .addend = if (symbol.?.flags.import) 0 else @intCast(symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()), | 731 | .addend = if (symbol.?.flags.import) 0 else symbol.?.address(.{}, elf_file) - elf_file.tlsAddress(), |
| 733 | }); | 732 | }); |
| 734 | }, | 733 | }, |
| 735 | } | 734 | } |
| ... | @@ -806,7 +805,7 @@ pub const GotSection = struct { | ... | @@ -806,7 +805,7 @@ pub const GotSection = struct { |
| 806 | .st_info = elf.STT_OBJECT, | 805 | .st_info = elf.STT_OBJECT, |
| 807 | .st_other = 0, | 806 | .st_other = 0, |
| 808 | .st_shndx = @intCast(elf_file.got_section_index.?), | 807 | .st_shndx = @intCast(elf_file.got_section_index.?), |
| 809 | .st_value = st_value, | 808 | .st_value = @intCast(st_value), |
| 810 | .st_size = st_size, | 809 | .st_size = st_size, |
| 811 | }; | 810 | }; |
| 812 | } | 811 | } |
| ... | @@ -900,7 +899,7 @@ pub const PltSection = struct { | ... | @@ -900,7 +899,7 @@ pub const PltSection = struct { |
| 900 | const sym = elf_file.symbol(sym_index); | 899 | const sym = elf_file.symbol(sym_index); |
| 901 | assert(sym.flags.import); | 900 | assert(sym.flags.import); |
| 902 | const extra = sym.extra(elf_file).?; | 901 | const extra = sym.extra(elf_file).?; |
| 903 | const r_offset = sym.gotPltAddress(elf_file); | 902 | const r_offset: u64 = @intCast(sym.gotPltAddress(elf_file)); |
| 904 | const r_sym: u64 = extra.dynamic; | 903 | const r_sym: u64 = extra.dynamic; |
| 905 | const r_type = relocation.encode(.jump_slot, cpu_arch); | 904 | const r_type = relocation.encode(.jump_slot, cpu_arch); |
| 906 | elf_file.rela_plt.appendAssumeCapacity(.{ | 905 | elf_file.rela_plt.appendAssumeCapacity(.{ |
| ... | @@ -936,7 +935,7 @@ pub const PltSection = struct { | ... | @@ -936,7 +935,7 @@ pub const PltSection = struct { |
| 936 | .st_info = elf.STT_FUNC, | 935 | .st_info = elf.STT_FUNC, |
| 937 | .st_other = 0, | 936 | .st_other = 0, |
| 938 | .st_shndx = @intCast(elf_file.plt_section_index.?), | 937 | .st_shndx = @intCast(elf_file.plt_section_index.?), |
| 939 | .st_value = sym.pltAddress(elf_file), | 938 | .st_value = @intCast(sym.pltAddress(elf_file)), |
| 940 | .st_size = entrySize(cpu_arch), | 939 | .st_size = entrySize(cpu_arch), |
| 941 | }; | 940 | }; |
| 942 | } | 941 | } |
| ... | @@ -1009,13 +1008,13 @@ pub const PltSection = struct { | ... | @@ -1009,13 +1008,13 @@ pub const PltSection = struct { |
| 1009 | const aarch64 = struct { | 1008 | const aarch64 = struct { |
| 1010 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | 1009 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { |
| 1011 | { | 1010 | { |
| 1012 | const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr; | 1011 | const plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr); |
| 1013 | const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr; | 1012 | const got_plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr); |
| 1014 | // TODO: relax if possible | 1013 | // TODO: relax if possible |
| 1015 | // .got.plt[2] | 1014 | // .got.plt[2] |
| 1016 | const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); | 1015 | const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); |
| 1017 | const ldr_off = try math.divExact(u12, @truncate(got_plt_addr + 16), 8); | 1016 | const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(got_plt_addr + 16))), 8); |
| 1018 | const add_off: u12 = @truncate(got_plt_addr + 16); | 1017 | const add_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16))); |
| 1019 | 1018 | ||
| 1020 | const preamble = &[_]Instruction{ | 1019 | const preamble = &[_]Instruction{ |
| 1021 | Instruction.stp( | 1020 | Instruction.stp( |
| ... | @@ -1043,8 +1042,8 @@ pub const PltSection = struct { | ... | @@ -1043,8 +1042,8 @@ pub const PltSection = struct { |
| 1043 | const target_addr = sym.gotPltAddress(elf_file); | 1042 | const target_addr = sym.gotPltAddress(elf_file); |
| 1044 | const source_addr = sym.pltAddress(elf_file); | 1043 | const source_addr = sym.pltAddress(elf_file); |
| 1045 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); | 1044 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); |
| 1046 | const ldr_off = try math.divExact(u12, @truncate(target_addr), 8); | 1045 | const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8); |
| 1047 | const add_off: u12 = @truncate(target_addr); | 1046 | const add_off: u12 = @truncate(@as(u64, @bitCast(target_addr))); |
| 1048 | const insts = &[_]Instruction{ | 1047 | const insts = &[_]Instruction{ |
| 1049 | Instruction.adrp(.x16, pages), | 1048 | Instruction.adrp(.x16, pages), |
| 1050 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)), | 1049 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)), |
| ... | @@ -1077,7 +1076,7 @@ pub const GotPltSection = struct { | ... | @@ -1077,7 +1076,7 @@ pub const GotPltSection = struct { |
| 1077 | { | 1076 | { |
| 1078 | // [0]: _DYNAMIC | 1077 | // [0]: _DYNAMIC |
| 1079 | const symbol = elf_file.symbol(elf_file.dynamic_index.?); | 1078 | const symbol = elf_file.symbol(elf_file.dynamic_index.?); |
| 1080 | try writer.writeInt(u64, symbol.address(.{}, elf_file), .little); | 1079 | try writer.writeInt(u64, @intCast(symbol.address(.{}, elf_file)), .little); |
| 1081 | } | 1080 | } |
| 1082 | // [1]: 0x0 | 1081 | // [1]: 0x0 |
| 1083 | // [2]: 0x0 | 1082 | // [2]: 0x0 |
| ... | @@ -1153,7 +1152,7 @@ pub const PltGotSection = struct { | ... | @@ -1153,7 +1152,7 @@ pub const PltGotSection = struct { |
| 1153 | .st_info = elf.STT_FUNC, | 1152 | .st_info = elf.STT_FUNC, |
| 1154 | .st_other = 0, | 1153 | .st_other = 0, |
| 1155 | .st_shndx = @intCast(elf_file.plt_got_section_index.?), | 1154 | .st_shndx = @intCast(elf_file.plt_got_section_index.?), |
| 1156 | .st_value = sym.pltGotAddress(elf_file), | 1155 | .st_value = @intCast(sym.pltGotAddress(elf_file)), |
| 1157 | .st_size = 16, | 1156 | .st_size = 16, |
| 1158 | }; | 1157 | }; |
| 1159 | } | 1158 | } |
| ... | @@ -1184,7 +1183,7 @@ pub const PltGotSection = struct { | ... | @@ -1184,7 +1183,7 @@ pub const PltGotSection = struct { |
| 1184 | const target_addr = sym.gotAddress(elf_file); | 1183 | const target_addr = sym.gotAddress(elf_file); |
| 1185 | const source_addr = sym.pltGotAddress(elf_file); | 1184 | const source_addr = sym.pltGotAddress(elf_file); |
| 1186 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); | 1185 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); |
| 1187 | const off = try math.divExact(u12, @truncate(target_addr), 8); | 1186 | const off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8); |
| 1188 | const insts = &[_]Instruction{ | 1187 | const insts = &[_]Instruction{ |
| 1189 | Instruction.adrp(.x16, pages), | 1188 | Instruction.adrp(.x16, pages), |
| 1190 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)), | 1189 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)), |
| ... | @@ -1247,9 +1246,9 @@ pub const CopyRelSection = struct { | ... | @@ -1247,9 +1246,9 @@ pub const CopyRelSection = struct { |
| 1247 | const symbol = elf_file.symbol(sym_index); | 1246 | const symbol = elf_file.symbol(sym_index); |
| 1248 | const shared_object = symbol.file(elf_file).?.shared_object; | 1247 | const shared_object = symbol.file(elf_file).?.shared_object; |
| 1249 | const alignment = try symbol.dsoAlignment(elf_file); | 1248 | const alignment = try symbol.dsoAlignment(elf_file); |
| 1250 | symbol.value = mem.alignForward(u64, shdr.sh_size, alignment); | 1249 | symbol.value = @intCast(mem.alignForward(u64, shdr.sh_size, alignment)); |
| 1251 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment); | 1250 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment); |
| 1252 | shdr.sh_size = symbol.value + symbol.elfSym(elf_file).st_size; | 1251 | shdr.sh_size = @as(u64, @intCast(symbol.value)) + symbol.elfSym(elf_file).st_size; |
| 1253 | 1252 | ||
| 1254 | const aliases = shared_object.symbolAliases(sym_index, elf_file); | 1253 | const aliases = shared_object.symbolAliases(sym_index, elf_file); |
| 1255 | for (aliases) |alias| { | 1254 | for (aliases) |alias| { |
| ... | @@ -1270,7 +1269,7 @@ pub const CopyRelSection = struct { | ... | @@ -1270,7 +1269,7 @@ pub const CopyRelSection = struct { |
| 1270 | assert(sym.flags.import and sym.flags.has_copy_rel); | 1269 | assert(sym.flags.import and sym.flags.has_copy_rel); |
| 1271 | const extra = sym.extra(elf_file).?; | 1270 | const extra = sym.extra(elf_file).?; |
| 1272 | elf_file.addRelaDynAssumeCapacity(.{ | 1271 | elf_file.addRelaDynAssumeCapacity(.{ |
| 1273 | .offset = sym.address(.{}, elf_file), | 1272 | .offset = @intCast(sym.address(.{}, elf_file)), |
| 1274 | .sym = extra.dynamic, | 1273 | .sym = extra.dynamic, |
| 1275 | .type = relocation.encode(.copy, cpu_arch), | 1274 | .type = relocation.encode(.copy, cpu_arch), |
| 1276 | }); | 1275 | }); |
src/link/Elf/thunks.zig+16-15| ... | @@ -7,7 +7,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { | ... | @@ -7,7 +7,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 7 | assert(atoms.len > 0); | 7 | assert(atoms.len > 0); |
| 8 | 8 | ||
| 9 | for (atoms) |atom_index| { | 9 | for (atoms) |atom_index| { |
| 10 | elf_file.atom(atom_index).?.value = @bitCast(@as(i64, -1)); | 10 | elf_file.atom(atom_index).?.value = -1; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | var i: usize = 0; | 13 | var i: usize = 0; |
| ... | @@ -22,7 +22,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { | ... | @@ -22,7 +22,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 22 | const atom_index = atoms[i]; | 22 | const atom_index = atoms[i]; |
| 23 | const atom = elf_file.atom(atom_index).?; | 23 | const atom = elf_file.atom(atom_index).?; |
| 24 | assert(atom.flags.alive); | 24 | assert(atom.flags.alive); |
| 25 | if (atom.alignment.forward(shdr.sh_size) - start_atom.value >= max_distance) break; | 25 | if (@as(i64, @intCast(atom.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance) |
| 26 | break; | ||
| 26 | atom.value = try advance(shdr, atom.size, atom.alignment); | 27 | atom.value = try advance(shdr, atom.size, atom.alignment); |
| 27 | } | 28 | } |
| 28 | 29 | ||
| ... | @@ -60,12 +61,12 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { | ... | @@ -60,12 +61,12 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 60 | } | 61 | } |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 { | 64 | fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !i64 { |
| 64 | const offset = alignment.forward(shdr.sh_size); | 65 | const offset = alignment.forward(shdr.sh_size); |
| 65 | const padding = offset - shdr.sh_size; | 66 | const padding = offset - shdr.sh_size; |
| 66 | shdr.sh_size += padding + size; | 67 | shdr.sh_size += padding + size; |
| 67 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); | 68 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); |
| 68 | return offset; | 69 | return @intCast(offset); |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | /// A branch will need an extender if its target is larger than | 72 | /// A branch will need an extender if its target is larger than |
| ... | @@ -79,7 +80,7 @@ fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 { | ... | @@ -79,7 +80,7 @@ fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 { |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | pub const Thunk = struct { | 82 | pub const Thunk = struct { |
| 82 | value: u64 = 0, | 83 | value: i64 = 0, |
| 83 | output_section_index: u32 = 0, | 84 | output_section_index: u32 = 0, |
| 84 | symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, | 85 | symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, |
| 85 | output_symtab_ctx: Elf.SymtabCtx = .{}, | 86 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| ... | @@ -93,14 +94,14 @@ pub const Thunk = struct { | ... | @@ -93,14 +94,14 @@ pub const Thunk = struct { |
| 93 | return thunk.symbols.keys().len * trampolineSize(cpu_arch); | 94 | return thunk.symbols.keys().len * trampolineSize(cpu_arch); |
| 94 | } | 95 | } |
| 95 | 96 | ||
| 96 | pub fn address(thunk: Thunk, elf_file: *Elf) u64 { | 97 | pub fn address(thunk: Thunk, elf_file: *Elf) i64 { |
| 97 | const shdr = elf_file.shdrs.items[thunk.output_section_index]; | 98 | const shdr = elf_file.shdrs.items[thunk.output_section_index]; |
| 98 | return shdr.sh_addr + thunk.value; | 99 | return @as(i64, @intCast(shdr.sh_addr)) + thunk.value; |
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | pub fn targetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) u64 { | 102 | pub fn targetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) i64 { |
| 102 | const cpu_arch = elf_file.getTarget().cpu.arch; | 103 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 103 | return thunk.address(elf_file) + thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch); | 104 | return thunk.address(elf_file) + @as(i64, @intCast(thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch))); |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { | 107 | pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| ... | @@ -132,7 +133,7 @@ pub const Thunk = struct { | ... | @@ -132,7 +133,7 @@ pub const Thunk = struct { |
| 132 | .st_info = elf.STT_FUNC, | 133 | .st_info = elf.STT_FUNC, |
| 133 | .st_other = 0, | 134 | .st_other = 0, |
| 134 | .st_shndx = @intCast(thunk.output_section_index), | 135 | .st_shndx = @intCast(thunk.output_section_index), |
| 135 | .st_value = thunk.targetAddress(sym_index, elf_file), | 136 | .st_value = @intCast(thunk.targetAddress(sym_index, elf_file)), |
| 136 | .st_size = trampolineSize(cpu_arch), | 137 | .st_size = trampolineSize(cpu_arch), |
| 137 | }; | 138 | }; |
| 138 | } | 139 | } |
| ... | @@ -205,9 +206,9 @@ const aarch64 = struct { | ... | @@ -205,9 +206,9 @@ const aarch64 = struct { |
| 205 | if (target.flags.has_plt) return false; | 206 | if (target.flags.has_plt) return false; |
| 206 | if (atom.output_section_index != target.output_section_index) return false; | 207 | if (atom.output_section_index != target.output_section_index) return false; |
| 207 | const target_atom = target.atom(elf_file).?; | 208 | const target_atom = target.atom(elf_file).?; |
| 208 | if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false; | 209 | if (target_atom.value == -1) return false; |
| 209 | const saddr = @as(i64, @intCast(atom.address(elf_file) + rel.r_offset)); | 210 | const saddr = atom.address(elf_file) + @as(i64, @intCast(rel.r_offset)); |
| 210 | const taddr: i64 = @intCast(target.address(.{}, elf_file)); | 211 | const taddr = target.address(.{}, elf_file); |
| 211 | _ = math.cast(i28, taddr + rel.r_addend - saddr) orelse return false; | 212 | _ = math.cast(i28, taddr + rel.r_addend - saddr) orelse return false; |
| 212 | return true; | 213 | return true; |
| 213 | } | 214 | } |
| ... | @@ -215,11 +216,11 @@ const aarch64 = struct { | ... | @@ -215,11 +216,11 @@ const aarch64 = struct { |
| 215 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { | 216 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| 216 | for (thunk.symbols.keys(), 0..) |sym_index, i| { | 217 | for (thunk.symbols.keys(), 0..) |sym_index, i| { |
| 217 | const sym = elf_file.symbol(sym_index); | 218 | const sym = elf_file.symbol(sym_index); |
| 218 | const saddr = thunk.address(elf_file) + i * trampoline_size; | 219 | const saddr = thunk.address(elf_file) + @as(i64, @intCast(i * trampoline_size)); |
| 219 | const taddr = sym.address(.{}, elf_file); | 220 | const taddr = sym.address(.{}, elf_file); |
| 220 | const pages = try util.calcNumberOfPages(saddr, taddr); | 221 | const pages = try util.calcNumberOfPages(saddr, taddr); |
| 221 | try writer.writeInt(u32, Instruction.adrp(.x16, pages).toU32(), .little); | 222 | try writer.writeInt(u32, Instruction.adrp(.x16, pages).toU32(), .little); |
| 222 | const off: u12 = @truncate(taddr); | 223 | const off: u12 = @truncate(@as(u64, @bitCast(taddr))); |
| 223 | try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little); | 224 | try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little); |
| 224 | try writer.writeInt(u32, Instruction.br(.x16).toU32(), .little); | 225 | try writer.writeInt(u32, Instruction.br(.x16).toU32(), .little); |
| 225 | } | 226 | } |
src/link/MachO/Atom.zig+1-1| ... | @@ -770,7 +770,7 @@ fn resolveRelocInner( | ... | @@ -770,7 +770,7 @@ fn resolveRelocInner( |
| 770 | }; | 770 | }; |
| 771 | break :target math.cast(u64, target) orelse return error.Overflow; | 771 | break :target math.cast(u64, target) orelse return error.Overflow; |
| 772 | }; | 772 | }; |
| 773 | const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target))); | 773 | const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)))); |
| 774 | aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]); | 774 | aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]); |
| 775 | }, | 775 | }, |
| 776 | 776 |
src/link/MachO/synthetic.zig+5-5| ... | @@ -267,7 +267,7 @@ pub const StubsSection = struct { | ... | @@ -267,7 +267,7 @@ pub const StubsSection = struct { |
| 267 | }, | 267 | }, |
| 268 | .aarch64 => { | 268 | .aarch64 => { |
| 269 | // TODO relax if possible | 269 | // TODO relax if possible |
| 270 | const pages = try aarch64.calcNumberOfPages(source, target); | 270 | const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)); |
| 271 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 271 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 272 | const off = try math.divExact(u12, @truncate(target), 8); | 272 | const off = try math.divExact(u12, @truncate(target), 8); |
| 273 | try writer.writeInt( | 273 | try writer.writeInt( |
| ... | @@ -411,7 +411,7 @@ pub const StubsHelperSection = struct { | ... | @@ -411,7 +411,7 @@ pub const StubsHelperSection = struct { |
| 411 | .aarch64 => { | 411 | .aarch64 => { |
| 412 | { | 412 | { |
| 413 | // TODO relax if possible | 413 | // TODO relax if possible |
| 414 | const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr); | 414 | const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr), @intCast(dyld_private_addr)); |
| 415 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); | 415 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); |
| 416 | const off: u12 = @truncate(dyld_private_addr); | 416 | const off: u12 = @truncate(dyld_private_addr); |
| 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); | 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); |
| ... | @@ -424,7 +424,7 @@ pub const StubsHelperSection = struct { | ... | @@ -424,7 +424,7 @@ pub const StubsHelperSection = struct { |
| 424 | ).toU32(), .little); | 424 | ).toU32(), .little); |
| 425 | { | 425 | { |
| 426 | // TODO relax if possible | 426 | // TODO relax if possible |
| 427 | const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); | 427 | const pages = try aarch64.calcNumberOfPages(@intCast(sect.addr + 12), @intCast(dyld_stub_binder_addr)); |
| 428 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 428 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 429 | const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8); | 429 | const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8); |
| 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( | 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( |
| ... | @@ -679,7 +679,7 @@ pub const ObjcStubsSection = struct { | ... | @@ -679,7 +679,7 @@ pub const ObjcStubsSection = struct { |
| 679 | { | 679 | { |
| 680 | const target = sym.getObjcSelrefsAddress(macho_file); | 680 | const target = sym.getObjcSelrefsAddress(macho_file); |
| 681 | const source = addr; | 681 | const source = addr; |
| 682 | const pages = try aarch64.calcNumberOfPages(source, target); | 682 | const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)); |
| 683 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); | 683 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); |
| 684 | const off = try math.divExact(u12, @truncate(target), 8); | 684 | const off = try math.divExact(u12, @truncate(target), 8); |
| 685 | try writer.writeInt( | 685 | try writer.writeInt( |
| ... | @@ -692,7 +692,7 @@ pub const ObjcStubsSection = struct { | ... | @@ -692,7 +692,7 @@ pub const ObjcStubsSection = struct { |
| 692 | const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); | 692 | const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); |
| 693 | const target = target_sym.getGotAddress(macho_file); | 693 | const target = target_sym.getGotAddress(macho_file); |
| 694 | const source = addr + 2 * @sizeOf(u32); | 694 | const source = addr + 2 * @sizeOf(u32); |
| 695 | const pages = try aarch64.calcNumberOfPages(source, target); | 695 | const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)); |
| 696 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 696 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 697 | const off = try math.divExact(u12, @truncate(target), 8); | 697 | const off = try math.divExact(u12, @truncate(target), 8); |
| 698 | try writer.writeInt( | 698 | try writer.writeInt( |
src/link/MachO/thunks.zig+1-1| ... | @@ -99,7 +99,7 @@ pub const Thunk = struct { | ... | @@ -99,7 +99,7 @@ pub const Thunk = struct { |
| 99 | const sym = macho_file.getSymbol(sym_index); | 99 | const sym = macho_file.getSymbol(sym_index); |
| 100 | const saddr = thunk.getAddress(macho_file) + i * trampoline_size; | 100 | const saddr = thunk.getAddress(macho_file) + i * trampoline_size; |
| 101 | const taddr = sym.getAddress(.{}, macho_file); | 101 | const taddr = sym.getAddress(.{}, macho_file); |
| 102 | const pages = try aarch64.calcNumberOfPages(saddr, taddr); | 102 | const pages = try aarch64.calcNumberOfPages(@intCast(saddr), @intCast(taddr)); |
| 103 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); | 103 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 104 | const off: u12 = @truncate(taddr); | 104 | const off: u12 = @truncate(taddr); |
| 105 | try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); | 105 | try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); |
src/link/aarch64.zig+1-1| ... | @@ -25,7 +25,7 @@ pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void { | ... | @@ -25,7 +25,7 @@ pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void { |
| 25 | mem.writeInt(u32, code, inst.toU32(), .little); | 25 | mem.writeInt(u32, code, inst.toU32(), .little); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 { | 28 | pub fn calcNumberOfPages(saddr: i64, taddr: i64) error{Overflow}!i21 { |
| 29 | const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; | 29 | const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; |
| 30 | const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; | 30 | const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; |
| 31 | const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; | 31 | const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; |