Skip to content

Commit

Permalink
wireshark-dissector-sys: Use raw-dylib on Windows
Browse files Browse the repository at this point in the history
Fixes #62.
  • Loading branch information
heinrich5991 committed May 16, 2024
1 parent 08bdc5d commit f6960cc
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 166 deletions.
43 changes: 1 addition & 42 deletions wireshark-dissector/build.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,9 @@
use std::env;
use std::path::PathBuf;

fn non_windows_msvc() {
println!("cargo:rustc-cdylib-link-arg=-Wl,-undefined,dynamic_lookup");
}

fn windows_msvc() {
let top_level =
PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").expect("missing CARGO_MANIFEST_DIR"));
let out_dir = PathBuf::from(env::var_os("OUT_DIR").expect("missing OUT_DIR"));
let target = env::var_os("TARGET")
.expect("missing TARGET")
.into_string()
.expect("invalid TARGET");

let lib = cc::windows_registry::find_tool(&target, "lib.exe").expect("lib.exe not found");
let build_and_link_lib = |def_filename: &str, lib_filename: &str| {
let def_file = top_level.join(def_filename);
let def_file = def_file
.into_os_string()
.into_string()
.expect("invalid CARGO_MANIFEST_DIR");

let lib_file = out_dir.join(lib_filename);
let lib_file = lib_file
.into_os_string()
.into_string()
.expect("invalid OUT_DIR");

let result = lib
.to_command()
.arg(format!("/def:{}", def_file))
.arg(format!("/out:{}", lib_file))
.status()
.expect("failed to execute lib.exe");
assert!(result.success());

println!("cargo:rustc-cdylib-link-arg={}", lib_file);
};

build_and_link_lib("sys\\src\\libwireshark.def", "libwireshark.lib");
build_and_link_lib("sys\\src\\libwsutil.def", "libwsutil.lib");
}

fn main() {
let msvc = env::var_os("CARGO_CFG_TARGET_VENDOR")
.map(|v| v == "pc")
Expand All @@ -53,9 +14,7 @@ fn main() {
&& env::var_os("CARGO_CFG_TARGET_ENV")
.map(|v| v == "msvc")
.unwrap_or(false);
if msvc {
windows_msvc();
} else {
if !msvc {
non_windows_msvc();
}
}
70 changes: 0 additions & 70 deletions wireshark-dissector/sys/extract_def_file.py

This file was deleted.

58 changes: 55 additions & 3 deletions wireshark-dissector/sys/fix.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import os.path
import re
import subprocess
import sys

def rindex(l, element):
return len(l) - 1 - l[::-1].index(element)
Expand Down Expand Up @@ -26,19 +29,68 @@ def replace_types(line):
return TYPE_REPLACEMENTS[line[:17]]
return line

def do(filename):
def extract_exported_functions(library):
"""
Returns the list of all exported functions from the shared object specified
by the file path `library`.
"""
output = subprocess.check_output(["nm", "-D", library], encoding="utf8")
symbols = [line.split() for line in output.splitlines()]
return [name for (*_, type_, name) in symbols if type_ == "T"]

RE_FUNCTION_NAME=re.compile(r'^ pub fn (?P<name>[A-Za-z0-9_]+).*$')
def annotate_imported_functions(lines, exported_functions):
result = []
extern_c = []
library = None
for line in lines:
if not extern_c:
if line == 'extern "C" {\n':
extern_c.append(line)
else:
result.append(line)
else:
m = RE_FUNCTION_NAME.match(line)
extern_c.append(line)
if line == "}\n":
result.append("#[cfg_attr(windows, link(name = \"lib{}.dll\", kind = \"raw-dylib\"))]\n".format(library))
result += extern_c
extern_c = []
library = None
elif m:
function = m.group("name")
if library is None:
library = exported_functions[function]
elif library != exported_functions[function]:
raise RuntimeError("extern \"C\" block has functions from two different libraries, can't annotate")
return result

def do(filename, libs_path, libraries):
with open(filename) as f:
input = list(f)
input = [replace_types(line) for line in input]

exported_functions_by_library = [(library, extract_exported_functions(os.path.join(libs_path, "lib{}.so".format(library)))) for library in libraries]
exported_functions = {}
for library, functions in exported_functions_by_library:
for function in functions:
if function in exported_functions:
print("Found symbol {} in two different libraries: {} and {}".format(function, exported_functions[function], library), file=sys.stderr)
return 1
exported_functions[function] = library

input = annotate_imported_functions(input, exported_functions)
with open(filename, "w") as f:
f.write("".join(input))

def main():
import argparse
p = argparse.ArgumentParser(description="Post-process a bindgen-generated Wireshark binding")
p = argparse.ArgumentParser(description="Post-process a bindgen-generated Wireshark binding. Only works on Linux and requires the `nm` tool.")
p.add_argument("filename", metavar="FILENAME", help="File to post-process")
p.add_argument("libs_path", metavar="LIBS_PATH", help="Path to the libraries to take the symbols from")
p.add_argument("libraries", metavar="LIBRARY", nargs="+", help="Library names (without lib prefix and without .so suffix)")
args = p.parse_args()
do(args.filename)
sys.exit(do(args.filename, args.libs_path, args.libraries))

if __name__ == '__main__':
main()
3 changes: 1 addition & 2 deletions wireshark-dissector/sys/generate
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ bindgen \
$(pkg-config wireshark --cflags)
echo
) > src/lib.rs
python3 fix.py src/lib.rs
python3 extract_def_file.py src/lib.rs /usr/lib src/ wireshark wsutil
python3 fix.py src/lib.rs /usr/lib wireshark wsutil
cargo fmt

# These makes the resulting source contain errors.
Expand Down
Loading

0 comments on commit f6960cc

Please sign in to comment.