mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-30 12:56:37 +03:00
Elf2: flush ehdr phoff when rodata moves
I should have realised what was going on here sooner, because it was really simple! We had a file offset which was being flushed in `flushMoved` instead of `flushFileOffset`, and since `flushMoved` does not bubble down to the PHDR segment from the "parent" read-only LOAD segment, we weren't updating `ehdr.phoff` if the rodata segment had to move. The tricky thing which meant I didn't catch this sooner is that this wasn't happening on all filesystems, because the behavior of `link.MappedFile` differs depending on the capabilities of the target filesystem. Resolves: https://codeberg.org/ziglang/zig/issues/32123 Resolves: https://codeberg.org/ziglang/zig/issues/35367
This commit is contained in:
+15
-8
@@ -4273,10 +4273,13 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||
},
|
||||
.segment => |phndx| {
|
||||
switch (elf.phdrSlice()) {
|
||||
inline else => |phdr| elf.targetStore(
|
||||
&phdr[phndx].offset,
|
||||
@intCast(ni.fileLocation(&elf.mf, false).offset),
|
||||
),
|
||||
inline else => |phdr, class| {
|
||||
const ph = &phdr[phndx];
|
||||
elf.targetStore(&ph.offset, @intCast(ni.fileLocation(&elf.mf, false).offset));
|
||||
if (elf.targetLoad(&ph.type) == .PHDR) {
|
||||
@field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset;
|
||||
}
|
||||
},
|
||||
}
|
||||
var child_it = ni.children(&elf.mf);
|
||||
while (child_it.next()) |child_ni| try elf.flushFileOffset(child_ni);
|
||||
@@ -4296,14 +4299,18 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void {
|
||||
.segment => |phndx| {
|
||||
try elf.flushFileOffset(ni);
|
||||
switch (elf.phdrSlice()) {
|
||||
inline else => |phdr, class| {
|
||||
inline else => |phdr| {
|
||||
const ph = &phdr[phndx];
|
||||
switch (elf.targetLoad(&ph.type)) {
|
||||
else => unreachable,
|
||||
.NULL, .LOAD => return,
|
||||
.DYNAMIC, .INTERP => {},
|
||||
.PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset,
|
||||
.TLS, std.elf.PT.GNU_RELRO => {},
|
||||
|
||||
.DYNAMIC,
|
||||
.INTERP,
|
||||
.PHDR,
|
||||
.TLS,
|
||||
.GNU_RELRO,
|
||||
=> {},
|
||||
}
|
||||
elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni)));
|
||||
ph.paddr = ph.vaddr;
|
||||
|
||||
Reference in New Issue
Block a user