| ... | @@ -3645,77 +3645,22 @@ fn initHeaders( | ... | @@ -3645,77 +3645,22 @@ fn initHeaders( |
| 3645 | | 3645 | |
| 3646 | const entsize: struct { ph: u32, sh: u32 } = switch (class) { | 3646 | const entsize: struct { ph: u32, sh: u32 } = switch (class) { |
| 3647 | .NONE, _ => unreachable, | 3647 | .NONE, _ => unreachable, |
| 3648 | inline else => |ct_class| entsize: { | 3648 | inline else => |ct_class| .{ |
| 3649 | const ElfN = ct_class.ElfN(); | 3649 | .ph = @sizeOf(ct_class.ElfN().Phdr), |
| 3650 | elf.ni.ehdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ | 3650 | .sh = @sizeOf(ct_class.ElfN().Shdr), |
| 3651 | .size = @sizeOf(ElfN.Ehdr), | | |
| 3652 | .alignment = addr_align, | | |
| 3653 | .fixed = true, | | |
| 3654 | }); | | |
| 3655 | elf.nodes.appendAssumeCapacity(.ehdr); | | |
| 3656 | | | |
| 3657 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); | | |
| 3658 | ehdr.ident = .{ | | |
| 3659 | .class = class, | | |
| 3660 | .data = data, | | |
| 3661 | .version = 1, | | |
| 3662 | .osabi = osabi, | | |
| 3663 | .abiversion = 0, | | |
| 3664 | }; | | |
| 3665 | ehdr.type = @"type".toElf(); | | |
| 3666 | ehdr.machine = machine.toElf(); | | |
| 3667 | ehdr.version = 1; | | |
| 3668 | ehdr.entry = 0; | | |
| 3669 | ehdr.phoff = 0; | | |
| 3670 | ehdr.shoff = 0; | | |
| 3671 | ehdr.flags = switch (machine) { | | |
| 3672 | .LOONGARCH => .{ .loongarch = .{ | | |
| 3673 | .base_abi_modifier = mod: { | | |
| 3674 | const cpu = comp.getTarget().cpu; | | |
| 3675 | if (cpu.has(.loongarch, .d)) break :mod .d; | | |
| 3676 | if (cpu.has(.loongarch, .f)) break :mod .f; | | |
| 3677 | break :mod .s; | | |
| 3678 | }, | | |
| 3679 | .abi_extension = .base, | | |
| 3680 | .abi_version = 1, | | |
| 3681 | } }, | | |
| 3682 | .SPARCV9 => .{ .sparc = .{ | | |
| 3683 | .mm = .rmo, | | |
| 3684 | .ext = .{ | | |
| 3685 | .@"32plus" = false, | | |
| 3686 | .sun_us1 = false, | | |
| 3687 | .hal_r1 = false, | | |
| 3688 | .sun_us3 = false, | | |
| 3689 | .le_data = false, | | |
| 3690 | }, | | |
| 3691 | } }, | | |
| 3692 | .X86_64 => .{ .int = 0 }, | | |
| 3693 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), | | |
| 3694 | }; | | |
| 3695 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); | | |
| 3696 | ehdr.phentsize = @sizeOf(ElfN.Phdr); | | |
| 3697 | ehdr.phnum = @min(phnum, std.elf.PN_XNUM); | | |
| 3698 | ehdr.shentsize = @sizeOf(ElfN.Shdr); | | |
| 3699 | ehdr.shnum = 1; // Only the null shdr initially---will be incremented by `addSection` | | |
| 3700 | ehdr.shstrndx = std.elf.SHN_UNDEF; | | |
| 3701 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); | | |
| 3702 | | | |
| 3703 | break :entsize .{ .ph = @sizeOf(ElfN.Phdr), .sh = @sizeOf(ElfN.Shdr) }; | | |
| 3704 | }, | 3651 | }, |
| 3705 | }; | 3652 | }; |
| 3706 | | 3653 | |
| 3707 | elf.ni.shdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ | 3654 | // We want to create the segment nodes *before* the ehdr, because the ehdr should go inside of |
| 3708 | .size = 1 * entsize.sh, // as above, only the null shdr initially | 3655 | // the rodata segment. Although to my knowledge neither ELF nor any ELF-based OS strictly |
| 3709 | .alignment = addr_align.max(node_block_align), | 3656 | // requires this, it is highly conventional and therefore sometimes relied upon. |
| 3710 | .moved = true, | | |
| 3711 | .resized = true, | | |
| 3712 | }); | | |
| 3713 | elf.nodes.appendAssumeCapacity(.shdr); | | |
| 3714 | | | |
| 3715 | if (@"type" != .REL) { | 3657 | if (@"type" != .REL) { |
| 3716 | elf.ni.rodata = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ | 3658 | elf.ni.rodata = try elf.mf.addOnlyChildNode(gpa, elf.ni.elf, .{ |
| 3717 | // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node | 3659 | // Must be at least `addr_align` for `elf.ni.phdr` to be placed inside this node |
| 3718 | .alignment = node_block_align.max(addr_align), | 3660 | .alignment = node_block_align.max(addr_align), |
| | 3661 | // This node will contain the ehdr, which must be at the start of the ELF file, so this |
| | 3662 | // node must itself be fixed. |
| | 3663 | .fixed = true, |
| 3719 | .moved = true, | 3664 | .moved = true, |
| 3720 | .bubbles_moved = false, | 3665 | .bubbles_moved = false, |
| 3721 | }); | 3666 | }); |
| ... | @@ -3781,6 +3726,79 @@ fn initHeaders( | ... | @@ -3781,6 +3726,79 @@ fn initHeaders( |
| 3781 | | 3726 | |
| 3782 | elf.phdrs.items[phndx.gnu_stack] = .none; | 3727 | elf.phdrs.items[phndx.gnu_stack] = .none; |
| 3783 | } | 3728 | } |
| | 3729 | |
| | 3730 | switch (class) { |
| | 3731 | .NONE, _ => unreachable, |
| | 3732 | inline else => |ct_class| { |
| | 3733 | const ElfN = ct_class.ElfN(); |
| | 3734 | // In loadable modules, the ehdr goes in the rodata segment, as described above. |
| | 3735 | const parent_ni = switch (@"type") { |
| | 3736 | .REL => elf.ni.elf, |
| | 3737 | .DYN, .EXEC => elf.ni.rodata, |
| | 3738 | }; |
| | 3739 | elf.ni.ehdr = try elf.mf.addFirstChildNode(gpa, parent_ni, .{ |
| | 3740 | .size = @sizeOf(ElfN.Ehdr), |
| | 3741 | .alignment = addr_align, |
| | 3742 | .fixed = true, |
| | 3743 | }); |
| | 3744 | elf.nodes.appendAssumeCapacity(.ehdr); |
| | 3745 | |
| | 3746 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); |
| | 3747 | ehdr.ident = .{ |
| | 3748 | .class = class, |
| | 3749 | .data = data, |
| | 3750 | .version = 1, |
| | 3751 | .osabi = osabi, |
| | 3752 | .abiversion = 0, |
| | 3753 | }; |
| | 3754 | ehdr.type = @"type".toElf(); |
| | 3755 | ehdr.machine = machine.toElf(); |
| | 3756 | ehdr.version = 1; |
| | 3757 | ehdr.entry = 0; |
| | 3758 | ehdr.phoff = 0; |
| | 3759 | ehdr.shoff = 0; |
| | 3760 | ehdr.flags = switch (machine) { |
| | 3761 | .LOONGARCH => .{ .loongarch = .{ |
| | 3762 | .base_abi_modifier = mod: { |
| | 3763 | const cpu = comp.getTarget().cpu; |
| | 3764 | if (cpu.has(.loongarch, .d)) break :mod .d; |
| | 3765 | if (cpu.has(.loongarch, .f)) break :mod .f; |
| | 3766 | break :mod .s; |
| | 3767 | }, |
| | 3768 | .abi_extension = .base, |
| | 3769 | .abi_version = 1, |
| | 3770 | } }, |
| | 3771 | .SPARCV9 => .{ .sparc = .{ |
| | 3772 | .mm = .rmo, |
| | 3773 | .ext = .{ |
| | 3774 | .@"32plus" = false, |
| | 3775 | .sun_us1 = false, |
| | 3776 | .hal_r1 = false, |
| | 3777 | .sun_us3 = false, |
| | 3778 | .le_data = false, |
| | 3779 | }, |
| | 3780 | } }, |
| | 3781 | .X86_64 => .{ .int = 0 }, |
| | 3782 | .AARCH64, .PPC64, .RISCV => @panic(@tagName(machine)), |
| | 3783 | }; |
| | 3784 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); |
| | 3785 | ehdr.phentsize = @sizeOf(ElfN.Phdr); |
| | 3786 | ehdr.phnum = @min(phnum, std.elf.PN_XNUM); |
| | 3787 | ehdr.shentsize = @sizeOf(ElfN.Shdr); |
| | 3788 | ehdr.shnum = 1; // Only the null shdr initially---will be incremented by `addSection` |
| | 3789 | ehdr.shstrndx = std.elf.SHN_UNDEF; |
| | 3790 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllFields(ElfN.Ehdr, ehdr); |
| | 3791 | }, |
| | 3792 | } |
| | 3793 | |
| | 3794 | elf.ni.shdr = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ |
| | 3795 | .size = 1 * entsize.sh, // as above, only the null shdr initially |
| | 3796 | .alignment = addr_align.max(node_block_align), |
| | 3797 | .moved = true, |
| | 3798 | .resized = true, |
| | 3799 | }); |
| | 3800 | elf.nodes.appendAssumeCapacity(.shdr); |
| | 3801 | |
| 3784 | switch (class) { | 3802 | switch (class) { |
| 3785 | .NONE, _ => unreachable, | 3803 | .NONE, _ => unreachable, |
| 3786 | inline else => |ct_class| { | 3804 | inline else => |ct_class| { |
| ... | @@ -3818,7 +3836,9 @@ fn initHeaders( | ... | @@ -3818,7 +3836,9 @@ fn initHeaders( |
| 3818 | // actually `PT_NULL` for now, because we initialize `filesz` and `memsz` to zero. | 3836 | // actually `PT_NULL` for now, because we initialize `filesz` and `memsz` to zero. |
| 3819 | // Any which end up non-empty will have their size populated (and their type set to | 3837 | // Any which end up non-empty will have their size populated (and their type set to |
| 3820 | // `PT_LOAD`) by the segment virtual address space allocation logic. | 3838 | // `PT_LOAD`) by the segment virtual address space allocation logic. |
| 3821 | const phdr: []ElfN.Phdr = @ptrCast(@alignCast(elf.ni.phdr.slice(&elf.mf))); | 3839 | const phdr: []ElfN.Phdr = @ptrCast(@alignCast( |
| | 3840 | elf.ni.phdr.slice(&elf.mf)[0 .. phnum * @sizeOf(ElfN.Phdr)], |
| | 3841 | )); |
| 3822 | | 3842 | |
| 3823 | const ph_phdr = &phdr[phndx.phdr]; | 3843 | const ph_phdr = &phdr[phndx.phdr]; |
| 3824 | ph_phdr.* = .{ | 3844 | ph_phdr.* = .{ |
| ... | @@ -4900,14 +4920,11 @@ const PhdrSlice = union(std.elf.CLASS) { | ... | @@ -4900,14 +4920,11 @@ const PhdrSlice = union(std.elf.CLASS) { |
| 4900 | }; | 4920 | }; |
| 4901 | fn phdrSlice(elf: *Elf) PhdrSlice { | 4921 | fn phdrSlice(elf: *Elf) PhdrSlice { |
| 4902 | assert(elf.ehdrType() != .REL); | 4922 | assert(elf.ehdrType() != .REL); |
| 4903 | const slice = elf.ni.phdr.slice(&elf.mf); | | |
| 4904 | return switch (elf.identClass()) { | 4923 | return switch (elf.identClass()) { |
| 4905 | .NONE, _ => unreachable, | 4924 | .NONE, _ => unreachable, |
| 4906 | inline else => |class| @unionInit( | 4925 | inline else => |class| @unionInit(PhdrSlice, @tagName(class), @ptrCast(@alignCast( |
| 4907 | PhdrSlice, | 4926 | elf.ni.phdr.slice(&elf.mf)[0 .. elf.phdrs.items.len * @sizeOf(class.ElfN().Phdr)], |
| 4908 | @tagName(class), | 4927 | ))), |
| 4909 | @ptrCast(@alignCast(slice)), | | |
| 4910 | ), | | |
| 4911 | }; | 4928 | }; |
| 4912 | } | 4929 | } |
| 4913 | | 4930 | |