| ... | ... | @@ -105,7 +105,7 @@ atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 105 | 105 | /// |
| 106 | 106 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| 107 | 107 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| 108 | | unnamed_const_atoms: UnnamedConstTable = .{}, |
| 108 | unnamed_consts: UnnamedConstTable = .{}, |
| 109 | 109 | |
| 110 | 110 | /// A table of relocations indexed by the owning them `TextBlock`. |
| 111 | 111 | relocs: RelocTable = .{}, |
| ... | ... | @@ -251,11 +251,11 @@ pub fn deinit(self: *Elf) void { |
| 251 | 251 | self.lazy_syms.deinit(gpa); |
| 252 | 252 | |
| 253 | 253 | { |
| 254 | | var it = self.unnamed_const_atoms.valueIterator(); |
| 255 | | while (it.next()) |atoms| { |
| 256 | | atoms.deinit(gpa); |
| 254 | var it = self.unnamed_consts.valueIterator(); |
| 255 | while (it.next()) |syms| { |
| 256 | syms.deinit(gpa); |
| 257 | 257 | } |
| 258 | | self.unnamed_const_atoms.deinit(gpa); |
| 258 | self.unnamed_consts.deinit(gpa); |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | 261 | { |
| ... | ... | @@ -279,7 +279,7 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link. |
| 279 | 279 | const vaddr = this_sym.value; |
| 280 | 280 | const parent_atom_index = self.symbol(reloc_info.parent_atom_index).atom_index; |
| 281 | 281 | try Atom.addRelocation(self, parent_atom_index, .{ |
| 282 | | .target = this_sym, |
| 282 | .target = this_sym_index, |
| 283 | 283 | .offset = reloc_info.offset, |
| 284 | 284 | .addend = reloc_info.addend, |
| 285 | 285 | .prev_vaddr = vaddr, |
| ... | ... | @@ -830,6 +830,12 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 830 | 830 | |
| 831 | 831 | try self.base.file.?.pwriteAll(&[_]u8{0}, max_file_offset); |
| 832 | 832 | } |
| 833 | |
| 834 | if (self.zig_module_index == null) { |
| 835 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 836 | self.files.set(index, .{ .zig_module = .{ .index = index } }); |
| 837 | self.zig_module_index = index; |
| 838 | } |
| 833 | 839 | } |
| 834 | 840 | |
| 835 | 841 | pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { |
| ... | ... | @@ -967,12 +973,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 967 | 973 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 968 | 974 | _ = module; |
| 969 | 975 | |
| 970 | | self.zig_module_index = blk: { |
| 971 | | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 972 | | self.files.set(index, .{ .zig_module = .{ .index = index } }); |
| 973 | | break :blk index; |
| 974 | | }; |
| 975 | | |
| 976 | 976 | self.linker_defined_index = blk: { |
| 977 | 977 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 978 | 978 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); |
| ... | ... | @@ -980,6 +980,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 980 | 980 | }; |
| 981 | 981 | |
| 982 | 982 | std.debug.print("{}\n", .{self.dumpState()}); |
| 983 | return error.FlushFailure; |
| 983 | 984 | |
| 984 | 985 | // if (self.lazy_syms.getPtr(.none)) |metadata| { |
| 985 | 986 | // // Most lazy symbols can be updated on first use, but |
| ... | ... | @@ -2078,78 +2079,21 @@ fn writeElfHeader(self: *Elf) !void { |
| 2078 | 2079 | try self.base.file.?.pwriteAll(hdr_buf[0..index], 0); |
| 2079 | 2080 | } |
| 2080 | 2081 | |
| 2081 | | fn freeAtom(self: *Elf, atom_index: Atom.Index) void { |
| 2082 | | const atom_ptr = self.atom(atom_index); |
| 2083 | | log.debug("freeAtom {d} ({s})", .{ atom_index, atom_ptr.name(self) }); |
| 2084 | | |
| 2085 | | Atom.freeRelocations(self, atom_index); |
| 2086 | | |
| 2087 | | const gpa = self.base.allocator; |
| 2088 | | const shndx = atom_ptr.symbol(self).st_shndx; |
| 2089 | | const free_list = &self.sections.items(.free_list)[shndx]; |
| 2090 | | var already_have_free_list_node = false; |
| 2091 | | { |
| 2092 | | var i: usize = 0; |
| 2093 | | // TODO turn free_list into a hash map |
| 2094 | | while (i < free_list.items.len) { |
| 2095 | | if (free_list.items[i] == atom_index) { |
| 2096 | | _ = free_list.swapRemove(i); |
| 2097 | | continue; |
| 2098 | | } |
| 2099 | | if (free_list.items[i] == atom_ptr.prev_index) { |
| 2100 | | already_have_free_list_node = true; |
| 2101 | | } |
| 2102 | | i += 1; |
| 2103 | | } |
| 2104 | | } |
| 2105 | | |
| 2106 | | const maybe_last_atom_index = &self.sections.items(.last_atom_index)[shndx]; |
| 2107 | | if (maybe_last_atom_index.*) |last_atom_index| { |
| 2108 | | if (last_atom_index == atom_index) { |
| 2109 | | if (atom_ptr.prev_index) |prev_index| { |
| 2110 | | // TODO shrink the section size here |
| 2111 | | maybe_last_atom_index.* = prev_index; |
| 2112 | | } else { |
| 2113 | | maybe_last_atom_index.* = null; |
| 2114 | | } |
| 2115 | | } |
| 2116 | | } |
| 2117 | | |
| 2118 | | if (atom_ptr.prev_index) |prev_index| { |
| 2119 | | const prev = self.atom(prev_index); |
| 2120 | | prev.next_index = atom_ptr.next_index; |
| 2121 | | |
| 2122 | | if (!already_have_free_list_node and prev.*.freeListEligible(self)) { |
| 2123 | | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 2124 | | // ignore the OOM here. |
| 2125 | | free_list.append(gpa, prev_index) catch {}; |
| 2126 | | } |
| 2127 | | } else { |
| 2128 | | atom_ptr.prev_index = null; |
| 2129 | | } |
| 2130 | | |
| 2131 | | if (atom_ptr.next_index) |next_index| { |
| 2132 | | self.atom(next_index).prev_index = atom_ptr.prev_index; |
| 2133 | | } else { |
| 2134 | | atom_ptr.next_index = null; |
| 2082 | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2083 | const unnamed_consts = self.unnamed_consts.getPtr(decl_index) orelse return; |
| 2084 | for (unnamed_consts.items) |sym_index| { |
| 2085 | self.freeDeclMetadata(sym_index); |
| 2135 | 2086 | } |
| 2087 | unnamed_consts.clearAndFree(self.base.allocator); |
| 2088 | } |
| 2136 | 2089 | |
| 2137 | | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 2138 | | const sym_index = atom_ptr.symbolIndex().?; |
| 2139 | | |
| 2090 | fn freeDeclMetadata(self: *Elf, sym_index: Symbol.Index) void { |
| 2091 | const sym = self.symbol(sym_index); |
| 2092 | sym.atom(self).?.free(self); |
| 2140 | 2093 | log.debug("adding %{d} to local symbols free list", .{sym_index}); |
| 2141 | | self.symbols_free_list.append(gpa, sym_index) catch {}; |
| 2094 | self.symbols_free_list.append(self.base.allocator, sym_index) catch {}; |
| 2142 | 2095 | self.symbols.items[sym_index] = .{}; |
| 2143 | | atom_ptr.sym_index = 0; |
| 2144 | | self.got_table.freeEntry(gpa, sym_index); |
| 2145 | | } |
| 2146 | | |
| 2147 | | fn freeUnnamedConsts(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2148 | | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| 2149 | | for (unnamed_consts.items) |atom_index| { |
| 2150 | | self.freeAtom(atom_index); |
| 2151 | | } |
| 2152 | | unnamed_consts.clearAndFree(self.base.allocator); |
| 2096 | self.got_table.freeEntry(self.base.allocator, sym_index); |
| 2153 | 2097 | } |
| 2154 | 2098 | |
| 2155 | 2099 | pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| ... | ... | @@ -2162,7 +2106,8 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2162 | 2106 | |
| 2163 | 2107 | if (self.decls.fetchRemove(decl_index)) |const_kv| { |
| 2164 | 2108 | var kv = const_kv; |
| 2165 | | self.freeAtom(kv.value.atom); |
| 2109 | const sym_index = kv.value.symbol_index; |
| 2110 | self.freeDeclMetadata(sym_index); |
| 2166 | 2111 | self.freeUnnamedConsts(decl_index); |
| 2167 | 2112 | kv.value.exports.deinit(self.base.allocator); |
| 2168 | 2113 | } |
| ... | ... | @@ -2196,7 +2141,7 @@ pub fn getOrCreateMetadataForLazySymbol(self: *Elf, sym: link.File.LazySymbol) ! |
| 2196 | 2141 | .code => self.text_section_index.?, |
| 2197 | 2142 | .const_data => self.rodata_section_index.?, |
| 2198 | 2143 | }, self), |
| 2199 | | .pending_flush => return metadata.atom.*, |
| 2144 | .pending_flush => return metadata.symbol_index.*, |
| 2200 | 2145 | .flushed => {}, |
| 2201 | 2146 | } |
| 2202 | 2147 | metadata.state.* = .pending_flush; |
| ... | ... | @@ -2271,6 +2216,7 @@ fn updateDeclCode( |
| 2271 | 2216 | esym.st_size = code.len; |
| 2272 | 2217 | |
| 2273 | 2218 | const old_size = atom_ptr.size; |
| 2219 | const old_vaddr = atom_ptr.value; |
| 2274 | 2220 | atom_ptr.alignment = math.log2_int(u64, required_alignment); |
| 2275 | 2221 | atom_ptr.size = code.len; |
| 2276 | 2222 | |
| ... | ... | @@ -2278,11 +2224,11 @@ fn updateDeclCode( |
| 2278 | 2224 | const capacity = atom_ptr.capacity(self); |
| 2279 | 2225 | const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment); |
| 2280 | 2226 | if (need_realloc) { |
| 2281 | | const vaddr = try atom_ptr.grow(self); |
| 2282 | | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, sym.value, vaddr }); |
| 2283 | | if (vaddr != sym.value) { |
| 2284 | | sym.value = vaddr; |
| 2285 | | esym.st_value = vaddr; |
| 2227 | try atom_ptr.grow(self); |
| 2228 | log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom_ptr.value }); |
| 2229 | if (old_vaddr != atom_ptr.value) { |
| 2230 | sym.value = atom_ptr.value; |
| 2231 | esym.st_value = atom_ptr.value; |
| 2286 | 2232 | |
| 2287 | 2233 | log.debug(" (writing new offset table entry)", .{}); |
| 2288 | 2234 | const got_entry_index = self.got_table.lookup.get(sym_index).?; |
| ... | ... | @@ -2293,12 +2239,16 @@ fn updateDeclCode( |
| 2293 | 2239 | atom_ptr.shrink(self); |
| 2294 | 2240 | } |
| 2295 | 2241 | } else { |
| 2296 | | const vaddr = try atom_ptr.allocate(self); |
| 2297 | | errdefer self.freeAtom(atom_ptr); |
| 2298 | | log.debug("allocated text block for {s} at 0x{x}", .{ decl_name, vaddr }); |
| 2242 | try atom_ptr.allocate(self); |
| 2243 | errdefer self.freeDeclMetadata(sym_index); |
| 2244 | log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{ |
| 2245 | decl_name, |
| 2246 | atom_ptr.value, |
| 2247 | atom_ptr.value + atom_ptr.size, |
| 2248 | }); |
| 2299 | 2249 | |
| 2300 | | sym.value = vaddr; |
| 2301 | | esym.st_value = vaddr; |
| 2250 | sym.value = atom_ptr.value; |
| 2251 | esym.st_value = atom_ptr.value; |
| 2302 | 2252 | |
| 2303 | 2253 | const got_entry_index = try sym.getOrCreateOffsetTableEntry(self); |
| 2304 | 2254 | try self.writeOffsetTableEntry(got_entry_index); |
| ... | ... | @@ -2518,17 +2468,23 @@ fn updateLazySymbol(self: *Elf, sym: link.File.LazySymbol, symbol_index: Symbol. |
| 2518 | 2468 | const atom_ptr = local_sym.atom(self).?; |
| 2519 | 2469 | atom_ptr.alignment = math.log2_int(u64, required_alignment); |
| 2520 | 2470 | atom_ptr.size = code.len; |
| 2521 | | const vaddr = try atom_ptr.allocate(self); |
| 2522 | | errdefer self.freeAtom(atom_ptr); |
| 2523 | | log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr }); |
| 2524 | 2471 | |
| 2525 | | local_sym.value = vaddr; |
| 2526 | | local_esym.st_value = vaddr; |
| 2472 | try atom_ptr.allocate(self); |
| 2473 | errdefer self.freeDeclMetadata(symbol_index); |
| 2474 | |
| 2475 | log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{ |
| 2476 | name, |
| 2477 | atom_ptr.value, |
| 2478 | atom_ptr.value + atom_ptr.size, |
| 2479 | }); |
| 2480 | |
| 2481 | local_sym.value = atom_ptr.value; |
| 2482 | local_esym.st_value = atom_ptr.value; |
| 2527 | 2483 | |
| 2528 | 2484 | const got_entry_index = try local_sym.getOrCreateOffsetTableEntry(self); |
| 2529 | 2485 | try self.writeOffsetTableEntry(got_entry_index); |
| 2530 | 2486 | |
| 2531 | | const section_offset = vaddr - self.program_headers.items[phdr_index].p_vaddr; |
| 2487 | const section_offset = atom_ptr.value - self.program_headers.items[phdr_index].p_vaddr; |
| 2532 | 2488 | const file_offset = self.sections.items(.shdr)[local_sym.output_section_index].sh_offset + section_offset; |
| 2533 | 2489 | try self.base.file.?.pwriteAll(code, file_offset); |
| 2534 | 2490 | } |
| ... | ... | @@ -2540,7 +2496,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2540 | 2496 | defer code_buffer.deinit(); |
| 2541 | 2497 | |
| 2542 | 2498 | const mod = self.base.options.module.?; |
| 2543 | | const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index); |
| 2499 | const gop = try self.unnamed_consts.getOrPut(gpa, decl_index); |
| 2544 | 2500 | if (!gop.found_existing) { |
| 2545 | 2501 | gop.value_ptr.* = .{}; |
| 2546 | 2502 | } |
| ... | ... | @@ -2586,17 +2542,18 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module |
| 2586 | 2542 | const atom_ptr = local_sym.atom(self).?; |
| 2587 | 2543 | atom_ptr.alignment = math.log2_int(u64, required_alignment); |
| 2588 | 2544 | atom_ptr.size = code.len; |
| 2589 | | const vaddr = try atom_ptr.allocateAtom(self); |
| 2590 | | errdefer self.freeAtom(atom_ptr); |
| 2591 | 2545 | |
| 2592 | | log.debug("allocated text block for {s} at 0x{x}", .{ name, local_sym.st_value }); |
| 2546 | try atom_ptr.allocate(self); |
| 2547 | errdefer self.freeDeclMetadata(sym_index); |
| 2548 | |
| 2549 | log.debug("allocated atom for {s} at 0x{x} to 0x{x}", .{ name, atom_ptr.value, atom_ptr.value + atom_ptr.size }); |
| 2593 | 2550 | |
| 2594 | | local_sym.value = vaddr; |
| 2595 | | local_esym.st_value = vaddr; |
| 2551 | local_sym.value = atom_ptr.value; |
| 2552 | local_esym.st_value = atom_ptr.value; |
| 2596 | 2553 | |
| 2597 | 2554 | try unnamed_consts.append(gpa, atom_ptr.atom_index); |
| 2598 | 2555 | |
| 2599 | | const section_offset = local_sym.value - self.program_headers.items[phdr_index].p_vaddr; |
| 2556 | const section_offset = atom_ptr.value - self.program_headers.items[phdr_index].p_vaddr; |
| 2600 | 2557 | const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset; |
| 2601 | 2558 | try self.base.file.?.pwriteAll(code, file_offset); |
| 2602 | 2559 | |
| ... | ... | @@ -2624,7 +2581,7 @@ pub fn updateDeclExports( |
| 2624 | 2581 | const decl = mod.declPtr(decl_index); |
| 2625 | 2582 | const decl_sym_index = try self.getOrCreateMetadataForDecl(decl_index); |
| 2626 | 2583 | const decl_sym = self.symbol(decl_sym_index); |
| 2627 | | const decl_esym = symbol.sourceSymbol(self); |
| 2584 | const decl_esym = decl_sym.sourceSymbol(self); |
| 2628 | 2585 | const decl_metadata = self.decls.getPtr(decl_index).?; |
| 2629 | 2586 | |
| 2630 | 2587 | for (exports) |exp| { |
| ... | ... | @@ -2658,7 +2615,7 @@ pub fn updateDeclExports( |
| 2658 | 2615 | continue; |
| 2659 | 2616 | }, |
| 2660 | 2617 | }; |
| 2661 | | const stt_bits: u8 = @as(u4, @truncate(decl_sym.st_info)); |
| 2618 | const stt_bits: u8 = @as(u4, @truncate(decl_esym.st_info)); |
| 2662 | 2619 | |
| 2663 | 2620 | const sym_index = if (decl_metadata.@"export"(self, exp_name)) |exp_index| exp_index.* else blk: { |
| 2664 | 2621 | const zig_module = self.file(self.zig_module_index.?).?.zig_module; |
| ... | ... | @@ -3220,7 +3177,7 @@ pub fn addSymbol(self: *Elf) !Symbol.Index { |
| 3220 | 3177 | break :blk index; |
| 3221 | 3178 | } |
| 3222 | 3179 | }; |
| 3223 | | self.symbols.items[index] = .{ .symbol_index = index }; |
| 3180 | self.symbols.items[index] = .{ .index = index }; |
| 3224 | 3181 | return index; |
| 3225 | 3182 | } |
| 3226 | 3183 | |