| ... | ... | @@ -1132,6 +1132,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1132 | 1132 | |
| 1133 | 1133 | const file = self.base.file.?; |
| 1134 | 1134 | const header_size = 5 + 1; |
| 1135 | const is_obj = self.base.options.output_mode == .Obj; |
| 1135 | 1136 | |
| 1136 | 1137 | // No need to rewrite the magic/version header |
| 1137 | 1138 | try file.setEndPos(@sizeOf(@TypeOf(wasm.magic ++ wasm.version))); |
| ... | ... | @@ -1443,7 +1444,7 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1443 | 1444 | } |
| 1444 | 1445 | |
| 1445 | 1446 | // Custom section "name" which contains symbol names |
| 1446 | | { |
| 1447 | if (!is_obj) { |
| 1447 | 1448 | const Name = struct { |
| 1448 | 1449 | index: u32, |
| 1449 | 1450 | name: []const u8, |
| ... | ... | @@ -1492,6 +1493,10 @@ pub fn flushModule(self: *Wasm, comp: *Compilation) !void { |
| 1492 | 1493 | @intCast(u32, (try file.getPos()) - header_offset - header_size), |
| 1493 | 1494 | ); |
| 1494 | 1495 | } |
| 1496 | |
| 1497 | if (is_obj) { |
| 1498 | try self.emitLinkSection(file, arena); |
| 1499 | } |
| 1495 | 1500 | } |
| 1496 | 1501 | |
| 1497 | 1502 | fn emitNameSubsection(self: *Wasm, section_id: std.wasm.NameSubsection, names: anytype, writer: anytype) !void { |
| ... | ... | @@ -2030,6 +2035,87 @@ fn writeCustomSectionHeader(file: fs.File, offset: u64, size: u32) !void { |
| 2030 | 2035 | try file.pwriteAll(&buf, offset); |
| 2031 | 2036 | } |
| 2032 | 2037 | |
| 2038 | fn emitLinkSection(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| 2039 | const offset = try reserveCustomSectionHeader(file); |
| 2040 | const writer = file.writer(); |
| 2041 | // emit "linking" custom section name |
| 2042 | const section_name = "linking"; |
| 2043 | try leb.writeULEB128(writer, section_name.len); |
| 2044 | try writer.writeAll(section_name); |
| 2045 | |
| 2046 | // meta data version, which is currently '2' |
| 2047 | try leb.writeULEB128(writer, @as(u32, 2)); |
| 2048 | |
| 2049 | // For each subsection type (found in types.Subsection) we can emit a section. |
| 2050 | // Currently, we only support emitting segment info and the symbol table. |
| 2051 | try self.emitSymbolTable(file, arena); |
| 2052 | |
| 2053 | const size = @intCast(u32, (try file.getPos()) - offset - 6); |
| 2054 | try writeCustomSectionHeader(file, offset, size); |
| 2055 | } |
| 2056 | |
| 2057 | fn emitSymbolTable(self: *Wasm, file: fs.File, arena: Allocator) !void { |
| 2058 | // After emitting the subtype, we must emit the subsection's length |
| 2059 | // so first write it to a temporary arraylist to calculate the length |
| 2060 | // and then write all data at once. |
| 2061 | var payload = std.ArrayList(u8).init(arena); |
| 2062 | const writer = payload.writer(); |
| 2063 | |
| 2064 | try leb.writeULEB128(file.writer(), @enumToInt(types.SubsectionType.WASM_SYMBOL_TABLE)); |
| 2065 | |
| 2066 | var symbol_count: u32 = 0; |
| 2067 | |
| 2068 | var atom_it = self.atoms.valueIterator(); |
| 2069 | while (atom_it.next()) |next_atom| { |
| 2070 | var atom: ?*Atom = next_atom.*.getFirst(); |
| 2071 | while (atom) |current_atom| { |
| 2072 | const sym_loc: SymbolLoc = .{ .file = current_atom.file, .index = current_atom.sym_index }; |
| 2073 | const symbol = sym_loc.getSymbol(self).*; |
| 2074 | if (symbol.tag == .dead) continue; // Do not emit dead symbols |
| 2075 | symbol_count += 1; |
| 2076 | try leb.writeULEB128(writer, @enumToInt(symbol.tag)); |
| 2077 | try leb.writeULEB128(writer, symbol.flags); |
| 2078 | |
| 2079 | switch (symbol.tag) { |
| 2080 | .data => { |
| 2081 | const name = mem.sliceTo(symbol.name, 0); |
| 2082 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| 2083 | try writer.writeAll(name); |
| 2084 | |
| 2085 | if (symbol.isDefined()) { |
| 2086 | try leb.writeULEB128(writer, symbol.index); |
| 2087 | try leb.writeULEB128(writer, @as(u32, current_atom.offset)); |
| 2088 | try leb.writeULEB128(writer, @as(u32, current_atom.size)); |
| 2089 | } |
| 2090 | }, |
| 2091 | .section => { |
| 2092 | try leb.writeULEB128(writer, symbol.index); |
| 2093 | }, |
| 2094 | else => { |
| 2095 | try leb.writeULEB128(writer, symbol.index); |
| 2096 | if (symbol.isDefined()) { |
| 2097 | const name = mem.sliceTo(symbol.name, 0); |
| 2098 | try leb.writeULEB128(writer, @intCast(u32, name.len)); |
| 2099 | try writer.writeAll(name); |
| 2100 | } |
| 2101 | }, |
| 2102 | } |
| 2103 | atom = current_atom.next orelse break; |
| 2104 | } |
| 2105 | } |
| 2106 | |
| 2107 | var buf: [5]u8 = undefined; |
| 2108 | leb.writeUnsignedFixed(5, &buf, symbol_count); |
| 2109 | try payload.insertSlice(0, &buf); |
| 2110 | try leb.writeULEB128(file.writer(), @intCast(u32, payload.items.len)); |
| 2111 | |
| 2112 | const iovec: std.os.iovec_const = .{ |
| 2113 | .iov_base = payload.items.ptr, |
| 2114 | .iov_len = payload.items.len, |
| 2115 | }; |
| 2116 | try file.writevAll(&.{iovec}); |
| 2117 | } |
| 2118 | |
| 2033 | 2119 | /// Searches for an a matching function signature, when not found |
| 2034 | 2120 | /// a new entry will be made. The index of the existing/new signature will be returned. |
| 2035 | 2121 | pub fn putOrGetFuncType(self: *Wasm, func_type: wasm.Type) !u32 { |