| author | |
| committer | |
| log | fa9327ac051031be21b6ccb494f31585d0b68915 |
| tree | ffb6ffb6bf9a92a01c13a232dcdee9211f4be6c1 |
| parent | 11dce78944ecfab1838cd678f75c354aa376a8bf |
| parent | fda75f53fa19ed561a8fc0d7d5ed0e6a26ee3b1d |
| signature |
wasm-linker: generate 'producers' section5 files changed, 144 insertions(+), 2 deletions(-)
lib/std/build/CheckObjectStep.zig+36| ... | ... | @@ -644,6 +644,8 @@ const WasmDumper = struct { |
| 644 | 644 | |
| 645 | 645 | if (mem.eql(u8, name, "name")) { |
| 646 | 646 | try parseDumpNames(reader, writer, data); |
| 647 | } else if (mem.eql(u8, name, "producers")) { | |
| 648 | try parseDumpProducers(reader, writer, data); | |
| 647 | 649 | } |
| 648 | 650 | // TODO: Implement parsing and dumping other custom sections (such as relocations) |
| 649 | 651 | }, |
| ... | ... | @@ -863,4 +865,38 @@ const WasmDumper = struct { |
| 863 | 865 | } |
| 864 | 866 | } |
| 865 | 867 | } |
| 868 | ||
| 869 | fn parseDumpProducers(reader: anytype, writer: anytype, data: []const u8) !void { | |
| 870 | const field_count = try std.leb.readULEB128(u32, reader); | |
| 871 | try writer.print("fields {d}\n", .{field_count}); | |
| 872 | var current_field: u32 = 0; | |
| 873 | while (current_field < field_count) : (current_field += 1) { | |
| 874 | const field_name_length = try std.leb.readULEB128(u32, reader); | |
| 875 | const field_name = data[reader.context.pos..][0..field_name_length]; | |
| 876 | reader.context.pos += field_name_length; | |
| 877 | ||
| 878 | const value_count = try std.leb.readULEB128(u32, reader); | |
| 879 | try writer.print( | |
| 880 | \\field_name {s} | |
| 881 | \\values {d} | |
| 882 | , .{ field_name, value_count }); | |
| 883 | try writer.writeByte('\n'); | |
| 884 | var current_value: u32 = 0; | |
| 885 | while (current_value < value_count) : (current_value += 1) { | |
| 886 | const value_length = try std.leb.readULEB128(u32, reader); | |
| 887 | const value = data[reader.context.pos..][0..value_length]; | |
| 888 | reader.context.pos += value_length; | |
| 889 | ||
| 890 | const version_length = try std.leb.readULEB128(u32, reader); | |
| 891 | const version = data[reader.context.pos..][0..version_length]; | |
| 892 | reader.context.pos += version_length; | |
| 893 | ||
| 894 | try writer.print( | |
| 895 | \\value_name {s} | |
| 896 | \\version {s} | |
| 897 | , .{ value, version }); | |
| 898 | try writer.writeByte('\n'); | |
| 899 | } | |
| 900 | } | |
| 901 | } | |
| 866 | 902 | }; |
src/link/Wasm.zig+65-1| ... | ... | @@ -2556,6 +2556,10 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2556 | 2556 | try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); |
| 2557 | 2557 | } |
| 2558 | 2558 | } else if (!wasm.base.options.strip) { |
| 2559 | try wasm.emitNameSection(&binary_bytes, arena); | |
| 2560 | } | |
| 2561 | ||
| 2562 | if (!wasm.base.options.strip) { | |
| 2559 | 2563 | if (wasm.dwarf) |*dwarf| { |
| 2560 | 2564 | const mod = wasm.base.options.module.?; |
| 2561 | 2565 | try dwarf.writeDbgAbbrev(&wasm.base); |
| ... | ... | @@ -2597,7 +2601,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod |
| 2597 | 2601 | debug_bytes.clearRetainingCapacity(); |
| 2598 | 2602 | } |
| 2599 | 2603 | } |
| 2600 | try wasm.emitNameSection(&binary_bytes, arena); | |
| 2604 | ||
| 2605 | try emitProducerSection(&binary_bytes); | |
| 2601 | 2606 | } |
| 2602 | 2607 | |
| 2603 | 2608 | // Only when writing all sections executed properly we write the magic |
| ... | ... | @@ -2631,6 +2636,65 @@ fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: [] |
| 2631 | 2636 | ); |
| 2632 | 2637 | } |
| 2633 | 2638 | |
| 2639 | fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void { | |
| 2640 | const header_offset = try reserveCustomSectionHeader(binary_bytes); | |
| 2641 | ||
| 2642 | const writer = binary_bytes.writer(); | |
| 2643 | const producers = "producers"; | |
| 2644 | try leb.writeULEB128(writer, @intCast(u32, producers.len)); | |
| 2645 | try writer.writeAll(producers); | |
| 2646 | ||
| 2647 | try leb.writeULEB128(writer, @as(u32, 2)); // 2 fields: Language + processed-by | |
| 2648 | ||
| 2649 | // used for the Zig version | |
| 2650 | var version_buf: [100]u8 = undefined; | |
| 2651 | const version = try std.fmt.bufPrint(&version_buf, "{}", .{build_options.semver}); | |
| 2652 | ||
| 2653 | // language field | |
| 2654 | { | |
| 2655 | const language = "language"; | |
| 2656 | try leb.writeULEB128(writer, @intCast(u32, language.len)); | |
| 2657 | try writer.writeAll(language); | |
| 2658 | ||
| 2659 | // field_value_count (TODO: Parse object files for producer sections to detect their language) | |
| 2660 | try leb.writeULEB128(writer, @as(u32, 1)); | |
| 2661 | ||
| 2662 | // versioned name | |
| 2663 | { | |
| 2664 | try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig" | |
| 2665 | try writer.writeAll("Zig"); | |
| 2666 | ||
| 2667 | try leb.writeULEB128(writer, @intCast(u32, version.len)); | |
| 2668 | try writer.writeAll(version); | |
| 2669 | } | |
| 2670 | } | |
| 2671 | ||
| 2672 | // processed-by field | |
| 2673 | { | |
| 2674 | const processed_by = "processed-by"; | |
| 2675 | try leb.writeULEB128(writer, @intCast(u32, processed_by.len)); | |
| 2676 | try writer.writeAll(processed_by); | |
| 2677 | ||
| 2678 | // field_value_count (TODO: Parse object files for producer sections to detect other used tools) | |
| 2679 | try leb.writeULEB128(writer, @as(u32, 1)); | |
| 2680 | ||
| 2681 | // versioned name | |
| 2682 | { | |
| 2683 | try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig" | |
| 2684 | try writer.writeAll("Zig"); | |
| 2685 | ||
| 2686 | try leb.writeULEB128(writer, @intCast(u32, version.len)); | |
| 2687 | try writer.writeAll(version); | |
| 2688 | } | |
| 2689 | } | |
| 2690 | ||
| 2691 | try writeCustomSectionHeader( | |
| 2692 | binary_bytes.items, | |
| 2693 | header_offset, | |
| 2694 | @intCast(u32, binary_bytes.items.len - header_offset - 6), | |
| 2695 | ); | |
| 2696 | } | |
| 2697 | ||
| 2634 | 2698 | fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void { |
| 2635 | 2699 | const Name = struct { |
| 2636 | 2700 | index: u32, |
test/link.zig+6-1| ... | ... | @@ -34,7 +34,7 @@ fn addWasmCases(cases: *tests.StandaloneContext) void { |
| 34 | 34 | }); |
| 35 | 35 | |
| 36 | 36 | cases.addBuildFile("test/link/wasm/bss/build.zig", .{ |
| 37 | .build_modes = true, | |
| 37 | .build_modes = false, | |
| 38 | 38 | .requires_stage2 = true, |
| 39 | 39 | }); |
| 40 | 40 | |
| ... | ... | @@ -44,6 +44,11 @@ fn addWasmCases(cases: *tests.StandaloneContext) void { |
| 44 | 44 | .use_emulation = true, |
| 45 | 45 | }); |
| 46 | 46 | |
| 47 | cases.addBuildFile("test/link/wasm/producers/build.zig", .{ | |
| 48 | .build_modes = true, | |
| 49 | .requires_stage2 = true, | |
| 50 | }); | |
| 51 | ||
| 47 | 52 | cases.addBuildFile("test/link/wasm/segments/build.zig", .{ |
| 48 | 53 | .build_modes = true, |
| 49 | 54 | .requires_stage2 = true, |
test/link/wasm/producers/build.zig created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const Builder = std.build.Builder; | |
| 4 | ||
| 5 | pub fn build(b: *Builder) void { | |
| 6 | const mode = b.standardReleaseOptions(); | |
| 7 | ||
| 8 | const test_step = b.step("test", "Test"); | |
| 9 | test_step.dependOn(b.getInstallStep()); | |
| 10 | ||
| 11 | const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned); | |
| 12 | lib.setBuildMode(mode); | |
| 13 | lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }); | |
| 14 | lib.use_llvm = false; | |
| 15 | lib.use_stage1 = false; | |
| 16 | lib.use_lld = false; | |
| 17 | lib.install(); | |
| 18 | ||
| 19 | const zig_version = builtin.zig_version; | |
| 20 | var version_buf: [100]u8 = undefined; | |
| 21 | const version_fmt = std.fmt.bufPrint(&version_buf, "version {}", .{zig_version}) catch unreachable; | |
| 22 | ||
| 23 | const check_lib = lib.checkObject(.wasm); | |
| 24 | check_lib.checkStart("name producers"); | |
| 25 | check_lib.checkNext("fields 2"); | |
| 26 | check_lib.checkNext("field_name language"); | |
| 27 | check_lib.checkNext("values 1"); | |
| 28 | check_lib.checkNext("value_name Zig"); | |
| 29 | check_lib.checkNext(version_fmt); | |
| 30 | check_lib.checkNext("field_name processed-by"); | |
| 31 | check_lib.checkNext("values 1"); | |
| 32 | check_lib.checkNext("value_name Zig"); | |
| 33 | check_lib.checkNext(version_fmt); | |
| 34 | ||
| 35 | test_step.dependOn(&check_lib.step); | |
| 36 | } |
test/link/wasm/producers/lib.zig created+1| ... | ... | @@ -0,0 +1 @@ |
| 1 | export fn foo() void {} |