Commit 9932372fae

Luuk de Gram <luuk@degram.dev>
2022-12-31 15:27:24
wasm-linker: support export flags
Adds support for both the `-rdynamic` and the `--export=<value>` flags. Support is added to both the incremental linker as well as the traditional linker (zld).
1 parent 4172c29
Changed files (2)
src
src/link/Wasm/Symbol.zig
@@ -139,12 +139,10 @@ pub fn isNoStrip(symbol: Symbol) bool {
     return symbol.flags & @enumToInt(Flag.WASM_SYM_NO_STRIP) != 0;
 }
 
-pub fn isExported(symbol: Symbol) bool {
+pub fn isExported(symbol: Symbol, is_dynamic: bool) bool {
     if (symbol.isUndefined() or symbol.isLocal()) return false;
-    if (symbol.isHidden()) return false;
-    if (symbol.hasFlag(.WASM_SYM_EXPORTED)) return true;
-    if (symbol.hasFlag(.WASM_SYM_BINDING_WEAK)) return false;
-    return true;
+    if (is_dynamic and symbol.isVisible()) return true;
+    return symbol.hasFlag(.WASM_SYM_EXPORTED);
 }
 
 pub fn isWeak(symbol: Symbol) bool {
src/link/Wasm.zig
@@ -1800,9 +1800,36 @@ fn setupExports(wasm: *Wasm) !void {
     if (wasm.base.options.output_mode == .Obj) return;
     log.debug("Building exports from symbols", .{});
 
+    const force_exp_names = wasm.base.options.export_symbol_names;
+    if (force_exp_names.len > 0) {
+        var failed_exports = try std.ArrayList([]const u8).initCapacity(wasm.base.allocator, force_exp_names.len);
+        defer failed_exports.deinit();
+
+        for (force_exp_names) |exp_name| {
+            const name_index = wasm.string_table.getOffset(exp_name) orelse {
+                failed_exports.appendAssumeCapacity(exp_name);
+                continue;
+            };
+            const loc = wasm.globals.get(name_index) orelse {
+                failed_exports.appendAssumeCapacity(exp_name);
+                continue;
+            };
+
+            const symbol = loc.getSymbol(wasm);
+            symbol.setFlag(.WASM_SYM_EXPORTED);
+        }
+
+        if (failed_exports.items.len > 0) {
+            for (failed_exports.items) |exp_name| {
+                log.err("could not export '{s}', symbol not found", .{exp_name});
+            }
+            return error.MissingSymbol;
+        }
+    }
+
     for (wasm.resolved_symbols.keys()) |sym_loc| {
         const symbol = sym_loc.getSymbol(wasm);
-        if (!symbol.isExported()) continue;
+        if (!symbol.isExported(wasm.base.options.rdynamic)) continue;
 
         const sym_name = sym_loc.getName(wasm);
         const export_name = if (wasm.export_names.get(sym_loc)) |name| name else blk: {