| ... | ... | @@ -967,7 +967,13 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u |
| 967 | 967 | self.markDirty(shdr_index, phdr_index); |
| 968 | 968 | } |
| 969 | 969 | |
| 970 | | pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_alignment: u32) !void { |
| 970 | pub fn growNonAllocSection( |
| 971 | self: *Elf, |
| 972 | shdr_index: u16, |
| 973 | needed_size: u64, |
| 974 | min_alignment: u32, |
| 975 | requires_file_copy: bool, |
| 976 | ) !void { |
| 971 | 977 | const shdr = &self.sections.items[shdr_index]; |
| 972 | 978 | |
| 973 | 979 | if (needed_size > self.allocatedSize(shdr.sh_offset)) { |
| ... | ... | @@ -982,13 +988,17 @@ pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_al |
| 982 | 988 | // Move all the symbols to a new file location. |
| 983 | 989 | const new_offset = self.findFreeSpace(needed_size, min_alignment); |
| 984 | 990 | log.debug("moving '{s}' from 0x{x} to 0x{x}", .{ self.getString(shdr.sh_name), shdr.sh_offset, new_offset }); |
| 985 | | const amt = try self.base.file.?.copyRangeAll( |
| 986 | | shdr.sh_offset, |
| 987 | | self.base.file.?, |
| 988 | | new_offset, |
| 989 | | existing_size, |
| 990 | | ); |
| 991 | | if (amt != existing_size) return error.InputOutput; |
| 991 | |
| 992 | if (requires_file_copy) { |
| 993 | const amt = try self.base.file.?.copyRangeAll( |
| 994 | shdr.sh_offset, |
| 995 | self.base.file.?, |
| 996 | new_offset, |
| 997 | existing_size, |
| 998 | ); |
| 999 | if (amt != existing_size) return error.InputOutput; |
| 1000 | } |
| 1001 | |
| 992 | 1002 | shdr.sh_offset = new_offset; |
| 993 | 1003 | } |
| 994 | 1004 | |
| ... | ... | @@ -1191,45 +1201,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1191 | 1201 | } |
| 1192 | 1202 | |
| 1193 | 1203 | { |
| 1194 | | const shstrtab_sect = &self.sections.items[self.shstrtab_index.?]; |
| 1195 | | if (self.shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) { |
| 1196 | | const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset); |
| 1197 | | const needed_size = self.shstrtab.items.len; |
| 1198 | | |
| 1199 | | if (needed_size > allocated_size) { |
| 1200 | | shstrtab_sect.sh_size = 0; // free the space |
| 1201 | | shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); |
| 1202 | | } |
| 1203 | | shstrtab_sect.sh_size = needed_size; |
| 1204 | | log.debug("writing shstrtab start=0x{x} end=0x{x}", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); |
| 1205 | | |
| 1204 | const shdr_index = self.shstrtab_index.?; |
| 1205 | if (self.shstrtab_dirty or self.shstrtab.items.len != self.sections.items[shdr_index].sh_size) { |
| 1206 | try self.growNonAllocSection(shdr_index, self.shstrtab.items.len, 1, false); |
| 1207 | const shstrtab_sect = self.sections.items[shdr_index]; |
| 1206 | 1208 | try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); |
| 1207 | | if (!self.shdr_table_dirty) { |
| 1208 | | // Then it won't get written with the others and we need to do it. |
| 1209 | | try self.writeSectHeader(self.shstrtab_index.?); |
| 1210 | | } |
| 1211 | 1209 | self.shstrtab_dirty = false; |
| 1212 | 1210 | } |
| 1213 | 1211 | } |
| 1214 | 1212 | |
| 1215 | 1213 | if (self.dwarf) |dwarf| { |
| 1216 | | const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?]; |
| 1217 | | if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) { |
| 1218 | | const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset); |
| 1219 | | const needed_size = dwarf.strtab.items.len; |
| 1220 | | |
| 1221 | | if (needed_size > allocated_size) { |
| 1222 | | debug_strtab_sect.sh_size = 0; // free the space |
| 1223 | | debug_strtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); |
| 1224 | | } |
| 1225 | | debug_strtab_sect.sh_size = needed_size; |
| 1226 | | log.debug("debug_strtab start=0x{x} end=0x{x}", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); |
| 1227 | | |
| 1214 | const shdr_index = self.debug_str_section_index.?; |
| 1215 | if (self.debug_strtab_dirty or dwarf.strtab.items.len != self.sections.items[shdr_index].sh_size) { |
| 1216 | try self.growNonAllocSection(shdr_index, dwarf.strtab.items.len, 1, false); |
| 1217 | const debug_strtab_sect = self.sections.items[shdr_index]; |
| 1228 | 1218 | try self.base.file.?.pwriteAll(dwarf.strtab.items, debug_strtab_sect.sh_offset); |
| 1229 | | if (!self.shdr_table_dirty) { |
| 1230 | | // Then it won't get written with the others and we need to do it. |
| 1231 | | try self.writeSectHeader(self.debug_str_section_index.?); |
| 1232 | | } |
| 1233 | 1219 | self.debug_strtab_dirty = false; |
| 1234 | 1220 | } |
| 1235 | 1221 | } |
| ... | ... | @@ -2861,7 +2847,7 @@ fn writeSymbol(self: *Elf, index: usize) !void { |
| 2861 | 2847 | .p64 => @alignOf(elf.Elf64_Sym), |
| 2862 | 2848 | }; |
| 2863 | 2849 | const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; |
| 2864 | | try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align); |
| 2850 | try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true); |
| 2865 | 2851 | syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len); |
| 2866 | 2852 | } |
| 2867 | 2853 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| ... | ... | @@ -2910,7 +2896,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void { |
| 2910 | 2896 | .p64 => @alignOf(elf.Elf64_Sym), |
| 2911 | 2897 | }; |
| 2912 | 2898 | const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; |
| 2913 | | try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align); |
| 2899 | try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true); |
| 2914 | 2900 | |
| 2915 | 2901 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| 2916 | 2902 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; |