aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-03-16 17:33:24 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-03-16 17:33:24 -0700
commit1ed569e0b23c4432cd00604dcae89a17edc852a9 (patch)
tree090e0b3817a0caa4f3e7b99ec1d4d965f2bc7438 /src/link
parent778ca2ae6bf025edb6babeec08c957be1fbb37a5 (diff)
parentb4d58e93ea4d0bbfe674f80d301279d302fe8fc8 (diff)
downloadzig-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.zig22
-rw-r--r--src/link/Coff.zig2
-rw-r--r--src/link/Elf.zig68
-rw-r--r--src/link/MachO.zig2
-rw-r--r--src/link/MachO/CodeSignature.zig4
-rw-r--r--src/link/Plan9.zig2
-rw-r--r--src/link/Wasm.zig125
-rw-r--r--src/link/Wasm/Atom.zig24
-rw-r--r--src/link/Wasm/Object.zig2
-rw-r--r--src/link/Wasm/Symbol.zig3
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,