authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-16 14:25:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-04-20 23:36:41+02:00
log9e0bca73e2ae8c29873c7280f28ce58502e6abab
tree3fd87d1fd8eca202b357d134327f90dbd1aa177e
parent09820a96b691f79403291d9b2179adbae50fc33b

link/elf: implement string merging


14 files changed, 711 insertions(+), 226 deletions(-)

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