authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-23 11:59:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-09-23 17:15:41+02:00
log29ebd96818bce4c4f2842d1bb76390247d47e198
tree9ffd3b6089dee7eb4b3abd5b14775f541f04c461
parent9f05cb318b77c18c312592cba52c782d70f2432f

elf: improve decl-to-section mapping logic


5 files changed, 200 insertions(+), 129 deletions(-)

src/link/Elf.zig+174-111
......@@ -415,16 +415,19 @@ const AllocateSegmentOpts = struct {
415415 flags: u32 = elf.PF_R,
416416};
417417
418fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) !u16 {
418fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) error{OutOfMemory}!u16 {
419419 const index = @as(u16, @intCast(self.phdrs.items.len));
420420 try self.phdrs.ensureUnusedCapacity(self.base.allocator, 1);
421421 const off = self.findFreeSpace(opts.size, opts.alignment);
422 log.debug("found PHDR {c}{c}{c} free space 0x{x} to 0x{x}", .{
422 log.debug("allocating phdr({d})({c}{c}{c}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{
423 index,
423424 if (opts.flags & elf.PF_R != 0) @as(u8, 'R') else '_',
424425 if (opts.flags & elf.PF_W != 0) @as(u8, 'W') else '_',
425426 if (opts.flags & elf.PF_X != 0) @as(u8, 'X') else '_',
426427 off,
427428 off + opts.size,
429 opts.addr,
430 opts.addr + opts.size,
428431 });
429432 self.phdrs.appendAssumeCapacity(.{
430433 .p_type = elf.PT_LOAD,
......@@ -440,6 +443,45 @@ fn allocateSegment(self: *Elf, opts: AllocateSegmentOpts) !u16 {
440443 return index;
441444}
442445
446const AllocateAllocSectionOpts = struct {
447 name: [:0]const u8,
448 phdr_index: u16,
449 alignment: u16 = 1,
450 flags: u16 = elf.SHF_ALLOC,
451 type: u32 = elf.SHT_PROGBITS,
452};
453
454fn allocateAllocSection(self: *Elf, opts: AllocateAllocSectionOpts) error{OutOfMemory}!u16 {
455 const gpa = self.base.allocator;
456 const phdr = &self.phdrs.items[opts.phdr_index];
457 const index = @as(u16, @intCast(self.shdrs.items.len));
458 try self.shdrs.ensureUnusedCapacity(gpa, 1);
459 const sh_name = try self.shstrtab.insert(gpa, opts.name);
460 try self.phdr_to_shdr_table.putNoClobber(gpa, index, opts.phdr_index);
461 log.debug("allocating '{s}' in PHDR({d}) from 0x{x} to 0x{x} (0x{x} - 0x{x})", .{
462 opts.name,
463 opts.phdr_index,
464 phdr.p_offset,
465 phdr.p_offset + phdr.p_filesz,
466 phdr.p_vaddr,
467 phdr.p_vaddr + phdr.p_memsz,
468 });
469 self.shdrs.appendAssumeCapacity(.{
470 .sh_name = sh_name,
471 .sh_type = opts.type,
472 .sh_flags = opts.flags,
473 .sh_addr = phdr.p_vaddr,
474 .sh_offset = phdr.p_offset,
475 .sh_size = phdr.p_filesz,
476 .sh_link = 0,
477 .sh_info = 0,
478 .sh_addralign = opts.alignment,
479 .sh_entsize = 0,
480 });
481 self.shdr_table_dirty = true;
482 return index;
483}
484
443485pub fn populateMissingMetadata(self: *Elf) !void {
444486 const gpa = self.base.allocator;
445487 const small_ptr = switch (self.ptr_width) {
......@@ -545,6 +587,8 @@ pub fn populateMissingMetadata(self: *Elf) !void {
545587 .alignment = alignment,
546588 .flags = elf.PF_R | elf.PF_W,
547589 });
590 const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?];
591 phdr.p_offset = self.phdrs.items[self.phdr_load_rw_index.?].p_offset; // .bss overlaps .data
548592 }
549593
550594 if (self.shstrtab_section_index == null) {
......@@ -592,102 +636,49 @@ pub fn populateMissingMetadata(self: *Elf) !void {
592636 }
593637
594638 if (self.text_section_index == null) {
595 self.text_section_index = @intCast(self.shdrs.items.len);
596 const phdr = &self.phdrs.items[self.phdr_load_re_index.?];
597 try self.shdrs.append(gpa, .{
598 .sh_name = try self.shstrtab.insert(gpa, ".text"),
599 .sh_type = elf.SHT_PROGBITS,
600 .sh_flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
601 .sh_addr = phdr.p_vaddr,
602 .sh_offset = phdr.p_offset,
603 .sh_size = phdr.p_filesz,
604 .sh_link = 0,
605 .sh_info = 0,
606 .sh_addralign = 1,
607 .sh_entsize = 0,
639 self.text_section_index = try self.allocateAllocSection(.{
640 .name = ".text",
641 .phdr_index = self.phdr_load_re_index.?,
642 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
608643 });
609 try self.phdr_to_shdr_table.putNoClobber(gpa, self.text_section_index.?, self.phdr_load_re_index.?);
610644 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.text_section_index.?, .{});
611 self.shdr_table_dirty = true;
612645 }
613646
614647 if (self.got_section_index == null) {
615 self.got_section_index = @intCast(self.shdrs.items.len);
616 const phdr = &self.phdrs.items[self.phdr_got_index.?];
617 try self.shdrs.append(gpa, .{
618 .sh_name = try self.shstrtab.insert(gpa, ".got"),
619 .sh_type = elf.SHT_PROGBITS,
620 .sh_flags = elf.SHF_ALLOC,
621 .sh_addr = phdr.p_vaddr,
622 .sh_offset = phdr.p_offset,
623 .sh_size = phdr.p_filesz,
624 .sh_link = 0,
625 .sh_info = 0,
626 .sh_addralign = @as(u16, ptr_size),
627 .sh_entsize = 0,
648 self.got_section_index = try self.allocateAllocSection(.{
649 .name = ".got",
650 .phdr_index = self.phdr_got_index.?,
651 .alignment = ptr_size,
628652 });
629 try self.phdr_to_shdr_table.putNoClobber(gpa, self.got_section_index.?, self.phdr_got_index.?);
630 self.shdr_table_dirty = true;
631653 }
632654
633655 if (self.rodata_section_index == null) {
634 self.rodata_section_index = @intCast(self.shdrs.items.len);
635 const phdr = &self.phdrs.items[self.phdr_load_ro_index.?];
636 try self.shdrs.append(gpa, .{
637 .sh_name = try self.shstrtab.insert(gpa, ".rodata"),
638 .sh_type = elf.SHT_PROGBITS,
639 .sh_flags = elf.SHF_ALLOC,
640 .sh_addr = phdr.p_vaddr,
641 .sh_offset = phdr.p_offset,
642 .sh_size = phdr.p_filesz,
643 .sh_link = 0,
644 .sh_info = 0,
645 .sh_addralign = 1,
646 .sh_entsize = 0,
656 self.rodata_section_index = try self.allocateAllocSection(.{
657 .name = ".rodata",
658 .phdr_index = self.phdr_load_ro_index.?,
647659 });
648 try self.phdr_to_shdr_table.putNoClobber(gpa, self.rodata_section_index.?, self.phdr_load_ro_index.?);
649660 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.rodata_section_index.?, .{});
650 self.shdr_table_dirty = true;
651661 }
652662
653663 if (self.data_section_index == null) {
654 self.data_section_index = @intCast(self.shdrs.items.len);
655 const phdr = &self.phdrs.items[self.phdr_load_rw_index.?];
656 try self.shdrs.append(gpa, .{
657 .sh_name = try self.shstrtab.insert(gpa, ".data"),
658 .sh_type = elf.SHT_PROGBITS,
659 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
660 .sh_addr = phdr.p_vaddr,
661 .sh_offset = phdr.p_offset,
662 .sh_size = phdr.p_filesz,
663 .sh_link = 0,
664 .sh_info = 0,
665 .sh_addralign = @as(u16, ptr_size),
666 .sh_entsize = 0,
664 self.data_section_index = try self.allocateAllocSection(.{
665 .name = ".data",
666 .phdr_index = self.phdr_load_rw_index.?,
667 .alignment = ptr_size,
668 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
667669 });
668 try self.phdr_to_shdr_table.putNoClobber(gpa, self.data_section_index.?, self.phdr_load_rw_index.?);
669670 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.data_section_index.?, .{});
670 self.shdr_table_dirty = true;
671671 }
672672
673673 if (self.bss_section_index == null) {
674 self.bss_section_index = @intCast(self.shdrs.items.len);
675 const phdr = &self.phdrs.items[self.phdr_load_zerofill_index.?];
676 try self.shdrs.append(gpa, .{
677 .sh_name = try self.shstrtab.insert(gpa, ".bss"),
678 .sh_type = elf.SHT_NOBITS,
679 .sh_flags = elf.SHF_WRITE | elf.SHF_ALLOC,
680 .sh_addr = phdr.p_vaddr,
681 .sh_offset = phdr.p_offset,
682 .sh_size = phdr.p_filesz,
683 .sh_link = 0,
684 .sh_info = 0,
685 .sh_addralign = @as(u16, ptr_size),
686 .sh_entsize = 0,
674 self.bss_section_index = try self.allocateAllocSection(.{
675 .name = ".bss",
676 .phdr_index = self.phdr_load_zerofill_index.?,
677 .alignment = ptr_size,
678 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
679 .type = elf.SHT_NOBITS,
687680 });
688 try self.phdr_to_shdr_table.putNoClobber(gpa, self.bss_section_index.?, self.phdr_load_zerofill_index.?);
689681 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.bss_section_index.?, .{});
690 self.shdr_table_dirty = true;
691682 }
692683
693684 if (self.symtab_section_index == null) {
......@@ -1154,7 +1145,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11541145 for (self.file(index).?.zig_module.atoms.keys()) |atom_index| {
11551146 const atom_ptr = self.atom(atom_index).?;
11561147 if (!atom_ptr.alive) continue;
1157 const shdr = &self.shdrs.items[atom_ptr.output_section_index];
1148 const shdr = &self.shdrs.items[atom_ptr.outputShndx().?];
11581149 const file_offset = shdr.sh_offset + atom_ptr.value - shdr.sh_addr;
11591150 const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
11601151 const code = try gpa.alloc(u8, size);
......@@ -1184,6 +1175,16 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
11841175 try self.updateSymtabSize();
11851176 try self.writeSymtab();
11861177
1178 // .bss always overlaps .data in file offset, but is zero-sized in file so it doesn't
1179 // get mapped by the loader
1180 if (self.data_section_index) |data_shndx| blk: {
1181 const bss_shndx = self.bss_section_index orelse break :blk;
1182 const data_phndx = self.phdr_to_shdr_table.get(data_shndx).?;
1183 const bss_phndx = self.phdr_to_shdr_table.get(bss_shndx).?;
1184 self.shdrs.items[bss_shndx].sh_offset = self.shdrs.items[data_shndx].sh_offset;
1185 self.phdrs.items[bss_phndx].p_offset = self.phdrs.items[data_phndx].p_offset;
1186 }
1187
11871188 // Dump the state for easy debugging.
11881189 // State can be dumped via `--debug-log link_state`.
11891190 if (build_options.enable_logging) {
......@@ -1683,7 +1684,7 @@ fn writeObjects(self: *Elf) !void {
16831684 const atom_ptr = self.atom(atom_index) orelse continue;
16841685 if (!atom_ptr.alive) continue;
16851686
1686 const shdr = &self.shdrs.items[atom_ptr.output_section_index];
1687 const shdr = &self.shdrs.items[atom_ptr.outputShndx().?];
16871688 if (shdr.sh_type == elf.SHT_NOBITS) continue;
16881689 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; // TODO we don't yet know how to handle non-alloc sections
16891690
......@@ -2557,15 +2558,15 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
25572558 }
25582559}
25592560
2560pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !Symbol.Index {
2561pub fn getOrCreateMetadataForLazySymbol(self: *Elf, lazy_sym: link.File.LazySymbol) !Symbol.Index {
25612562 const mod = self.base.options.module.?;
2562 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));
2563 const gop = try self.lazy_syms.getOrPut(self.base.allocator, lazy_sym.getDecl(mod));
25632564 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
25642565 if (!gop.found_existing) gop.value_ptr.* = .{};
25652566 const metadata: struct {
25662567 symbol_index: *Symbol.Index,
25672568 state: *LazySymbolMetadata.State,
2568 } = switch (sym.kind) {
2569 } = switch (lazy_sym.kind) {
25692570 .code => .{
25702571 .symbol_index = &gop.value_ptr.text_symbol_index,
25712572 .state = &gop.value_ptr.text_state,
......@@ -2577,17 +2578,14 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) !
25772578 };
25782579 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
25792580 switch (metadata.state.*) {
2580 .unused => metadata.symbol_index.* = try zig_module.addAtom(switch (sym.kind) {
2581 .code => self.text_section_index.?,
2582 .const_data => self.rodata_section_index.?,
2583 }, self),
2581 .unused => metadata.symbol_index.* = try zig_module.addAtom(self),
25842582 .pending_flush => return metadata.symbol_index.*,
25852583 .flushed => {},
25862584 }
25872585 metadata.state.* = .pending_flush;
25882586 const symbol_index = metadata.symbol_index.*;
25892587 // anyerror needs to be deferred until flushModule
2590 if (sym.getDecl(mod) != .none) try self.updateLazySymbol(sym, symbol_index);
2588 if (lazy_sym.getDecl(mod) != .none) try self.updateLazySymbol(lazy_sym, symbol_index);
25912589 return symbol_index;
25922590}
25932591
......@@ -2596,35 +2594,37 @@ pub fn getOrCreateMetadataForDecl(self: *Elf, decl_index: Module.Decl.Index) !Sy
25962594 if (!gop.found_existing) {
25972595 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
25982596 gop.value_ptr.* = .{
2599 .symbol_index = try zig_module.addAtom(self.getDeclShdrIndex(decl_index), self),
2597 .symbol_index = try zig_module.addAtom(self),
26002598 .exports = .{},
26012599 };
26022600 }
26032601 return gop.value_ptr.symbol_index;
26042602}
26052603
2606fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
2604fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index, code: []const u8) u16 {
26072605 const mod = self.base.options.module.?;
26082606 const decl = mod.declPtr(decl_index);
2609 const ty = decl.ty;
2610 const zig_ty = ty.zigTypeTag(mod);
2611 const val = decl.val;
2612 const shdr_index: u16 = blk: {
2613 if (val.isUndefDeep(mod)) {
2614 // TODO in release-fast and release-small, we should put undef in .bss
2615 break :blk self.data_section_index.?;
2616 }
2617
2618 switch (zig_ty) {
2619 // TODO: what if this is a function pointer?
2620 .Fn => break :blk self.text_section_index.?,
2621 else => {
2622 if (val.getVariable(mod)) |_| {
2623 break :blk self.data_section_index.?;
2607 const shdr_index = switch (decl.ty.zigTypeTag(mod)) {
2608 // TODO: what if this is a function pointer?
2609 .Fn => self.text_section_index.?,
2610 else => blk: {
2611 if (decl.getOwnedVariable(mod)) |variable| {
2612 if (variable.is_const) break :blk self.rodata_section_index.?;
2613 if (variable.init.toValue().isUndefDeep(mod)) {
2614 const mode = self.base.options.optimize_mode;
2615 if (mode == .Debug or mode == .ReleaseSafe) break :blk self.data_section_index.?;
2616 break :blk self.bss_section_index.?;
26242617 }
2625 break :blk self.rodata_section_index.?;
2626 },
2627 }
2618 // TODO I blatantly copied the logic from the Wasm linker, but is there a less
2619 // intrusive check for all zeroes than this?
2620 const is_all_zeroes = for (code) |byte| {
2621 if (byte != 0) break false;
2622 } else true;
2623 if (is_all_zeroes) break :blk self.bss_section_index.?;
2624 break :blk self.data_section_index.?;
2625 }
2626 break :blk self.rodata_section_index.?;
2627 },
26282628 };
26292629 return shdr_index;
26302630}
......@@ -2649,7 +2649,10 @@ fn updateDeclCode(
26492649 const sym = self.symbol(sym_index);
26502650 const esym = &zig_module.local_esyms.items[sym.esym_index];
26512651 const atom_ptr = sym.atom(self).?;
2652 const shdr_index = sym.output_section_index;
2652
2653 const shdr_index = self.getDeclShdrIndex(decl_index, code);
2654 sym.output_section_index = shdr_index;
2655 atom_ptr.output_section_index = shdr_index;
26532656
26542657 sym.name_offset = try self.strtab.insert(gpa, decl_name);
26552658 atom_ptr.alive = true;
......@@ -2902,9 +2905,14 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
29022905 },
29032906 };
29042907
2908 const output_section_index = switch (sym.kind) {
2909 .code => self.text_section_index.?,
2910 .const_data => self.rodata_section_index.?,
2911 };
29052912 const local_sym = self.symbol(symbol_index);
2906 const phdr_index = self.phdr_to_shdr_table.get(local_sym.output_section_index).?;
2913 const phdr_index = self.phdr_to_shdr_table.get(output_section_index).?;
29072914 local_sym.name_offset = name_str_index;
2915 local_sym.output_section_index = output_section_index;
29082916 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
29092917 local_esym.st_name = name_str_index;
29102918 local_esym.st_info |= elf.STT_OBJECT;
......@@ -2914,6 +2922,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
29142922 atom_ptr.name_offset = name_str_index;
29152923 atom_ptr.alignment = required_alignment;
29162924 atom_ptr.size = code.len;
2925 atom_ptr.output_section_index = output_section_index;
29172926
29182927 try atom_ptr.allocate(self);
29192928 errdefer self.freeDeclMetadata(symbol_index);
......@@ -2932,7 +2941,7 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol.
29322941 try self.got.writeEntry(self, gop.index);
29332942
29342943 const section_offset = atom_ptr.value - self.phdrs.items[phdr_index].p_vaddr;
2935 const file_offset = self.shdrs.items[local_sym.output_section_index].sh_offset + section_offset;
2944 const file_offset = self.shdrs.items[output_section_index].sh_offset + section_offset;
29362945 try self.base.file.?.pwriteAll(code, file_offset);
29372946}
29382947
......@@ -2960,7 +2969,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
29602969 const name = self.strtab.get(name_str_index).?;
29612970
29622971 const zig_module = self.file(self.zig_module_index.?).?.zig_module;
2963 const sym_index = try zig_module.addAtom(self.rodata_section_index.?, self);
2972 const sym_index = try zig_module.addAtom(self);
29642973
29652974 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{
29662975 .none = {},
......@@ -2982,6 +2991,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
29822991 const phdr_index = self.phdr_to_shdr_table.get(shdr_index).?;
29832992 const local_sym = self.symbol(sym_index);
29842993 local_sym.name_offset = name_str_index;
2994 local_sym.output_section_index = self.rodata_section_index.?;
29852995 const local_esym = &zig_module.local_esyms.items[local_sym.esym_index];
29862996 local_esym.st_name = name_str_index;
29872997 local_esym.st_info |= elf.STT_OBJECT;
......@@ -2991,6 +3001,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
29913001 atom_ptr.name_offset = name_str_index;
29923002 atom_ptr.alignment = required_alignment;
29933003 atom_ptr.size = code.len;
3004 atom_ptr.output_section_index = self.rodata_section_index.?;
29943005
29953006 try atom_ptr.allocate(self);
29963007 errdefer self.freeDeclMetadata(sym_index);
......@@ -4008,6 +4019,54 @@ fn reportParseError(
40084019 });
40094020}
40104021
4022fn fmtShdrs(self: *Elf) std.fmt.Formatter(formatShdrs) {
4023 return .{ .data = self };
4024}
4025
4026fn formatShdrs(
4027 self: *Elf,
4028 comptime unused_fmt_string: []const u8,
4029 options: std.fmt.FormatOptions,
4030 writer: anytype,
4031) !void {
4032 _ = options;
4033 _ = unused_fmt_string;
4034 for (self.shdrs.items, 0..) |shdr, i| {
4035 try writer.print("shdr({d}) : phdr({?d}) : {s} : @{x} ({x}) : align({x}) : size({x})\n", .{
4036 i, self.phdr_to_shdr_table.get(@intCast(i)),
4037 self.shstrtab.getAssumeExists(shdr.sh_name), shdr.sh_offset,
4038 shdr.sh_addr, shdr.sh_addralign,
4039 shdr.sh_size,
4040 });
4041 }
4042}
4043
4044fn fmtPhdrs(self: *Elf) std.fmt.Formatter(formatPhdrs) {
4045 return .{ .data = self };
4046}
4047
4048fn formatPhdrs(
4049 self: *Elf,
4050 comptime unused_fmt_string: []const u8,
4051 options: std.fmt.FormatOptions,
4052 writer: anytype,
4053) !void {
4054 _ = options;
4055 _ = unused_fmt_string;
4056 for (self.phdrs.items, 0..) |phdr, i| {
4057 const write = phdr.p_flags & elf.PF_W != 0;
4058 const read = phdr.p_flags & elf.PF_R != 0;
4059 const exec = phdr.p_flags & elf.PF_X != 0;
4060 var flags: [3]u8 = [_]u8{'_'} ** 3;
4061 if (exec) flags[0] = 'X';
4062 if (write) flags[1] = 'W';
4063 if (read) flags[2] = 'R';
4064 try writer.print("phdr({d}) : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})\n", .{
4065 i, flags, phdr.p_offset, phdr.p_vaddr, phdr.p_align, phdr.p_filesz, phdr.p_memsz,
4066 });
4067 }
4068}
4069
40114070fn dumpState(self: *Elf) std.fmt.Formatter(fmtDumpState) {
40124071 return .{ .data = self };
40134072}
......@@ -4047,6 +4106,10 @@ fn fmtDumpState(
40474106 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
40484107 }
40494108 try writer.print("{}\n", .{self.got.fmt(self)});
4109 try writer.writeAll("Output shdrs\n");
4110 try writer.print("{}\n", .{self.fmtShdrs()});
4111 try writer.writeAll("Output phdrs\n");
4112 try writer.print("{}\n", .{self.fmtPhdrs()});
40504113}
40514114
40524115/// Binary search
src/link/Elf/Atom.zig+10-5
......@@ -17,7 +17,7 @@ alignment: Alignment = .@"1",
1717input_section_index: Index = 0,
1818
1919/// Index of the output section.
20output_section_index: Index = 0,
20output_section_index: u16 = 0,
2121
2222/// Index of the input section containing this atom's relocs.
2323relocs_section_index: Index = 0,
......@@ -53,6 +53,11 @@ pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
5353 return object.shdrs.items[self.input_section_index];
5454}
5555
56pub fn outputShndx(self: Atom) ?u16 {
57 if (self.output_section_index == 0) return null;
58 return self.output_section_index;
59}
60
5661pub fn codeInObject(self: Atom, elf_file: *Elf) error{Overflow}![]const u8 {
5762 const object = elf_file.file(self.file_index).?.object;
5863 return object.shdrContents(self.input_section_index);
......@@ -109,8 +114,8 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
109114}
110115
111116pub fn allocate(self: *Atom, elf_file: *Elf) !void {
112 const shdr = &elf_file.shdrs.items[self.output_section_index];
113 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
117 const shdr = &elf_file.shdrs.items[self.outputShndx().?];
118 const meta = elf_file.last_atom_and_free_list_table.getPtr(self.outputShndx().?).?;
114119 const free_list = &meta.free_list;
115120 const last_atom_index = &meta.last_atom_index;
116121 const new_atom_ideal_capacity = Elf.padToIdeal(self.size);
......@@ -179,7 +184,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
179184 true;
180185 if (expand_section) {
181186 const needed_size = (self.value + self.size) - shdr.sh_addr;
182 try elf_file.growAllocSection(self.output_section_index, needed_size);
187 try elf_file.growAllocSection(self.outputShndx().?, needed_size);
183188 last_atom_index.* = self.atom_index;
184189
185190 if (elf_file.dwarf) |_| {
......@@ -234,7 +239,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
234239
235240 const gpa = elf_file.base.allocator;
236241 const zig_module = elf_file.file(self.file_index).?.zig_module;
237 const shndx = self.output_section_index;
242 const shndx = self.outputShndx().?;
238243 const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?;
239244 const free_list = &meta.free_list;
240245 const last_atom_index = &meta.last_atom_index;
src/link/Elf/Object.zig+4-4
......@@ -272,9 +272,9 @@ fn initSymtab(self: *Object, elf_file: *Elf) !void {
272272 sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];
273273 sym_ptr.file_index = self.index;
274274 sym_ptr.output_section_index = if (sym_ptr.atom(elf_file)) |atom_ptr|
275 atom_ptr.output_section_index
275 atom_ptr.outputShndx().?
276276 else
277 0;
277 elf.SHN_UNDEF;
278278 }
279279
280280 for (self.symtab[first_global..]) |sym| {
......@@ -440,9 +440,9 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
440440 else => self.atoms.items[esym.st_shndx],
441441 };
442442 const output_section_index = if (elf_file.atom(atom_index)) |atom|
443 atom.output_section_index
443 atom.outputShndx().?
444444 else
445 0;
445 elf.SHN_UNDEF;
446446 global.value = esym.st_value;
447447 global.atom_index = atom_index;
448448 global.esym_index = esym_index;
src/link/Elf/Symbol.zig+9-4
......@@ -33,10 +33,15 @@ extra_index: u32 = 0,
3333pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool {
3434 const file_ptr = symbol.file(elf_file).?;
3535 // if (file_ptr == .shared) return symbol.sourceSymbol(elf_file).st_shndx == elf.SHN_ABS;
36 return !symbol.flags.import and symbol.atom(elf_file) == null and symbol.output_section_index == 0 and
36 return !symbol.flags.import and symbol.atom(elf_file) == null and symbol.outputShndx() == null and
3737 file_ptr != .linker_defined;
3838}
3939
40pub fn outputShndx(symbol: Symbol) ?u16 {
41 if (symbol.output_section_index == 0) return null;
42 return symbol.output_section_index;
43}
44
4045pub fn isLocal(symbol: Symbol) bool {
4146 return !(symbol.flags.import or symbol.flags.@"export");
4247}
......@@ -183,7 +188,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
183188 // if (file_ptr == .shared or s_sym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
184189 if (symbol.atom(elf_file) == null and file_ptr != .linker_defined)
185190 break :blk elf.SHN_ABS;
186 break :blk symbol.output_section_index;
191 break :blk symbol.outputShndx() orelse elf.SHN_UNDEF;
187192 };
188193 const st_value = blk: {
189194 // if (symbol.flags.copy_rel) break :blk symbol.address(.{}, elf_file);
......@@ -276,8 +281,8 @@ fn format2(
276281 } else {
277282 try writer.writeAll(" : absolute");
278283 }
279 } else if (symbol.output_section_index != 0) {
280 try writer.print(" : sect({d})", .{symbol.output_section_index});
284 } else if (symbol.outputShndx()) |shndx| {
285 try writer.print(" : sect({d})", .{shndx});
281286 }
282287 if (symbol.atom(ctx.elf_file)) |atom_ptr| {
283288 try writer.print(" : atom({d})", .{atom_ptr.atom_index});
src/link/Elf/ZigModule.zig+3-5
......@@ -49,21 +49,19 @@ pub fn addGlobalEsym(self: *ZigModule, allocator: Allocator) !Symbol.Index {
4949 return index | 0x10000000;
5050}
5151
52pub fn addAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
52pub fn addAtom(self: *ZigModule, elf_file: *Elf) !Symbol.Index {
5353 const gpa = elf_file.base.allocator;
5454
5555 const atom_index = try elf_file.addAtom();
5656 try self.atoms.putNoClobber(gpa, atom_index, {});
5757 const atom_ptr = elf_file.atom(atom_index).?;
5858 atom_ptr.file_index = self.index;
59 atom_ptr.output_section_index = output_section_index;
6059
6160 const symbol_index = try elf_file.addSymbol();
6261 try self.local_symbols.append(gpa, symbol_index);
6362 const symbol_ptr = elf_file.symbol(symbol_index);
6463 symbol_ptr.file_index = self.index;
6564 symbol_ptr.atom_index = atom_index;
66 symbol_ptr.output_section_index = output_section_index;
6765
6866 const esym_index = try self.addLocalEsym(gpa);
6967 const esym = &self.local_esyms.items[esym_index];
......@@ -98,9 +96,9 @@ pub fn resolveSymbols(self: *ZigModule, elf_file: *Elf) void {
9896 else => esym.st_shndx,
9997 };
10098 const output_section_index = if (elf_file.atom(atom_index)) |atom|
101 atom.output_section_index
99 atom.outputShndx().?
102100 else
103 0;
101 elf.SHN_UNDEF;
104102 global.value = esym.st_value;
105103 global.atom_index = atom_index;
106104 global.esym_index = esym_index;