Commit 4b9dc2922f

Andrew Kelley <andrew@ziglang.org>
2024-12-23 22:53:13
wasm linker: fix relocation parsing
1 parent 9cd7cad
Changed files (2)
src
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,
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));
+            },
         }
     }