| 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 | 210 | /// List of range extension thunks. |
| 211 | 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 | 221 | /// Table of last atom index in a section and matching atom free list if any. |
| 214 | 222 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 215 | 223 | |
| ... | ... | @@ -380,6 +388,8 @@ pub fn createEmpty( |
| 380 | 388 | _ = try self.addSection(.{ .name = "" }); |
| 381 | 389 | // Append null symbol in output symtab |
| 382 | 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 | 394 | if (!is_obj_or_ar) { |
| 385 | 395 | try self.dynstrtab.append(gpa, 0); |
| ... | ... | @@ -498,6 +508,15 @@ pub fn deinit(self: *Elf) void { |
| 498 | 508 | th.deinit(gpa); |
| 499 | 509 | } |
| 500 | 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 | 520 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 502 | 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 | 1314 | // symbol for potential resolution at load-time. |
| 1296 | 1315 | self.resolveSymbols(); |
| 1297 | 1316 | self.markEhFrameAtomsDead(); |
| 1317 | try self.resolveMergeSections(); | |
| 1298 | 1318 | |
| 1299 | 1319 | try self.convertCommonSymbols(); |
| 1300 | 1320 | self.markImportsExports(); |
| ... | ... | @@ -1319,6 +1339,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1319 | 1339 | else => |e| return e, |
| 1320 | 1340 | }; |
| 1321 | 1341 | |
| 1342 | try self.addCommentString(); | |
| 1343 | try self.sortMergeSections(); | |
| 1322 | 1344 | try self.initOutputSections(); |
| 1323 | 1345 | try self.addLinkerDefinedSymbols(); |
| 1324 | 1346 | self.claimUnresolved(); |
| ... | ... | @@ -1338,6 +1360,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1338 | 1360 | self.sortDynamicSymtab(); |
| 1339 | 1361 | try self.setHashSections(); |
| 1340 | 1362 | try self.setVersionSymtab(); |
| 1363 | try self.updateMergeSectionSizes(); | |
| 1341 | 1364 | try self.updateSectionSizes(); |
| 1342 | 1365 | |
| 1343 | 1366 | try self.allocatePhdrTable(); |
| ... | ... | @@ -1365,7 +1388,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1365 | 1388 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1366 | 1389 | const code = try zig_object.codeAlloc(self, atom_index); |
| 1367 | 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 | 1392 | atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) { |
| 1370 | 1393 | error.RelocFailure, error.RelaxFailure => has_reloc_errors = true, |
| 1371 | 1394 | error.UnsupportedCpuArch => { |
| ... | ... | @@ -1383,6 +1406,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) |
| 1383 | 1406 | try self.writePhdrTable(); |
| 1384 | 1407 | try self.writeShdrTable(); |
| 1385 | 1408 | try self.writeAtoms(); |
| 1409 | try self.writeMergeSections(); | |
| 1386 | 1410 | self.writeSyntheticSections() catch |err| switch (err) { |
| 1387 | 1411 | error.RelocFailure => return error.FlushFailure, |
| 1388 | 1412 | error.UnsupportedCpuArch => { |
| ... | ... | @@ -2952,7 +2976,10 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2952 | 2976 | mem.writeInt(u32, hdr_buf[index..][0..4], 1, endian); |
| 2953 | 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 | 2983 | const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; |
| 2957 | 2984 | switch (self.ptr_width) { |
| 2958 | 2985 | .p32 => { |
| ... | ... | @@ -3138,14 +3165,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3138 | 3165 | if (self.dynamic_section_index) |shndx| { |
| 3139 | 3166 | const shdr = &self.shdrs.items[shndx]; |
| 3140 | 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 | 3169 | symbol_ptr.output_section_index = shndx; |
| 3143 | 3170 | } |
| 3144 | 3171 | |
| 3145 | 3172 | // __ehdr_start |
| 3146 | 3173 | { |
| 3147 | 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 | 3176 | symbol_ptr.output_section_index = 1; |
| 3150 | 3177 | } |
| 3151 | 3178 | |
| ... | ... | @@ -3155,9 +3182,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3155 | 3182 | const end_sym = self.symbol(self.init_array_end_index.?); |
| 3156 | 3183 | const shdr = &self.shdrs.items[shndx]; |
| 3157 | 3184 | start_sym.output_section_index = shndx; |
| 3158 | start_sym.value = shdr.sh_addr; | |
| 3185 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3159 | 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 | 3190 | // __fini_array_start, __fini_array_end |
| ... | ... | @@ -3166,9 +3193,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3166 | 3193 | const end_sym = self.symbol(self.fini_array_end_index.?); |
| 3167 | 3194 | const shdr = &self.shdrs.items[shndx]; |
| 3168 | 3195 | start_sym.output_section_index = shndx; |
| 3169 | start_sym.value = shdr.sh_addr; | |
| 3196 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3170 | 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 | 3201 | // __preinit_array_start, __preinit_array_end |
| ... | ... | @@ -3177,9 +3204,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3177 | 3204 | const end_sym = self.symbol(self.preinit_array_end_index.?); |
| 3178 | 3205 | const shdr = &self.shdrs.items[shndx]; |
| 3179 | 3206 | start_sym.output_section_index = shndx; |
| 3180 | start_sym.value = shdr.sh_addr; | |
| 3207 | start_sym.value = @intCast(shdr.sh_addr); | |
| 3181 | 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 | 3212 | // _GLOBAL_OFFSET_TABLE_ |
| ... | ... | @@ -3187,14 +3214,14 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3187 | 3214 | if (self.got_plt_section_index) |shndx| { |
| 3188 | 3215 | const shdr = self.shdrs.items[shndx]; |
| 3189 | 3216 | const sym = self.symbol(self.got_index.?); |
| 3190 | sym.value = shdr.sh_addr; | |
| 3217 | sym.value = @intCast(shdr.sh_addr); | |
| 3191 | 3218 | sym.output_section_index = shndx; |
| 3192 | 3219 | } |
| 3193 | 3220 | } else { |
| 3194 | 3221 | if (self.got_section_index) |shndx| { |
| 3195 | 3222 | const shdr = self.shdrs.items[shndx]; |
| 3196 | 3223 | const sym = self.symbol(self.got_index.?); |
| 3197 | sym.value = shdr.sh_addr; | |
| 3224 | sym.value = @intCast(shdr.sh_addr); | |
| 3198 | 3225 | sym.output_section_index = shndx; |
| 3199 | 3226 | } |
| 3200 | 3227 | } |
| ... | ... | @@ -3203,7 +3230,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3203 | 3230 | if (self.plt_section_index) |shndx| { |
| 3204 | 3231 | const shdr = &self.shdrs.items[shndx]; |
| 3205 | 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 | 3234 | symbol_ptr.output_section_index = shndx; |
| 3208 | 3235 | } |
| 3209 | 3236 | |
| ... | ... | @@ -3211,7 +3238,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3211 | 3238 | if (self.dso_handle_index) |index| { |
| 3212 | 3239 | const shdr = &self.shdrs.items[1]; |
| 3213 | 3240 | const symbol_ptr = self.symbol(index); |
| 3214 | symbol_ptr.value = shdr.sh_addr; | |
| 3241 | symbol_ptr.value = @intCast(shdr.sh_addr); | |
| 3215 | 3242 | symbol_ptr.output_section_index = 0; |
| 3216 | 3243 | } |
| 3217 | 3244 | |
| ... | ... | @@ -3219,7 +3246,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3219 | 3246 | if (self.eh_frame_hdr_section_index) |shndx| { |
| 3220 | 3247 | const shdr = &self.shdrs.items[shndx]; |
| 3221 | 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 | 3250 | symbol_ptr.output_section_index = shndx; |
| 3224 | 3251 | } |
| 3225 | 3252 | |
| ... | ... | @@ -3231,9 +3258,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3231 | 3258 | const start_addr = end_addr - self.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); |
| 3232 | 3259 | const start_sym = self.symbol(self.rela_iplt_start_index.?); |
| 3233 | 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 | 3262 | start_sym.output_section_index = shndx; |
| 3236 | end_sym.value = end_addr; | |
| 3263 | end_sym.value = @intCast(end_addr); | |
| 3237 | 3264 | end_sym.output_section_index = shndx; |
| 3238 | 3265 | } |
| 3239 | 3266 | |
| ... | ... | @@ -3242,7 +3269,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3242 | 3269 | const end_symbol = self.symbol(self.end_index.?); |
| 3243 | 3270 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 3244 | 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 | 3273 | end_symbol.output_section_index = @intCast(shndx); |
| 3247 | 3274 | } |
| 3248 | 3275 | } |
| ... | ... | @@ -3257,9 +3284,9 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3257 | 3284 | const stop = self.symbol(self.start_stop_indexes.items[index + 1]); |
| 3258 | 3285 | const shndx = self.sectionByName(name["__start_".len..]).?; |
| 3259 | 3286 | const shdr = &self.shdrs.items[shndx]; |
| 3260 | start.value = shdr.sh_addr; | |
| 3287 | start.value = @intCast(shdr.sh_addr); | |
| 3261 | 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 | 3290 | stop.output_section_index = shndx; |
| 3264 | 3291 | } |
| 3265 | 3292 | } |
| ... | ... | @@ -3269,7 +3296,7 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3269 | 3296 | const sym = self.symbol(index); |
| 3270 | 3297 | if (self.sectionByName(".sdata")) |shndx| { |
| 3271 | 3298 | const shdr = self.shdrs.items[shndx]; |
| 3272 | sym.value = shdr.sh_addr + 0x800; | |
| 3299 | sym.value = @intCast(shdr.sh_addr + 0x800); | |
| 3273 | 3300 | sym.output_section_index = shndx; |
| 3274 | 3301 | } else { |
| 3275 | 3302 | sym.value = 0; |
| ... | ... | @@ -3299,10 +3326,109 @@ fn checkDuplicates(self: *Elf) !void { |
| 3299 | 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 | 3417 | fn initOutputSections(self: *Elf) !void { |
| 3303 | 3418 | for (self.objects.items) |index| { |
| 3304 | 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 | 3434 | fn initSyntheticSections(self: *Elf) !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 | 4105 | var output_rela_sections = try self.output_rela_sections.clone(gpa); |
| 3976 | 4106 | defer output_rela_sections.deinit(gpa); |
| ... | ... | @@ -4058,7 +4188,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4058 | 4188 | if (!atom_ptr.flags.alive) continue; |
| 4059 | 4189 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 4060 | 4190 | const padding = offset - shdr.sh_size; |
| 4061 | atom_ptr.value = offset; | |
| 4191 | atom_ptr.value = @intCast(offset); | |
| 4062 | 4192 | shdr.sh_size += padding + atom_ptr.size; |
| 4063 | 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 | 4671 | const atom_ptr = self.atom(atom_index).?; |
| 4542 | 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 | 4675 | return error.Overflow; |
| 4546 | 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 | 4712 | const thunk_size = th.size(self); |
| 4583 | 4713 | try buffer.ensureUnusedCapacity(thunk_size); |
| 4584 | 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 | 4716 | try th.write(self, buffer.writer()); |
| 4587 | 4717 | assert(buffer.items.len == thunk_size); |
| 4588 | 4718 | try self.base.file.?.pwriteAll(buffer.items, offset); |
| ... | ... | @@ -4617,6 +4747,7 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4617 | 4747 | if (self.eh_frame_section_index) |_| { |
| 4618 | 4748 | nlocals += 1; |
| 4619 | 4749 | } |
| 4750 | nlocals += @intCast(self.merge_sections.items.len); | |
| 4620 | 4751 | |
| 4621 | 4752 | if (self.requiresThunks()) for (self.thunks.items) |*th| { |
| 4622 | 4753 | th.output_symtab_ctx.ilocal = nlocals + 1; |
| ... | ... | @@ -4953,12 +5084,29 @@ fn writeSectionSymbols(self: *Elf) void { |
| 4953 | 5084 | }; |
| 4954 | 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 | 5103 | pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { |
| 4959 | 5104 | if (self.eh_frame_section_index) |index| { |
| 4960 | 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 | 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 | 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 | 5891 | const shndx = blk: { |
| 5692 | 5892 | if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null) |
| 5693 | 5893 | break :blk self.got_plt_section_index.?; |
| 5694 | 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 | 5900 | const index = self.phdr_tls_index orelse return 0; |
| 5701 | 5901 | const phdr = self.phdrs.items[index]; |
| 5702 | return switch (self.getTarget().cpu.arch) { | |
| 5902 | const addr = switch (self.getTarget().cpu.arch) { | |
| 5703 | 5903 | .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), |
| 5704 | 5904 | .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), |
| 5705 | 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 | 5911 | const index = self.phdr_tls_index orelse return 0; |
| 5711 | 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 | 5917 | const index = self.phdr_tls_index orelse return 0; |
| 5717 | 5918 | const phdr = self.phdrs.items[index]; |
| 5718 | return phdr.p_vaddr; | |
| 5919 | return @intCast(phdr.p_vaddr); | |
| 5719 | 5920 | } |
| 5720 | 5921 | |
| 5721 | 5922 | const ErrorWithNotes = struct { |
| ... | ... | @@ -6093,6 +6294,11 @@ fn fmtDumpState( |
| 6093 | 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 | 6302 | try writer.writeAll("\nOutput shdrs\n"); |
| 6097 | 6303 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 6098 | 6304 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| ... | ... | @@ -6285,6 +6491,7 @@ const gc = @import("Elf/gc.zig"); |
| 6285 | 6491 | const glibc = @import("../glibc.zig"); |
| 6286 | 6492 | const link = @import("../link.zig"); |
| 6287 | 6493 | const lldMain = @import("../main.zig").lldMain; |
| 6494 | const merge_section = @import("Elf/merge_section.zig"); | |
| 6288 | 6495 | const musl = @import("../musl.zig"); |
| 6289 | 6496 | const relocatable = @import("Elf/relocatable.zig"); |
| 6290 | 6497 | const relocation = @import("Elf/relocation.zig"); |
| ... | ... | @@ -6310,10 +6517,13 @@ const GnuHashSection = synthetic_sections.GnuHashSection; |
| 6310 | 6517 | const GotSection = synthetic_sections.GotSection; |
| 6311 | 6518 | const GotPltSection = synthetic_sections.GotPltSection; |
| 6312 | 6519 | const HashSection = synthetic_sections.HashSection; |
| 6520 | const InputMergeSection = merge_section.InputMergeSection; | |
| 6313 | 6521 | const LdScript = @import("Elf/LdScript.zig"); |
| 6314 | 6522 | const LinkerDefined = @import("Elf/LinkerDefined.zig"); |
| 6315 | 6523 | const Liveness = @import("../Liveness.zig"); |
| 6316 | 6524 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 6525 | const MergeSection = merge_section.MergeSection; | |
| 6526 | const MergeSubsection = merge_section.MergeSubsection; | |
| 6317 | 6527 | const Module = @import("../Module.zig"); |
| 6318 | 6528 | const Object = @import("Elf/Object.zig"); |
| 6319 | 6529 | const InternPool = @import("../InternPool.zig"); |
src/link/Elf/Atom.zig+113-86| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | /// Address allocated for this Atom. |
| 2 | value: u64 = 0, | |
| 2 | value: i64 = 0, | |
| 3 | 3 | |
| 4 | 4 | /// Name of this Atom. |
| 5 | 5 | name_offset: u32 = 0, |
| ... | ... | @@ -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 | 48 | const shndx = self.outputShndx() orelse return self.value; |
| 49 | 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 | 65 | pub fn file(self: Atom, elf_file: *Elf) ?File { |
| ... | ... | @@ -91,13 +103,13 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 91 | 103 | next.address(elf_file) |
| 92 | 104 | else |
| 93 | 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 | 109 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 98 | 110 | // No need to keep a free list node for the last block. |
| 99 | 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 | 113 | const ideal_cap = Elf.padToIdeal(self.size); |
| 102 | 114 | if (cap <= ideal_cap) return false; |
| 103 | 115 | const surplus = cap - ideal_cap; |
| ... | ... | @@ -130,8 +142,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 130 | 142 | // Is it enough that we could fit this new atom? |
| 131 | 143 | const cap = big_atom.capacity(elf_file); |
| 132 | 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; | |
| 134 | const capacity_end_vaddr = big_atom.value + cap; | |
| 145 | const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity; | |
| 146 | const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap; | |
| 135 | 147 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; |
| 136 | 148 | const new_start_vaddr = self.alignment.backward(new_start_vaddr_unaligned); |
| 137 | 149 | if (new_start_vaddr < ideal_capacity_end_vaddr) { |
| ... | ... | @@ -156,14 +168,14 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 156 | 168 | if (!keep_free_list_node) { |
| 157 | 169 | free_list_removal = i; |
| 158 | 170 | } |
| 159 | break :blk new_start_vaddr; | |
| 171 | break :blk @intCast(new_start_vaddr); | |
| 160 | 172 | } else if (elf_file.atom(last_atom_index.*)) |last| { |
| 161 | 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 | 175 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); |
| 164 | 176 | // Set up the metadata to be updated, after errors are no longer possible. |
| 165 | 177 | atom_placement = last.atom_index; |
| 166 | break :blk new_start_vaddr; | |
| 178 | break :blk @intCast(new_start_vaddr); | |
| 167 | 179 | } else { |
| 168 | 180 | break :blk 0; |
| 169 | 181 | } |
| ... | ... | @@ -173,7 +185,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 173 | 185 | self.atom_index, |
| 174 | 186 | self.name(elf_file), |
| 175 | 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 | 191 | const expand_section = if (atom_placement) |placement_index| |
| ... | ... | @@ -181,7 +193,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 181 | 193 | else |
| 182 | 194 | true; |
| 183 | 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 | 197 | try elf_file.growAllocSection(self.outputShndx().?, needed_size); |
| 186 | 198 | last_atom_index.* = self.atom_index; |
| 187 | 199 | |
| ... | ... | @@ -231,7 +243,7 @@ pub fn shrink(self: *Atom, elf_file: *Elf) void { |
| 231 | 243 | } |
| 232 | 244 | |
| 233 | 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 | 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 | 333 | }; |
| 322 | 334 | const target = elf_file.symbol(target_index); |
| 323 | 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 | 337 | var r_addend = rel.r_addend; |
| 326 | 338 | var r_sym: u32 = 0; |
| 327 | 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 | 344 | r_addend += @intCast(target.address(.{}, elf_file)); |
| 330 | 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 | 427 | }; |
| 413 | 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 | 436 | // Check for violation of One Definition Rule for COMDATs. |
| 416 | 437 | if (symbol.file(elf_file) == null) { |
| 417 | 438 | // TODO convert into an error |
| ... | ... | @@ -424,7 +445,8 @@ pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype |
| 424 | 445 | } |
| 425 | 446 | |
| 426 | 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 | 451 | if (symbol.isIFunc(elf_file)) { |
| 430 | 452 | symbol.flags.needs_got = true; |
| ... | ... | @@ -733,21 +755,21 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi |
| 733 | 755 | // https://intezer.com/blog/malware-analysis/executable-and-linkable-format-101-part-3-relocations/ |
| 734 | 756 | // |
| 735 | 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 | 759 | // Addend from the relocation. |
| 738 | 760 | const A = rel.r_addend; |
| 739 | 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 | 763 | // Address of the global offset table. |
| 742 | const GOT = @as(i64, @intCast(elf_file.gotAddress())); | |
| 764 | const GOT = elf_file.gotAddress(); | |
| 743 | 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 | 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 | 769 | // // Address of the thread pointer. |
| 748 | const TP = @as(i64, @intCast(elf_file.tpAddress())); | |
| 770 | const TP = elf_file.tpAddress(); | |
| 749 | 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 | 774 | relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ |
| 753 | 775 | relocation.fmtRelocType(rel.r_type(), cpu_arch), |
| ... | ... | @@ -804,9 +826,9 @@ fn resolveDynAbsReloc( |
| 804 | 826 | const comp = elf_file.base.comp; |
| 805 | 827 | const gpa = comp.gpa; |
| 806 | 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 | 830 | const A = rel.r_addend; |
| 809 | const S = @as(i64, @intCast(target.address(.{}, elf_file))); | |
| 831 | const S = target.address(.{}, elf_file); | |
| 810 | 832 | const is_writeable = self.inputShdr(elf_file).sh_flags & elf.SHF_WRITE != 0; |
| 811 | 833 | |
| 812 | 834 | const num_dynrelocs = switch (self.file(elf_file).?) { |
| ... | ... | @@ -874,7 +896,7 @@ fn resolveDynAbsReloc( |
| 874 | 896 | }, |
| 875 | 897 | |
| 876 | 898 | .ifunc => { |
| 877 | const S_ = @as(i64, @intCast(target.address(.{ .plt = false }, elf_file))); | |
| 899 | const S_ = target.address(.{ .plt = false }, elf_file); | |
| 878 | 900 | elf_file.addRelaDynAssumeCapacity(.{ |
| 879 | 901 | .offset = P, |
| 880 | 902 | .type = relocation.encode(.irel, cpu_arch), |
| ... | ... | @@ -914,6 +936,11 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 914 | 936 | else => unreachable, |
| 915 | 937 | }; |
| 916 | 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 | 945 | // Check for violation of One Definition Rule for COMDATs. |
| 919 | 946 | if (target.file(elf_file) == null) { |
| ... | ... | @@ -927,20 +954,21 @@ pub fn resolveRelocsNonAlloc(self: Atom, elf_file: *Elf, code: []u8, undefs: any |
| 927 | 954 | } |
| 928 | 955 | |
| 929 | 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 | 960 | // We will use equation format to resolve relocations: |
| 933 | 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 | 964 | // Addend from the relocation. |
| 937 | 965 | const A = rel.r_addend; |
| 938 | 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 | 968 | // Address of the global offset table. |
| 941 | const GOT = @as(i64, @intCast(elf_file.gotAddress())); | |
| 969 | const GOT = elf_file.gotAddress(); | |
| 942 | 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 | 973 | const args = ResolveArgs{ P, A, S, GOT, 0, 0, DTP, 0 }; |
| 946 | 974 | |
| ... | ... | @@ -1261,10 +1289,10 @@ const x86_64 = struct { |
| 1261 | 1289 | |
| 1262 | 1290 | .TLSGD => { |
| 1263 | 1291 | if (target.flags.has_tlsgd) { |
| 1264 | const S_ = @as(i64, @intCast(target.tlsGdAddress(elf_file))); | |
| 1292 | const S_ = target.tlsGdAddress(elf_file); | |
| 1265 | 1293 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1266 | 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 | 1296 | try x86_64.relaxTlsGdToIe(atom, &.{ rel, it.next().? }, @intCast(S_ - P), elf_file, stream); |
| 1269 | 1297 | } else { |
| 1270 | 1298 | try x86_64.relaxTlsGdToLe( |
| ... | ... | @@ -1280,13 +1308,13 @@ const x86_64 = struct { |
| 1280 | 1308 | .TLSLD => { |
| 1281 | 1309 | if (elf_file.got.tlsld_index) |entry_index| { |
| 1282 | 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 | 1312 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1285 | 1313 | } else { |
| 1286 | 1314 | try x86_64.relaxTlsLdToLe( |
| 1287 | 1315 | atom, |
| 1288 | 1316 | &.{ rel, it.next().? }, |
| 1289 | @as(i32, @intCast(TP - @as(i64, @intCast(elf_file.tlsAddress())))), | |
| 1317 | @as(i32, @intCast(TP - elf_file.tlsAddress())), | |
| 1290 | 1318 | elf_file, |
| 1291 | 1319 | stream, |
| 1292 | 1320 | ); |
| ... | ... | @@ -1295,7 +1323,7 @@ const x86_64 = struct { |
| 1295 | 1323 | |
| 1296 | 1324 | .GOTPC32_TLSDESC => { |
| 1297 | 1325 | if (target.flags.has_tlsdesc) { |
| 1298 | const S_ = @as(i64, @intCast(target.tlsDescAddress(elf_file))); | |
| 1326 | const S_ = target.tlsDescAddress(elf_file); | |
| 1299 | 1327 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1300 | 1328 | } else { |
| 1301 | 1329 | x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch { |
| ... | ... | @@ -1319,7 +1347,7 @@ const x86_64 = struct { |
| 1319 | 1347 | |
| 1320 | 1348 | .GOTTPOFF => { |
| 1321 | 1349 | if (target.flags.has_gottp) { |
| 1322 | const S_ = @as(i64, @intCast(target.gotTpAddress(elf_file))); | |
| 1350 | const S_ = target.gotTpAddress(elf_file); | |
| 1323 | 1351 | try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); |
| 1324 | 1352 | } else { |
| 1325 | 1353 | x86_64.relaxGotTpOff(code[r_offset - 3 ..]); |
| ... | ... | @@ -1362,9 +1390,18 @@ const x86_64 = struct { |
| 1362 | 1390 | .@"16" => try cwriter.writeInt(u16, @as(u16, @bitCast(@as(i16, @intCast(S + A)))), .little), |
| 1363 | 1391 | .@"32" => try cwriter.writeInt(u32, @as(u32, @bitCast(@as(i32, @intCast(S + A)))), .little), |
| 1364 | 1392 | .@"32S" => try cwriter.writeInt(i32, @as(i32, @intCast(S + A)), .little), |
| 1365 | .@"64" => try cwriter.writeInt(i64, S + A, .little), | |
| 1366 | .DTPOFF32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - DTP)), .little), | |
| 1367 | .DTPOFF64 => try cwriter.writeInt(i64, S + A - DTP, .little), | |
| 1393 | .@"64" => if (atom.debugTombstoneValue(target.*, elf_file)) |value| | |
| 1394 | try cwriter.writeInt(u64, value, .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 | 1405 | .GOTOFF64 => try cwriter.writeInt(i64, S + A - GOT, .little), |
| 1369 | 1406 | .GOTPC64 => try cwriter.writeInt(i64, GOT + A, .little), |
| 1370 | 1407 | .SIZE32 => { |
| ... | ... | @@ -1746,7 +1783,7 @@ const aarch64 = struct { |
| 1746 | 1783 | .object => |x| x.symbols.items[rel.r_sym()], |
| 1747 | 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 | 1787 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; |
| 1751 | 1788 | }; |
| 1752 | 1789 | aarch64_util.writeBranchImm(disp, code); |
| ... | ... | @@ -1764,16 +1801,12 @@ const aarch64 = struct { |
| 1764 | 1801 | |
| 1765 | 1802 | .ADR_PREL_PG_HI21 => { |
| 1766 | 1803 | // TODO: check for relaxation of ADRP+ADD |
| 1767 | const saddr = @as(u64, @intCast(P)); | |
| 1768 | const taddr = @as(u64, @intCast(S + A)); | |
| 1769 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr))); | |
| 1804 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, S + A))); | |
| 1770 | 1805 | aarch64_util.writeAdrpInst(pages, code); |
| 1771 | 1806 | }, |
| 1772 | 1807 | |
| 1773 | 1808 | .ADR_GOT_PAGE => if (target.flags.has_got) { |
| 1774 | const saddr = @as(u64, @intCast(P)); | |
| 1775 | const taddr = @as(u64, @intCast(G + GOT + A)); | |
| 1776 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr))); | |
| 1809 | const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(P, G + GOT + A))); | |
| 1777 | 1810 | aarch64_util.writeAdrpInst(pages, code); |
| 1778 | 1811 | } else { |
| 1779 | 1812 | // TODO: relax |
| ... | ... | @@ -1828,46 +1861,38 @@ const aarch64 = struct { |
| 1828 | 1861 | }, |
| 1829 | 1862 | |
| 1830 | 1863 | .TLSIE_ADR_GOTTPREL_PAGE21 => { |
| 1831 | const S_: i64 = @intCast(target.gotTpAddress(elf_file)); | |
| 1832 | const saddr: u64 = @intCast(P); | |
| 1833 | const taddr: u64 = @intCast(S_ + A); | |
| 1834 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1835 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | |
| 1864 | const S_ = target.gotTpAddress(elf_file); | |
| 1865 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1866 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); | |
| 1836 | 1867 | aarch64_util.writeAdrpInst(pages, code); |
| 1837 | 1868 | }, |
| 1838 | 1869 | |
| 1839 | 1870 | .TLSIE_LD64_GOTTPREL_LO12_NC => { |
| 1840 | const S_: i64 = @intCast(target.gotTpAddress(elf_file)); | |
| 1841 | const taddr: u64 = @intCast(S_ + A); | |
| 1842 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1843 | const offset: u12 = try math.divExact(u12, @truncate(taddr), 8); | |
| 1871 | const S_ = target.gotTpAddress(elf_file); | |
| 1872 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1873 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); | |
| 1844 | 1874 | aarch64_util.writeLoadStoreRegInst(offset, code); |
| 1845 | 1875 | }, |
| 1846 | 1876 | |
| 1847 | 1877 | .TLSGD_ADR_PAGE21 => { |
| 1848 | const S_: i64 = @intCast(target.tlsGdAddress(elf_file)); | |
| 1849 | const saddr: u64 = @intCast(P); | |
| 1850 | const taddr: u64 = @intCast(S_ + A); | |
| 1851 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1852 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | |
| 1878 | const S_ = target.tlsGdAddress(elf_file); | |
| 1879 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1880 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); | |
| 1853 | 1881 | aarch64_util.writeAdrpInst(pages, code); |
| 1854 | 1882 | }, |
| 1855 | 1883 | |
| 1856 | 1884 | .TLSGD_ADD_LO12_NC => { |
| 1857 | const S_: i64 = @intCast(target.tlsGdAddress(elf_file)); | |
| 1858 | const taddr: u64 = @intCast(S_ + A); | |
| 1859 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1860 | const offset: u12 = @truncate(taddr); | |
| 1885 | const S_ = target.tlsGdAddress(elf_file); | |
| 1886 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1887 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); | |
| 1861 | 1888 | aarch64_util.writeAddImmInst(offset, code); |
| 1862 | 1889 | }, |
| 1863 | 1890 | |
| 1864 | 1891 | .TLSDESC_ADR_PAGE21 => { |
| 1865 | 1892 | if (target.flags.has_tlsdesc) { |
| 1866 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | |
| 1867 | const saddr: u64 = @intCast(P); | |
| 1868 | const taddr: u64 = @intCast(S_ + A); | |
| 1869 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1870 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)); | |
| 1893 | const S_ = target.tlsDescAddress(elf_file); | |
| 1894 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1895 | const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(P, S_ + A)); | |
| 1871 | 1896 | aarch64_util.writeAdrpInst(pages, code); |
| 1872 | 1897 | } else { |
| 1873 | 1898 | relocs_log.debug(" relaxing adrp => nop", .{}); |
| ... | ... | @@ -1877,10 +1902,9 @@ const aarch64 = struct { |
| 1877 | 1902 | |
| 1878 | 1903 | .TLSDESC_LD64_LO12 => { |
| 1879 | 1904 | if (target.flags.has_tlsdesc) { |
| 1880 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | |
| 1881 | const taddr: u64 = @intCast(S_ + A); | |
| 1882 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1883 | const offset: u12 = try math.divExact(u12, @truncate(taddr), 8); | |
| 1905 | const S_ = target.tlsDescAddress(elf_file); | |
| 1906 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1907 | const offset: u12 = try math.divExact(u12, @truncate(@as(u64, @bitCast(S_ + A))), 8); | |
| 1884 | 1908 | aarch64_util.writeLoadStoreRegInst(offset, code); |
| 1885 | 1909 | } else { |
| 1886 | 1910 | relocs_log.debug(" relaxing ldr => nop", .{}); |
| ... | ... | @@ -1890,10 +1914,9 @@ const aarch64 = struct { |
| 1890 | 1914 | |
| 1891 | 1915 | .TLSDESC_ADD_LO12 => { |
| 1892 | 1916 | if (target.flags.has_tlsdesc) { |
| 1893 | const S_: i64 = @intCast(target.tlsDescAddress(elf_file)); | |
| 1894 | const taddr: u64 = @intCast(S_ + A); | |
| 1895 | relocs_log.debug(" [{x} => {x}]", .{ P, taddr }); | |
| 1896 | const offset: u12 = @truncate(taddr); | |
| 1917 | const S_ = target.tlsDescAddress(elf_file); | |
| 1918 | relocs_log.debug(" [{x} => {x}]", .{ P, S_ + A }); | |
| 1919 | const offset: u12 = @truncate(@as(u64, @bitCast(S_ + A))); | |
| 1897 | 1920 | aarch64_util.writeAddImmInst(offset, code); |
| 1898 | 1921 | } else { |
| 1899 | 1922 | const old_inst = Instruction{ |
| ... | ... | @@ -1938,7 +1961,6 @@ const aarch64 = struct { |
| 1938 | 1961 | ) !void { |
| 1939 | 1962 | _ = it; |
| 1940 | 1963 | _ = code; |
| 1941 | _ = target; | |
| 1942 | 1964 | |
| 1943 | 1965 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1944 | 1966 | const cwriter = stream.writer(); |
| ... | ... | @@ -1948,7 +1970,10 @@ const aarch64 = struct { |
| 1948 | 1970 | switch (r_type) { |
| 1949 | 1971 | .NONE => unreachable, |
| 1950 | 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 | 1977 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| 1953 | 1978 | } |
| 1954 | 1979 | } |
| ... | ... | @@ -2073,7 +2098,7 @@ const riscv = struct { |
| 2073 | 2098 | const atom_addr = atom.address(elf_file); |
| 2074 | 2099 | const pos = it.pos; |
| 2075 | 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 | 2102 | } else { |
| 2078 | 2103 | // TODO: implement searching forward |
| 2079 | 2104 | var err = try elf_file.addErrorWithNotes(1); |
| ... | ... | @@ -2091,10 +2116,10 @@ const riscv = struct { |
| 2091 | 2116 | .object => |x| elf_file.symbol(x.symbols.items[pair.r_sym()]), |
| 2092 | 2117 | else => unreachable, |
| 2093 | 2118 | }; |
| 2094 | const S_ = @as(i64, @intCast(target_.address(.{}, elf_file))); | |
| 2119 | const S_ = target_.address(.{}, elf_file); | |
| 2095 | 2120 | const A_ = pair.r_addend; |
| 2096 | const P_ = @as(i64, @intCast(atom_addr + pair.r_offset)); | |
| 2097 | const G_ = @as(i64, @intCast(target_.gotAddress(elf_file))) - GOT; | |
| 2121 | const P_ = atom_addr + @as(i64, @intCast(pair.r_offset)); | |
| 2122 | const G_ = target_.gotAddress(elf_file) - GOT; | |
| 2098 | 2123 | const disp = switch (@as(elf.R_RISCV, @enumFromInt(pair.r_type()))) { |
| 2099 | 2124 | .PCREL_HI20 => math.cast(i32, S_ + A_ - P_) orelse return error.Overflow, |
| 2100 | 2125 | .GOT_HI20 => math.cast(i32, G_ + GOT + A_ - P_) orelse return error.Overflow, |
| ... | ... | @@ -2122,7 +2147,6 @@ const riscv = struct { |
| 2122 | 2147 | code: []u8, |
| 2123 | 2148 | stream: anytype, |
| 2124 | 2149 | ) !void { |
| 2125 | _ = target; | |
| 2126 | 2150 | _ = it; |
| 2127 | 2151 | |
| 2128 | 2152 | const r_type: elf.R_RISCV = @enumFromInt(rel.r_type()); |
| ... | ... | @@ -2137,7 +2161,10 @@ const riscv = struct { |
| 2137 | 2161 | .NONE => unreachable, |
| 2138 | 2162 | |
| 2139 | 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 | 2169 | .ADD8 => riscv_util.writeAddend(i8, .add, code[r_offset..][0..1], S + A), |
| 2143 | 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 | 15 | comdat_group_data: std.ArrayListUnmanaged(u32) = .{}, |
| 16 | 16 | relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 17 | 17 | |
| 18 | merge_sections: std.ArrayListUnmanaged(InputMergeSection.Index) = .{}, | |
| 19 | ||
| 18 | 20 | fdes: std.ArrayListUnmanaged(Fde) = .{}, |
| 19 | 21 | cies: std.ArrayListUnmanaged(Cie) = .{}, |
| 20 | 22 | eh_frame_data: std.ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -51,6 +53,7 @@ pub fn deinit(self: *Object, allocator: Allocator) void { |
| 51 | 53 | self.fdes.deinit(allocator); |
| 52 | 54 | self.cies.deinit(allocator); |
| 53 | 55 | self.eh_frame_data.deinit(allocator); |
| 56 | self.merge_sections.deinit(allocator); | |
| 54 | 57 | } |
| 55 | 58 | |
| 56 | 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 | 283 | const name = blk: { |
| 281 | 284 | const name = self.getString(shdr.sh_name); |
| 282 | 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 | 286 | const sh_name_prefixes: []const [:0]const u8 = &.{ |
| 286 | 287 | ".text", ".data.rel.ro", ".data", ".rodata", ".bss.rel.ro", ".bss", |
| 287 | 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 | 336 | const name = self.getString(shdr.sh_name); |
| 336 | 337 | const ignore = blk: { |
| 337 | 338 | if (mem.startsWith(u8, name, ".note")) break :blk true; |
| 338 | if (mem.startsWith(u8, name, ".comment")) break :blk true; | |
| 339 | 339 | if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true; |
| 340 | 340 | if (mem.startsWith(u8, name, ".riscv.attributes")) break :blk true; // TODO: riscv attributes |
| 341 | 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 | 354 | const index = try elf_file.addSymbol(); |
| 355 | 355 | self.symbols.appendAssumeCapacity(index); |
| 356 | 356 | const sym_ptr = elf_file.symbol(index); |
| 357 | sym_ptr.value = sym.st_value; | |
| 357 | sym_ptr.value = @intCast(sym.st_value); | |
| 358 | 358 | sym_ptr.name_offset = sym.st_name; |
| 359 | 359 | sym_ptr.esym_index = @as(u32, @intCast(i)); |
| 360 | 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 | 547 | elf.SHN_ABS, elf.SHN_COMMON => 0, |
| 548 | 548 | else => self.atoms.items[esym.st_shndx], |
| 549 | 549 | }; |
| 550 | global.value = esym.st_value; | |
| 550 | global.value = @intCast(esym.st_value); | |
| 551 | 551 | global.atom_index = atom_index; |
| 552 | 552 | global.esym_index = esym_index; |
| 553 | 553 | global.file_index = self.index; |
| ... | ... | @@ -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 | 829 | /// We will create dummy shdrs per each resolved common symbols to make it |
| 663 | 830 | /// play nicely with the rest of the system. |
| 664 | 831 | pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| ... | ... | @@ -749,6 +916,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 749 | 916 | |
| 750 | 917 | for (self.locals()) |local_index| { |
| 751 | 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 | 924 | const atom = local.atom(elf_file) orelse continue; |
| 753 | 925 | if (!atom.flags.alive) continue; |
| 754 | 926 | local.output_section_index = atom.output_section_index; |
| ... | ... | @@ -756,11 +928,23 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 756 | 928 | |
| 757 | 929 | for (self.globals()) |global_index| { |
| 758 | 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 | 937 | const atom = global.atom(elf_file) orelse continue; |
| 760 | 938 | if (!atom.flags.alive) continue; |
| 761 | if (global.file(elf_file).?.index() != self.index) continue; | |
| 762 | 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 | 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 | 1029 | } |
| 846 | 1030 | |
| 847 | 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 | 1040 | for (self.locals()) |local_index| { |
| 849 | 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 | 1043 | const esym = local.elfSym(elf_file); |
| 852 | 1044 | switch (esym.st_type()) { |
| 853 | 1045 | elf.STT_SECTION => continue, |
| ... | ... | @@ -864,7 +1056,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 864 | 1056 | const global = elf_file.symbol(global_index); |
| 865 | 1057 | const file_ptr = global.file(elf_file) orelse continue; |
| 866 | 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 | 1060 | global.flags.output_symtab = true; |
| 869 | 1061 | if (global.isLocal(elf_file)) { |
| 870 | 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 | 1096 | |
| 905 | 1097 | pub fn locals(self: Object) []const Symbol.Index { |
| 906 | 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 | 1101 | return self.symbols.items[0..end]; |
| 909 | 1102 | } |
| 910 | 1103 | |
| 911 | 1104 | pub fn globals(self: Object) []const Symbol.Index { |
| 912 | 1105 | if (self.symbols.items.len == 0) return &[0]Symbol.Index{}; |
| 913 | const start = self.first_global orelse self.symbols.items.len; | |
| 914 | return self.symbols.items[start..]; | |
| 1106 | assert(self.symbols.items.len >= self.symtab.items.len); | |
| 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 | 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 | 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 | 1161 | /// Caller owns the memory. |
| 960 | 1162 | fn preadShdrContentsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, index: u32) ![]u8 { |
| 961 | 1163 | assert(index < self.shdrs.items.len); |
| ... | ... | @@ -1161,5 +1363,6 @@ const Cie = eh_frame.Cie; |
| 1161 | 1363 | const Elf = @import("../Elf.zig"); |
| 1162 | 1364 | const Fde = eh_frame.Fde; |
| 1163 | 1365 | const File = @import("file.zig").File; |
| 1366 | const InputMergeSection = @import("merge_section.zig").InputMergeSection; | |
| 1164 | 1367 | const Symbol = @import("Symbol.zig"); |
| 1165 | 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 | 231 | |
| 232 | 232 | const global = elf_file.symbol(index); |
| 233 | 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 | 235 | global.atom_index = 0; |
| 236 | 236 | global.esym_index = esym_index; |
| 237 | 237 | global.version_index = self.versyms.items[esym_index]; |
src/link/Elf/Symbol.zig+43-21| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | //! Represents a defined symbol. |
| 2 | 2 | |
| 3 | 3 | /// Allocated address value of this symbol. |
| 4 | value: u64 = 0, | |
| 4 | value: i64 = 0, | |
| 5 | 5 | |
| 6 | 6 | /// Offset into the linker's string table. |
| 7 | 7 | name_offset: u32 = 0, |
| ... | ... | @@ -14,7 +14,7 @@ file_index: File.Index = 0, |
| 14 | 14 | /// Use `atom` to get the pointer to the atom. |
| 15 | 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 | 18 | output_section_index: u32 = 0, |
| 19 | 19 | |
| 20 | 20 | /// Index of the source symbol this symbol references. |
| ... | ... | @@ -33,7 +33,8 @@ extra_index: u32 = 0, |
| 33 | 33 | pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool { |
| 34 | 34 | const file_ptr = symbol.file(elf_file).?; |
| 35 | 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 | 38 | file_ptr != .linker_defined; |
| 38 | 39 | } |
| 39 | 40 | |
| ... | ... | @@ -70,6 +71,12 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { |
| 70 | 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 | 80 | pub fn file(symbol: Symbol, elf_file: *Elf) ?File { |
| 74 | 81 | return elf_file.file(symbol.file_index); |
| 75 | 82 | } |
| ... | ... | @@ -92,7 +99,11 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 { |
| 92 | 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 | 107 | if (symbol.flags.has_copy_rel) { |
| 97 | 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 | 119 | if (!atom_ptr.flags.alive) { |
| 109 | 120 | if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) { |
| 110 | 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 | 127 | if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or |
| 112 | 128 | mem.startsWith(u8, sym_name, "__EH_FRAME_LIST__") or |
| 113 | 129 | mem.startsWith(u8, sym_name, ".eh_frame_seg") or |
| 114 | 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 | 135 | if (mem.startsWith(u8, sym_name, "__FRAME_END__") or |
| 120 | 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.?]; | |
| 123 | return shdr.sh_addr + shdr.sh_size; | |
| 138 | return @intCast(sh_addr + sh_size); | |
| 124 | 139 | } |
| 125 | 140 | |
| 126 | 141 | // TODO I think we potentially should error here |
| ... | ... | @@ -143,57 +158,57 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 { |
| 143 | 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 | 162 | if (!symbol.flags.has_got) return 0; |
| 148 | 163 | const extras = symbol.extra(elf_file).?; |
| 149 | 164 | const entry = elf_file.got.entries.items[extras.got]; |
| 150 | 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 | 169 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; |
| 155 | 170 | const extras = symbol.extra(elf_file).?; |
| 156 | 171 | const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?]; |
| 157 | 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 | 177 | if (!symbol.flags.has_plt) return 0; |
| 163 | 178 | const extras = symbol.extra(elf_file).?; |
| 164 | 179 | const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?]; |
| 165 | 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 | 185 | if (!symbol.flags.has_plt) return 0; |
| 171 | 186 | const extras = symbol.extra(elf_file).?; |
| 172 | 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 | 192 | if (!symbol.flags.has_copy_rel) return 0; |
| 178 | 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 | 198 | if (!symbol.flags.has_tlsgd) return 0; |
| 184 | 199 | const extras = symbol.extra(elf_file).?; |
| 185 | 200 | const entry = elf_file.got.entries.items[extras.tlsgd]; |
| 186 | 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 | 205 | if (!symbol.flags.has_gottp) return 0; |
| 191 | 206 | const extras = symbol.extra(elf_file).?; |
| 192 | 207 | const entry = elf_file.got.entries.items[extras.gottp]; |
| 193 | 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 | 212 | if (!symbol.flags.has_tlsdesc) return 0; |
| 198 | 213 | const extras = symbol.extra(elf_file).?; |
| 199 | 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 | 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 | 232 | if (!symbol.flags.has_zig_got) return 0; |
| 218 | 233 | const extras = symbol.extra(elf_file).?; |
| 219 | 234 | return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); |
| ... | ... | @@ -243,6 +258,7 @@ const AddExtraOpts = struct { |
| 243 | 258 | gottp: ?u32 = null, |
| 244 | 259 | tlsdesc: ?u32 = null, |
| 245 | 260 | zig_got: ?u32 = null, |
| 261 | subsection: ?u32 = null, | |
| 246 | 262 | }; |
| 247 | 263 | |
| 248 | 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 | 296 | if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?); |
| 281 | 297 | if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; |
| 282 | 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 | 300 | if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS; |
| 284 | 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 | 315 | out.st_info = (st_bind << 4) | st_type; |
| 299 | 316 | out.st_other = esym.st_other; |
| 300 | 317 | out.st_shndx = st_shndx; |
| 301 | out.st_value = st_value; | |
| 318 | out.st_value = @intCast(st_value); | |
| 302 | 319 | out.st_size = esym.st_size; |
| 303 | 320 | } |
| 304 | 321 | |
| ... | ... | @@ -450,6 +467,9 @@ pub const Flags = packed struct { |
| 450 | 467 | /// TODO this is really not needed if only we operated on esyms between |
| 451 | 468 | /// codegen and ZigObject. |
| 452 | 469 | is_tls: bool = false, |
| 470 | ||
| 471 | /// Whether the symbol is a merge subsection. | |
| 472 | merge_subsection: bool = false, | |
| 453 | 473 | }; |
| 454 | 474 | |
| 455 | 475 | pub const Extra = struct { |
| ... | ... | @@ -463,6 +483,7 @@ pub const Extra = struct { |
| 463 | 483 | gottp: u32 = 0, |
| 464 | 484 | tlsdesc: u32 = 0, |
| 465 | 485 | zig_got: u32 = 0, |
| 486 | subsection: u32 = 0, | |
| 466 | 487 | }; |
| 467 | 488 | |
| 468 | 489 | pub const Index = u32; |
| ... | ... | @@ -479,6 +500,7 @@ const File = @import("file.zig").File; |
| 479 | 500 | const GotSection = synthetic_sections.GotSection; |
| 480 | 501 | const GotPltSection = synthetic_sections.GotPltSection; |
| 481 | 502 | const LinkerDefined = @import("LinkerDefined.zig"); |
| 503 | const MergeSubsection = @import("merge_section.zig").MergeSubsection; | |
| 482 | 504 | const Object = @import("Object.zig"); |
| 483 | 505 | const PltSection = synthetic_sections.PltSection; |
| 484 | 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 | 343 | atom.outputShndx().? |
| 344 | 344 | else |
| 345 | 345 | elf.SHN_UNDEF; |
| 346 | global.value = esym.st_value; | |
| 346 | global.value = @intCast(esym.st_value); | |
| 347 | 347 | global.atom_index = atom_index; |
| 348 | 348 | global.esym_index = esym_index; |
| 349 | 349 | global.file_index = self.index; |
| ... | ... | @@ -631,7 +631,7 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 |
| 631 | 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 | 635 | const size = std.math.cast(usize, atom.size) orelse return error.Overflow; |
| 636 | 636 | const code = try gpa.alloc(u8, size); |
| 637 | 637 | errdefer gpa.free(code); |
| ... | ... | @@ -659,7 +659,7 @@ pub fn getDeclVAddr( |
| 659 | 659 | .r_info = (@as(u64, @intCast(this_sym.esym_index)) << 32) | r_type, |
| 660 | 660 | .r_addend = reloc_info.addend, |
| 661 | 661 | }); |
| 662 | return vaddr; | |
| 662 | return @intCast(vaddr); | |
| 663 | 663 | } |
| 664 | 664 | |
| 665 | 665 | pub fn getAnonDeclVAddr( |
| ... | ... | @@ -678,7 +678,7 @@ pub fn getAnonDeclVAddr( |
| 678 | 678 | .r_info = (@as(u64, @intCast(sym.esym_index)) << 32) | r_type, |
| 679 | 679 | .r_addend = reloc_info.addend, |
| 680 | 680 | }); |
| 681 | return vaddr; | |
| 681 | return @intCast(vaddr); | |
| 682 | 682 | } |
| 683 | 683 | |
| 684 | 684 | pub fn lowerAnonDecl( |
| ... | ... | @@ -929,7 +929,7 @@ fn updateDeclCode( |
| 929 | 929 | |
| 930 | 930 | if (old_size > 0 and elf_file.base.child_pid == null) { |
| 931 | 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 | 933 | if (need_realloc) { |
| 934 | 934 | try atom_ptr.grow(elf_file); |
| 935 | 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 | 984 | |
| 985 | 985 | const shdr = elf_file.shdrs.items[shdr_index]; |
| 986 | 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 | 988 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 989 | 989 | } |
| 990 | 990 | } |
| ... | ... | @@ -1107,7 +1107,7 @@ pub fn updateFunc( |
| 1107 | 1107 | try self.dwarf.?.commitDeclState( |
| 1108 | 1108 | mod, |
| 1109 | 1109 | decl_index, |
| 1110 | sym.address(.{}, elf_file), | |
| 1110 | @intCast(sym.address(.{}, elf_file)), | |
| 1111 | 1111 | sym.atom(elf_file).?.size, |
| 1112 | 1112 | ds, |
| 1113 | 1113 | ); |
| ... | ... | @@ -1186,7 +1186,7 @@ pub fn updateDecl( |
| 1186 | 1186 | try self.dwarf.?.commitDeclState( |
| 1187 | 1187 | mod, |
| 1188 | 1188 | decl_index, |
| 1189 | sym.address(.{}, elf_file), | |
| 1189 | @intCast(sym.address(.{}, elf_file)), | |
| 1190 | 1190 | sym.atom(elf_file).?.size, |
| 1191 | 1191 | ds, |
| 1192 | 1192 | ); |
| ... | ... | @@ -1275,7 +1275,7 @@ fn updateLazySymbol( |
| 1275 | 1275 | } |
| 1276 | 1276 | |
| 1277 | 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 | 1279 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1280 | 1280 | } |
| 1281 | 1281 | |
| ... | ... | @@ -1373,7 +1373,7 @@ fn lowerConst( |
| 1373 | 1373 | local_esym.st_value = 0; |
| 1374 | 1374 | |
| 1375 | 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 | 1377 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1378 | 1378 | |
| 1379 | 1379 | return .{ .ok = sym_index }; |
| ... | ... | @@ -1457,7 +1457,7 @@ pub fn updateExports( |
| 1457 | 1457 | |
| 1458 | 1458 | const actual_esym_index = global_esym_index & symbol_mask; |
| 1459 | 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 | 1461 | global_esym.st_shndx = esym.st_shndx; |
| 1462 | 1462 | global_esym.st_info = (stb_bits << 4) | stt_bits; |
| 1463 | 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 | 68 | } |
| 69 | 69 | |
| 70 | 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 | 75 | const atom = sym.atom(elf_file) orelse return; |
| 72 | 76 | if (markAtom(atom)) try roots.append(atom); |
| 73 | 77 | } |
| ... | ... | @@ -96,6 +100,10 @@ fn markLive(atom: *Atom, elf_file: *Elf) void { |
| 96 | 100 | |
| 97 | 101 | for (atom.relocs(elf_file)) |rel| { |
| 98 | 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 | 107 | const target_atom = target_sym.atom(elf_file) orelse continue; |
| 100 | 108 | target_atom.flags.alive = true; |
| 101 | 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 | 181 | elf_file.markEhFrameAtomsDead(); |
| 182 | 182 | claimUnresolved(elf_file); |
| 183 | 183 | |
| 184 | try elf_file.addCommentString(); | |
| 185 | try elf_file.sortMergeSections(); | |
| 184 | 186 | try initSections(elf_file); |
| 185 | 187 | try elf_file.sortShdrs(); |
| 186 | 188 | if (elf_file.zigObjectPtr()) |zig_object| { |
| ... | ... | @@ -191,6 +193,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 191 | 193 | try object.addAtomsToOutputSections(elf_file); |
| 192 | 194 | try object.addAtomsToRelaSections(elf_file); |
| 193 | 195 | } |
| 196 | try elf_file.updateMergeSectionSizes(); | |
| 194 | 197 | try updateSectionSizes(elf_file); |
| 195 | 198 | |
| 196 | 199 | try allocateAllocSections(elf_file); |
| ... | ... | @@ -201,6 +204,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 201 | 204 | } |
| 202 | 205 | |
| 203 | 206 | try writeAtoms(elf_file); |
| 207 | try elf_file.writeMergeSections(); | |
| 204 | 208 | try writeSyntheticSections(elf_file); |
| 205 | 209 | try elf_file.writeShdrTable(); |
| 206 | 210 | try elf_file.writeElfHeader(); |
| ... | ... | @@ -275,6 +279,17 @@ fn initSections(elf_file: *Elf) !void { |
| 275 | 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 | 293 | const needs_eh_frame = for (elf_file.objects.items) |index| { |
| 279 | 294 | if (elf_file.file(index).?.object.cies.items.len > 0) break true; |
| 280 | 295 | } else false; |
| ... | ... | @@ -328,7 +343,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 328 | 343 | if (!atom_ptr.flags.alive) continue; |
| 329 | 344 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 330 | 345 | const padding = offset - shdr.sh_size; |
| 331 | atom_ptr.value = offset; | |
| 346 | atom_ptr.value = @intCast(offset); | |
| 332 | 347 | shdr.sh_size += padding + atom_ptr.size; |
| 333 | 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 | 449 | const atom_ptr = elf_file.atom(atom_index).?; |
| 435 | 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 | 453 | return error.Overflow; |
| 439 | 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 | 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 | 274 | _ = zig_got; |
| 275 | 275 | const entry_size = elf_file.archPtrWidthBytes(); |
| 276 | 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 | 280 | pub fn size(zig_got: ZigGotSection, elf_file: *Elf) usize { |
| ... | ... | @@ -291,23 +291,23 @@ pub const ZigGotSection = struct { |
| 291 | 291 | const target = elf_file.getTarget(); |
| 292 | 292 | const endian = target.cpu.arch.endian(); |
| 293 | 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 | 295 | const entry = zig_got.entries.items[index]; |
| 296 | 296 | const value = elf_file.symbol(entry).address(.{}, elf_file); |
| 297 | 297 | switch (entry_size) { |
| 298 | 298 | 2 => { |
| 299 | 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 | 301 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 302 | 302 | }, |
| 303 | 303 | 4 => { |
| 304 | 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 | 306 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 307 | 307 | }, |
| 308 | 308 | 8 => { |
| 309 | 309 | var buf: [8]u8 = undefined; |
| 310 | std.mem.writeInt(u64, &buf, value, endian); | |
| 310 | std.mem.writeInt(u64, &buf, @intCast(value), endian); | |
| 311 | 311 | try elf_file.base.file.?.pwriteAll(&buf, off); |
| 312 | 312 | |
| 313 | 313 | if (elf_file.base.child_pid) |pid| { |
| ... | ... | @@ -356,9 +356,9 @@ pub const ZigGotSection = struct { |
| 356 | 356 | const symbol = elf_file.symbol(entry); |
| 357 | 357 | const offset = symbol.zigGotAddress(elf_file); |
| 358 | 358 | elf_file.addRelaDynAssumeCapacity(.{ |
| 359 | .offset = offset, | |
| 359 | .offset = @intCast(offset), | |
| 360 | 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 | 386 | .st_info = elf.STT_OBJECT, |
| 387 | 387 | .st_other = 0, |
| 388 | 388 | .st_shndx = @intCast(elf_file.zig_got_section_index.?), |
| 389 | .st_value = st_value, | |
| 389 | .st_value = @intCast(st_value), | |
| 390 | 390 | .st_size = st_size, |
| 391 | 391 | }; |
| 392 | 392 | } |
| ... | ... | @@ -457,10 +457,10 @@ pub const GotSection = struct { |
| 457 | 457 | }; |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | pub fn address(entry: Entry, elf_file: *Elf) u64 { | |
| 461 | const ptr_bytes = @as(u64, elf_file.archPtrWidthBytes()); | |
| 460 | pub fn address(entry: Entry, elf_file: *Elf) i64 { | |
| 461 | const ptr_bytes = elf_file.archPtrWidthBytes(); | |
| 462 | 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 | 608 | 0; |
| 609 | 609 | try writeInt(offset, elf_file, writer); |
| 610 | 610 | } else { |
| 611 | const offset = @as(i64, @intCast(symbol.?.address(.{}, elf_file))) - | |
| 612 | @as(i64, @intCast(elf_file.tpAddress())); | |
| 611 | const offset = symbol.?.address(.{}, elf_file) - elf_file.tpAddress(); | |
| 613 | 612 | try writeInt(offset, elf_file, writer); |
| 614 | 613 | } |
| 615 | 614 | }, |
| ... | ... | @@ -620,7 +619,7 @@ pub const GotSection = struct { |
| 620 | 619 | } else { |
| 621 | 620 | try writeInt(0, elf_file, writer); |
| 622 | 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 | 623 | else |
| 625 | 624 | 0; |
| 626 | 625 | try writeInt(offset, elf_file, writer); |
| ... | ... | @@ -646,7 +645,7 @@ pub const GotSection = struct { |
| 646 | 645 | |
| 647 | 646 | switch (entry.tag) { |
| 648 | 647 | .got => { |
| 649 | const offset = symbol.?.gotAddress(elf_file); | |
| 648 | const offset: u64 = @intCast(symbol.?.gotAddress(elf_file)); | |
| 650 | 649 | if (symbol.?.flags.import) { |
| 651 | 650 | elf_file.addRelaDynAssumeCapacity(.{ |
| 652 | 651 | .offset = offset, |
| ... | ... | @@ -659,7 +658,7 @@ pub const GotSection = struct { |
| 659 | 658 | elf_file.addRelaDynAssumeCapacity(.{ |
| 660 | 659 | .offset = offset, |
| 661 | 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 | 663 | continue; |
| 665 | 664 | } |
| ... | ... | @@ -669,14 +668,14 @@ pub const GotSection = struct { |
| 669 | 668 | elf_file.addRelaDynAssumeCapacity(.{ |
| 670 | 669 | .offset = offset, |
| 671 | 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 | 676 | .tlsld => { |
| 678 | 677 | if (is_dyn_lib) { |
| 679 | const offset = entry.address(elf_file); | |
| 678 | const offset: u64 = @intCast(entry.address(elf_file)); | |
| 680 | 679 | elf_file.addRelaDynAssumeCapacity(.{ |
| 681 | 680 | .offset = offset, |
| 682 | 681 | .type = relocation.encode(.dtpmod, cpu_arch), |
| ... | ... | @@ -685,7 +684,7 @@ pub const GotSection = struct { |
| 685 | 684 | }, |
| 686 | 685 | |
| 687 | 686 | .tlsgd => { |
| 688 | const offset = symbol.?.tlsGdAddress(elf_file); | |
| 687 | const offset: u64 = @intCast(symbol.?.tlsGdAddress(elf_file)); | |
| 689 | 688 | if (symbol.?.flags.import) { |
| 690 | 689 | elf_file.addRelaDynAssumeCapacity(.{ |
| 691 | 690 | .offset = offset, |
| ... | ... | @@ -707,7 +706,7 @@ pub const GotSection = struct { |
| 707 | 706 | }, |
| 708 | 707 | |
| 709 | 708 | .gottp => { |
| 710 | const offset = symbol.?.gotTpAddress(elf_file); | |
| 709 | const offset: u64 = @intCast(symbol.?.gotTpAddress(elf_file)); | |
| 711 | 710 | if (symbol.?.flags.import) { |
| 712 | 711 | elf_file.addRelaDynAssumeCapacity(.{ |
| 713 | 712 | .offset = offset, |
| ... | ... | @@ -718,18 +717,18 @@ pub const GotSection = struct { |
| 718 | 717 | elf_file.addRelaDynAssumeCapacity(.{ |
| 719 | 718 | .offset = offset, |
| 720 | 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 | 725 | .tlsdesc => { |
| 727 | const offset = symbol.?.tlsDescAddress(elf_file); | |
| 726 | const offset: u64 = @intCast(symbol.?.tlsDescAddress(elf_file)); | |
| 728 | 727 | elf_file.addRelaDynAssumeCapacity(.{ |
| 729 | 728 | .offset = offset, |
| 730 | 729 | .sym = if (symbol.?.flags.import) extra.?.dynamic else 0, |
| 731 | 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 | 805 | .st_info = elf.STT_OBJECT, |
| 807 | 806 | .st_other = 0, |
| 808 | 807 | .st_shndx = @intCast(elf_file.got_section_index.?), |
| 809 | .st_value = st_value, | |
| 808 | .st_value = @intCast(st_value), | |
| 810 | 809 | .st_size = st_size, |
| 811 | 810 | }; |
| 812 | 811 | } |
| ... | ... | @@ -900,7 +899,7 @@ pub const PltSection = struct { |
| 900 | 899 | const sym = elf_file.symbol(sym_index); |
| 901 | 900 | assert(sym.flags.import); |
| 902 | 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 | 903 | const r_sym: u64 = extra.dynamic; |
| 905 | 904 | const r_type = relocation.encode(.jump_slot, cpu_arch); |
| 906 | 905 | elf_file.rela_plt.appendAssumeCapacity(.{ |
| ... | ... | @@ -936,7 +935,7 @@ pub const PltSection = struct { |
| 936 | 935 | .st_info = elf.STT_FUNC, |
| 937 | 936 | .st_other = 0, |
| 938 | 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 | 939 | .st_size = entrySize(cpu_arch), |
| 941 | 940 | }; |
| 942 | 941 | } |
| ... | ... | @@ -1009,13 +1008,13 @@ pub const PltSection = struct { |
| 1009 | 1008 | const aarch64 = struct { |
| 1010 | 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; | |
| 1013 | const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr; | |
| 1011 | const plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.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 | 1013 | // TODO: relax if possible |
| 1015 | 1014 | // .got.plt[2] |
| 1016 | 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); | |
| 1018 | const add_off: u12 = @truncate(got_plt_addr + 16); | |
| 1016 | const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(got_plt_addr + 16))), 8); | |
| 1017 | const add_off: u12 = @truncate(@as(u64, @bitCast(got_plt_addr + 16))); | |
| 1019 | 1018 | |
| 1020 | 1019 | const preamble = &[_]Instruction{ |
| 1021 | 1020 | Instruction.stp( |
| ... | ... | @@ -1043,8 +1042,8 @@ pub const PltSection = struct { |
| 1043 | 1042 | const target_addr = sym.gotPltAddress(elf_file); |
| 1044 | 1043 | const source_addr = sym.pltAddress(elf_file); |
| 1045 | 1044 | const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr); |
| 1046 | const ldr_off = try math.divExact(u12, @truncate(target_addr), 8); | |
| 1047 | const add_off: u12 = @truncate(target_addr); | |
| 1045 | const ldr_off = try math.divExact(u12, @truncate(@as(u64, @bitCast(target_addr))), 8); | |
| 1046 | const add_off: u12 = @truncate(@as(u64, @bitCast(target_addr))); | |
| 1048 | 1047 | const insts = &[_]Instruction{ |
| 1049 | 1048 | Instruction.adrp(.x16, pages), |
| 1050 | 1049 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)), |
| ... | ... | @@ -1077,7 +1076,7 @@ pub const GotPltSection = struct { |
| 1077 | 1076 | { |
| 1078 | 1077 | // [0]: _DYNAMIC |
| 1079 | 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 | 1081 | // [1]: 0x0 |
| 1083 | 1082 | // [2]: 0x0 |
| ... | ... | @@ -1153,7 +1152,7 @@ pub const PltGotSection = struct { |
| 1153 | 1152 | .st_info = elf.STT_FUNC, |
| 1154 | 1153 | .st_other = 0, |
| 1155 | 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 | 1156 | .st_size = 16, |
| 1158 | 1157 | }; |
| 1159 | 1158 | } |
| ... | ... | @@ -1184,7 +1183,7 @@ pub const PltGotSection = struct { |
| 1184 | 1183 | const target_addr = sym.gotAddress(elf_file); |
| 1185 | 1184 | const source_addr = sym.pltGotAddress(elf_file); |
| 1186 | 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 | 1187 | const insts = &[_]Instruction{ |
| 1189 | 1188 | Instruction.adrp(.x16, pages), |
| 1190 | 1189 | Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)), |
| ... | ... | @@ -1247,9 +1246,9 @@ pub const CopyRelSection = struct { |
| 1247 | 1246 | const symbol = elf_file.symbol(sym_index); |
| 1248 | 1247 | const shared_object = symbol.file(elf_file).?.shared_object; |
| 1249 | 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 | 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 | 1253 | const aliases = shared_object.symbolAliases(sym_index, elf_file); |
| 1255 | 1254 | for (aliases) |alias| { |
| ... | ... | @@ -1270,7 +1269,7 @@ pub const CopyRelSection = struct { |
| 1270 | 1269 | assert(sym.flags.import and sym.flags.has_copy_rel); |
| 1271 | 1270 | const extra = sym.extra(elf_file).?; |
| 1272 | 1271 | elf_file.addRelaDynAssumeCapacity(.{ |
| 1273 | .offset = sym.address(.{}, elf_file), | |
| 1272 | .offset = @intCast(sym.address(.{}, elf_file)), | |
| 1274 | 1273 | .sym = extra.dynamic, |
| 1275 | 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 | assert(atoms.len > 0); |
| 8 | 8 | |
| 9 | 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 | 13 | var i: usize = 0; |
| ... | ... | @@ -22,7 +22,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void { |
| 22 | 22 | const atom_index = atoms[i]; |
| 23 | 23 | const atom = elf_file.atom(atom_index).?; |
| 24 | 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 | 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 | 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 | 65 | const offset = alignment.forward(shdr.sh_size); |
| 65 | 66 | const padding = offset - shdr.sh_size; |
| 66 | 67 | shdr.sh_size += padding + size; |
| 67 | 68 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); |
| 68 | return offset; | |
| 69 | return @intCast(offset); | |
| 69 | 70 | } |
| 70 | 71 | |
| 71 | 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 | 80 | } |
| 80 | 81 | |
| 81 | 82 | pub const Thunk = struct { |
| 82 | value: u64 = 0, | |
| 83 | value: i64 = 0, | |
| 83 | 84 | output_section_index: u32 = 0, |
| 84 | 85 | symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{}, |
| 85 | 86 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| ... | ... | @@ -93,14 +94,14 @@ pub const Thunk = struct { |
| 93 | 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 | 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 | 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 | 107 | pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| ... | ... | @@ -132,7 +133,7 @@ pub const Thunk = struct { |
| 132 | 133 | .st_info = elf.STT_FUNC, |
| 133 | 134 | .st_other = 0, |
| 134 | 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 | 137 | .st_size = trampolineSize(cpu_arch), |
| 137 | 138 | }; |
| 138 | 139 | } |
| ... | ... | @@ -205,9 +206,9 @@ const aarch64 = struct { |
| 205 | 206 | if (target.flags.has_plt) return false; |
| 206 | 207 | if (atom.output_section_index != target.output_section_index) return false; |
| 207 | 208 | const target_atom = target.atom(elf_file).?; |
| 208 | if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false; | |
| 209 | const saddr = @as(i64, @intCast(atom.address(elf_file) + rel.r_offset)); | |
| 210 | const taddr: i64 = @intCast(target.address(.{}, elf_file)); | |
| 209 | if (target_atom.value == -1) return false; | |
| 210 | const saddr = atom.address(elf_file) + @as(i64, @intCast(rel.r_offset)); | |
| 211 | const taddr = target.address(.{}, elf_file); | |
| 211 | 212 | _ = math.cast(i28, taddr + rel.r_addend - saddr) orelse return false; |
| 212 | 213 | return true; |
| 213 | 214 | } |
| ... | ... | @@ -215,11 +216,11 @@ const aarch64 = struct { |
| 215 | 216 | fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void { |
| 216 | 217 | for (thunk.symbols.keys(), 0..) |sym_index, i| { |
| 217 | 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 | 220 | const taddr = sym.address(.{}, elf_file); |
| 220 | 221 | const pages = try util.calcNumberOfPages(saddr, taddr); |
| 221 | 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 | 224 | try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little); |
| 224 | 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 | 770 | }; |
| 771 | 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 | 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 | 267 | }, |
| 268 | 268 | .aarch64 => { |
| 269 | 269 | // TODO relax if possible |
| 270 | const pages = try aarch64.calcNumberOfPages(source, target); | |
| 270 | const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)); | |
| 271 | 271 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 272 | 272 | const off = try math.divExact(u12, @truncate(target), 8); |
| 273 | 273 | try writer.writeInt( |
| ... | ... | @@ -411,7 +411,7 @@ pub const StubsHelperSection = struct { |
| 411 | 411 | .aarch64 => { |
| 412 | 412 | { |
| 413 | 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 | 415 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little); |
| 416 | 416 | const off: u12 = @truncate(dyld_private_addr); |
| 417 | 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); |
| ... | ... | @@ -424,7 +424,7 @@ pub const StubsHelperSection = struct { |
| 424 | 424 | ).toU32(), .little); |
| 425 | 425 | { |
| 426 | 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 | 428 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 429 | 429 | const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8); |
| 430 | 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( |
| ... | ... | @@ -679,7 +679,7 @@ pub const ObjcStubsSection = struct { |
| 679 | 679 | { |
| 680 | 680 | const target = sym.getObjcSelrefsAddress(macho_file); |
| 681 | 681 | const source = addr; |
| 682 | const pages = try aarch64.calcNumberOfPages(source, target); | |
| 682 | const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target)); | |
| 683 | 683 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little); |
| 684 | 684 | const off = try math.divExact(u12, @truncate(target), 8); |
| 685 | 685 | try writer.writeInt( |
| ... | ... | @@ -692,7 +692,7 @@ pub const ObjcStubsSection = struct { |
| 692 | 692 | const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?); |
| 693 | 693 | const target = target_sym.getGotAddress(macho_file); |
| 694 | 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 | 696 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 697 | 697 | const off = try math.divExact(u12, @truncate(target), 8); |
| 698 | 698 | try writer.writeInt( |
src/link/MachO/thunks.zig+1-1| ... | ... | @@ -99,7 +99,7 @@ pub const Thunk = struct { |
| 99 | 99 | const sym = macho_file.getSymbol(sym_index); |
| 100 | 100 | const saddr = thunk.getAddress(macho_file) + i * trampoline_size; |
| 101 | 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 | 103 | try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little); |
| 104 | 104 | const off: u12 = @truncate(taddr); |
| 105 | 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 | 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 | 29 | const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; |
| 30 | 30 | const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; |
| 31 | 31 | const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; |