authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-05 22:33:02-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-11-09 03:31:26-05:00
log80c961159b56c117281a87bfe7acf853182fb427
treee648f6583066b3ef1babb2499cc86bba1c99bf3e
parent7bcefe5a221fc9f0f277f9e909c1b63fbe0b830b

Elf2: elide unused nodes when emitting objects


2 files changed, 344 insertions(+), 196 deletions(-)

lib/std/elf.zig+227-100
......@@ -286,105 +286,111 @@ pub const VER_FLG_BASE = 1;
286286/// Weak version identifier
287287pub const VER_FLG_WEAK = 2;
288288
289/// Program header table entry unused
290pub const PT_NULL = 0;
291/// Loadable program segment
292pub const PT_LOAD = 1;
293/// Dynamic linking information
294pub const PT_DYNAMIC = 2;
295/// Program interpreter
296pub const PT_INTERP = 3;
297/// Auxiliary information
298pub const PT_NOTE = 4;
299/// Reserved
300pub const PT_SHLIB = 5;
301/// Entry for header table itself
302pub const PT_PHDR = 6;
303/// Thread-local storage segment
304pub const PT_TLS = 7;
305/// Number of defined types
306pub const PT_NUM = 8;
307/// Start of OS-specific
308pub const PT_LOOS = 0x60000000;
309/// GCC .eh_frame_hdr segment
310pub const PT_GNU_EH_FRAME = 0x6474e550;
311/// Indicates stack executability
312pub const PT_GNU_STACK = 0x6474e551;
313/// Read-only after relocation
314pub const PT_GNU_RELRO = 0x6474e552;
315pub const PT_LOSUNW = 0x6ffffffa;
316/// Sun specific segment
317pub const PT_SUNWBSS = 0x6ffffffa;
318/// Stack segment
319pub const PT_SUNWSTACK = 0x6ffffffb;
320pub const PT_HISUNW = 0x6fffffff;
321/// End of OS-specific
322pub const PT_HIOS = 0x6fffffff;
323/// Start of processor-specific
324pub const PT_LOPROC = 0x70000000;
325/// End of processor-specific
326pub const PT_HIPROC = 0x7fffffff;
289/// Deprecated, use `@intFromEnum(std.elf.PT.NULL)`
290pub const PT_NULL = @intFromEnum(std.elf.PT.NULL);
291/// Deprecated, use `@intFromEnum(std.elf.PT.LOAD)`
292pub const PT_LOAD = @intFromEnum(std.elf.PT.LOAD);
293/// Deprecated, use `@intFromEnum(std.elf.PT.DYNAMIC)`
294pub const PT_DYNAMIC = @intFromEnum(std.elf.PT.DYNAMIC);
295/// Deprecated, use `@intFromEnum(std.elf.PT.INTERP)`
296pub const PT_INTERP = @intFromEnum(std.elf.PT.INTERP);
297/// Deprecated, use `@intFromEnum(std.elf.PT.NOTE)`
298pub const PT_NOTE = @intFromEnum(std.elf.PT.NOTE);
299/// Deprecated, use `@intFromEnum(std.elf.PT.SHLIB)`
300pub const PT_SHLIB = @intFromEnum(std.elf.PT.SHLIB);
301/// Deprecated, use `@intFromEnum(std.elf.PT.PHDR)`
302pub const PT_PHDR = @intFromEnum(std.elf.PT.PHDR);
303/// Deprecated, use `@intFromEnum(std.elf.PT.TLS)`
304pub const PT_TLS = @intFromEnum(std.elf.PT.TLS);
305/// Deprecated, use `std.elf.PT.NUM`.
306pub const PT_NUM = PT.NUM;
307/// Deprecated, use `@intFromEnum(std.elf.PT.LOOS)`
308pub const PT_LOOS = @intFromEnum(std.elf.PT.LOOS);
309/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_EH_FRAME)`
310pub const PT_GNU_EH_FRAME = @intFromEnum(std.elf.PT.GNU_EH_FRAME);
311/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_STACK)`
312pub const PT_GNU_STACK = @intFromEnum(std.elf.PT.GNU_STACK);
313/// Deprecated, use `@intFromEnum(std.elf.PT.GNU_RELRO)`
314pub const PT_GNU_RELRO = @intFromEnum(std.elf.PT.GNU_RELRO);
315/// Deprecated, use `@intFromEnum(std.elf.PT.LOSUNW)`
316pub const PT_LOSUNW = @intFromEnum(std.elf.PT.LOSUNW);
317/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWBSS)`
318pub const PT_SUNWBSS = @intFromEnum(std.elf.PT.SUNWBSS);
319/// Deprecated, use `@intFromEnum(std.elf.PT.SUNWSTACK)`
320pub const PT_SUNWSTACK = @intFromEnum(std.elf.PT.SUNWSTACK);
321/// Deprecated, use `@intFromEnum(std.elf.PT.HISUNW)`
322pub const PT_HISUNW = @intFromEnum(std.elf.PT.HISUNW);
323/// Deprecated, use `@intFromEnum(std.elf.PT.HIOS)`
324pub const PT_HIOS = @intFromEnum(std.elf.PT.HIOS);
325/// Deprecated, use `@intFromEnum(std.elf.PT.LOPROC)`
326pub const PT_LOPROC = @intFromEnum(std.elf.PT.LOPROC);
327/// Deprecated, use `@intFromEnum(std.elf.PT.HIPROC)`
328pub const PT_HIPROC = @intFromEnum(std.elf.PT.HIPROC);
327329
328330pub const PN_XNUM = 0xffff;
329331
330/// Section header table entry unused
331pub const SHT_NULL = 0;
332/// Program data
333pub const SHT_PROGBITS = 1;
334/// Symbol table
335pub const SHT_SYMTAB = 2;
336/// String table
337pub const SHT_STRTAB = 3;
338/// Relocation entries with addends
339pub const SHT_RELA = 4;
340/// Symbol hash table
341pub const SHT_HASH = 5;
342/// Dynamic linking information
343pub const SHT_DYNAMIC = 6;
344/// Notes
345pub const SHT_NOTE = 7;
346/// Program space with no data (bss)
347pub const SHT_NOBITS = 8;
348/// Relocation entries, no addends
349pub const SHT_REL = 9;
350/// Reserved
351pub const SHT_SHLIB = 10;
352/// Dynamic linker symbol table
353pub const SHT_DYNSYM = 11;
354/// Array of constructors
355pub const SHT_INIT_ARRAY = 14;
356/// Array of destructors
357pub const SHT_FINI_ARRAY = 15;
358/// Array of pre-constructors
359pub const SHT_PREINIT_ARRAY = 16;
360/// Section group
361pub const SHT_GROUP = 17;
362/// Extended section indices
363pub const SHT_SYMTAB_SHNDX = 18;
364/// Start of OS-specific
365pub const SHT_LOOS = 0x60000000;
366/// LLVM address-significance table
367pub const SHT_LLVM_ADDRSIG = 0x6fff4c03;
368/// GNU hash table
369pub const SHT_GNU_HASH = 0x6ffffff6;
370/// GNU version definition table
371pub const SHT_GNU_VERDEF = 0x6ffffffd;
372/// GNU needed versions table
373pub const SHT_GNU_VERNEED = 0x6ffffffe;
374/// GNU symbol version table
375pub const SHT_GNU_VERSYM = 0x6fffffff;
376/// End of OS-specific
377pub const SHT_HIOS = 0x6fffffff;
378/// Start of processor-specific
379pub const SHT_LOPROC = 0x70000000;
380/// Unwind information
381pub const SHT_X86_64_UNWIND = 0x70000001;
382/// End of processor-specific
383pub const SHT_HIPROC = 0x7fffffff;
384/// Start of application-specific
385pub const SHT_LOUSER = 0x80000000;
386/// End of application-specific
387pub const SHT_HIUSER = 0xffffffff;
332/// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)`
333pub const SHT_NULL = @intFromEnum(std.elf.SHT.NULL);
334/// Deprecated, use `@intFromEnum(std.elf.SHT.PROGBITS)`
335pub const SHT_PROGBITS = @intFromEnum(std.elf.SHT.PROGBITS);
336/// Deprecated, use `@intFromEnum(std.elf.SHT.SYMTAB)`
337pub const SHT_SYMTAB = @intFromEnum(std.elf.SHT.SYMTAB);
338/// Deprecated, use `@intFromEnum(std.elf.SHT.STRTAB)`
339pub const SHT_STRTAB = @intFromEnum(std.elf.SHT.STRTAB);
340/// Deprecated, use `@intFromEnum(std.elf.SHT.RELA)`
341pub const SHT_RELA = @intFromEnum(std.elf.SHT.RELA);
342/// Deprecated, use `@intFromEnum(std.elf.SHT.HASH)`
343pub const SHT_HASH = @intFromEnum(std.elf.SHT.HASH);
344/// Deprecated, use `@intFromEnum(std.elf.SHT.DYNAMIC)`
345pub const SHT_DYNAMIC = @intFromEnum(std.elf.SHT.DYNAMIC);
346/// Deprecated, use `@intFromEnum(std.elf.SHT.NOTE)`
347pub const SHT_NOTE = @intFromEnum(std.elf.SHT.NOTE);
348/// Deprecated, use `@intFromEnum(std.elf.SHT.NOBITS)`
349pub const SHT_NOBITS = @intFromEnum(std.elf.SHT.NOBITS);
350/// Deprecated, use `@intFromEnum(std.elf.SHT.REL)`
351pub const SHT_REL = @intFromEnum(std.elf.SHT.REL);
352/// Deprecated, use `@intFromEnum(std.elf.SHT.SHLIB)`
353pub const SHT_SHLIB = @intFromEnum(std.elf.SHT.SHLIB);
354/// Deprecated, use `@intFromEnum(std.elf.SHT.DYNSYM)`
355pub const SHT_DYNSYM = @intFromEnum(std.elf.SHT.DYNSYM);
356/// Deprecated, use `@intFromEnum(std.elf.SHT.INIT_ARRAY)`
357pub const SHT_INIT_ARRAY = @intFromEnum(std.elf.SHT.INIT_ARRAY);
358/// Deprecated, use `@intFromEnum(std.elf.SHT.FINI_ARRAY)`
359pub const SHT_FINI_ARRAY = @intFromEnum(std.elf.SHT.FINI_ARRAY);
360/// Deprecated, use `@intFromEnum(std.elf.SHT.PREINIT_ARRAY)`
361pub const SHT_PREINIT_ARRAY = @intFromEnum(std.elf.SHT.PREINIT_ARRAY);
362/// Deprecated, use `@intFromEnum(std.elf.SHT.GROUP)`
363pub const SHT_GROUP = @intFromEnum(std.elf.SHT.GROUP);
364/// Deprecated, use `@intFromEnum(std.elf.SHT.SYMTAB_SHNDX)`
365pub const SHT_SYMTAB_SHNDX = @intFromEnum(std.elf.SHT.SYMTAB_SHNDX);
366/// Deprecated, use `@intFromEnum(std.elf.SHT.RELR)`
367pub const SHT_RELR = @intFromEnum(std.elf.SHT.RELR);
368/// Deprecated, use `std.elf.SHT.NUM`.
369pub const SHT_NUM = SHT.NUM;
370/// Deprecated, use `@intFromEnum(std.elf.SHT.LOOS)`
371pub const SHT_LOOS = @intFromEnum(std.elf.SHT.LOOS);
372/// Deprecated, use `@intFromEnum(std.elf.SHT.LLVM_ADDRSIG)`
373pub const SHT_LLVM_ADDRSIG = @intFromEnum(std.elf.SHT.LLVM_ADDRSIG);
374/// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_HASH)`
375pub const SHT_GNU_HASH = @intFromEnum(std.elf.SHT.GNU_HASH);
376/// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERDEF)`
377pub const SHT_GNU_VERDEF = @intFromEnum(std.elf.SHT.GNU_VERDEF);
378/// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERNEED)`
379pub const SHT_GNU_VERNEED = @intFromEnum(std.elf.SHT.GNU_VERNEED);
380/// Deprecated, use `@intFromEnum(std.elf.SHT.GNU_VERSYM)`
381pub const SHT_GNU_VERSYM = @intFromEnum(std.elf.SHT.GNU_VERSYM);
382/// Deprecated, use `@intFromEnum(std.elf.SHT.HIOS)`
383pub const SHT_HIOS = @intFromEnum(std.elf.SHT.HIOS);
384/// Deprecated, use `@intFromEnum(std.elf.SHT.LOPROC)`
385pub const SHT_LOPROC = @intFromEnum(std.elf.SHT.LOPROC);
386/// Deprecated, use `@intFromEnum(std.elf.SHT.X86_64_UNWIND)`
387pub const SHT_X86_64_UNWIND = @intFromEnum(std.elf.SHT.X86_64_UNWIND);
388/// Deprecated, use `@intFromEnum(std.elf.SHT.HIPROC)`
389pub const SHT_HIPROC = @intFromEnum(std.elf.SHT.HIPROC);
390/// Deprecated, use `@intFromEnum(std.elf.SHT.LOUSER)`
391pub const SHT_LOUSER = @intFromEnum(std.elf.SHT.LOUSER);
392/// Deprecated, use `@intFromEnum(std.elf.SHT.HIUSER)`
393pub const SHT_HIUSER = @intFromEnum(std.elf.SHT.HIUSER);
388394
389395// Note type for .note.gnu.build_id
390396pub const NT_GNU_BUILD_ID = 3;
......@@ -454,6 +460,127 @@ pub const STT_ARM_TFUNC = @intFromEnum(STT.ARM_TFUNC);
454460/// Deprecated, use `@intFromEnum(std.elf.STT.ARM_16BIT)`
455461pub const STT_ARM_16BIT = @intFromEnum(STT.ARM_16BIT);
456462
463pub const PT = enum(Word) {
464 /// Program header table entry unused
465 NULL = 0,
466 /// Loadable program segment
467 LOAD = 1,
468 /// Dynamic linking information
469 DYNAMIC = 2,
470 /// Program interpreter
471 INTERP = 3,
472 /// Auxiliary information
473 NOTE = 4,
474 /// Reserved
475 SHLIB = 5,
476 /// Entry for header table itself
477 PHDR = 6,
478 /// Thread-local storage segment
479 TLS = 7,
480 _,
481
482 /// Number of defined types
483 pub const NUM = @typeInfo(PT).@"enum".fields.len;
484
485 /// Start of OS-specific
486 pub const LOOS: PT = @enumFromInt(0x60000000);
487 /// End of OS-specific
488 pub const HIOS: PT = @enumFromInt(0x6fffffff);
489
490 /// GCC .eh_frame_hdr segment
491 pub const GNU_EH_FRAME: PT = @enumFromInt(0x6474e550);
492 /// Indicates stack executability
493 pub const GNU_STACK: PT = @enumFromInt(0x6474e551);
494 /// Read-only after relocation
495 pub const GNU_RELRO: PT = @enumFromInt(0x6474e552);
496
497 pub const LOSUNW: PT = @enumFromInt(0x6ffffffa);
498 pub const HISUNW: PT = @enumFromInt(0x6fffffff);
499
500 /// Sun specific segment
501 pub const SUNWBSS: PT = @enumFromInt(0x6ffffffa);
502 /// Stack segment
503 pub const SUNWSTACK: PT = @enumFromInt(0x6ffffffb);
504
505 /// Start of processor-specific
506 pub const LOPROC: PT = @enumFromInt(0x70000000);
507 /// End of processor-specific
508 pub const HIPROC: PT = @enumFromInt(0x7fffffff);
509};
510
511pub const SHT = enum(Word) {
512 /// Section header table entry unused
513 NULL = 0,
514 /// Program data
515 PROGBITS = 1,
516 /// Symbol table
517 SYMTAB = 2,
518 /// String table
519 STRTAB = 3,
520 /// Relocation entries with addends
521 RELA = 4,
522 /// Symbol hash table
523 HASH = 5,
524 /// Dynamic linking information
525 DYNAMIC = 6,
526 /// Notes
527 NOTE = 7,
528 /// Program space with no data (bss)
529 NOBITS = 8,
530 /// Relocation entries, no addends
531 REL = 9,
532 /// Reserved
533 SHLIB = 10,
534 /// Dynamic linker symbol table
535 DYNSYM = 11,
536 /// Array of constructors
537 INIT_ARRAY = 14,
538 /// Array of destructors
539 FINI_ARRAY = 15,
540 /// Array of pre-constructors
541 PREINIT_ARRAY = 16,
542 /// Section group
543 GROUP = 17,
544 /// Extended section indices
545 SYMTAB_SHNDX = 18,
546 /// RELR relative relocations
547 RELR = 19,
548 _,
549
550 /// Number of defined types
551 pub const NUM = @typeInfo(SHT).@"enum".fields.len;
552
553 /// Start of OS-specific
554 pub const LOOS: SHT = @enumFromInt(0x60000000);
555 /// End of OS-specific
556 pub const HIOS: SHT = @enumFromInt(0x6fffffff);
557
558 /// LLVM address-significance table
559 pub const LLVM_ADDRSIG: SHT = @enumFromInt(0x6fff4c03);
560
561 /// GNU hash table
562 pub const GNU_HASH: SHT = @enumFromInt(0x6ffffff6);
563 /// GNU version definition table
564 pub const GNU_VERDEF: SHT = @enumFromInt(0x6ffffffd);
565 /// GNU needed versions table
566 pub const GNU_VERNEED: SHT = @enumFromInt(0x6ffffffe);
567 /// GNU symbol version table
568 pub const GNU_VERSYM: SHT = @enumFromInt(0x6fffffff);
569
570 /// Start of processor-specific
571 pub const LOPROC: SHT = @enumFromInt(0x70000000);
572 /// End of processor-specific
573 pub const HIPROC: SHT = @enumFromInt(0x7fffffff);
574
575 /// Unwind information
576 pub const X86_64_UNWIND: SHT = @enumFromInt(0x70000001);
577
578 /// Start of application-specific
579 pub const LOUSER: SHT = @enumFromInt(0x80000000);
580 /// End of application-specific
581 pub const HIUSER: SHT = @enumFromInt(0xffffffff);
582};
583
457584pub const STB = enum(u4) {
458585 /// Local symbol
459586 LOCAL = 0,
......@@ -899,7 +1026,7 @@ pub const Elf32 = struct {
8991026 shstrndx: Half,
9001027 };
9011028 pub const Phdr = extern struct {
902 type: Word,
1029 type: PT,
9031030 offset: Elf32.Off,
9041031 vaddr: Elf32.Addr,
9051032 paddr: Elf32.Addr,
......@@ -910,7 +1037,7 @@ pub const Elf32 = struct {
9101037 };
9111038 pub const Shdr = extern struct {
9121039 name: Word,
913 type: Word,
1040 type: SHT,
9141041 flags: packed struct { shf: SHF },
9151042 addr: Elf32.Addr,
9161043 offset: Elf32.Off,
......@@ -989,7 +1116,7 @@ pub const Elf64 = struct {
9891116 shstrndx: Half,
9901117 };
9911118 pub const Phdr = extern struct {
992 type: Word,
1119 type: PT,
9931120 flags: PF,
9941121 offset: Elf64.Off,
9951122 vaddr: Elf64.Addr,
......@@ -1000,7 +1127,7 @@ pub const Elf64 = struct {
10001127 };
10011128 pub const Shdr = extern struct {
10021129 name: Word,
1003 type: Word,
1130 type: SHT,
10041131 flags: packed struct { shf: SHF, unused: Word = 0 },
10051132 addr: Elf64.Addr,
10061133 offset: Elf64.Off,
src/link/Elf2.zig+117-96
......@@ -462,7 +462,7 @@ pub const Reloc = extern struct {
462462 .TPOFF32 => {
463463 const phdr = @field(elf.phdrSlice(), @tagName(class));
464464 const ph = &phdr[elf.getNode(elf.ni.tls).segment];
465 assert(elf.targetLoad(&ph.type) == std.elf.PT_TLS);
465 assert(elf.targetLoad(&ph.type) == .TLS);
466466 std.mem.writeInt(
467467 i32,
468468 loc_slice[0..4],
......@@ -715,12 +715,15 @@ fn initHeaders(
715715 break :phndx phnum;
716716 } else undefined;
717717
718 const expected_nodes_len = expected_nodes_len: {
719 const expected_nodes_len = 5 + phnum * 2 + @as(usize, 2) * @intFromBool(have_dynamic_section);
720 if (@"type" != .REL) break :expected_nodes_len expected_nodes_len;
721 phnum = 0;
722 break :expected_nodes_len expected_nodes_len -
723 @intFromBool(comp.config.any_non_single_threaded);
718 const expected_nodes_len = expected_nodes_len: switch (@"type") {
719 .NONE => unreachable,
720 .REL => {
721 defer phnum = 0;
722 break :expected_nodes_len 5 + phnum;
723 },
724 .EXEC, .DYN => break :expected_nodes_len 5 + phnum * 2 +
725 @as(usize, 2) * @intFromBool(have_dynamic_section),
726 .CORE, _ => unreachable,
724727 };
725728 try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len);
726729 try elf.phdrs.resize(gpa, phnum);
......@@ -771,51 +774,53 @@ fn initHeaders(
771774 }));
772775 elf.nodes.appendAssumeCapacity(.shdr);
773776
774 assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
775 .alignment = elf.mf.flags.block_size,
776 .moved = @"type" != .REL,
777 .bubbles_moved = false,
778 }));
779 elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx });
780 if (@"type" != .REL) elf.phdrs.items[rodata_phndx] = elf.ni.rodata;
777 var ph_vaddr: u32 = if (@"type" != .REL) ph_vaddr: {
778 assert(elf.ni.rodata == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
779 .alignment = elf.mf.flags.block_size,
780 .moved = true,
781 .bubbles_moved = false,
782 }));
783 elf.nodes.appendAssumeCapacity(.{ .segment = rodata_phndx });
784 elf.phdrs.items[rodata_phndx] = elf.ni.rodata;
781785
782 assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{
783 .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum),
784 .alignment = addr_align,
785 .moved = @"type" != .REL,
786 .resized = @"type" != .REL,
787 .bubbles_moved = false,
788 }));
789 elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx });
790 if (@"type" != .REL) elf.phdrs.items[phdr_phndx] = elf.ni.phdr;
786 assert(elf.ni.phdr == try elf.mf.addOnlyChildNode(gpa, elf.ni.rodata, .{
787 .size = elf.ehdrField(.phentsize) * elf.ehdrField(.phnum),
788 .alignment = addr_align,
789 .moved = true,
790 .resized = true,
791 .bubbles_moved = false,
792 }));
793 elf.nodes.appendAssumeCapacity(.{ .segment = phdr_phndx });
794 elf.phdrs.items[phdr_phndx] = elf.ni.phdr;
791795
792 assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
793 .alignment = elf.mf.flags.block_size,
794 .moved = @"type" != .REL,
795 .bubbles_moved = false,
796 }));
797 elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx });
798 if (@"type" != .REL) elf.phdrs.items[text_phndx] = elf.ni.text;
796 assert(elf.ni.text == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
797 .alignment = elf.mf.flags.block_size,
798 .moved = true,
799 .bubbles_moved = false,
800 }));
801 elf.nodes.appendAssumeCapacity(.{ .segment = text_phndx });
802 elf.phdrs.items[text_phndx] = elf.ni.text;
799803
800 assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
801 .alignment = elf.mf.flags.block_size,
802 .moved = @"type" != .REL,
803 .bubbles_moved = false,
804 }));
805 elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx });
806 if (@"type" != .REL) elf.phdrs.items[data_phndx] = elf.ni.data;
807
808 var ph_vaddr: u32 = switch (elf.ehdrField(.type)) {
809 else => 0,
810 .EXEC => switch (elf.ehdrField(.machine)) {
811 .@"386" => 0x400000,
812 .AARCH64, .X86_64 => 0x200000,
813 .PPC, .PPC64 => 0x10000000,
814 .S390, .S390_OLD => 0x1000000,
815 .OLD_SPARCV9, .SPARCV9 => 0x100000,
816 else => 0x10000,
817 },
818 };
804 assert(elf.ni.data == try elf.mf.addLastChildNode(gpa, elf.ni.file, .{
805 .alignment = elf.mf.flags.block_size,
806 .moved = true,
807 .bubbles_moved = false,
808 }));
809 elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx });
810 elf.phdrs.items[data_phndx] = elf.ni.data;
811
812 break :ph_vaddr switch (elf.ehdrField(.type)) {
813 else => 0,
814 .EXEC => switch (elf.ehdrField(.machine)) {
815 .@"386" => 0x400000,
816 .AARCH64, .X86_64 => 0x200000,
817 .PPC, .PPC64 => 0x10000000,
818 .S390, .S390_OLD => 0x1000000,
819 .OLD_SPARCV9, .SPARCV9 => 0x100000,
820 else => 0x10000,
821 },
822 };
823 } else undefined;
819824 switch (class) {
820825 .NONE, _ => unreachable,
821826 inline else => |ct_class| {
......@@ -826,7 +831,7 @@ fn initHeaders(
826831 const phdr: []ElfN.Phdr = @ptrCast(@alignCast(elf.ni.phdr.slice(&elf.mf)));
827832 const ph_phdr = &phdr[phdr_phndx];
828833 ph_phdr.* = .{
829 .type = std.elf.PT_PHDR,
834 .type = .PHDR,
830835 .offset = 0,
831836 .vaddr = 0,
832837 .paddr = 0,
......@@ -840,7 +845,7 @@ fn initHeaders(
840845 if (maybe_interp) |_| {
841846 const ph_interp = &phdr[interp_phndx];
842847 ph_interp.* = .{
843 .type = std.elf.PT_INTERP,
848 .type = .INTERP,
844849 .offset = 0,
845850 .vaddr = 0,
846851 .paddr = 0,
......@@ -855,7 +860,7 @@ fn initHeaders(
855860 _, const rodata_size = elf.ni.rodata.location(&elf.mf).resolve(&elf.mf);
856861 const ph_rodata = &phdr[rodata_phndx];
857862 ph_rodata.* = .{
858 .type = std.elf.PT_NULL,
863 .type = if (rodata_size == 0) .NULL else .LOAD,
859864 .offset = 0,
860865 .vaddr = ph_vaddr,
861866 .paddr = ph_vaddr,
......@@ -870,7 +875,7 @@ fn initHeaders(
870875 _, const text_size = elf.ni.text.location(&elf.mf).resolve(&elf.mf);
871876 const ph_text = &phdr[text_phndx];
872877 ph_text.* = .{
873 .type = std.elf.PT_NULL,
878 .type = if (text_size == 0) .NULL else .LOAD,
874879 .offset = 0,
875880 .vaddr = ph_vaddr,
876881 .paddr = ph_vaddr,
......@@ -885,7 +890,7 @@ fn initHeaders(
885890 _, const data_size = elf.ni.data.location(&elf.mf).resolve(&elf.mf);
886891 const ph_data = &phdr[data_phndx];
887892 ph_data.* = .{
888 .type = std.elf.PT_NULL,
893 .type = if (data_size == 0) .NULL else .LOAD,
889894 .offset = 0,
890895 .vaddr = ph_vaddr,
891896 .paddr = ph_vaddr,
......@@ -900,7 +905,7 @@ fn initHeaders(
900905 if (have_dynamic_section) {
901906 const ph_dynamic = &phdr[dynamic_phndx];
902907 ph_dynamic.* = .{
903 .type = std.elf.PT_DYNAMIC,
908 .type = .DYNAMIC,
904909 .offset = 0,
905910 .vaddr = 0,
906911 .paddr = 0,
......@@ -915,7 +920,7 @@ fn initHeaders(
915920 if (comp.config.any_non_single_threaded) {
916921 const ph_tls = &phdr[tls_phndx];
917922 ph_tls.* = .{
918 .type = std.elf.PT_TLS,
923 .type = .TLS,
919924 .offset = 0,
920925 .vaddr = 0,
921926 .paddr = 0,
......@@ -931,7 +936,7 @@ fn initHeaders(
931936 const sh_null: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf)));
932937 sh_null.* = .{
933938 .name = try elf.string(.shstrtab, ""),
934 .type = std.elf.SHT_NULL,
939 .type = .NULL,
935940 .flags = .{ .shf = .{} },
936941 .addr = 0,
937942 .offset = 0,
......@@ -951,7 +956,7 @@ fn initHeaders(
951956 .unused = 0,
952957 };
953958 assert(elf.si.symtab == try elf.addSection(elf.ni.file, .{
954 .type = std.elf.SHT_SYMTAB,
959 .type = .SYMTAB,
955960 .size = @sizeOf(ElfN.Sym) * 1,
956961 .addralign = addr_align,
957962 .entsize = @sizeOf(ElfN.Sym),
......@@ -972,7 +977,7 @@ fn initHeaders(
972977 },
973978 }
974979 assert(elf.si.shstrtab == try elf.addSection(elf.ni.file, .{
975 .type = std.elf.SHT_STRTAB,
980 .type = .STRTAB,
976981 .addralign = elf.mf.flags.block_size,
977982 .entsize = 1,
978983 }));
......@@ -982,7 +987,7 @@ fn initHeaders(
982987
983988 assert(elf.si.strtab == try elf.addSection(elf.ni.file, .{
984989 .name = ".strtab",
985 .type = std.elf.SHT_STRTAB,
990 .type = .STRTAB,
986991 .size = 1,
987992 .addralign = elf.mf.flags.block_size,
988993 .entsize = 1,
......@@ -1016,6 +1021,7 @@ fn initHeaders(
10161021 elf.phdrs.items[interp_phndx] = interp_ni;
10171022
10181023 const sec_interp_si = try elf.addSection(interp_ni, .{
1024 .type = .PROGBITS,
10191025 .name = ".interp",
10201026 .flags = .{ .ALLOC = true },
10211027 .size = @intCast(interp.len + 1),
......@@ -1038,7 +1044,7 @@ fn initHeaders(
10381044 const ElfN = ct_class.ElfN();
10391045 elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{
10401046 .name = ".dynsym",
1041 .type = std.elf.SHT_DYNSYM,
1047 .type = .DYNSYM,
10421048 .size = @sizeOf(ElfN.Sym) * 1,
10431049 .addralign = addr_align,
10441050 .entsize = @sizeOf(ElfN.Sym),
......@@ -1057,14 +1063,14 @@ fn initHeaders(
10571063 }
10581064 elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{
10591065 .name = ".dynstr",
1060 .type = std.elf.SHT_STRTAB,
1066 .type = .STRTAB,
10611067 .size = 1,
10621068 .addralign = elf.mf.flags.block_size,
10631069 .entsize = 1,
10641070 });
10651071 elf.si.dynamic = try elf.addSection(dynamic_ni, .{
10661072 .name = ".dynamic",
1067 .type = std.elf.SHT_DYNAMIC,
1073 .type = .DYNAMIC,
10681074 .flags = .{ .ALLOC = true, .WRITE = true },
10691075 .addralign = addr_align,
10701076 });
......@@ -1126,7 +1132,7 @@ fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 {
11261132 .file => return 0,
11271133 .ehdr, .shdr => unreachable,
11281134 .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) {
1129 inline else => |ph| elf.targetLoad(&ph[phndx].vaddr),
1135 inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr),
11301136 },
11311137 .section => |si| si,
11321138 .input_section => unreachable,
......@@ -1581,7 +1587,7 @@ fn loadObject(
15811587 };
15821588 try r.discardAll(ehdr.shentsize);
15831589 switch (section.shdr.type) {
1584 std.elf.SHT_NULL, std.elf.SHT_NOBITS => {},
1590 .NULL, .NOBITS => {},
15851591 else => if (section.shdr.offset + section.shdr.size > fl.size)
15861592 return diags.failParse(path, "bad section location", .{}),
15871593 }
......@@ -1590,8 +1596,7 @@ fn loadObject(
15901596 if (ehdr.shstrndx == std.elf.SHN_UNDEF or ehdr.shstrndx >= ehdr.shnum)
15911597 return diags.failParse(path, "missing section names", .{});
15921598 const shdr = &sections[ehdr.shstrndx].shdr;
1593 if (shdr.type != std.elf.SHT_STRTAB)
1594 return diags.failParse(path, "invalid shstrtab type", .{});
1599 if (shdr.type != .STRTAB) return diags.failParse(path, "invalid shstrtab type", .{});
15951600 const shstrtab = try gpa.alloc(u8, @intCast(shdr.size));
15961601 errdefer gpa.free(shstrtab);
15971602 try fr.seekTo(fl.offset + shdr.offset);
......@@ -1604,7 +1609,7 @@ fn loadObject(
16041609 try elf.input_sections.ensureUnusedCapacity(gpa, ehdr.shnum - 1);
16051610 for (sections[1..]) |*section| switch (section.shdr.type) {
16061611 else => {},
1607 std.elf.SHT_PROGBITS, std.elf.SHT_NOBITS => {
1612 .PROGBITS, .NOBITS => {
16081613 if (section.shdr.name >= shstrtab.len) continue;
16091614 const name = std.mem.sliceTo(shstrtab[section.shdr.name..], 0);
16101615 const parent_si = elf.namedSection(name) orelse continue;
......@@ -1639,14 +1644,14 @@ fn loadObject(
16391644 defer symmap.deinit(gpa);
16401645 for (sections[1..], 1..) |*symtab, symtab_shndx| switch (symtab.shdr.type) {
16411646 else => {},
1642 std.elf.SHT_SYMTAB => {
1647 .SYMTAB => {
16431648 if (symtab.shdr.entsize < @sizeOf(ElfN.Sym))
16441649 return diags.failParse(path, "unsupported symtab entsize", .{});
16451650 const strtab = strtab: {
16461651 if (symtab.shdr.link == std.elf.SHN_UNDEF or symtab.shdr.link >= ehdr.shnum)
16471652 return diags.failParse(path, "missing symbol names", .{});
16481653 const shdr = &sections[symtab.shdr.link].shdr;
1649 if (shdr.type != std.elf.SHT_STRTAB)
1654 if (shdr.type != .STRTAB)
16501655 return diags.failParse(path, "invalid strtab type", .{});
16511656 const strtab = try gpa.alloc(u8, @intCast(shdr.size));
16521657 errdefer gpa.free(strtab);
......@@ -1729,13 +1734,13 @@ fn loadObject(
17291734 }
17301735 for (sections[1..]) |*rels| switch (rels.shdr.type) {
17311736 else => {},
1732 inline std.elf.SHT_REL, std.elf.SHT_RELA => |sht| {
1737 inline .REL, .RELA => |sht| {
17331738 if (rels.shdr.link != symtab_shndx or rels.shdr.info == std.elf.SHN_UNDEF or
17341739 rels.shdr.info >= ehdr.shnum) continue;
17351740 const Rel = switch (sht) {
17361741 else => comptime unreachable,
1737 std.elf.SHT_REL => ElfN.Rel,
1738 std.elf.SHT_RELA => ElfN.Rela,
1742 .REL => ElfN.Rel,
1743 .RELA => ElfN.Rela,
17391744 };
17401745 if (rels.shdr.entsize < @sizeOf(Rel))
17411746 return diags.failParse(path, "unsupported rel entsize", .{});
......@@ -1810,7 +1815,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void
18101815 try r.discardAll(ehdr.phentsize);
18111816 switch (ph.type) {
18121817 else => {},
1813 std.elf.PT_DYNAMIC => break ph,
1818 .DYNAMIC => break ph,
18141819 }
18151820 } else return diags.failParse(path, "no dynamic segment", .{});
18161821 const dynnum = std.math.divExact(
......@@ -1846,7 +1851,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void
18461851 try r.discardAll(ehdr.phentsize);
18471852 switch (ph.type) {
18481853 else => {},
1849 std.elf.PT_LOAD => if (strtab.? >= ph.vaddr and
1854 .LOAD => if (strtab.? >= ph.vaddr and
18501855 strtab.? + (strsz orelse 0) <= ph.vaddr + ph.filesz) break ph,
18511856 }
18521857 } else return diags.failParse(path, "strtab not part of a loaded segment", .{});
......@@ -1982,15 +1987,15 @@ pub fn getVAddr(elf: *Elf, reloc_info: link.File.RelocInfo, target_si: Symbol.In
19821987
19831988fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
19841989 name: []const u8 = "",
1985 type: std.elf.Word = std.elf.SHT_NULL,
1990 type: std.elf.SHT = .NULL,
19861991 flags: std.elf.SHF = .{},
19871992 size: std.elf.Word = 0,
19881993 addralign: std.mem.Alignment = .@"1",
19891994 entsize: std.elf.Word = 0,
19901995}) !Symbol.Index {
19911996 switch (opts.type) {
1992 std.elf.SHT_NULL => assert(opts.size == 0),
1993 std.elf.SHT_PROGBITS => assert(opts.size > 0),
1997 .NULL => assert(opts.size == 0),
1998 .PROGBITS => assert(opts.size > 0),
19941999 else => {},
19952000 }
19962001 const gpa = elf.base.comp.gpa;
......@@ -2626,10 +2631,10 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
26262631 const ph = &phdr[phndx];
26272632 switch (elf.targetLoad(&ph.type)) {
26282633 else => unreachable,
2629 std.elf.PT_NULL, std.elf.PT_LOAD => return,
2630 std.elf.PT_DYNAMIC, std.elf.PT_INTERP => {},
2631 std.elf.PT_PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset,
2632 std.elf.PT_TLS => {},
2634 .NULL, .LOAD => return,
2635 .DYNAMIC, .INTERP => {},
2636 .PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset,
2637 .TLS => {},
26332638 }
26342639 elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni)));
26352640 ph.paddr = ph.vaddr;
......@@ -2694,22 +2699,18 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
26942699 elf.targetStore(&ph.memsz, @intCast(memsz));
26952700 switch (elf.targetLoad(&ph.type)) {
26962701 else => unreachable,
2697 std.elf.PT_NULL => if (size > 0) elf.targetStore(&ph.type, std.elf.PT_LOAD),
2698 std.elf.PT_LOAD => if (size == 0) elf.targetStore(&ph.type, std.elf.PT_NULL),
2699 std.elf.PT_DYNAMIC, std.elf.PT_INTERP, std.elf.PT_PHDR => return,
2700 std.elf.PT_TLS => return ni.childrenMoved(elf.base.comp.gpa, &elf.mf),
2702 .NULL => if (size > 0) elf.targetStore(&ph.type, .LOAD),
2703 .LOAD => if (size == 0) elf.targetStore(&ph.type, .NULL),
2704 .DYNAMIC, .INTERP, .PHDR => return,
2705 .TLS => return ni.childrenMoved(elf.base.comp.gpa, &elf.mf),
27012706 }
27022707 var vaddr = elf.targetLoad(&ph.vaddr);
27032708 var new_phndx = phndx;
27042709 for (phdr[phndx + 1 ..], phndx + 1..) |*next_ph, next_phndx| {
27052710 switch (elf.targetLoad(&next_ph.type)) {
27062711 else => unreachable,
2707 std.elf.PT_NULL, std.elf.PT_LOAD => {},
2708 std.elf.PT_DYNAMIC,
2709 std.elf.PT_INTERP,
2710 std.elf.PT_PHDR,
2711 std.elf.PT_TLS,
2712 => break,
2712 .NULL, .LOAD => {},
2713 .DYNAMIC, .INTERP, .PHDR, .TLS => break,
27132714 }
27142715 const next_vaddr = elf.targetLoad(&next_ph.vaddr);
27152716 if (vaddr + memsz <= next_vaddr) break;
......@@ -2737,13 +2738,13 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void {
27372738 elf.targetStore(&sh.size, @intCast(size));
27382739 switch (elf.targetLoad(&sh.type)) {
27392740 else => unreachable,
2740 std.elf.SHT_NULL => if (size > 0) elf.targetStore(&sh.type, std.elf.SHT_PROGBITS),
2741 std.elf.SHT_PROGBITS => if (size == 0) elf.targetStore(&sh.type, std.elf.SHT_NULL),
2742 std.elf.SHT_SYMTAB, std.elf.SHT_DYNSYM => elf.targetStore(
2741 .NULL => if (size > 0) elf.targetStore(&sh.type, .PROGBITS),
2742 .PROGBITS => if (size == 0) elf.targetStore(&sh.type, .NULL),
2743 .SYMTAB, .DYNSYM => elf.targetStore(
27432744 &sh.info,
27442745 @intCast(@divExact(size, elf.targetLoad(&sh.entsize))),
27452746 ),
2746 std.elf.SHT_STRTAB, std.elf.SHT_DYNAMIC => {},
2747 .STRTAB, .DYNAMIC => {},
27472748 }
27482749 },
27492750 },
......@@ -2870,6 +2871,26 @@ pub fn printNode(
28702871 try w.writeAll(@tagName(node));
28712872 switch (node) {
28722873 else => {},
2874 .segment => |phndx| switch (elf.phdrSlice()) {
2875 inline else => |phdr| {
2876 const ph = &phdr[phndx];
2877 try w.writeByte('(');
2878 const pt = elf.targetLoad(&ph.type);
2879 if (std.enums.tagName(std.elf.PT, pt)) |pt_name|
2880 try w.writeAll(pt_name)
2881 else inline for (@typeInfo(std.elf.PT).@"enum".decls) |decl| {
2882 const decl_val = @field(std.elf.PT, decl.name);
2883 if (@TypeOf(decl_val) != std.elf.PT) continue;
2884 if (pt == @field(std.elf.PT, decl.name)) break try w.writeAll(decl.name);
2885 } else try w.print("0x{x}", .{pt});
2886 try w.writeAll(", ");
2887 const pf = elf.targetLoad(&ph.flags);
2888 if (pf.R) try w.writeByte('R');
2889 if (pf.W) try w.writeByte('W');
2890 if (pf.X) try w.writeByte('X');
2891 try w.writeByte(')');
2892 },
2893 },
28732894 .section => |si| try w.print("({s})", .{elf.sectionName(si)}),
28742895 .input_section => |isi| {
28752896 const ii = isi.input(elf);