| ... | ... | @@ -562,7 +562,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void { |
| 562 | 562 | } |
| 563 | 563 | } |
| 564 | 564 | |
| 565 | | pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { |
| 565 | pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { |
| 566 | 566 | const gpa = elf_file.base.comp.gpa; |
| 567 | 567 | |
| 568 | 568 | const first_global = self.first_global orelse return; |
| ... | ... | @@ -585,12 +585,12 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void { |
| 585 | 585 | resolv.* = gop.index; |
| 586 | 586 | |
| 587 | 587 | if (esym.st_shndx == elf.SHN_UNDEF) continue; |
| 588 | | if (elf_file.symbol(gop.ref) == null) { |
| 588 | if (elf_file.symbol(gop.ref.*) == null) { |
| 589 | 589 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; |
| 590 | 590 | continue; |
| 591 | 591 | } |
| 592 | 592 | |
| 593 | | if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref).?.symbolRank(elf_file)) { |
| 593 | if (self.asFile().symbolRank(esym, !self.alive) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) { |
| 594 | 594 | gop.ref.* = .{ .index = @intCast(i), .file = self.index }; |
| 595 | 595 | } |
| 596 | 596 | } |
| ... | ... | @@ -625,34 +625,40 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void { |
| 625 | 625 | |
| 626 | 626 | pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void { |
| 627 | 627 | const first_global = self.first_global orelse return; |
| 628 | | for (self.globals(), 0..) |index, i| { |
| 628 | for (self.globals(), 0..) |*sym, i| { |
| 629 | 629 | const esym_index = @as(u32, @intCast(first_global + i)); |
| 630 | 630 | const esym = self.symtab.items[esym_index]; |
| 631 | 631 | if (esym.st_shndx != elf.SHN_UNDEF) continue; |
| 632 | if (elf_file.symbol(self.resolveSymbol(esym_index, elf_file)) != null) continue; |
| 632 | 633 | |
| 633 | | const global = elf_file.symbol(index); |
| 634 | | if (global.file(elf_file)) |file| { |
| 635 | | if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; |
| 636 | | } |
| 634 | // TODO: audit this |
| 635 | // const global = elf_file.symbol(index); |
| 636 | // if (global.file(elf_file)) |file| { |
| 637 | // if (global.elfSym(elf_file).st_shndx != elf.SHN_UNDEF or file.index() <= self.index) continue; |
| 638 | // } |
| 637 | 639 | |
| 638 | | global.value = 0; |
| 639 | | global.ref = .{ .index = 0, .file = 0 }; |
| 640 | | global.esym_index = esym_index; |
| 641 | | global.file_index = self.index; |
| 640 | sym.value = 0; |
| 641 | sym.ref = .{ .index = 0, .file = 0 }; |
| 642 | sym.esym_index = esym_index; |
| 643 | sym.file_index = self.index; |
| 644 | |
| 645 | const idx = self.symbols_resolver.items[i]; |
| 646 | elf_file.resolver.items[idx - 1] = .{ .index = esym_index, .file = self.index }; |
| 642 | 647 | } |
| 643 | 648 | } |
| 644 | 649 | |
| 645 | 650 | pub fn markLive(self: *Object, elf_file: *Elf) void { |
| 646 | 651 | const first_global = self.first_global orelse return; |
| 647 | | for (self.globals(), 0..) |index, i| { |
| 648 | | const sym_idx = first_global + i; |
| 649 | | const sym = self.symtab.items[sym_idx]; |
| 650 | | if (sym.st_bind() == elf.STB_WEAK) continue; |
| 651 | | |
| 652 | | const global = elf_file.symbol(index); |
| 653 | | const file = global.file(elf_file) orelse continue; |
| 654 | | const should_keep = sym.st_shndx == elf.SHN_UNDEF or |
| 655 | | (sym.st_shndx == elf.SHN_COMMON and global.elfSym(elf_file).st_shndx != elf.SHN_COMMON); |
| 652 | for (0..self.globals().len) |i| { |
| 653 | const esym_idx = first_global + i; |
| 654 | const esym = self.symtab.items[esym_idx]; |
| 655 | if (esym.st_bind() == elf.STB_WEAK) continue; |
| 656 | |
| 657 | const ref = self.resolveSymbol(@intCast(esym_idx), elf_file); |
| 658 | const sym = elf_file.symbol(ref) orelse continue; |
| 659 | const file = sym.file(elf_file).?; |
| 660 | const should_keep = esym.st_shndx == elf.SHN_UNDEF or |
| 661 | (esym.st_shndx == elf.SHN_COMMON and sym.elfSym(elf_file).st_shndx != elf.SHN_COMMON); |
| 656 | 662 | if (should_keep and !file.isAlive()) { |
| 657 | 663 | file.setAlive(); |
| 658 | 664 | file.markLive(elf_file); |
| ... | ... | @@ -672,24 +678,25 @@ pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void { |
| 672 | 678 | |
| 673 | 679 | pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutOfMemory}!void { |
| 674 | 680 | const first_global = self.first_global orelse return; |
| 675 | | for (self.globals(), 0..) |index, i| { |
| 676 | | const sym_idx = first_global + i; |
| 677 | | const sym = self.symtab.items[sym_idx]; |
| 678 | | const global = elf_file.symbol(index); |
| 679 | | const global_file = global.file(elf_file) orelse continue; |
| 680 | | |
| 681 | | if (self.index == global_file.index() or |
| 682 | | sym.st_shndx == elf.SHN_UNDEF or |
| 683 | | sym.st_bind() == elf.STB_WEAK or |
| 684 | | sym.st_shndx == elf.SHN_COMMON) continue; |
| 685 | | |
| 686 | | if (sym.st_shndx != elf.SHN_ABS) { |
| 687 | | const atom_index = self.atoms_indexes.items[sym.st_shndx]; |
| 681 | for (0..self.globals().len) |i| { |
| 682 | const esym_idx = first_global + i; |
| 683 | const esym = self.symtab.items[esym_idx]; |
| 684 | const ref = self.resolveSymbol(@intCast(esym_idx), elf_file); |
| 685 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 686 | const ref_file = ref_sym.file(elf_file).?; |
| 687 | |
| 688 | if (self.index == ref_file.index() or |
| 689 | esym.st_shndx == elf.SHN_UNDEF or |
| 690 | esym.st_bind() == elf.STB_WEAK or |
| 691 | esym.st_shndx == elf.SHN_COMMON) continue; |
| 692 | |
| 693 | if (esym.st_shndx != elf.SHN_ABS) { |
| 694 | const atom_index = self.atoms_indexes.items[esym.st_shndx]; |
| 688 | 695 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 689 | 696 | if (!atom_ptr.alive) continue; |
| 690 | 697 | } |
| 691 | 698 | |
| 692 | | const gop = try dupes.getOrPut(index); |
| 699 | const gop = try dupes.getOrPut(self.symbols_resolver.items[i]); |
| 693 | 700 | if (!gop.found_existing) { |
| 694 | 701 | gop.value_ptr.* = .{}; |
| 695 | 702 | } |
| ... | ... | @@ -819,8 +826,8 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 819 | 826 | } |
| 820 | 827 | |
| 821 | 828 | for (self.symtab.items, 0..) |*esym, idx| { |
| 822 | | const sym_index = self.symbols.items[idx]; |
| 823 | | const sym = elf_file.symbol(sym_index); |
| 829 | const sym = &self.symbols.items[idx]; |
| 830 | // TODO: do we need ref here? |
| 824 | 831 | |
| 825 | 832 | if (esym.st_shndx == elf.SHN_COMMON or esym.st_shndx == elf.SHN_UNDEF or esym.st_shndx == elf.SHN_ABS) continue; |
| 826 | 833 | |
| ... | ... | @@ -860,23 +867,20 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 860 | 867 | return error.MalformedObject; |
| 861 | 868 | }; |
| 862 | 869 | |
| 863 | | const out_sym_idx: u64 = @intCast(self.symbols.items.len); |
| 864 | | try self.symbols.ensureUnusedCapacity(gpa, 1); |
| 870 | const sym_index = try self.addSymbol(gpa); |
| 871 | const sym = &self.symbols.items[sym_index]; |
| 865 | 872 | const name = try std.fmt.allocPrint(gpa, "{s}$subsection{d}", .{ msec.name(elf_file), res.msub_index }); |
| 866 | 873 | defer gpa.free(name); |
| 867 | | const sym_index = try elf_file.addSymbol(); |
| 868 | | const sym = elf_file.symbol(sym_index); |
| 869 | 874 | sym.* = .{ |
| 870 | 875 | .value = @bitCast(@as(i64, @intCast(res.offset)) - rel.r_addend), |
| 871 | 876 | .name_offset = try self.addString(gpa, name), |
| 872 | 877 | .esym_index = rel.r_sym(), |
| 873 | 878 | .file_index = self.index, |
| 874 | | .extra_index = try elf_file.addSymbolExtra(.{}), |
| 879 | .extra_index = try self.addSymbolExtra(gpa, .{}), |
| 875 | 880 | }; |
| 876 | 881 | sym.ref = .{ .index = res.msub_index, .file = imsec.merge_section_index }; |
| 877 | 882 | sym.flags.merge_subsection = true; |
| 878 | | self.symbols.addOneAssumeCapacity().* = sym_index; |
| 879 | | rel.r_info = (out_sym_idx << 32) | rel.r_type(); |
| 883 | rel.r_info = (@as(u64, @intCast(sym_index)) << 32) | rel.r_type(); |
| 880 | 884 | } |
| 881 | 885 | } |
| 882 | 886 | } |
| ... | ... | @@ -885,27 +889,16 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void { |
| 885 | 889 | /// play nicely with the rest of the system. |
| 886 | 890 | pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 887 | 891 | const first_global = self.first_global orelse return; |
| 888 | | for (self.globals(), 0..) |index, i| { |
| 889 | | const sym_idx = @as(u32, @intCast(first_global + i)); |
| 890 | | const this_sym = self.symtab.items[sym_idx]; |
| 891 | | if (this_sym.st_shndx != elf.SHN_COMMON) continue; |
| 892 | | |
| 893 | | const global = elf_file.symbol(index); |
| 894 | | const global_file = global.file(elf_file).?; |
| 895 | | if (global_file.index() != self.index) { |
| 896 | | // if (elf_file.options.warn_common) { |
| 897 | | // elf_file.base.warn("{}: multiple common symbols: {s}", .{ |
| 898 | | // self.fmtPath(), |
| 899 | | // global.getName(elf_file), |
| 900 | | // }); |
| 901 | | // } |
| 902 | | continue; |
| 903 | | } |
| 892 | for (self.globals(), self.symbols_resolver.items, 0..) |*sym, resolv, i| { |
| 893 | const esym_idx = @as(u32, @intCast(first_global + i)); |
| 894 | const esym = self.symtab.items[esym_idx]; |
| 895 | if (esym.st_shndx != elf.SHN_COMMON) continue; |
| 896 | if (elf_file.resolver.get(resolv).?.file != self.index) continue; |
| 904 | 897 | |
| 905 | 898 | const comp = elf_file.base.comp; |
| 906 | 899 | const gpa = comp.gpa; |
| 907 | 900 | |
| 908 | | const is_tls = global.type(elf_file) == elf.STT_TLS; |
| 901 | const is_tls = sym.type(elf_file) == elf.STT_TLS; |
| 909 | 902 | const name = if (is_tls) ".tls_common" else ".common"; |
| 910 | 903 | const name_offset = @as(u32, @intCast(self.strtab.items.len)); |
| 911 | 904 | try self.strtab.writer(gpa).print("{s}\x00", .{name}); |
| ... | ... | @@ -914,7 +907,7 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 914 | 907 | if (is_tls) sh_flags |= elf.SHF_TLS; |
| 915 | 908 | const shndx = @as(u32, @intCast(self.shdrs.items.len)); |
| 916 | 909 | const shdr = try self.shdrs.addOne(gpa); |
| 917 | | const sh_size = math.cast(usize, this_sym.st_size) orelse return error.Overflow; |
| 910 | const sh_size = math.cast(usize, esym.st_size) orelse return error.Overflow; |
| 918 | 911 | shdr.* = .{ |
| 919 | 912 | .sh_name = name_offset, |
| 920 | 913 | .sh_type = elf.SHT_NOBITS, |
| ... | ... | @@ -924,21 +917,21 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 924 | 917 | .sh_size = sh_size, |
| 925 | 918 | .sh_link = 0, |
| 926 | 919 | .sh_info = 0, |
| 927 | | .sh_addralign = this_sym.st_value, |
| 920 | .sh_addralign = esym.st_value, |
| 928 | 921 | .sh_entsize = 0, |
| 929 | 922 | }; |
| 930 | 923 | |
| 931 | 924 | const atom_index = try self.addAtom(gpa, .{ |
| 932 | 925 | .name = name_offset, |
| 933 | 926 | .shndx = shndx, |
| 934 | | .size = this_sym.st_size, |
| 935 | | .alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value), |
| 927 | .size = esym.st_size, |
| 928 | .alignment = Alignment.fromNonzeroByteUnits(esym.st_value), |
| 936 | 929 | }); |
| 937 | 930 | try self.atoms_indexes.append(gpa, atom_index); |
| 938 | 931 | |
| 939 | | global.value = 0; |
| 940 | | global.ref = .{ .index = atom_index, .file = self.index }; |
| 941 | | global.flags.weak = false; |
| 932 | sym.value = 0; |
| 933 | sym.ref = .{ .index = atom_index, .file = self.index }; |
| 934 | sym.flags.weak = false; |
| 942 | 935 | } |
| 943 | 936 | } |
| 944 | 937 | |
| ... | ... | @@ -1080,7 +1073,7 @@ pub fn writeAr(self: Object, elf_file: *Elf, writer: anytype) !void { |
| 1080 | 1073 | try writer.writeAll(data); |
| 1081 | 1074 | } |
| 1082 | 1075 | |
| 1083 | | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1076 | pub fn updateSymtabSize(self: *Object, elf_file: *Elf) void { |
| 1084 | 1077 | const isAlive = struct { |
| 1085 | 1078 | fn isAlive(sym: *const Symbol, ctx: *Elf) bool { |
| 1086 | 1079 | if (sym.mergeSubsection(ctx)) |msub| return msub.alive; |
| ... | ... | @@ -1089,8 +1082,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1089 | 1082 | } |
| 1090 | 1083 | }.isAlive; |
| 1091 | 1084 | |
| 1092 | | for (self.locals()) |local_index| { |
| 1093 | | const local = elf_file.symbol(local_index); |
| 1085 | for (self.locals()) |*local| { |
| 1094 | 1086 | if (!isAlive(local, elf_file)) continue; |
| 1095 | 1087 | const esym = local.elfSym(elf_file); |
| 1096 | 1088 | switch (esym.st_type()) { |
| ... | ... | @@ -1099,22 +1091,22 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1099 | 1091 | else => {}, |
| 1100 | 1092 | } |
| 1101 | 1093 | local.flags.output_symtab = true; |
| 1102 | | try local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 1094 | local.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 1103 | 1095 | self.output_symtab_ctx.nlocals += 1; |
| 1104 | 1096 | self.output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1; |
| 1105 | 1097 | } |
| 1106 | 1098 | |
| 1107 | | for (self.globals()) |global_index| { |
| 1108 | | const global = elf_file.symbol(global_index); |
| 1109 | | const file_ptr = global.file(elf_file) orelse continue; |
| 1110 | | if (file_ptr.index() != self.index) continue; |
| 1099 | for (self.globals(), self.symbols_resolver.items) |*global, resolv| { |
| 1100 | const ref = elf_file.resolver.items[resolv]; |
| 1101 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 1102 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 1111 | 1103 | if (!isAlive(global, elf_file)) continue; |
| 1112 | 1104 | global.flags.output_symtab = true; |
| 1113 | 1105 | if (global.isLocal(elf_file)) { |
| 1114 | | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 1106 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file); |
| 1115 | 1107 | self.output_symtab_ctx.nlocals += 1; |
| 1116 | 1108 | } else { |
| 1117 | | try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); |
| 1109 | global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file); |
| 1118 | 1110 | self.output_symtab_ctx.nglobals += 1; |
| 1119 | 1111 | } |
| 1120 | 1112 | self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1; |
| ... | ... | @@ -1122,8 +1114,7 @@ pub fn updateSymtabSize(self: *Object, elf_file: *Elf) !void { |
| 1122 | 1114 | } |
| 1123 | 1115 | |
| 1124 | 1116 | pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 1125 | | for (self.locals()) |local_index| { |
| 1126 | | const local = elf_file.symbol(local_index); |
| 1117 | for (self.locals()) |local| { |
| 1127 | 1118 | const idx = local.outputSymtabIndex(elf_file) orelse continue; |
| 1128 | 1119 | const out_sym = &elf_file.symtab.items[idx]; |
| 1129 | 1120 | out_sym.st_name = @intCast(elf_file.strtab.items.len); |
| ... | ... | @@ -1132,10 +1123,10 @@ pub fn writeSymtab(self: Object, elf_file: *Elf) void { |
| 1132 | 1123 | local.setOutputSym(elf_file, out_sym); |
| 1133 | 1124 | } |
| 1134 | 1125 | |
| 1135 | | for (self.globals()) |global_index| { |
| 1136 | | const global = elf_file.symbol(global_index); |
| 1137 | | const file_ptr = global.file(elf_file) orelse continue; |
| 1138 | | if (file_ptr.index() != self.index) continue; |
| 1126 | for (self.globals(), self.symbols_resolver.items) |global, resolv| { |
| 1127 | const ref = elf_file.resolver.items[resolv]; |
| 1128 | const ref_sym = elf_file.symbol(ref) orelse continue; |
| 1129 | if (ref_sym.file(elf_file).?.index() != self.index) continue; |
| 1139 | 1130 | const idx = global.outputSymtabIndex(elf_file) orelse continue; |
| 1140 | 1131 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| 1141 | 1132 | elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file)); |