aboutsummaryrefslogtreecommitdiff
path: root/src/link/Wasm/Atom.zig
diff options
context:
space:
mode:
authorLuuk de Gram <luuk@degram.dev>2023-01-01 17:10:51 +0100
committerLuuk de Gram <luuk@degram.dev>2023-01-02 18:36:18 +0100
commite475ddb08e4bb3bacbc50bdd26fa83f579783dbb (patch)
tree366a5b3b61c6598b23bc7e8a3551860ba9ac39af /src/link/Wasm/Atom.zig
parent86ed96d9336c06668a727893e41856b2e4fe3d23 (diff)
downloadzig-e475ddb08e4bb3bacbc50bdd26fa83f579783dbb.tar.gz
zig-e475ddb08e4bb3bacbc50bdd26fa83f579783dbb.zip
wasm-linker: export symbols by virtual address
When exporting a data symbol, generate a regular global and use the data symbol's virtual addres as the value (init) of the global.
Diffstat (limited to 'src/link/Wasm/Atom.zig')
-rw-r--r--src/link/Wasm/Atom.zig42
1 files changed, 18 insertions, 24 deletions
diff --git a/src/link/Wasm/Atom.zig b/src/link/Wasm/Atom.zig
index eb3a31b8a0..de9cefebdc 100644
--- a/src/link/Wasm/Atom.zig
+++ b/src/link/Wasm/Atom.zig
@@ -90,24 +90,26 @@ pub fn getFirst(atom: *Atom) *Atom {
return tmp;
}
-/// Unlike `getFirst` this returns the first `*Atom` that was
-/// produced from Zig code, rather than an object file.
-/// This is useful for debug sections where we want to extend
-/// the bytes, and don't want to overwrite existing Atoms.
-pub fn getFirstZigAtom(atom: *Atom) *Atom {
- if (atom.file == null) return atom;
- var tmp = atom;
- return while (tmp.prev) |prev| {
- if (prev.file == null) break prev;
- tmp = prev;
- } else unreachable; // must allocate an Atom first!
-}
-
/// Returns the location of the symbol that represents this `Atom`
pub fn symbolLoc(atom: Atom) Wasm.SymbolLoc {
return .{ .file = atom.file, .index = 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 {
@@ -159,7 +161,7 @@ pub fn resolveRelocs(atom: *Atom, wasm_bin: *const Wasm) void {
/// The final value must be casted to the correct size.
fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wasm) u64 {
const target_loc = (Wasm.SymbolLoc{ .file = atom.file, .index = relocation.index }).finalLoc(wasm_bin);
- const symbol = target_loc.getSymbol(wasm_bin).*;
+ const symbol = target_loc.getSymbol(wasm_bin);
switch (relocation.relocation_type) {
.R_WASM_FUNCTION_INDEX_LEB => return symbol.index,
.R_WASM_TABLE_NUMBER_LEB => return symbol.index,
@@ -190,17 +192,9 @@ fn relocationValue(atom: Atom, relocation: types.Relocation, wasm_bin: *const Wa
if (symbol.isUndefined()) {
return 0;
}
-
- const merge_segment = wasm_bin.base.options.output_mode != .Obj;
const target_atom = wasm_bin.symbol_atom.get(target_loc).?;
- const segment_info = if (target_atom.file) |object_index| blk: {
- break :blk wasm_bin.objects.items[object_index].segment_info;
- } else wasm_bin.segment_info.values();
- const segment_name = segment_info[symbol.index].outputName(merge_segment);
- const segment_index = wasm_bin.data_segments.get(segment_name).?;
- const segment = wasm_bin.segments.items[segment_index];
- const rel_value = @intCast(i32, target_atom.offset + segment.offset) + relocation.addend;
- return @intCast(u32, rel_value);
+ const va = @intCast(i32, target_atom.getVA(wasm_bin, symbol));
+ return @intCast(u32, va + relocation.addend);
},
.R_WASM_EVENT_INDEX_LEB => return symbol.index,
.R_WASM_SECTION_OFFSET_I32 => {