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,