| ... | @@ -843,6 +843,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { | ... | @@ -843,6 +843,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 843 | sym.name_offset = name_off; | 843 | sym.name_offset = name_off; |
| 844 | esym.st_name = name_off; | 844 | esym.st_name = name_off; |
| 845 | esym.st_info |= elf.STT_FILE; | 845 | esym.st_info |= elf.STT_FILE; |
| | 846 | esym.st_shndx = elf.SHN_ABS; |
| 846 | } | 847 | } |
| 847 | } | 848 | } |
| 848 | } | 849 | } |
| ... | @@ -1299,22 +1300,19 @@ fn parseObject(self: *Elf, in_file: std.fs.File, path: []const u8, ctx: *ParseEr | ... | @@ -1299,22 +1300,19 @@ fn parseObject(self: *Elf, in_file: std.fs.File, path: []const u8, ctx: *ParseEr |
| 1299 | | 1300 | |
| 1300 | const gpa = self.base.allocator; | 1301 | const gpa = self.base.allocator; |
| 1301 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); | 1302 | const data = try in_file.readToEndAlloc(gpa, std.math.maxInt(u32)); |
| 1302 | const index = @as(File.Index, @intCast(self.files.slice().len)); | 1303 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1303 | | 1304 | self.files.set(index, .{ .object = .{ |
| 1304 | var object = Object{ | | |
| 1305 | .path = path, | 1305 | .path = path, |
| 1306 | .data = data, | 1306 | .data = data, |
| 1307 | .index = index, | 1307 | .index = index, |
| 1308 | }; | 1308 | } }); |
| 1309 | errdefer object.deinit(gpa); | 1309 | try self.objects.append(gpa, index); |
| | 1310 | |
| | 1311 | const object = self.file(index).?.object; |
| 1310 | try object.parse(self); | 1312 | try object.parse(self); |
| 1311 | | 1313 | |
| 1312 | ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; | 1314 | ctx.detected_cpu_arch = object.header.?.e_machine.toTargetCpuArch().?; |
| 1313 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; | 1315 | if (ctx.detected_cpu_arch != self.base.options.target.cpu.arch) return error.InvalidCpuArch; |
| 1314 | | | |
| 1315 | _ = try self.files.addOne(gpa); | | |
| 1316 | self.files.set(index, .{ .object = object }); | | |
| 1317 | try self.objects.append(gpa, index); | | |
| 1318 | } | 1316 | } |
| 1319 | | 1317 | |
| 1320 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { | 1318 | fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| ... | @@ -2690,12 +2688,14 @@ pub fn updateDeclExports( | ... | @@ -2690,12 +2688,14 @@ pub fn updateDeclExports( |
| 2690 | break :blk sym_index; | 2688 | break :blk sym_index; |
| 2691 | }; | 2689 | }; |
| 2692 | const sym = self.symbol(sym_index); | 2690 | const sym = self.symbol(sym_index); |
| | 2691 | sym.flags.@"export" = true; |
| 2693 | sym.value = decl_sym.value; | 2692 | sym.value = decl_sym.value; |
| 2694 | sym.atom_index = decl_sym.atom_index; | 2693 | sym.atom_index = decl_sym.atom_index; |
| 2695 | sym.output_section_index = decl_sym.output_section_index; | 2694 | sym.output_section_index = decl_sym.output_section_index; |
| 2696 | const esym = zig_module.sourceSymbol(sym_index, self); | 2695 | const esym = zig_module.sourceSymbol(sym_index, self); |
| 2697 | esym.* = decl_esym; | 2696 | esym.* = decl_esym; |
| 2698 | esym.st_info = (stb_bits << 4) | stt_bits; | 2697 | esym.st_info = (stb_bits << 4) | stt_bits; |
| | 2698 | _ = self.unresolved.swapRemove(sym_index); |
| 2699 | } | 2699 | } |
| 2700 | } | 2700 | } |
| 2701 | | 2701 | |
| ... | @@ -3468,13 +3468,8 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { | ... | @@ -3468,13 +3468,8 @@ pub fn globalByName(self: *Elf, name: []const u8) ?Symbol.Index { |
| 3468 | | 3468 | |
| 3469 | pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { | 3469 | pub fn getGlobalSymbol(self: *Elf, name: []const u8, lib_name: ?[]const u8) !u32 { |
| 3470 | _ = lib_name; | 3470 | _ = lib_name; |
| 3471 | const gpa = self.base.allocator; | 3471 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| 3472 | const name_off = try self.strtab.insert(gpa, name); | 3472 | return zig_module.addGlobal(name, self); |
| 3473 | const gop = try self.getOrPutGlobal(name_off); | | |
| 3474 | if (!gop.found_existing) { | | |
| 3475 | try self.unresolved.putNoClobber(gpa, gop.index, {}); | | |
| 3476 | } | | |
| 3477 | return gop.index; | | |
| 3478 | } | 3473 | } |
| 3479 | | 3474 | |
| 3480 | const GetOrCreateComdatGroupOwnerResult = struct { | 3475 | const GetOrCreateComdatGroupOwnerResult = struct { |
| ... | @@ -3519,42 +3514,83 @@ fn reportUndefined(self: *Elf) !void { | ... | @@ -3519,42 +3514,83 @@ fn reportUndefined(self: *Elf) !void { |
| 3519 | | 3514 | |
| 3520 | try self.misc_errors.ensureUnusedCapacity(gpa, self.unresolved.keys().len); | 3515 | try self.misc_errors.ensureUnusedCapacity(gpa, self.unresolved.keys().len); |
| 3521 | | 3516 | |
| 3522 | for (self.unresolved.keys()) |sym_index| { | 3517 | const CollectStruct = struct { |
| 3523 | const undef_sym = self.symbol(sym_index); | 3518 | notes: [max_notes]link.File.ErrorMsg = [_]link.File.ErrorMsg{.{ .msg = undefined }} ** max_notes, |
| | 3519 | notes_len: u3 = 0, |
| | 3520 | notes_count: usize = 0, |
| | 3521 | }; |
| 3524 | | 3522 | |
| 3525 | var all_notes: usize = 0; | 3523 | const collect: []CollectStruct = try gpa.alloc(CollectStruct, self.unresolved.keys().len); |
| 3526 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, max_notes + 1); | 3524 | defer gpa.free(collect); |
| 3527 | defer notes.deinit(); | 3525 | @memset(collect, .{}); |
| 3528 | | 3526 | |
| 3529 | // Collect all references across all input files | 3527 | // Collect all references across all input files |
| 3530 | if (self.zig_module_index) |index| { | 3528 | if (self.zig_module_index) |index| { |
| 3531 | const zig_module = self.file(index).?.zig_module; | 3529 | const zig_module = self.file(index).?.zig_module; |
| 3532 | for (zig_module.atoms.keys()) |atom_index| { | 3530 | for (zig_module.atoms.keys()) |atom_index| { |
| 3533 | const atom_ptr = self.atom(atom_index).?; | 3531 | const atom_ptr = self.atom(atom_index).?; |
| 3534 | if (!atom_ptr.alive) continue; | 3532 | if (!atom_ptr.alive) continue; |
| 3535 | | 3533 | |
| 3536 | for (atom_ptr.relocs(self)) |rel| { | 3534 | for (atom_ptr.relocs(self)) |rel| { |
| 3537 | if (sym_index == rel.r_sym()) { | 3535 | if (self.unresolved.getIndex(rel.r_sym())) |bin_index| { |
| 3538 | const note = try std.fmt.allocPrint(gpa, "referenced by {s}:{s}", .{ | 3536 | const note = try std.fmt.allocPrint(gpa, "referenced by {s}:{s}", .{ |
| 3539 | zig_module.path, | 3537 | zig_module.path, |
| 3540 | atom_ptr.name(self), | 3538 | atom_ptr.name(self), |
| 3541 | }); | 3539 | }); |
| 3542 | notes.appendAssumeCapacity(.{ .msg = note }); | 3540 | const bin = &collect[bin_index]; |
| 3543 | all_notes += 1; | 3541 | if (bin.notes_len < max_notes) { |
| 3544 | break; | 3542 | bin.notes[bin.notes_len] = .{ .msg = note }; |
| | 3543 | bin.notes_len += 1; |
| 3545 | } | 3544 | } |
| | 3545 | bin.notes_count += 1; |
| 3546 | } | 3546 | } |
| 3547 | } | 3547 | } |
| 3548 | } | 3548 | } |
| | 3549 | } |
| | 3550 | |
| | 3551 | for (self.objects.items) |index| { |
| | 3552 | const object = self.file(index).?.object; |
| | 3553 | for (object.atoms.items) |atom_index| { |
| | 3554 | const atom_ptr = self.atom(atom_index) orelse continue; |
| | 3555 | if (!atom_ptr.alive) continue; |
| | 3556 | |
| | 3557 | for (atom_ptr.relocs(self)) |rel| { |
| | 3558 | const sym_index = object.symbols.items[rel.r_sym()]; |
| | 3559 | if (self.unresolved.getIndex(sym_index)) |bin_index| { |
| | 3560 | const note = try std.fmt.allocPrint(gpa, "referenced by {}:{s}", .{ |
| | 3561 | object.fmtPath(), |
| | 3562 | atom_ptr.name(self), |
| | 3563 | }); |
| | 3564 | const bin = &collect[bin_index]; |
| | 3565 | if (bin.notes_len < max_notes) { |
| | 3566 | bin.notes[bin.notes_len] = .{ .msg = note }; |
| | 3567 | bin.notes_len += 1; |
| | 3568 | } |
| | 3569 | bin.notes_count += 1; |
| | 3570 | } |
| | 3571 | } |
| | 3572 | } |
| | 3573 | } |
| | 3574 | |
| | 3575 | // Generate error notes |
| | 3576 | for (self.unresolved.keys(), 0..) |sym_index, bin_index| { |
| | 3577 | const collected = &collect[bin_index]; |
| | 3578 | |
| | 3579 | var notes = try std.ArrayList(link.File.ErrorMsg).initCapacity(gpa, max_notes + 1); |
| | 3580 | defer notes.deinit(); |
| | 3581 | |
| | 3582 | for (collected.notes[0..collected.notes_len]) |note| { |
| | 3583 | notes.appendAssumeCapacity(note); |
| | 3584 | } |
| 3549 | | 3585 | |
| 3550 | if (all_notes > max_notes) { | 3586 | if (collected.notes_count > max_notes) { |
| 3551 | const remaining = all_notes - max_notes; | 3587 | const remaining = collected.notes_count - max_notes; |
| 3552 | const note = try std.fmt.allocPrint(gpa, "referenced {d} more times", .{remaining}); | 3588 | const note = try std.fmt.allocPrint(gpa, "referenced {d} more times", .{remaining}); |
| 3553 | notes.appendAssumeCapacity(.{ .msg = note }); | 3589 | notes.appendAssumeCapacity(.{ .msg = note }); |
| 3554 | } | 3590 | } |
| 3555 | | 3591 | |
| 3556 | var err_msg = link.File.ErrorMsg{ | 3592 | var err_msg = link.File.ErrorMsg{ |
| 3557 | .msg = try std.fmt.allocPrint(gpa, "undefined symbol: {s}", .{undef_sym.name(self)}), | 3593 | .msg = try std.fmt.allocPrint(gpa, "undefined symbol: {s}", .{self.symbol(sym_index).name(self)}), |
| 3558 | }; | 3594 | }; |
| 3559 | err_msg.notes = try notes.toOwnedSlice(); | 3595 | err_msg.notes = try notes.toOwnedSlice(); |
| 3560 | | 3596 | |