authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-10-01 15:33:15+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2022-10-08 09:43:35+02:00
log43b55ea9f4a5a05c9ff295ea00aab687141e24c3
treeae58bd2515e76213f9c55be68655d19bfd5f452b
parent11dce78944ecfab1838cd678f75c354aa376a8bf
signaturelock-open Commit is signed but in an unrecognized format.

wasm-linker: generate 'producers' section

The `producers` section contains meta data of the binary and/or object file. It *can* contain the source language, the tool it was processed by, and/or the SDK that was used to produce the file. For now, we always set the language and processed-by fields to Zig. In the future we will parse linked object files to detect their producers sections and append (if different) their language, SDK and processed-by fields.

1 files changed, 65 insertions(+), 1 deletions(-)

src/link/Wasm.zig+65-1
...@@ -2556,6 +2556,10 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2556,6 +2556,10 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2556 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);2556 try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table);
2557 }2557 }
2558 } else if (!wasm.base.options.strip) {2558 } else if (!wasm.base.options.strip) {
2559 try wasm.emitNameSection(&binary_bytes, arena);
2560 }
2561
2562 if (!wasm.base.options.strip) {
2559 if (wasm.dwarf) |*dwarf| {2563 if (wasm.dwarf) |*dwarf| {
2560 const mod = wasm.base.options.module.?;2564 const mod = wasm.base.options.module.?;
2561 try dwarf.writeDbgAbbrev(&wasm.base);2565 try dwarf.writeDbgAbbrev(&wasm.base);
...@@ -2597,7 +2601,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -2597,7 +2601,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
2597 debug_bytes.clearRetainingCapacity();2601 debug_bytes.clearRetainingCapacity();
2598 }2602 }
2599 }2603 }
2600 try wasm.emitNameSection(&binary_bytes, arena);2604
2605 try emitProducerSection(&binary_bytes);
2601 }2606 }
26022607
2603 // Only when writing all sections executed properly we write the magic2608 // 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,6 +2636,65 @@ fn emitDebugSection(binary_bytes: *std.ArrayList(u8), data: []const u8, name: []
2631 );2636 );
2632}2637}
26332638
2639fn 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
2634fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {2698fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void {
2635 const Name = struct {2699 const Name = struct {
2636 index: u32,2700 index: u32,