Localise fr to avoid collisions with other libraries.

This commit is contained in:
Alejandro Cabeza Romero 2026-06-05 20:30:56 +02:00
parent 72a98e84eb
commit 24157522a8
No known key found for this signature in database
GPG Key ID: DA3D14AE478030FD
3 changed files with 11 additions and 11 deletions

View File

@ -59,8 +59,9 @@ windows: $(BIN)
windows-lib: CXXFLAGS=$(PRIORITY_FLAGS) $(CXXFLAGS_COMMON) -fPIC -I/include -Duint="unsigned int"
windows-lib: $(LIB)
# Localizes all circuit-specific code to prevent conflicts when multiple circuit
# libraries are linked into the same binary. See CONTRIBUTING.md § "Symbol Isolation".
# Localizes witness-generator implementation symbols to prevent conflicts when multiple circuit libraries are linked
# into the same binary.
# See CONTRIBUTING.md § "Symbol Isolation".
PUBLIC_SYMS := $(PROJECT)_generate_witness $(PROJECT)_generate_witness_from_files
LOCAL_OBJ := $(PROJECT)_local.o
OBJCOPY := $(if $(filter windows,$(OS)),objcopy,llvm-objcopy)
@ -71,9 +72,10 @@ $(BIN): $(COMMON_OBJS)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@
$(LIB): $(LIB_OBJS)
ld -r -o $(LOCAL_OBJ) $(filter-out fr.o,$^)
ld -r -o $(LOCAL_OBJ) $^
$(OBJCOPY) $(foreach sym,$(PUBLIC_SYMS),--keep-global-symbol=$(SYM_PREFIX)$(sym)) $(LOCAL_OBJ)
ar rcs $@ fr.o $(LOCAL_OBJ)
rm -f $@
ar rcs $@ $(LOCAL_OBJ)
rm $(LOCAL_OBJ)
%.o: %.cpp $(DEPS_HPP)

View File

@ -75,11 +75,11 @@ page, which results in a **SIGSEGV**.
#### The Fix
The Makefile uses a two-step process to hide all circuit-specific symbols before archiving:
The Makefile uses a two-step process to hide all witness-generator implementation symbols before archiving:
1. **Partial link** (`ld -r`): merges all circuit-specific `.o` files into a single relocatable
object. `fr.o` is excluded — it contains only field arithmetic with no circuit-specific calls
and is safe to deduplicate across circuits.
1. **Partial link** (`ld -r`): merges every witness-generator `.o` file into a single relocatable object.
`fr.o` is included because its `Fr_*` symbols also appear in other native ZK libraries, such as rapidsnark, and must
not leak into the final link.
2. **Symbol localization**: demotes every global symbol to local except the two public FFI entry
points (`$(PROJECT)_generate_witness` and `$(PROJECT)_generate_witness_from_files`). Local
symbols are invisible to the final linker, so each archive retains a private copy.

View File

@ -89,12 +89,10 @@ with different circuit-specific constants. When multiple circuits are linked int
picks one definition per symbol and discards the rest, mixing constants across circuits and corrupting witness
generation.
To prevent this, every internal symbol is hidden: circuit objects are merged into a single
To prevent this, every internal symbol is hidden: witness-generator objects are merged into a single
relocatable object, then all symbols except the two public entry points are demoted to local.
Local symbols are invisible to the final linker, so each circuit keeps its own private copy.
`fr.o` is the exception: it stays global and is added to the archive separately since it doesn't vary between circuits.
See [CONTRIBUTING.md § Symbol Isolation](../CONTRIBUTING.md#symbol-isolation-in-circuit-libraries) for the full
explanation and implementation details.