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