diff options
| author | Luuk de Gram <luuk@degram.dev> | 2022-10-01 15:33:15 +0200 |
|---|---|---|
| committer | Luuk de Gram <luuk@degram.dev> | 2022-10-08 09:43:35 +0200 |
| commit | 43b55ea9f4a5a05c9ff295ea00aab687141e24c3 (patch) | |
| tree | ae58bd2515e76213f9c55be68655d19bfd5f452b /src | |
| parent | 11dce78944ecfab1838cd678f75c354aa376a8bf (diff) | |
| download | zig-43b55ea9f4a5a05c9ff295ea00aab687141e24c3.tar.gz zig-43b55ea9f4a5a05c9ff295ea00aab687141e24c3.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Wasm.zig | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 0e6fe5dcc2..67b4218b3f 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2556,6 +2556,10 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod try wasm.emitDataRelocations(&binary_bytes, data_index, symbol_table); } } else if (!wasm.base.options.strip) { + try wasm.emitNameSection(&binary_bytes, arena); + } + + if (!wasm.base.options.strip) { if (wasm.dwarf) |*dwarf| { const mod = wasm.base.options.module.?; try dwarf.writeDbgAbbrev(&wasm.base); @@ -2597,7 +2601,8 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod debug_bytes.clearRetainingCapacity(); } } - try wasm.emitNameSection(&binary_bytes, arena); + + try emitProducerSection(&binary_bytes); } // 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: [] ); } +fn emitProducerSection(binary_bytes: *std.ArrayList(u8)) !void { + const header_offset = try reserveCustomSectionHeader(binary_bytes); + + const writer = binary_bytes.writer(); + const producers = "producers"; + try leb.writeULEB128(writer, @intCast(u32, producers.len)); + try writer.writeAll(producers); + + try leb.writeULEB128(writer, @as(u32, 2)); // 2 fields: Language + processed-by + + // used for the Zig version + var version_buf: [100]u8 = undefined; + const version = try std.fmt.bufPrint(&version_buf, "{}", .{build_options.semver}); + + // language field + { + const language = "language"; + try leb.writeULEB128(writer, @intCast(u32, language.len)); + try writer.writeAll(language); + + // field_value_count (TODO: Parse object files for producer sections to detect their language) + try leb.writeULEB128(writer, @as(u32, 1)); + + // versioned name + { + try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig" + try writer.writeAll("Zig"); + + try leb.writeULEB128(writer, @intCast(u32, version.len)); + try writer.writeAll(version); + } + } + + // processed-by field + { + const processed_by = "processed_by"; + try leb.writeULEB128(writer, @intCast(u32, processed_by.len)); + try writer.writeAll(processed_by); + + // field_value_count (TODO: Parse object files for producer sections to detect other used tools) + try leb.writeULEB128(writer, @as(u32, 1)); + + // versioned name + { + try leb.writeULEB128(writer, @as(u32, 3)); // len of "Zig" + try writer.writeAll("Zig"); + + try leb.writeULEB128(writer, @intCast(u32, version.len)); + try writer.writeAll(version); + } + } + + try writeCustomSectionHeader( + binary_bytes.items, + header_offset, + @intCast(u32, binary_bytes.items.len - header_offset - 6), + ); +} + fn emitNameSection(wasm: *Wasm, binary_bytes: *std.ArrayList(u8), arena: std.mem.Allocator) !void { const Name = struct { index: u32, |
