tursodatabase/turso · error · SystemExit
{path} has no .dynsym section
Error message
{path} has no .dynsym section What it means
After scanning the ELF section header table, the script falls back from a section literally named '.dynsym' to any section of type SHT_DYNSYM (11). If neither exists, the binary has no dynamic symbol table, so there are no exported dynamic symbols to check and the script exits with this message.
Source
Thrown at bindings/dotnet/scripts/check_elf_dynsym_exports.py:142
raise SystemExit(f"{path} has unsupported ELF class {elf_class}")
def find_dynsym(data: bytes, layout: dict, path: Path):
string_header = section_header(data, layout, layout["string_table_index"])
names = slice_bytes(data, string_header[OFFSET], string_header[SIZE])
named = None
typed = None
for index in range(layout["section_count"]):
header = section_header(data, layout, index)
name = names[header[NAME] :].split(b"\x00", 1)[0]
if name == b".dynsym":
named = header
break
if typed is None and header[TYPE] == 11:
typed = header
dynsym = named or typed
if dynsym is None:
raise SystemExit(f"{path} has no .dynsym section")
return dynsym
def names_from_dynsym(data: bytes, layout: dict, dynsym) -> set[str]:
strings = section_header(data, layout, dynsym[LINK])
string_table = slice_bytes(data, strings[OFFSET], strings[SIZE])
entry_size = dynsym[ENTRY_SIZE] or struct.calcsize(layout["symbol_format"])
names: set[str] = set()
for index in range(dynsym[SIZE] // entry_size):
offset = dynsym[OFFSET] + index * entry_size
symbol = struct.unpack_from(layout["symbol_format"], data, offset)
raw = string_table[symbol[0] :].split(b"\x00", 1)[0]
name = raw.decode("utf-8", "replace")
if name:
names.add(name)
return names
View on GitHub (pinned to 492c4a71cd)
Solutions
- Confirm the target is a shared object with exports: `readelf -S <path> | grep dynsym`.
- Rebuild with dynamic symbols retained (don't strip .dynsym; ensure the crate/library produces a cdylib/shared artifact).
- Point the script at the correct .so file in the build output.
- If the platform legitimately has no dynsym, skip or relax the check in CI.
Example fix
// before python check_elf_dynsym_exports.py ./target/release/tursodb // after python check_elf_dynsym_exports.py ./target/release/libturso_dotnet.so
Defensive patterns
Strategy: validation
Validate before calling
import subprocess
def has_dynsym(path: str) -> bool:
out = subprocess.run(["readelf", "-S", path], capture_output=True, text=True)
return ".dynsym" in out.stdout Prevention
- Only run export checks against shared objects (cdylib), not executables or static libs
- Avoid stripping dynamic symbols from artifacts destined for export verification
- Sanity-check with readelf/objdump before automated checks
When it happens
Trigger: Calling find_dynsym (via dynsym_names) on an ELF that was stripped of its dynamic symbol table, statically linked without exports, or built as a non-shared object with no dynsym section.
Common situations: Checking an executable or static library instead of a shared .so; a release build configured to strip dynamic exports; wrong artifact selected in packaging CI.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- {path} has unsupported ELF class {elf_class}
- {path} is missing dynsym exports: {', '.join(missing)}
- {path} is not an ELF file
- pyturso's SQLAlchemy dialects require SQLAlchemy >= 2.0.45 (
- Cannot get raw connection from SQLAlchemy connection
AI-assisted analysis of tursodatabase/turso@492c4a71cd (2026-09-13).
Data as JSON: /api/errors/89fceb002cbf5202.
Report an issue: GitHub.