I'm creating a Free Pascal dynamic library (.dylib) on macOS that works on Windows but fails to load symbols on macOS. The symbols appear in the symbol table when checked with nm, but dlsym cannot find them. Working Windows exports:
pascal
exports
GetName name 'GetName',
GetBid name 'GetBid',
GetCard name 'GetCard';
Symbol table shows exports correctly:
bash$ nm -gU libplayer.dylib
0000000000005360 T GetBid
0000000000005370 T GetCard
0000000000005350 T GetName
But dlsym fails to find them:
c
void* handle = dlopen("./libplayer.dylib", RTLD_LAZY); // Loads successfully
void* symbol = dlsym(handle, "GetName"); // Returns NULL
printf("Error: %s\n", dlerror()); // "symbol not found"
The library loads successfully, symbols appear in nm output, but are not accessible via dlsym. This only happens on macOS - the same code works fine on Windows.
Environment:
- macOS (Apple Silicon)
- Free Pascal 3.2.2
- Compiled with: -fPIC -k-no_order_inits -k-dylib
What causes this issue and how can I make the symbols accessible to dlsym?
Answer
The issue is caused by the name
clauses in the exports
section. On macOS, Free Pascal's name
clause creates symbols that appear in the static symbol table (visible to nm
) but are not properly added to the dynamic symbol table (required for dlsym
).
Solution: Remove the name
clauses entirely
Change from:
exports
GetName name 'GetName',
GetX name 'GetBid',
GetY name 'GetCard';
To:
exports
GetName,
GetBid,
GetCard;
Why this works:
The function names remain identical
Symbols are properly exported to both static and dynamic symbol tables
dlsym
can now find the symbols successfullyWorks on both Windows and macOS
Verification:
void* handle = dlopen("./libplayer.dylib", RTLD_LAZY);
void* symbol = dlsym(handle, "GetName"); // Now returns valid pointer
Key insight: The name
clause is only necessary when you want to change the exported symbol name. When the exported name matches the function name exactly, omitting the name
clause avoids this macOS-specific linking issue.
This appears to be a Free Pascal compiler/linker quirk specific to macOS dylib generation.