authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-21 19:13:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-21 19:13:52-07:00
logb1930a3b57577e6a61582ae536943512ea31bcb6
tree1a13f5dc13a9fcc6e0353040e3e5aabca03a0253
parentdefb30901388127f4e640e0a8b1107d327877108

Elf: keep the logic for updates but condition on hcs


1 files changed, 62 insertions(+), 2 deletions(-)

src/link/Elf.zig+62-2
......@@ -2097,6 +2097,7 @@ fn growTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock,
20972097fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
20982098 const phdr = &self.program_headers.items[block_list.phdr_index.?];
20992099 const shdr = &self.sections.items[block_list.section_index.?];
2100 const new_block_ideal_capacity = padToIdeal(new_block_size);
21002101
21012102 // We use these to indicate our intention to update metadata, placing the new block,
21022103 // and possibly removing a free list node.
......@@ -2109,7 +2110,42 @@ fn allocateTextBlock(self: *Elf, block_list: *TextBlockList, text_block: *TextBl
21092110 // First we look for an appropriately sized free list node.
21102111 // The list is unordered. We'll just take the first thing that works.
21112112 const vaddr = blk: {
2112 if (block_list.last_block) |last| {
2113 var i: usize = if (self.base.child_pid == null) 0 else block_list.free_list.items.len;
2114 while (i < block_list.free_list.items.len) {
2115 const big_block = block_list.free_list.items[i];
2116 // We now have a pointer to a live text block that has too much capacity.
2117 // Is it enough that we could fit this new text block?
2118 const sym = self.local_symbols.items[big_block.local_sym_index];
2119 const capacity = big_block.capacity(self.*);
2120 const ideal_capacity = padToIdeal(capacity);
2121 const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity;
2122 const capacity_end_vaddr = sym.st_value + capacity;
2123 const new_start_vaddr_unaligned = capacity_end_vaddr - new_block_ideal_capacity;
2124 const new_start_vaddr = mem.alignBackwardGeneric(u64, new_start_vaddr_unaligned, alignment);
2125 if (new_start_vaddr < ideal_capacity_end_vaddr) {
2126 // Additional bookkeeping here to notice if this free list node
2127 // should be deleted because the block that it points to has grown to take up
2128 // more of the extra capacity.
2129 if (!big_block.freeListEligible(self.*)) {
2130 _ = block_list.free_list.swapRemove(i);
2131 } else {
2132 i += 1;
2133 }
2134 continue;
2135 }
2136 // At this point we know that we will place the new block here. But the
2137 // remaining question is whether there is still yet enough capacity left
2138 // over for there to still be a free list node.
2139 const remaining_capacity = new_start_vaddr - ideal_capacity_end_vaddr;
2140 const keep_free_list_node = remaining_capacity >= min_text_capacity;
2141
2142 // Set up the metadata to be updated, after errors are no longer possible.
2143 block_placement = big_block;
2144 if (!keep_free_list_node) {
2145 free_list_removal = i;
2146 }
2147 break :blk new_start_vaddr;
2148 } else if (block_list.last_block) |last| {
21132149 const sym = self.local_symbols.items[last.local_sym_index];
21142150 const ideal_capacity = padToIdeal(sym.st_size);
21152151 const ideal_capacity_end_vaddr = sym.st_value + ideal_capacity;
......@@ -2282,7 +2318,31 @@ fn updateDeclCode(self: *Elf, decl: *Module.Decl, code: []const u8, stt_bits: u8
22822318
22832319 assert(decl.link.elf.local_sym_index != 0); // Caller forgot to allocateDeclIndexes()
22842320 const local_sym = &self.local_symbols.items[decl.link.elf.local_sym_index];
2285 {
2321 if (local_sym.st_size != 0 and self.base.child_pid == null) {
2322 const capacity = decl.link.elf.capacity(self.*);
2323 const need_realloc = code.len > capacity or
2324 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
2325 if (need_realloc) {
2326 const vaddr = try self.growTextBlock(block_list, &decl.link.elf, code.len, required_alignment);
2327 log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl.name, local_sym.st_value, vaddr });
2328 if (vaddr != local_sym.st_value) {
2329 local_sym.st_value = vaddr;
2330
2331 log.debug(" (writing new offset table entry)", .{});
2332 self.offset_table.items[decl.link.elf.offset_table_index] = vaddr;
2333 try self.writeOffsetTableEntry(decl.link.elf.offset_table_index);
2334 }
2335 } else if (code.len < local_sym.st_size) {
2336 self.shrinkTextBlock(block_list, &decl.link.elf, code.len);
2337 }
2338 local_sym.st_size = code.len;
2339 local_sym.st_name = try self.updateString(local_sym.st_name, mem.sliceTo(decl.name, 0));
2340 local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits;
2341 local_sym.st_other = 0;
2342 local_sym.st_shndx = block_list.section_index.?;
2343 // TODO this write could be avoided if no fields of the symbol were changed.
2344 try self.writeSymbol(decl.link.elf.local_sym_index);
2345 } else {
22862346 const decl_name = mem.sliceTo(decl.name, 0);
22872347 const name_str_index = try self.makeString(decl_name);
22882348 const vaddr = try self.allocateTextBlock(block_list, &decl.link.elf, code.len, required_alignment);