diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-03-16 17:33:24 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-03-16 17:33:24 -0700 |
| commit | 1ed569e0b23c4432cd00604dcae89a17edc852a9 (patch) | |
| tree | 090e0b3817a0caa4f3e7b99ec1d4d965f2bc7438 /src/link | |
| parent | 778ca2ae6bf025edb6babeec08c957be1fbb37a5 (diff) | |
| parent | b4d58e93ea4d0bbfe674f80d301279d302fe8fc8 (diff) | |
| download | zig-1ed569e0b23c4432cd00604dcae89a17edc852a9.tar.gz zig-1ed569e0b23c4432cd00604dcae89a17edc852a9.zip | |
Merge remote-tracking branch 'origin/master' into llvm16
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/C.zig | 22 | ||||
| -rw-r--r-- | src/link/Coff.zig | 2 | ||||
| -rw-r--r-- | src/link/Elf.zig | 68 | ||||
| -rw-r--r-- | src/link/MachO.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/CodeSignature.zig | 4 | ||||
| -rw-r--r-- | src/link/Plan9.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 125 | ||||
| -rw-r--r-- | src/link/Wasm/Atom.zig | 24 | ||||
| -rw-r--r-- | src/link/Wasm/Object.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm/Symbol.zig | 3 |
10 files changed, 164 insertions, 90 deletions
diff --git a/src/link/C.zig b/src/link/C.zig index 5663ba71e2..7e3ad2eddd 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -221,14 +221,19 @@ pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void return self.flushModule(comp, prog_node); } -fn abiDefine(comp: *Compilation) ?[]const u8 { - return switch (comp.getTarget().abi) { - .msvc => "#define ZIG_TARGET_ABI_MSVC\n", - else => null, - }; +fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) { + var defines = std.ArrayList(u8).init(self.base.allocator); + errdefer defines.deinit(); + const writer = defines.writer(); + switch (target.abi) { + .msvc => try writer.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), + else => {}, + } + try writer.print("#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", .{target.maxIntAlignment()}); + return defines; } -pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void { +pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); @@ -245,12 +250,13 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) var f: Flush = .{}; defer f.deinit(gpa); - const abi_define = abiDefine(comp); + const abi_defines = try self.abiDefines(module.getTarget()); + defer abi_defines.deinit(); // Covers defines, zig.h, ctypes, asm, lazy fwd. try f.all_buffers.ensureUnusedCapacity(gpa, 5); - if (abi_define) |buf| f.appendBufAssumeCapacity(buf); + f.appendBufAssumeCapacity(abi_defines.items); f.appendBufAssumeCapacity(zig_h); const ctypes_index = f.all_buffers.items.len; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index c0ac7e0b88..f210f2f2b3 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1060,7 +1060,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In decl.analysis = .codegen_failure; try mod.failed_decls.put(mod.gpa, decl_index, em); log.err("{s}", .{em.msg}); - return error.AnalysisFail; + return error.CodegenFail; }, }; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1a9d594c56..f1ab98372e 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -467,7 +467,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { .p_paddr = entry_addr, .p_memsz = file_size, .p_align = p_align, - .p_flags = elf.PF_X | elf.PF_R, + .p_flags = elf.PF_X | elf.PF_R | elf.PF_W, }); self.entry_addr = null; self.phdr_table_dirty = true; @@ -493,7 +493,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { .p_paddr = got_addr, .p_memsz = file_size, .p_align = p_align, - .p_flags = elf.PF_R, + .p_flags = elf.PF_R | elf.PF_W, }); self.phdr_table_dirty = true; } @@ -516,7 +516,7 @@ pub fn populateMissingMetadata(self: *Elf) !void { .p_paddr = rodata_addr, .p_memsz = file_size, .p_align = p_align, - .p_flags = elf.PF_R, + .p_flags = elf.PF_R | elf.PF_W, }); self.phdr_table_dirty = true; } @@ -2097,9 +2097,16 @@ fn freeAtom(self: *Elf, atom_index: Atom.Index) void { // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. const local_sym_index = atom.getSymbolIndex().?; + log.debug("adding %{d} to local symbols free list", .{local_sym_index}); self.local_symbol_free_list.append(gpa, local_sym_index) catch {}; - self.local_symbols.items[local_sym_index].st_info = 0; - self.local_symbols.items[local_sym_index].st_shndx = 0; + self.local_symbols.items[local_sym_index] = .{ + .st_name = 0, + .st_info = 0, + .st_other = 0, + .st_shndx = 0, + .st_value = 0, + .st_size = 0, + }; _ = self.atom_by_index_table.remove(local_sym_index); self.getAtomPtr(atom_index).local_sym_index = 0; @@ -2159,7 +2166,7 @@ fn allocateAtom(self: *Elf, atom_index: Atom.Index, new_block_size: u64, alignme // First we look for an appropriately sized free list node. // The list is unordered. We'll just take the first thing that works. const vaddr = blk: { - var i: usize = 0; + var i: usize = if (self.base.child_pid == null) 0 else free_list.items.len; while (i < free_list.items.len) { const big_atom_index = free_list.items[i]; const big_atom = self.getAtom(big_atom_index); @@ -2390,7 +2397,7 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s const atom = self.getAtom(atom_index); const shdr_index = decl_metadata.shdr; - if (atom.getSymbol(self).st_size != 0) { + if (atom.getSymbol(self).st_size != 0 and self.base.child_pid == null) { const local_sym = atom.getSymbolPtr(self); local_sym.st_name = try self.shstrtab.insert(gpa, decl_name); local_sym.st_info = (elf.STB_LOCAL << 4) | stt_bits; @@ -2444,6 +2451,28 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s const phdr_index = self.sections.items(.phdr_index)[shdr_index]; const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr; const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset; + + if (self.base.child_pid) |pid| { + switch (builtin.os.tag) { + .linux => { + var code_vec: [1]std.os.iovec_const = .{.{ + .iov_base = code.ptr, + .iov_len = code.len, + }}; + var remote_vec: [1]std.os.iovec_const = .{.{ + .iov_base = @intToPtr([*]u8, @intCast(usize, local_sym.st_value)), + .iov_len = code.len, + }}; + const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0); + switch (std.os.errno(rc)) { + .SUCCESS => assert(rc == code.len), + else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}), + } + }, + else => return error.HotSwapUnavailableOnHostOperatingSystem, + } + } + try self.base.file.?.pwriteAll(code, file_offset); return local_sym; @@ -2618,7 +2647,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module decl.analysis = .codegen_failure; try mod.failed_decls.put(mod.gpa, decl_index, em); log.err("{s}", .{em.msg}); - return error.AnalysisFail; + return error.CodegenFail; }, }; @@ -2813,6 +2842,8 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void { const endian = self.base.options.target.cpu.arch.endian(); const shdr = &self.sections.items(.shdr)[self.got_section_index.?]; const off = shdr.sh_offset + @as(u64, entry_size) * index; + const phdr = &self.program_headers.items[self.phdr_got_index.?]; + const vaddr = phdr.p_vaddr + @as(u64, entry_size) * index; switch (entry_size) { 2 => { var buf: [2]u8 = undefined; @@ -2828,6 +2859,27 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void { var buf: [8]u8 = undefined; mem.writeInt(u64, &buf, self.offset_table.items[index], endian); try self.base.file.?.pwriteAll(&buf, off); + + if (self.base.child_pid) |pid| { + switch (builtin.os.tag) { + .linux => { + var local_vec: [1]std.os.iovec_const = .{.{ + .iov_base = &buf, + .iov_len = buf.len, + }}; + var remote_vec: [1]std.os.iovec_const = .{.{ + .iov_base = @intToPtr([*]u8, @intCast(usize, vaddr)), + .iov_len = buf.len, + }}; + const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0); + switch (std.os.errno(rc)) { + .SUCCESS => assert(rc == buf.len), + else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}), + } + }, + else => return error.HotSwapUnavailableOnHostOperatingSystem, + } + } }, else => unreachable, } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 7c1d4776af..eaf16e4009 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -2089,7 +2089,7 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu decl.analysis = .codegen_failure; try module.failed_decls.put(module.gpa, decl_index, em); log.err("{s}", .{em.msg}); - return error.AnalysisFail; + return error.CodegenFail; }, }; diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig index 8bc00d9181..6d1cd7b536 100644 --- a/src/link/MachO/CodeSignature.zig +++ b/src/link/MachO/CodeSignature.zig @@ -7,12 +7,12 @@ const log = std.log.scoped(.link); const macho = std.macho; const mem = std.mem; const testing = std.testing; +const ThreadPool = std.Thread.Pool; +const WaitGroup = std.Thread.WaitGroup; const Allocator = mem.Allocator; const Compilation = @import("../../Compilation.zig"); const Sha256 = std.crypto.hash.sha2.Sha256; -const ThreadPool = @import("../../ThreadPool.zig"); -const WaitGroup = @import("../../WaitGroup.zig"); const hash_size = Sha256.digest_length; diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 87e3ca5c22..cf6e4f8418 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -377,7 +377,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I decl.analysis = .codegen_failure; try mod.failed_decls.put(mod.gpa, decl_index, em); log.err("{s}", .{em.msg}); - return error.AnalysisFail; + return error.CodegenFail; }, }; // duped_code is freed when the unnamed const is freed diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 74525138a1..e998a8d50e 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -468,6 +468,7 @@ fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !Symbol .flags = 0, .tag = tag, .index = undefined, + .virtual_address = undefined, }); try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, loc, {}); try wasm.globals.put(wasm.base.allocator, name_offset, loc); @@ -886,32 +887,12 @@ fn resolveLazySymbols(wasm: *Wasm) !void { const loc = try wasm.createSyntheticSymbol("__heap_base", .data); try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations. - - // TODO: Can we use `createAtom` here while also re-using the symbol - // from `createSyntheticSymbol`. - const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); - atom.* = Atom.empty; - atom.sym_index = loc.index; - atom.alignment = 1; - - try wasm.parseAtom(atom_index, .{ .data = .synthetic }); - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); } if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| { const loc = try wasm.createSyntheticSymbol("__heap_end", .data); try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc); _ = wasm.resolved_symbols.swapRemove(loc); - - const atom_index = @intCast(Atom.Index, wasm.managed_atoms.items.len); - const atom = try wasm.managed_atoms.addOne(wasm.base.allocator); - atom.* = Atom.empty; - atom.sym_index = loc.index; - atom.alignment = 1; - - try wasm.parseAtom(atom_index, .{ .data = .synthetic }); - try wasm.symbol_atom.putNoClobber(wasm.base.allocator, loc, atom_index); } } @@ -1011,6 +992,7 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 { .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .tag = undefined, // will be set after updateDecl .index = undefined, // will be set after updateDecl + .virtual_address = undefined, // will be set during atom allocation }; if (wasm.symbols_free_list.popOrNull()) |index| { wasm.symbols.items[index] = symbol; @@ -1246,6 +1228,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL), .tag = .data, .index = undefined, + .virtual_address = undefined, }; try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, atom.symbolLoc(), {}); @@ -1265,7 +1248,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In .fail => |em| { decl.analysis = .codegen_failure; try mod.failed_decls.put(mod.gpa, decl_index, em); - return error.AnalysisFail; + return error.CodegenFail; }, }; }; @@ -1292,6 +1275,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8) !u32 { .flags = 0, .index = undefined, // index to type will be set after merging function symbols .tag = .function, + .virtual_address = undefined, }; symbol.setGlobal(true); symbol.setUndefined(true); @@ -1610,7 +1594,6 @@ const Kind = union(enum) { read_only, uninitialized, initialized, - synthetic, }, function: void, @@ -1621,7 +1604,6 @@ const Kind = union(enum) { .read_only => return ".rodata.", .uninitialized => return ".bss.", .initialized => return ".data.", - .synthetic => return ".synthetic", } } }; @@ -1788,6 +1770,30 @@ fn allocateAtoms(wasm: *Wasm) !void { } } +/// For each data symbol, sets the virtual address. +fn allocateVirtualAddresses(wasm: *Wasm) void { + for (wasm.resolved_symbols.keys()) |loc| { + const symbol = loc.getSymbol(wasm); + if (symbol.tag != .data) { + continue; // only data symbols have virtual addresses + } + const atom_index = wasm.symbol_atom.get(loc) orelse { + // synthetic symbol that does not contain an atom + continue; + }; + + const atom = wasm.getAtom(atom_index); + const merge_segment = wasm.base.options.output_mode != .Obj; + const segment_info = if (atom.file) |object_index| blk: { + break :blk wasm.objects.items[object_index].segment_info; + } else wasm.segment_info.values(); + const segment_name = segment_info[symbol.index].outputName(merge_segment); + const segment_index = wasm.data_segments.get(segment_name).?; + const segment = wasm.segments.items[segment_index]; + symbol.virtual_address = atom.offset + segment.offset; + } +} + fn sortDataSegments(wasm: *Wasm) !void { var new_mapping: std.StringArrayHashMapUnmanaged(u32) = .{}; try new_mapping.ensureUnusedCapacity(wasm.base.allocator, wasm.data_segments.count()); @@ -1805,7 +1811,6 @@ fn sortDataSegments(wasm: *Wasm) !void { if (mem.startsWith(u8, name, ".rodata")) return 0; if (mem.startsWith(u8, name, ".data")) return 1; if (mem.startsWith(u8, name, ".text")) return 2; - if (mem.startsWith(u8, name, ".synthetic")) return 100; // always at end return 3; } }; @@ -2137,13 +2142,10 @@ fn setupExports(wasm: *Wasm) !void { break :blk try wasm.string_table.put(wasm.base.allocator, sym_name); }; const exp: types.Export = if (symbol.tag == .data) exp: { - const atom_index = wasm.symbol_atom.get(sym_loc).?; - const atom = wasm.getAtom(atom_index); - const va = atom.getVA(wasm, symbol); const global_index = @intCast(u32, wasm.imported_globals_count + wasm.wasm_globals.items.len); try wasm.wasm_globals.append(wasm.base.allocator, .{ .global_type = .{ .valtype = .i32, .mutable = false }, - .init = .{ .i32_const = @intCast(i32, va) }, + .init = .{ .i32_const = @intCast(i32, symbol.virtual_address) }, }); break :exp .{ .name = export_name, @@ -2220,10 +2222,6 @@ fn setupMemory(wasm: *Wasm) !void { var offset: u32 = @intCast(u32, memory_ptr); var data_seg_it = wasm.data_segments.iterator(); while (data_seg_it.next()) |entry| { - if (mem.eql(u8, entry.key_ptr.*, ".synthetic")) { - // do not update synthetic segments as they are not part of the output - continue; - } const segment = &wasm.segments.items[entry.value_ptr.*]; memory_ptr = std.mem.alignForwardGeneric(u64, memory_ptr, segment.alignment); memory_ptr += segment.size; @@ -2240,12 +2238,8 @@ fn setupMemory(wasm: *Wasm) !void { // One of the linked object files has a reference to the __heap_base symbol. // We must set its virtual address so it can be used in relocations. if (wasm.findGlobalSymbol("__heap_base")) |loc| { - const segment_index = wasm.data_segments.get(".synthetic").?; - const segment = &wasm.segments.items[segment_index]; - segment.offset = 0; // for simplicity we store the entire VA into atom's offset. - const atom_index = wasm.symbol_atom.get(loc).?; - const atom = wasm.getAtomPtr(atom_index); - atom.offset = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment)); + const symbol = loc.getSymbol(wasm); + symbol.virtual_address = @intCast(u32, mem.alignForwardGeneric(u64, memory_ptr, heap_alignment)); } // Setup the max amount of pages @@ -2274,12 +2268,8 @@ fn setupMemory(wasm: *Wasm) !void { log.debug("Total memory pages: {d}", .{wasm.memories.limits.min}); if (wasm.findGlobalSymbol("__heap_end")) |loc| { - const segment_index = wasm.data_segments.get(".synthetic").?; - const segment = &wasm.segments.items[segment_index]; - segment.offset = 0; - const atom_index = wasm.symbol_atom.get(loc).?; - const atom = wasm.getAtomPtr(atom_index); - atom.offset = @intCast(u32, memory_ptr); + const symbol = loc.getSymbol(wasm); + symbol.virtual_address = @intCast(u32, memory_ptr); } if (wasm.base.options.max_memory) |max_memory| { @@ -2417,6 +2407,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 { .tag = .data, .flags = 0, .index = 0, + .virtual_address = undefined, }; symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); @@ -2449,6 +2440,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void { .tag = .data, .flags = 0, .index = 0, + .virtual_address = undefined, }; names_symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN); @@ -2635,6 +2627,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try man.addOptionalFile(compiler_rt_path); man.hash.addOptionalBytes(options.entry); man.hash.addOptional(options.stack_size_override); + man.hash.add(wasm.base.options.build_id); man.hash.add(options.import_memory); man.hash.add(options.import_table); man.hash.add(options.export_table); @@ -2748,6 +2741,7 @@ fn linkWithZld(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) l try wasm.allocateAtoms(); try wasm.setupMemory(); + wasm.allocateVirtualAddresses(); wasm.mapFunctionTable(); try wasm.mergeSections(); try wasm.mergeTypes(); @@ -2866,6 +2860,7 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try wasm.allocateAtoms(); try wasm.setupMemory(); + wasm.allocateVirtualAddresses(); wasm.mapFunctionTable(); try wasm.mergeSections(); try wasm.mergeTypes(); @@ -3225,6 +3220,12 @@ fn writeToFile( } if (!wasm.base.options.strip) { + // The build id must be computed on the main sections only, + // so we have to do it now, before the debug sections. + if (wasm.base.options.build_id) { + try emitBuildIdSection(&binary_bytes); + } + // if (wasm.dwarf) |*dwarf| { // const mod = wasm.base.options.module.?; // try dwarf.writeDbgAbbrev(); @@ -3363,6 +3364,33 @@ fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void { ); } +fn emitBuildIdSection(binary_bytes: *std.ArrayList(u8)) !void { + const header_offset = try reserveCustomSectionHeader(binary_bytes); + + const writer = binary_bytes.writer(); + const build_id = "build_id"; + try leb.writeULEB128(writer, @intCast(u32, build_id.len)); + try writer.writeAll(build_id); + + var id: [16]u8 = undefined; + std.crypto.hash.sha3.TurboShake128(null).hash(binary_bytes.items, &id, .{}); + var uuid: [36]u8 = undefined; + _ = try std.fmt.bufPrint(&uuid, "{s}-{s}-{s}-{s}-{s}", .{ + std.fmt.fmtSliceHexLower(id[0..4]), std.fmt.fmtSliceHexLower(id[4..6]), std.fmt.fmtSliceHexLower(id[6..8]), + std.fmt.fmtSliceHexLower(id[8..10]), std.fmt.fmtSliceHexLower(id[10..]), + }); + + try leb.writeULEB128(writer, @as(u32, 1)); + try leb.writeULEB128(writer, @as(u32, uuid.len)); + try writer.writeAll(&uuid); + + try writeCustomSectionHeader( + binary_bytes.items, + header_offset, + @intCast(u32, binary_bytes.items.len - header_offset - 6), + ); +} + fn emitFeaturesSection(binary_bytes: *std.ArrayList(u8), enabled_features: []const bool, features_count: u32) !void { const header_offset = try reserveCustomSectionHeader(binary_bytes); @@ -3426,8 +3454,6 @@ fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem // bss section is not emitted when this condition holds true, so we also // do not output a name for it. if (!wasm.base.options.import_memory and std.mem.eql(u8, key, ".bss")) continue; - // Synthetic segments are not emitted - if (std.mem.eql(u8, key, ".synthetic")) continue; segments.appendAssumeCapacity(.{ .index = data_segment_index, .name = key }); data_segment_index += 1; } @@ -3594,6 +3620,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try man.addOptionalFile(compiler_rt_path); man.hash.addOptionalBytes(wasm.base.options.entry); man.hash.addOptional(wasm.base.options.stack_size_override); + man.hash.add(wasm.base.options.build_id); man.hash.add(wasm.base.options.import_memory); man.hash.add(wasm.base.options.import_table); man.hash.add(wasm.base.options.export_table); @@ -3760,6 +3787,12 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! if (wasm.base.options.import_symbols) { try argv.append("--allow-undefined"); } + + // XXX - TODO: add when wasm-ld supports --build-id. + // if (wasm.base.options.build_id) { + // try argv.append("--build-id=tree"); + // } + try argv.appendSlice(&.{ "-o", full_out_path }); if (target.cpu.arch == .wasm64) { diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig index e719f8dfcc..0c9d761f05 100644 --- a/src/link/Wasm/Atom.zig +++ b/src/link/Wasm/Atom.zig @@ -89,21 +89,6 @@ pub fn getSymbolIndex(atom: Atom) ?u32 { return atom.sym_index; } -/// Returns the virtual address of the `Atom`. This is the address starting -/// from the first entry within a section. -pub fn getVA(atom: Atom, wasm: *const Wasm, symbol: *const Symbol) u32 { - if (symbol.tag == .function) return atom.offset; - std.debug.assert(symbol.tag == .data); - const merge_segment = wasm.base.options.output_mode != .Obj; - const segment_info = if (atom.file) |object_index| blk: { - break :blk wasm.objects.items[object_index].segment_info; - } else wasm.segment_info.values(); - const segment_name = segment_info[symbol.index].outputName(merge_segment); - const segment_index = wasm.data_segments.get(segment_name).?; - const segment = wasm.segments.items[segment_index]; - return segment.offset + atom.offset; -} - /// Resolves the relocations within the atom, writing the new value /// at the calculated offset. pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void { @@ -186,14 +171,7 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa if (symbol.isUndefined()) { return 0; } - const target_atom_index = wasm_bin.symbol_atom.get(target_loc) orelse { - // this can only occur during incremental-compilation when a relocation - // still points to a freed decl. It is fine to emit the value 0 here - // as no actual code will point towards it. - return 0; - }; - const target_atom = wasm_bin.getAtom(target_atom_index); - const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol)); + const va = @intCast(i64, symbol.virtual_address); return @intCast(u32, va + relocation.addend); }, .R_WASM_EVENT_INDEX_LEB => return symbol.index, diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 82cab2528a..45c9464ec8 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -270,6 +270,7 @@ fn checkLegacyIndirectFunctionTable(object: *Object) !?Symbol { .name = table_import.name, .tag = .table, .index = 0, + .virtual_address = undefined, }; table_symbol.setFlag(.WASM_SYM_UNDEFINED); table_symbol.setFlag(.WASM_SYM_NO_STRIP); @@ -758,6 +759,7 @@ fn Parser(comptime ReaderType: type) type { .tag = tag, .name = undefined, .index = undefined, + .virtual_address = undefined, }; switch (tag) { diff --git a/src/link/Wasm/Symbol.zig b/src/link/Wasm/Symbol.zig index 089eee289e..156b507a32 100644 --- a/src/link/Wasm/Symbol.zig +++ b/src/link/Wasm/Symbol.zig @@ -20,6 +20,9 @@ name: u32, index: u32, /// Represents the kind of the symbol, such as a function or global. tag: Tag, +/// Contains the virtual address of the symbol, relative to the start of its section. +/// This differs from the offset of an `Atom` which is relative to the start of a segment. +virtual_address: u32, pub const Tag = enum { function, |
