| ... | @@ -3521,6 +3521,10 @@ fn initHeaders( | ... | @@ -3521,6 +3521,10 @@ fn initHeaders( |
| 3521 | rodata: u32, | 3521 | rodata: u32, |
| 3522 | text: u32, | 3522 | text: u32, |
| 3523 | data: u32, | 3523 | data: u32, |
| | 3524 | /// On most targets this is `undefined`, but on machines where JUMP_SLOT relocations write |
| | 3525 | /// directly to the PLT, we place the PLT in its own segment in order to avoid making the |
| | 3526 | /// general data segment RWX. |
| | 3527 | plt: u32, |
| 3524 | tls: u32, | 3528 | tls: u32, |
| 3525 | dynamic: u32, | 3529 | dynamic: u32, |
| 3526 | relro: u32, | 3530 | relro: u32, |
| ... | @@ -3552,6 +3556,10 @@ fn initHeaders( | ... | @@ -3552,6 +3556,10 @@ fn initHeaders( |
| 3552 | defer phnum += 1; | 3556 | defer phnum += 1; |
| 3553 | break :phndx phnum; | 3557 | break :phndx phnum; |
| 3554 | }, | 3558 | }, |
| | 3559 | .plt = if (plt.got_plt == null) phndx: { |
| | 3560 | defer phnum += 1; |
| | 3561 | break :phndx phnum; |
| | 3562 | } else undefined, |
| 3555 | .tls = if (comp.config.any_non_single_threaded) phndx: { | 3563 | .tls = if (comp.config.any_non_single_threaded) phndx: { |
| 3556 | defer phnum += 1; | 3564 | defer phnum += 1; |
| 3557 | break :phndx phnum; | 3565 | break :phndx phnum; |
| ... | @@ -3721,6 +3729,16 @@ fn initHeaders( | ... | @@ -3721,6 +3729,16 @@ fn initHeaders( |
| 3721 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); | 3729 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); |
| 3722 | elf.phdrs.items[phndx.data] = elf.ni.data; | 3730 | elf.phdrs.items[phndx.data] = elf.ni.data; |
| 3723 | | 3731 | |
| | 3732 | if (plt.got_plt == null) { |
| | 3733 | const plt_ni = try elf.mf.addLastChildNode(gpa, elf.ni.elf, .{ |
| | 3734 | .alignment = node_block_align, |
| | 3735 | .moved = true, |
| | 3736 | .bubbles_moved = false, |
| | 3737 | }); |
| | 3738 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.plt }); |
| | 3739 | elf.phdrs.items[phndx.plt] = plt_ni; |
| | 3740 | } |
| | 3741 | |
| 3724 | elf.ni.data_rel_ro = try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ | 3742 | elf.ni.data_rel_ro = try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ |
| 3725 | // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one | 3743 | // Must be at least `addr_align` for the `PT_DYNAMIC` node to be placed inside this one |
| 3726 | // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above. | 3744 | // later (if `have_dynamic_section`). Keep in sync with `elf.ni.data` alignment above. |
| ... | @@ -3844,6 +3862,20 @@ fn initHeaders( | ... | @@ -3844,6 +3862,20 @@ fn initHeaders( |
| 3844 | .@"align" = @intCast(page_align.toByteUnits()), | 3862 | .@"align" = @intCast(page_align.toByteUnits()), |
| 3845 | }; | 3863 | }; |
| 3846 | | 3864 | |
| | 3865 | if (plt.got_plt == null) { |
| | 3866 | const ph_plt = &phdr[phndx.plt]; |
| | 3867 | ph_plt.* = .{ |
| | 3868 | .type = .NULL, |
| | 3869 | .offset = 0, |
| | 3870 | .vaddr = @intCast(base_vaddr), |
| | 3871 | .paddr = @intCast(base_vaddr), |
| | 3872 | .filesz = 0, |
| | 3873 | .memsz = 0, |
| | 3874 | .flags = .{ .R = true, .W = true, .X = true }, |
| | 3875 | .@"align" = @intCast(page_align.toByteUnits()), |
| | 3876 | }; |
| | 3877 | } |
| | 3878 | |
| 3847 | if (comp.config.any_non_single_threaded) { | 3879 | if (comp.config.any_non_single_threaded) { |
| 3848 | const ph_tls = &phdr[phndx.tls]; | 3880 | const ph_tls = &phdr[phndx.tls]; |
| 3849 | ph_tls.* = .{ | 3881 | ph_tls.* = .{ |
| ... | @@ -4001,29 +4033,34 @@ fn initHeaders( | ... | @@ -4001,29 +4033,34 @@ fn initHeaders( |
| 4001 | .addralign = addr_align, | 4033 | .addralign = addr_align, |
| 4002 | .entsize = @intCast(addr_align.toByteUnits()), | 4034 | .entsize = @intCast(addr_align.toByteUnits()), |
| 4003 | }); | 4035 | }); |
| 4004 | if (plt.got_plt) |got_plt| elf.shndx.got_plt = try elf.addSection( | 4036 | if (plt.got_plt) |got_plt| { |
| 4005 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, | 4037 | const got_plt_segment_ni = if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data; |
| 4006 | .{ | 4038 | elf.shndx.got_plt = try elf.addSection(got_plt_segment_ni, .{ |
| 4007 | .name = ".got.plt", | 4039 | .name = ".got.plt", |
| 4008 | .type = .PROGBITS, | 4040 | .type = .PROGBITS, |
| 4009 | .flags = .{ .WRITE = true, .ALLOC = true }, | 4041 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 4010 | .size = got_plt.header_entries * elf.targetPtrSize(), | 4042 | .size = got_plt.header_entries * elf.targetPtrSize(), |
| 4011 | .addralign = addr_align, | 4043 | .addralign = addr_align, |
| 4012 | .entsize = @intCast(addr_align.toByteUnits()), | 4044 | .entsize = @intCast(addr_align.toByteUnits()), |
| 4013 | }, | 4045 | }); |
| 4014 | ); | 4046 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 4015 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ | 4047 | .name = ".plt", |
| 4016 | .name = ".plt", | 4048 | .type = .PROGBITS, |
| 4017 | .type = .PROGBITS, | 4049 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| 4018 | .flags = .{ | 4050 | .size = plt.entry_size * plt.header_entries, |
| 4019 | .ALLOC = true, | 4051 | .addralign = plt.@"align", |
| 4020 | .EXECINSTR = true, | 4052 | .node_align = node_block_align, |
| 4021 | .WRITE = plt.got_plt == null, | 4053 | }); |
| 4022 | }, | 4054 | } else { |
| 4023 | .size = plt.entry_size * plt.header_entries, | 4055 | elf.shndx.plt = try elf.addSection(elf.phdrs.items[phndx.plt], .{ |
| 4024 | .addralign = plt.@"align", | 4056 | .name = ".plt", |
| 4025 | .node_align = node_block_align, | 4057 | .type = .PROGBITS, |
| 4026 | }); | 4058 | .flags = .{ .ALLOC = true, .WRITE = true, .EXECINSTR = true }, |
| | 4059 | .size = plt.entry_size * plt.header_entries, |
| | 4060 | .addralign = plt.@"align", |
| | 4061 | .node_align = node_block_align, |
| | 4062 | }); |
| | 4063 | } |
| 4027 | if (plt.plt_sec != null) elf.shndx.plt_sec = try elf.addSection(elf.ni.text, .{ | 4064 | if (plt.plt_sec != null) elf.shndx.plt_sec = try elf.addSection(elf.ni.text, .{ |
| 4028 | .name = ".plt.sec", | 4065 | .name = ".plt.sec", |
| 4029 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, | 4066 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |