| ... | ... | @@ -137,11 +137,18 @@ node_global_symbols: std.array_hash_map.Auto(MappedFile.Node.Index, Symbol.Globa |
| 137 | 137 | /// See the definition of `DsoGlobals`. |
| 138 | 138 | dso_globals: DsoGlobals, |
| 139 | 139 | |
| 140 | | /// Contains all defined global symbols that do not have a node. |
| 141 | | nodeless_globals: std.array_hash_map.Auto(Symbol.Global.Index, void), |
| 142 | | |
| 143 | | // These are needed to find local symbols when a nodeless section moves. |
| 140 | /// Contains all global symbols defined relative to `.bss`. These globals are not associated with |
| 141 | /// any `MappedFile.Node`, but they need to be updated when the address of `.bss` changes. |
| 142 | bss_globals: std.array_hash_map.Auto(Symbol.Global.Index, void), |
| 143 | /// Contains all global symbols defined relative to `.tbss`. These globals are not associated with |
| 144 | /// any `MappedFile.Node`, but they need to be updated when the address of `.tbss` changes. |
| 145 | tbss_globals: std.array_hash_map.Auto(Symbol.Global.Index, void), |
| 146 | |
| 147 | /// Contains all inputs which have added input sections to `.bss`, so that we can update local |
| 148 | /// symbols when the address of `.bss` changes. |
| 144 | 149 | bss_inputs: std.ArrayList(Node.InputIndex), |
| 150 | /// Contains all inputs which have added input sections to `.tbss`, so that we can update local |
| 151 | /// symbols when the address of `.tbss` changes. |
| 145 | 152 | tbss_inputs: std.ArrayList(Node.InputIndex), |
| 146 | 153 | |
| 147 | 154 | shstrtab: StringTable, |
| ... | ... | @@ -2747,7 +2754,6 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ |
| 2747 | 2754 | try elf.globals.ensureUnusedCapacity(gpa, 1); |
| 2748 | 2755 | try elf.globals_by_name.ensureUnusedCapacity(gpa, 1); |
| 2749 | 2756 | try elf.node_global_symbols.ensureUnusedCapacity(gpa, 1); |
| 2750 | | try elf.nodeless_globals.ensureUnusedCapacity(gpa, 1); |
| 2751 | 2757 | |
| 2752 | 2758 | try Section.Index.symtab.node(elf).ensureMinimumSize(gpa, &elf.mf, switch (elf.shdrPtr(.symtab)) { |
| 2753 | 2759 | inline else => |shdr, class| elf.targetLoad(&shdr.size) + @sizeOf(class.ElfN().Sym), |
| ... | ... | @@ -2915,8 +2921,16 @@ fn addGlobalSymbol(elf: *Elf, opts: Symbol.Global.AddOptions) (error{ |
| 2915 | 2921 | old_head_ptr.prev_in_node = .wrap(gsi); |
| 2916 | 2922 | } |
| 2917 | 2923 | |
| 2918 | | if (opts.node == .none and opts.shndx != .UNDEF) { |
| 2919 | | elf.nodeless_globals.putAssumeCapacity(gsi, {}); |
| 2924 | if (elf.ehdrType() != .REL) { |
| 2925 | if (opts.shndx == elf.shndx.bss) { |
| 2926 | assert(opts.node == .none); |
| 2927 | try elf.bss_globals.put(gpa, gsi, {}); |
| 2928 | } else if (elf.ni.tls != .none and opts.shndx == elf.shndx.tbss) { |
| 2929 | assert(opts.node == .none); |
| 2930 | try elf.tbss_globals.put(gpa, gsi, {}); |
| 2931 | } else if (opts.shndx != .UNDEF and opts.shndx != .ABS) { |
| 2932 | assert(opts.node != .none); |
| 2933 | } |
| 2920 | 2934 | } |
| 2921 | 2935 | |
| 2922 | 2936 | if (force_local_bind) { |
| ... | ... | @@ -3356,8 +3370,9 @@ fn setGlobalSymbolValue(elf: *Elf, gsi: Symbol.Global.Index, new: struct { |
| 3356 | 3370 | type: std.elf.STT, |
| 3357 | 3371 | shndx: Section.Index, |
| 3358 | 3372 | }) Error!void { |
| 3359 | | assert(new.shndx != .UNDEF); |
| 3373 | const gpa = elf.base.comp.gpa; |
| 3360 | 3374 | |
| 3375 | assert(new.shndx != .UNDEF); |
| 3361 | 3376 | const global_ptr = gsi.ptr(elf); |
| 3362 | 3377 | |
| 3363 | 3378 | if (global_ptr.symtab_index.ptr(elf).node.unwrap()) |old_node| { |
| ... | ... | @@ -3379,11 +3394,21 @@ fn setGlobalSymbolValue(elf: *Elf, gsi: Symbol.Global.Index, new: struct { |
| 3379 | 3394 | } else { |
| 3380 | 3395 | assert(global_ptr.next_in_node == .none); |
| 3381 | 3396 | assert(global_ptr.prev_in_node == .none); |
| 3397 | // If the symbol didn't have a node, it may have been in `.bss` or `.tbss`. |
| 3398 | _ = elf.bss_globals.swapRemove(gsi); |
| 3399 | _ = elf.tbss_globals.swapRemove(gsi); |
| 3382 | 3400 | } |
| 3383 | 3401 | |
| 3384 | | _ = elf.nodeless_globals.swapRemove(gsi); |
| 3385 | | if (new.node == .none) { |
| 3386 | | try elf.nodeless_globals.put(elf.base.comp.gpa, gsi, {}); |
| 3402 | if (elf.ehdrType() != .REL) { |
| 3403 | if (new.shndx == elf.shndx.bss) { |
| 3404 | assert(new.node == .none); |
| 3405 | try elf.bss_globals.put(gpa, gsi, {}); |
| 3406 | } else if (elf.ni.tls != .none and new.shndx == elf.shndx.tbss) { |
| 3407 | assert(new.node == .none); |
| 3408 | try elf.tbss_globals.put(gpa, gsi, {}); |
| 3409 | } else if (new.shndx != .UNDEF) { |
| 3410 | assert(new.node != .none); |
| 3411 | } |
| 3387 | 3412 | } |
| 3388 | 3413 | |
| 3389 | 3414 | global_ptr.symtab_index.ptr(elf).node = new.node; |
| ... | ... | @@ -3667,7 +3692,8 @@ fn deleteOwnedDynsym(elf: *Elf, gsi: Symbol.Global.Index) std.mem.Allocator.Erro |
| 3667 | 3692 | |
| 3668 | 3693 | const Symbol = struct { |
| 3669 | 3694 | /// The node which this symbol's value is defined relative to. Possible values are: |
| 3670 | | /// * `.none` for a SHN_ABS or SHN_UNDEF symbol |
| 3695 | /// * `.none` for a SHN_ABS or SHN_UNDEF symbol, *or* a symbol in `.bss`/`.tbss` |
| 3696 | /// (see `Elf.bss_globals` and `Elf.tbss_globals`) |
| 3671 | 3697 | /// * A section (the symbol's value is some vaddr in that section) |
| 3672 | 3698 | /// * An input section (the symbol's value is some vaddr in that input section) |
| 3673 | 3699 | /// * A NAV, UAV, or lazy code/data (the symbol's value is exactly the vaddr of that node) |
| ... | ... | @@ -4783,7 +4809,8 @@ fn create( |
| 4783 | 4809 | .symbols = .empty, |
| 4784 | 4810 | .default_sym_vers = .empty, |
| 4785 | 4811 | }, |
| 4786 | | .nodeless_globals = .empty, |
| 4812 | .bss_globals = .empty, |
| 4813 | .tbss_globals = .empty, |
| 4787 | 4814 | .bss_inputs = .empty, |
| 4788 | 4815 | .tbss_inputs = .empty, |
| 4789 | 4816 | .shstrtab = .{ .map = .empty }, |
| ... | ... | @@ -4868,7 +4895,8 @@ pub fn deinit(elf: *Elf) void { |
| 4868 | 4895 | elf.dso_globals.string_bytes.deinit(gpa); |
| 4869 | 4896 | elf.dso_globals.symbols.deinit(gpa); |
| 4870 | 4897 | elf.dso_globals.default_sym_vers.deinit(gpa); |
| 4871 | | elf.nodeless_globals.deinit(gpa); |
| 4898 | elf.bss_globals.deinit(gpa); |
| 4899 | elf.tbss_globals.deinit(gpa); |
| 4872 | 4900 | elf.bss_inputs.deinit(gpa); |
| 4873 | 4901 | elf.tbss_inputs.deinit(gpa); |
| 4874 | 4902 | elf.shstrtab.map.deinit(gpa); |
| ... | ... | @@ -11601,6 +11629,7 @@ fn updateNobitsAddress( |
| 11601 | 11629 | old_symbol_base: u64, |
| 11602 | 11630 | new_symbol_base: u64, |
| 11603 | 11631 | inputs: []const Node.InputIndex, |
| 11632 | globals: []const Symbol.Global.Index, |
| 11604 | 11633 | ) void { |
| 11605 | 11634 | assert(shndx != .UNDEF); |
| 11606 | 11635 | |
| ... | ... | @@ -11611,8 +11640,6 @@ fn updateNobitsAddress( |
| 11611 | 11640 | }, |
| 11612 | 11641 | } |
| 11613 | 11642 | |
| 11614 | | const expected_shndx = shndx.toSection().?; |
| 11615 | | |
| 11616 | 11643 | // Update local symbols. |
| 11617 | 11644 | for (inputs) |ii| { |
| 11618 | 11645 | var lsi, const end_lsi = ii.localSymbolRange(elf); |
| ... | ... | @@ -11620,14 +11647,14 @@ fn updateNobitsAddress( |
| 11620 | 11647 | while (lsi != end_lsi) : (lsi = @fromBackingInt( |
| 11621 | 11648 | @backingInt(lsi) + 1, |
| 11622 | 11649 | )) { |
| 11623 | | const symbol_shndx, const visibility = switch (elf.symPtr(lsi.index())) { |
| 11650 | const symbol_shndx: Section.Index, const visibility = switch (elf.symPtr(lsi.index())) { |
| 11624 | 11651 | inline else => |sym| .{ |
| 11625 | | elf.targetLoad(&sym.shndx), |
| 11652 | .fromSection(elf.targetLoad(&sym.shndx)), |
| 11626 | 11653 | elf.targetLoad(&sym.other).visibility, |
| 11627 | 11654 | }, |
| 11628 | 11655 | }; |
| 11629 | 11656 | |
| 11630 | | if (symbol_shndx != expected_shndx) continue; |
| 11657 | if (symbol_shndx != shndx) continue; |
| 11631 | 11658 | |
| 11632 | 11659 | switch (visibility) { |
| 11633 | 11660 | // These are globals demoted to STB_LOCAL and are updated below. |
| ... | ... | @@ -11644,16 +11671,14 @@ fn updateNobitsAddress( |
| 11644 | 11671 | } |
| 11645 | 11672 | } |
| 11646 | 11673 | |
| 11647 | | // Update globals. |
| 11648 | | // Since nobits sections have no nodes, we can't just iterate over `node_global_symbols`, |
| 11649 | | // so instead filter manually through nodeless symbols. |
| 11650 | | for (elf.nodeless_globals.keys()) |gsi| { |
| 11674 | // Update global symbols. |
| 11675 | for (globals) |gsi| { |
| 11651 | 11676 | const symbol: Symbol.Id = .global(gsi); |
| 11652 | 11677 | |
| 11653 | | const symbol_shndx = switch (elf.symPtr(symbol.index(elf))) { |
| 11654 | | inline else => |sym| elf.targetLoad(&sym.shndx), |
| 11678 | const sym_shndx: Section.Index = switch (elf.symPtr(symbol.index(elf))) { |
| 11679 | inline else => |sym| .fromSection(elf.targetLoad(&sym.shndx)), |
| 11655 | 11680 | }; |
| 11656 | | if (symbol_shndx != expected_shndx) continue; |
| 11681 | assert(sym_shndx == shndx); |
| 11657 | 11682 | |
| 11658 | 11683 | symbol.flushMoved( |
| 11659 | 11684 | elf, |
| ... | ... | @@ -11687,6 +11712,7 @@ fn loadSegmentChildrenMoved( |
| 11687 | 11712 | old_bss_addr, |
| 11688 | 11713 | new_bss_addr, |
| 11689 | 11714 | elf.bss_inputs.items, |
| 11715 | elf.bss_globals.keys(), |
| 11690 | 11716 | ); |
| 11691 | 11717 | } |
| 11692 | 11718 | |
| ... | ... | @@ -11920,6 +11946,7 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!vo |
| 11920 | 11946 | old_tbss_base, |
| 11921 | 11947 | new_tbss_base, |
| 11922 | 11948 | elf.tbss_inputs.items, |
| 11949 | elf.tbss_globals.keys(), |
| 11923 | 11950 | ); |
| 11924 | 11951 | |
| 11925 | 11952 | // TPOFF relocations care about the size of the TLS segment. Re-apply |