Skip to content

Missing BN_* prefixed symbols and library in output binary when dynamic linking #25982

Description

@bullekeup

Zig Version

0.16.0-dev.1364+f0a3df98d

Steps to Reproduce and Observed Behavior

When dynamically linking system provided OpenSSL with 0.16.0-dev.1364+f0a3df98d, every symbol that starts with BN_* is stripped out of the output binary, nothing shown with readelf -s.

If only BN_* functions are used libcrypto is not linked at all (not shown in ldd output).

This only affects BN_* prefixed OpenSSL symbols, if used, other symbols (X509, ...) are present and properly linked. Something related to the BN_* name that triggers a specific behaviour at build / link time maybe ? I looked through the code but failed to find anything relevant.

I tried to link with lld, it fails to link and crash.

Building with LLVM also fails with the following linkage issue:

error: Global is external, but doesn't have external or weak linkage!
       ptr @openssl_bn.main
       LLVM ERROR: Broken module found, compilation aborted!

Sample code :

// openssl_bn.zig
const std = @import("std");

pub const log_level = std.log.Level.debug;

pub const c = @cImport({
    @cInclude("openssl/bn.h");
});

pub fn main() void {
    std.log.info("*Start test*", .{});

    const value: ?*c.BIGNUM = c.BN_new() orelse {
        std.log.err("Failed to create BN", .{});
        return;
    };
    defer c.BN_free(value);
    _ = c.BN_set_word(value, 1);
    std.log.debug("value: {d}", .{c.BN_get_word(value)});
}

Interestingly, building a small test.c file with zig cc works properly

// zig cc -lc -lcrypto test.c -o test
#include <openssl/bn.h>
#include <stdio.h>

int main() {
  BIGNUM *bn = BN_new();
  BN_set_word(bn, 1);
  printf("%lu\n", BN_get_word(bn));
  BN_free(bn);
  return 0;
}

Reproduced on Ubuntu 25.10 x86_64 and Fedora 43 aarch64

Note: building with zig 0.15.2 works as expected, BN_* symbols are present in the binary.

I made a small repo to reproduce easily at https://github.com/bullekeup/zig-issue-openssl.git

Expected Behavior

Symbols present in the binary as reported by readelf :

readelf -s ./zig-out/bin/bn | grep BN_
  3539: 000000000101a220    16 FUNC    LOCAL  DEFAULT   17 BN_set_word$plt
  3540: 000000000101a230    16 FUNC    LOCAL  DEFAULT   17 BN_new$plt
  3541: 000000000101a240    16 FUNC    LOCAL  DEFAULT   17 BN_get_word$plt
  3542: 000000000101a250    16 FUNC    LOCAL  DEFAULT   17 BN_free$plt
  3575: 0000000000000000   103 FUNC    GLOBAL DEFAULT  UND BN_set_word
  3576: 0000000000000000    50 FUNC    GLOBAL DEFAULT  UND BN_new
  3577: 0000000000000000    41 FUNC    GLOBAL DEFAULT  UND BN_get_word
  3578: 0000000000000000   129 FUNC    GLOBAL DEFAULT  UND BN_free

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions