codegen: write the updated code size to PT_LOAD section header

master
Andrew Kelley 2020-04-23 23:53:52 -04:00
parent 2d35f71fa9
commit 229e99ca37
1 changed files with 67 additions and 57 deletions

View File

@ -332,61 +332,6 @@ const Update = struct {
phdr_table_dirty = true;
}
const foreign_endian = self.module.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
if (phdr_table_dirty) {
const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
const needed_size = self.program_headers.items.len * phsize;
if (needed_size > allocated_size) {
self.phdr_table_offset = null; // free the space
self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
}
const allocator = self.program_headers.allocator;
switch (ptr_width) {
.p32 => {
const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
defer allocator.free(buf);
for (buf) |*phdr, i| {
phdr.* = .{
.p_type = self.program_headers.items[i].p_type,
.p_flags = self.program_headers.items[i].p_flags,
.p_offset = @intCast(u32, self.program_headers.items[i].p_offset),
.p_vaddr = @intCast(u32, self.program_headers.items[i].p_vaddr),
.p_paddr = @intCast(u32, self.program_headers.items[i].p_paddr),
.p_filesz = @intCast(u32, self.program_headers.items[i].p_filesz),
.p_memsz = @intCast(u32, self.program_headers.items[i].p_memsz),
.p_align = @intCast(u32, self.program_headers.items[i].p_align),
};
if (foreign_endian) {
bswapAllFields(elf.Elf32_Phdr, phdr);
}
}
try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
},
.p64 => {
const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
defer allocator.free(buf);
for (buf) |*phdr, i| {
phdr.* = .{
.p_type = self.program_headers.items[i].p_type,
.p_flags = self.program_headers.items[i].p_flags,
.p_offset = self.program_headers.items[i].p_offset,
.p_vaddr = self.program_headers.items[i].p_vaddr,
.p_paddr = self.program_headers.items[i].p_paddr,
.p_filesz = self.program_headers.items[i].p_filesz,
.p_memsz = self.program_headers.items[i].p_memsz,
.p_align = self.program_headers.items[i].p_align,
};
if (foreign_endian) {
bswapAllFields(elf.Elf64_Phdr, phdr);
}
}
try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
},
}
}
if (shdr_table_dirty) {
const allocated_size = self.allocatedSize(self.shdr_table_offset.?);
const needed_size = self.sections.items.len * phsize;
@ -446,7 +391,64 @@ const Update = struct {
},
}
}
try self.writeCodeAndSymbols();
try self.writeCodeAndSymbols(&phdr_table_dirty);
if (phdr_table_dirty) {
const allocated_size = self.allocatedSize(self.phdr_table_offset.?);
const needed_size = self.program_headers.items.len * phsize;
if (needed_size > allocated_size) {
self.phdr_table_offset = null; // free the space
self.phdr_table_offset = self.findFreeSpace(needed_size, phalign);
}
const allocator = self.program_headers.allocator;
switch (ptr_width) {
.p32 => {
const buf = try allocator.alloc(elf.Elf32_Phdr, self.program_headers.items.len);
defer allocator.free(buf);
for (buf) |*phdr, i| {
phdr.* = .{
.p_type = self.program_headers.items[i].p_type,
.p_flags = self.program_headers.items[i].p_flags,
.p_offset = @intCast(u32, self.program_headers.items[i].p_offset),
.p_vaddr = @intCast(u32, self.program_headers.items[i].p_vaddr),
.p_paddr = @intCast(u32, self.program_headers.items[i].p_paddr),
.p_filesz = @intCast(u32, self.program_headers.items[i].p_filesz),
.p_memsz = @intCast(u32, self.program_headers.items[i].p_memsz),
.p_align = @intCast(u32, self.program_headers.items[i].p_align),
};
if (foreign_endian) {
bswapAllFields(elf.Elf32_Phdr, phdr);
}
}
try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
},
.p64 => {
const buf = try allocator.alloc(elf.Elf64_Phdr, self.program_headers.items.len);
defer allocator.free(buf);
for (buf) |*phdr, i| {
phdr.* = .{
.p_type = self.program_headers.items[i].p_type,
.p_flags = self.program_headers.items[i].p_flags,
.p_offset = self.program_headers.items[i].p_offset,
.p_vaddr = self.program_headers.items[i].p_vaddr,
.p_paddr = self.program_headers.items[i].p_paddr,
.p_filesz = self.program_headers.items[i].p_filesz,
.p_memsz = self.program_headers.items[i].p_memsz,
.p_align = self.program_headers.items[i].p_align,
};
if (foreign_endian) {
bswapAllFields(elf.Elf64_Phdr, phdr);
}
}
try self.file.pwriteAll(mem.sliceAsBytes(buf), self.phdr_table_offset.?);
},
}
}
const shstrtab_sect = &self.sections.items[self.shstrtab_index.?];
if (shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) {
@ -590,7 +592,7 @@ const Update = struct {
try self.file.pwriteAll(hdr_buf[0..index], 0);
}
fn writeCodeAndSymbols(self: *Update) !void {
fn writeCodeAndSymbols(self: *Update, phdr_table_dirty: *bool) !void {
// index 0 is always a null symbol
try self.symbols.resize(1);
self.symbols.items[0] = .{
@ -638,6 +640,14 @@ const Update = struct {
vaddr += code.items.len;
}
{
// Now that we know the code size, we need to update the program header for executable code
phdr.p_memsz = vaddr - phdr.p_vaddr;
phdr.p_filesz = phdr.p_memsz;
phdr_table_dirty.* = true;
}
return self.writeSymbols();
}