Skip to content

Instantly share code, notes, and snippets.

@goranmoomin
Created June 10, 2026 20:33
Show Gist options
  • Select an option

  • Save goranmoomin/14ab1fccd528beeb261feb82a7949d2e to your computer and use it in GitHub Desktop.

Select an option

Save goranmoomin/14ab1fccd528beeb261feb82a7949d2e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -euo pipefail
MDT="${1:-${MACOSX_DEPLOYMENT_TARGET:-$(sw_vers -productVersion | cut -d. -f1).0}}"
RUSTC="${RUSTC:-$(rustup which rustc)}"
ROOT="${ROOT:-$PWD/linkedit-repro-${MDT}}"
mkdir -p "$ROOT"
cd "$ROOT"
cat > pm.rs <<'RS'
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Foo)]
pub fn foo(_input: TokenStream) -> TokenStream { TokenStream::new() }
RS
cat > cdylib_simple.rs <<'RS'
#[no_mangle]
pub extern "C" fn answer() -> i32 { 42 }
RS
cat > cdylib_static_str.rs <<'RS'
#[no_mangle]
pub extern "C" fn answer() -> usize { "hello from a static string".len() }
RS
cat > cdylib_std_env.rs <<'RS'
#[no_mangle]
pub extern "C" fn answer() -> usize {
std::env::var("PATH").unwrap_or_default().len()
}
RS
cat > main.rs <<'RS'
fn main() { println!("hello from executable"); }
RS
build() {
local label="$1"; shift
echo "--- building $label"
MACOSX_DEPLOYMENT_TARGET="$MDT" "$RUSTC" "$@"
}
report_macho() {
local label="$1" file="$2"
echo
echo "=== $label: $file"
file "$file"
/usr/bin/otool -l "$file" | awk '
/cmd LC_DYLD/ { print " " $0 }
/cmd LC_BUILD_VERSION/ { b=1; next }
b && /cmd / { b=0 }
b && /(minos|sdk)/ { print " " $0 }
/cmd LC_SYMTAB/ { s=1; next }
s && /cmd / { s=0 }
s && /(symoff|nsyms|stroff|strsize)/ { print " " $0 }
/cmd LC_DYSYMTAB/ { d=1; next }
d && /cmd / { d=0 }
d && /(indirectsymoff|nindirectsyms)/ { print " " $0 }
'
local stroff
stroff=$(/usr/bin/otool -l "$file" | awk '/cmd LC_SYMTAB/{s=1;next} s&&/cmd /{s=0} s&&/stroff/{print $2}')
if [ -n "$stroff" ]; then
echo " stroff % 8 = $((stroff % 8))"
if [ $((stroff % 8)) -ne 0 ]; then
echo " LINKEDIT string pool is MISALIGNED for dyld's 8-byte check"
else
echo " LINKEDIT string pool is aligned"
fi
fi
}
dlcheck() {
local file="$1"
python3 - "$file" <<'PY'
import ctypes, sys
p = sys.argv[1]
try:
lib = ctypes.CDLL(p)
msg = " dlopen: OK"
if hasattr(lib, "answer"):
lib.answer.restype = ctypes.c_size_t
msg += f" answer()={lib.answer()}"
print(msg)
except OSError as e:
print(" dlopen: FAIL")
print(" ", e)
PY
}
# Build with Rust's problematic strip path.
build proc-macro --crate-name p --crate-type proc-macro pm.rs -C strip=debuginfo -o libpm.dylib
build cdylib-simple --crate-type cdylib cdylib_simple.rs -C strip=debuginfo -o libcdylib_simple.dylib
build cdylib-static-str --crate-type cdylib cdylib_static_str.rs -C strip=debuginfo -o libcdylib_static_str.dylib
build cdylib-std-env --crate-type cdylib cdylib_std_env.rs -C strip=debuginfo -o libcdylib_std_env.dylib
build executable main.rs -C strip=debuginfo -o app
report_macho proc-macro libpm.dylib
cat > use_pm.rs <<'RS'
extern crate p;
RS
if "$RUSTC" --crate-type lib use_pm.rs --extern p="$PWD/libpm.dylib" -o libuse_pm.rlib > proc_macro_load.log 2>&1; then
echo " rustc proc-macro load: OK"
else
echo " rustc proc-macro load: FAIL"
sed -n '1,4p' proc_macro_load.log | sed 's/^/ /'
fi
dlcheck "$PWD/libpm.dylib"
report_macho cdylib-simple libcdylib_simple.dylib
dlcheck "$PWD/libcdylib_simple.dylib"
report_macho cdylib-static-str libcdylib_static_str.dylib
dlcheck "$PWD/libcdylib_static_str.dylib"
report_macho cdylib-std-env libcdylib_std_env.dylib
dlcheck "$PWD/libcdylib_std_env.dylib"
report_macho executable app
if ./app; then echo " exec: OK"; else echo " exec: FAIL"; fi
echo
echo "Repro dir: $PWD"
echo "Rustc: $($RUSTC -Vv | tr '\n' '; ')"
echo "MACOSX_DEPLOYMENT_TARGET=$MDT"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment