Commit 229e99ca37

Andrew Kelley <andrew@ziglang.org>
2020-04-24 05:53:52
codegen: write the updated code size to PT_LOAD section header
1 parent 2d35f71
Changed files (1)
src-self-hosted
src-self-hosted/link.zig
@@ -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();
     }