authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-12-23 13:53:13-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-01-15 15:11:36-08:00
log4b9dc2922ff0c5d873971f6f6f25db709df21cc0
tree463888d6f48f1f96dbf10c404878ae8ec2cc661c
parent9cd7cad42ec65bf2bfa2875dfedf5e84da950ced

wasm linker: fix relocation parsing


2 files changed, 62 insertions(+), 7 deletions(-)

src/link/Wasm.zig+19-2
......@@ -1955,6 +1955,8 @@ pub const ObjectRelocation = struct {
19551955 symbol_name: String,
19561956 type_index: FunctionType.Index,
19571957 section: ObjectSectionIndex,
1958 data_segment: ObjectDataSegmentIndex,
1959 function: Wasm.ObjectFunctionIndex,
19581960 };
19591961
19601962 pub const Slice = extern struct {
......@@ -1968,14 +1970,17 @@ pub const ObjectRelocation = struct {
19681970 };
19691971
19701972 pub const Tag = enum(u8) {
1971 /// Uses `symbol_name`.
1973 /// Uses `function`.
19721974 FUNCTION_INDEX_LEB = 0,
19731975 /// Uses `table_index`.
19741976 TABLE_INDEX_SLEB = 1,
19751977 /// Uses `table_index`.
19761978 TABLE_INDEX_I32 = 2,
1979 /// Uses `data_segment`.
19771980 MEMORY_ADDR_LEB = 3,
1981 /// Uses `data_segment`.
19781982 MEMORY_ADDR_SLEB = 4,
1983 /// Uses `data_segment`.
19791984 MEMORY_ADDR_I32 = 5,
19801985 /// Uses `type_index`.
19811986 TYPE_INDEX_LEB = 6,
......@@ -1984,23 +1989,31 @@ pub const ObjectRelocation = struct {
19841989 FUNCTION_OFFSET_I32 = 8,
19851990 SECTION_OFFSET_I32 = 9,
19861991 TAG_INDEX_LEB = 10,
1992 /// Uses `data_segment`.
19871993 MEMORY_ADDR_REL_SLEB = 11,
19881994 TABLE_INDEX_REL_SLEB = 12,
19891995 /// Uses `symbol_name`.
19901996 GLOBAL_INDEX_I32 = 13,
1997 /// Uses `data_segment`.
19911998 MEMORY_ADDR_LEB64 = 14,
1999 /// Uses `data_segment`.
19922000 MEMORY_ADDR_SLEB64 = 15,
2001 /// Uses `data_segment`.
19932002 MEMORY_ADDR_I64 = 16,
2003 /// Uses `data_segment`.
19942004 MEMORY_ADDR_REL_SLEB64 = 17,
19952005 /// Uses `table_index`.
19962006 TABLE_INDEX_SLEB64 = 18,
19972007 /// Uses `table_index`.
19982008 TABLE_INDEX_I64 = 19,
19992009 TABLE_NUMBER_LEB = 20,
2010 /// Uses `data_segment`.
20002011 MEMORY_ADDR_TLS_SLEB = 21,
20012012 FUNCTION_OFFSET_I64 = 22,
2013 /// Uses `data_segment`.
20022014 MEMORY_ADDR_LOCREL_I32 = 23,
20032015 TABLE_INDEX_REL_SLEB64 = 24,
2016 /// Uses `data_segment`.
20042017 MEMORY_ADDR_TLS_SLEB64 = 25,
20052018 /// Uses `symbol_name`.
20062019 FUNCTION_INDEX_I32 = 26,
......@@ -2282,6 +2295,7 @@ fn openParseObjectReportingFailure(wasm: *Wasm, path: Path) void {
22822295}
22832296
22842297fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
2298 log.debug("parseObject {}", .{obj.path});
22852299 const gpa = wasm.base.comp.gpa;
22862300 const gc_sections = wasm.base.gc_sections;
22872301
......@@ -2305,6 +2319,7 @@ fn parseObject(wasm: *Wasm, obj: link.Input.Object) !void {
23052319}
23062320
23072321fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
2322 log.debug("parseArchive {}", .{obj.path});
23082323 const gpa = wasm.base.comp.gpa;
23092324 const gc_sections = wasm.base.gc_sections;
23102325
......@@ -2567,7 +2582,9 @@ pub fn loadInput(wasm: *Wasm, input: link.Input) !void {
25672582 .res => unreachable,
25682583 .dso_exact => unreachable,
25692584 .dso => unreachable,
2570 .object, .archive => |obj| try argv.append(gpa, try obj.path.toString(comp.arena)),
2585 .object, .archive => |obj| {
2586 try argv.append(gpa, try obj.path.toString(comp.arena));
2587 },
25712588 }
25722589 }
25732590
src/link/Wasm/Object.zig+43-5
......@@ -140,7 +140,7 @@ pub const ScratchSpace = struct {
140140 const FuncImportIndex = enum(u32) {
141141 _,
142142
143 fn ptr(index: FunctionImport, ss: *const ScratchSpace) *FunctionImport {
143 fn ptr(index: FuncImportIndex, ss: *const ScratchSpace) *FunctionImport {
144144 return &ss.func_imports.items[@intFromEnum(index)];
145145 }
146146 };
......@@ -351,10 +351,13 @@ pub fn parse(
351351 .function => {
352352 const local_index, pos = readLeb(u32, bytes, pos);
353353 if (symbol.flags.undefined) {
354 symbol.pointee = .{ .function_import = @enumFromInt(local_index) };
354 const function_import: ScratchSpace.FuncImportIndex = @enumFromInt(local_index);
355 symbol.pointee = .{ .function_import = function_import };
355356 if (symbol.flags.explicit_name) {
356357 const name, pos = readBytes(bytes, pos);
357358 symbol.name = (try wasm.internString(name)).toOptional();
359 } else {
360 symbol.name = function_import.ptr(ss).name.toOptional();
358361 }
359362 } else {
360363 symbol.pointee = .{ .function = @enumFromInt(functions_start + local_index) };
......@@ -365,10 +368,13 @@ pub fn parse(
365368 .global => {
366369 const local_index, pos = readLeb(u32, bytes, pos);
367370 if (symbol.flags.undefined) {
368 symbol.pointee = .{ .global_import = @enumFromInt(global_imports_start + local_index) };
371 const global_import: Wasm.GlobalImport.Index = @enumFromInt(global_imports_start + local_index);
372 symbol.pointee = .{ .global_import = global_import };
369373 if (symbol.flags.explicit_name) {
370374 const name, pos = readBytes(bytes, pos);
371375 symbol.name = (try wasm.internString(name)).toOptional();
376 } else {
377 symbol.name = global_import.key(wasm).toOptional();
372378 }
373379 } else {
374380 symbol.pointee = .{ .global = @enumFromInt(globals_start + local_index) };
......@@ -380,10 +386,13 @@ pub fn parse(
380386 table_count += 1;
381387 const local_index, pos = readLeb(u32, bytes, pos);
382388 if (symbol.flags.undefined) {
383 symbol.pointee = .{ .table_import = @enumFromInt(table_imports_start + local_index) };
389 const table_import: Wasm.TableImport.Index = @enumFromInt(table_imports_start + local_index);
390 symbol.pointee = .{ .table_import = table_import };
384391 if (symbol.flags.explicit_name) {
385392 const name, pos = readBytes(bytes, pos);
386393 symbol.name = (try wasm.internString(name)).toOptional();
394 } else {
395 symbol.name = table_import.key(wasm).toOptional();
387396 }
388397 } else {
389398 symbol.pointee = .{ .table = @enumFromInt(tables_start + local_index) };
......@@ -439,10 +448,39 @@ pub fn parse(
439448 .MEMORY_ADDR_TLS_SLEB,
440449 .MEMORY_ADDR_LOCREL_I32,
441450 .MEMORY_ADDR_TLS_SLEB64,
451 => {
452 const addend: i32, pos = readLeb(i32, bytes, pos);
453 const sym_section = ss.symbol_table.items[index].pointee.data;
454 if (sym_section.segment_offset != 0) {
455 return diags.failParse(path, "data symbol {d} has nonzero offset {d}", .{
456 index, sym_section.segment_offset,
457 });
458 }
459 const seg_size = sym_section.segment_index.ptr(wasm).payload.len;
460 if (sym_section.size != seg_size) {
461 return diags.failParse(path, "data symbol {d} has size {d}, inequal to corresponding data segment {d} size {d}", .{
462 index, sym_section.size, @intFromEnum(sym_section.segment_index), seg_size,
463 });
464 }
465 wasm.object_relocations.appendAssumeCapacity(.{
466 .tag = tag,
467 .offset = offset,
468 .pointee = .{ .data_segment = sym_section.segment_index },
469 .addend = addend,
470 });
471 },
442472 .FUNCTION_OFFSET_I32,
443 .SECTION_OFFSET_I32,
444473 .FUNCTION_OFFSET_I64,
445474 => {
475 const addend: i32, pos = readLeb(i32, bytes, pos);
476 wasm.object_relocations.appendAssumeCapacity(.{
477 .tag = tag,
478 .offset = offset,
479 .pointee = .{ .function = ss.symbol_table.items[index].pointee.function },
480 .addend = addend,
481 });
482 },
483 .SECTION_OFFSET_I32 => {
446484 const addend: i32, pos = readLeb(i32, bytes, pos);
447485 wasm.object_relocations.appendAssumeCapacity(.{
448486 .tag = tag,