| ... | ... | @@ -684,16 +684,18 @@ const Section = struct { |
| 684 | 684 | } |
| 685 | 685 | } else { |
| 686 | 686 | // For sections without nodes (NOBITS), propagate alignment to the parent. |
| 687 | | assert(switch (elf.shdrPtr(shndx)) { |
| 688 | | inline else => |shdr| elf.targetLoad(&shdr.type) == .NOBITS, |
| 689 | | }); |
| 687 | switch (elf.shdrPtr(shndx)) { |
| 688 | inline else => |shdr| assert(elf.targetLoad(&shdr.type) == .NOBITS), |
| 689 | } |
| 690 | 690 | |
| 691 | 691 | if (elf.ehdrType() == .REL) return; |
| 692 | 692 | |
| 693 | | const segment_ni = if (shndx.flags(elf).TLS) |
| 694 | | elf.ni.tls.unwrap().? |
| 695 | | else |
| 696 | | elf.ni.data; |
| 693 | const segment_ni: MappedFile.Node.Index = seg: { |
| 694 | if (shndx == elf.shndx.bss) break :seg elf.ni.data; |
| 695 | if (shndx == elf.shndx.tbss) break :seg elf.ni.tls.unwrap().?; |
| 696 | // NOBITS sections other than `.bss` and `.tbss` are only emitted in `ET_REL`s. |
| 697 | unreachable; |
| 698 | }; |
| 697 | 699 | |
| 698 | 700 | try elf.ensureSegmentAligned(elf.getNode(segment_ni).segment, min_align); |
| 699 | 701 | } |
| ... | ... | @@ -7052,7 +7054,11 @@ fn mapInputSection(elf: *Elf, opts: struct { |
| 7052 | 7054 | name: []const u8, |
| 7053 | 7055 | flags: std.elf.SHF, |
| 7054 | 7056 | entsize: std.elf.Xword, |
| 7055 | | type: std.elf.SHT = .PROGBITS, |
| 7057 | /// Must be one of: |
| 7058 | /// * `.PROGBITS` |
| 7059 | /// * `.NOBITS` |
| 7060 | /// * `.X86_64_UNWIND` |
| 7061 | type: std.elf.SHT, |
| 7056 | 7062 | }) (Error || error{ |
| 7057 | 7063 | UnsupportedSectionFlags, |
| 7058 | 7064 | TlsSectionUnavailable, |
| ... | ... | @@ -7193,6 +7199,7 @@ fn navMapIndex(elf: *Elf, zcu: *Zcu, nav_index: InternPool.Nav.Index) Error!Node |
| 7193 | 7199 | nav.resolved.?.@"threadlocal", |
| 7194 | 7200 | }, |
| 7195 | 7201 | .entsize = 0, |
| 7202 | .type = .PROGBITS, |
| 7196 | 7203 | })) |shndx| { |
| 7197 | 7204 | break :section shndx; |
| 7198 | 7205 | } else |err| switch (err) { |
| ... | ... | @@ -7900,27 +7907,32 @@ fn loadObject( |
| 7900 | 7907 | }, |
| 7901 | 7908 | }; |
| 7902 | 7909 | |
| 7903 | | const placement = sections[input_sym.shndx].placement; |
| 7904 | | |
| 7905 | | if (placement == .none) continue; |
| 7906 | | |
| 7907 | | const symbol_oni: MappedFile.Node.Index.Optional, const output_shndx, const symbol_value = switch (placement) { |
| 7910 | const symbol_oni: MappedFile.Node.Index.Optional, const output_shndx: Section.Index, const symbol_value: u64 = switch (sections[input_sym.shndx].placement) { |
| 7911 | .none => continue, |
| 7908 | 7912 | .progbits => |isi| .{ |
| 7909 | 7913 | .wrap(isi.node(elf)), |
| 7910 | 7914 | elf.getNodeShndx(isi.node(elf)), |
| 7911 | 7915 | input_sym.value, |
| 7912 | 7916 | }, |
| 7913 | | .nobits => |nobits| .{ |
| 7914 | | .none, |
| 7915 | | nobits.shndx, |
| 7916 | | (if (elf.ehdrType() == .REL) |
| 7917 | | @as(u64, 0) |
| 7918 | | else if (nobits.shndx.flags(elf).TLS) |
| 7919 | | elf.tbssBaseOffset() |
| 7920 | | else |
| 7921 | | nobits.shndx.vaddr(elf)) + nobits.offset + input_sym.value, |
| 7917 | .nobits => |nobits| sym: { |
| 7918 | const section_base: u64 = switch (elf.ehdrType()) { |
| 7919 | .REL => 0, |
| 7920 | .EXEC, .DYN => base: { |
| 7921 | if (elf.ni.tls != .none and |
| 7922 | nobits.shndx == elf.shndx.tbss) |
| 7923 | { |
| 7924 | break :base elf.tbssBaseOffset(); |
| 7925 | } |
| 7926 | assert(nobits.shndx == elf.shndx.bss); |
| 7927 | break :base nobits.shndx.vaddr(elf); |
| 7928 | }, |
| 7929 | }; |
| 7930 | break :sym .{ |
| 7931 | .none, |
| 7932 | nobits.shndx, |
| 7933 | section_base + nobits.offset + input_sym.value, |
| 7934 | }; |
| 7922 | 7935 | }, |
| 7923 | | .none => unreachable, |
| 7924 | 7936 | }; |
| 7925 | 7937 | |
| 7926 | 7938 | switch (input_sym.info.bind) { |
| ... | ... | @@ -9109,15 +9121,18 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 9109 | 9121 | .EXEC, .DYN => segment_ni, |
| 9110 | 9122 | }; |
| 9111 | 9123 | assert(opts.addralign.check(opts.size)); |
| 9112 | | const oni: MappedFile.Node.Index.Optional = if (opts.type == .NOBITS) .none else .wrap(elf.addNodeAssumeCapacity(try parent_ni.addFloatingChild(gpa, &elf.mf, .{ |
| 9113 | | .size = opts.node_align.forward(opts.size), |
| 9114 | | .alignment = opts.addralign.max(opts.node_align), |
| 9115 | | .resized = opts.size > 0, |
| 9116 | | .bubbles_moved = opts.flags.ALLOC, |
| 9117 | | }), switch (opts.manual_size) { |
| 9118 | | false => .{ .section = shndx }, |
| 9119 | | true => .{ .section_manual_size = shndx }, |
| 9120 | | })); |
| 9124 | const oni: MappedFile.Node.Index.Optional = switch (opts.type) { |
| 9125 | .NOBITS => .none, |
| 9126 | else => .wrap(elf.addNodeAssumeCapacity( |
| 9127 | try parent_ni.addFloatingChild(gpa, &elf.mf, .{ |
| 9128 | .size = opts.node_align.forward(opts.size), |
| 9129 | .alignment = opts.addralign.max(opts.node_align), |
| 9130 | .resized = opts.size > 0, |
| 9131 | .bubbles_moved = opts.flags.ALLOC, |
| 9132 | }), |
| 9133 | if (opts.manual_size) .{ .section_manual_size = shndx } else .{ .section = shndx }, |
| 9134 | )), |
| 9135 | }; |
| 9121 | 9136 | const addr = if (oni.unwrap()) |ni| elf.computeNodeVAddr(ni) else 0; |
| 9122 | 9137 | elf.shdrs.appendAssumeCapacity(.{ |
| 9123 | 9138 | .lsi = if (want_symbol) try elf.addLocalSymbol(.{ |
| ... | ... | @@ -11700,7 +11715,7 @@ fn loadSegmentChildrenMoved( |
| 11700 | 11715 | offset: u64, |
| 11701 | 11716 | filesz: u64, |
| 11702 | 11717 | ) std.mem.Allocator.Error!void { |
| 11703 | | if (segment_ni == elf.ni.data and elf.shndx.bss != .UNDEF) { |
| 11718 | if (segment_ni == elf.ni.data) { |
| 11704 | 11719 | const bss_shndx = elf.shndx.bss; |
| 11705 | 11720 | const old_bss_addr = bss_shndx.vaddr(elf); |
| 11706 | 11721 | const new_bss_addr = new_vaddr + filesz; |