From 4b9dc2922ff0c5d873971f6f6f25db709df21cc0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 23 Dec 2024 13:53:13 -0800 Subject: [PATCH] wasm linker: fix relocation parsing --- src/link/Wasm.zig | 21 ++++++++++++++++-- src/link/Wasm/Object.zig | 48 +++++++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 39fe65f2e9..c705bfbbab 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -1955,6 +1955,8 @@ pub const ObjectRelocation = struct { symbol_name: String, type_index: FunctionType.Index, section: ObjectSectionIndex, + data_segment: ObjectDataSegmentIndex, + function: Wasm.ObjectFunctionIndex, }; pub const Slice = extern struct { @@ -1968,14 +1970,17 @@ pub const ObjectRelocation = struct { }; pub const Tag = enum(u8) { - /// Uses `symbol_name`. + /// Uses `function`. FUNCTION_INDEX_LEB = 0, /// Uses `table_index`. TABLE_INDEX_SLEB = 1, /// Uses `table_index`. TABLE_INDEX_I32 = 2, + /// Uses `data_segment`. MEMORY_ADDR_LEB = 3, + /// Uses `data_segment`. MEMORY_ADDR_SLEB = 4, + /// Uses `data_segment`. MEMORY_ADDR_I32 = 5, /// Uses `type_index`. TYPE_INDEX_LEB = 6, @@ -1984,23 +1989,31 @@ pub const ObjectRelocation = struct { FUNCTION_OFFSET_I32 = 8, SECTION_OFFSET_I32 = 9, TAG_INDEX_LEB = 10, + /// Uses `data_segment`. MEMORY_ADDR_REL_SLEB = 11, TABLE_INDEX_REL_SLEB = 12, /// Uses `symbol_name`. GLOBAL_INDEX_I32 = 13, + /// Uses `data_segment`. MEMORY_ADDR_LEB64 = 14, + /// Uses `data_segment`. MEMORY_ADDR_SLEB64 = 15, + /// Uses `data_segment`. MEMORY_ADDR_I64 = 16, + /// Uses `data_segment`. MEMORY_ADDR_REL_SLEB64 = 17, /// Uses `table_index`. TABLE_INDEX_SLEB64 = 18, /// Uses `table_index`. TABLE_INDEX_I64 = 19, TABLE_NUMBER_LEB = 20, + /// Uses `data_segment`. MEMORY_ADDR_TLS_SLEB = 21, FUNCTION_OFFSET_I64 = 22, + /// Uses `data_segment`. MEMORY_ADDR_LOCREL_I32 = 23, TABLE_INDEX_REL_SLEB64 = 24, + /// Uses `data_segment`. MEMORY_ADDR_TLS_SLEB64 = 25, /// Uses `symbol_name`. FUNCTION_INDEX_I32 = 26, @@ -2282,6 +2295,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void { } fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { + log.debug("parseObject {}", .{obj.path}); const gpa = wasm.base.comp.gpa; const gc_sections = wasm.base.gc_sections; @@ -2305,6 +2319,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void { } fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void { + log.debug("parseArchive {}", .{obj.path}); const gpa = wasm.base.comp.gpa; const gc_sections = wasm.base.gc_sections; @@ -2567,7 +2582,9 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void { .res => unreachable, .dso_exact => unreachable, .dso => unreachable, - .object, .archive => |obj| try argv.append(gpa, try obj.path.toString(comp.arena)), + .object, .archive => |obj| { + try argv.append(gpa, try obj.path.toString(comp.arena)); + }, } } diff --git a/src/link/Wasm/Object.zig b/src/link/Wasm/Object.zig index 5dd755fe54..ac96956bb4 100644 --- a/src/link/Wasm/Object.zig +++ b/src/link/Wasm/Object.zig @@ -140,7 +140,7 @@ pub const ScratchSpace = struct { const FuncImportIndex = enum(u32) { _, - fn ptr(index: FunctionImport, ss: *const ScratchSpace) *FunctionImport { + fn ptr(index: FuncImportIndex, ss: *const ScratchSpace) *FunctionImport { return &ss.func_imports.items[@intFromEnum(index)]; } }; @@ -351,10 +351,13 @@ pub fn parse( .function => { const local_index, pos = readLeb(u32, bytes, pos); if (symbol.flags.undefined) { - symbol.pointee = .{ .function_import = @enumFromInt(local_index) }; + const function_import: ScratchSpace.FuncImportIndex = @enumFromInt(local_index); + symbol.pointee = .{ .function_import = function_import }; if (symbol.flags.explicit_name) { const name, pos = readBytes(bytes, pos); symbol.name = (try wasm.internString(name)).toOptional(); + } else { + symbol.name = function_import.ptr(ss).name.toOptional(); } } else { symbol.pointee = .{ .function = @enumFromInt(functions_start + local_index) }; @@ -365,10 +368,13 @@ pub fn parse( .global => { const local_index, pos = readLeb(u32, bytes, pos); if (symbol.flags.undefined) { - symbol.pointee = .{ .global_import = @enumFromInt(global_imports_start + local_index) }; + const global_import: Wasm.GlobalImport.Index = @enumFromInt(global_imports_start + local_index); + symbol.pointee = .{ .global_import = global_import }; if (symbol.flags.explicit_name) { const name, pos = readBytes(bytes, pos); symbol.name = (try wasm.internString(name)).toOptional(); + } else { + symbol.name = global_import.key(wasm).toOptional(); } } else { symbol.pointee = .{ .global = @enumFromInt(globals_start + local_index) }; @@ -380,10 +386,13 @@ pub fn parse( table_count += 1; const local_index, pos = readLeb(u32, bytes, pos); if (symbol.flags.undefined) { - symbol.pointee = .{ .table_import = @enumFromInt(table_imports_start + local_index) }; + const table_import: Wasm.TableImport.Index = @enumFromInt(table_imports_start + local_index); + symbol.pointee = .{ .table_import = table_import }; if (symbol.flags.explicit_name) { const name, pos = readBytes(bytes, pos); symbol.name = (try wasm.internString(name)).toOptional(); + } else { + symbol.name = table_import.key(wasm).toOptional(); } } else { symbol.pointee = .{ .table = @enumFromInt(tables_start + local_index) }; @@ -439,10 +448,39 @@ pub fn parse( .MEMORY_ADDR_TLS_SLEB, .MEMORY_ADDR_LOCREL_I32, .MEMORY_ADDR_TLS_SLEB64, + => { + const addend: i32, pos = readLeb(i32, bytes, pos); + const sym_section = ss.symbol_table.items[index].pointee.data; + if (sym_section.segment_offset != 0) { + return diags.failParse(path, "data symbol {d} has nonzero offset {d}", .{ + index, sym_section.segment_offset, + }); + } + const seg_size = sym_section.segment_index.ptr(wasm).payload.len; + if (sym_section.size != seg_size) { + return diags.failParse(path, "data symbol {d} has size {d}, inequal to corresponding data segment {d} size {d}", .{ + index, sym_section.size, @intFromEnum(sym_section.segment_index), seg_size, + }); + } + wasm.object_relocations.appendAssumeCapacity(.{ + .tag = tag, + .offset = offset, + .pointee = .{ .data_segment = sym_section.segment_index }, + .addend = addend, + }); + }, .FUNCTION_OFFSET_I32, - .SECTION_OFFSET_I32, .FUNCTION_OFFSET_I64, => { + const addend: i32, pos = readLeb(i32, bytes, pos); + wasm.object_relocations.appendAssumeCapacity(.{ + .tag = tag, + .offset = offset, + .pointee = .{ .function = ss.symbol_table.items[index].pointee.function }, + .addend = addend, + }); + }, + .SECTION_OFFSET_I32 => { const addend: i32, pos = readLeb(i32, bytes, pos); wasm.object_relocations.appendAssumeCapacity(.{ .tag = tag,