Skip to content

Proposal: complete libcCall and runtime trampoline support #2129

Description

@cpunion

Background

LLGo already supports the syscall and x/sys trampoline pattern used on Darwin: FuncPCABI0 and *_trampoline_addr resolve to a C function pointer, and LLGo calls that pointer with the actual syscall arguments. PR #2098 now uses that existing path for Darwin sysctlbyname.

The Go runtime has a different path for many libc calls. libcCall(fn, arg) receives a pointer to a packed argument structure, records runtime call state, switches to the system stack through asmcgocall, and invokes an assembly trampoline that unpacks the structure. Existing LLGo trampoline support does not implement this argument-block ABI or its runtime bookkeeping.

Proposal

Define a complete but staged LLGo runtime libc-call contract:

  • represent both existing actual-argument trampolines and Go runtime argument-block trampolines without guessing from symbol names
  • reuse go:cgo_import_dynamic symbol and address handling already supported by LLGo
  • define errno, pointer-liveness, reentrancy, signal, unwind, and profiler behavior
  • define which system-stack or scheduler transitions are meaningful for the LLGo runtime model
  • allow selected upstream runtime sources and assembly only after their calling convention is covered
  • validate executable, c-shared, and c-archive modes on Darwin and Linux

The first implementation should extend existing facilities. It should not create a parallel trampoline system.

syscall.cgocaller

The standard Linux syscall package has two credential-changing paths. Without cgo it uses AllThreadsSyscall; with cgo, runtime/cgo installs pointers such as cgo_libc_setuid, and syscall.cgocaller invokes the corresponding C wrapper through the runtime cgo-call path and returns its errno result.

LLGo can call C directly, but it does not currently provide that standard packed cgo bridge or initialize those setter pointers. The declaration can still be retained by a C-library build, which is why #2098 supplies an ENOTSUP hook so the symbol links and any unexpected call fails safely.

A complete implementation must:

  • define how the standard cgo_libc_set* pointers are registered
  • call the target with the correct generated wrapper signature and packed arguments
  • preserve errno and pointer-liveness semantics
  • coordinate with runtime thread ownership and callbacks from C
  • keep ENOTSUP when the required bridge cannot be made safe

Acceptance criteria

  • a documented ABI for actual-argument and packed-argument trampolines
  • focused tests for direct, nested, and callback-adjacent libc calls
  • functional credential-setter tests where privileges permit, plus deterministic error-path tests
  • signal/unwind and sanitizer validation appropriate to each supported mode
  • no regression to the simpler syscall trampoline path already in use

Related: #840, #1582, #2098

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions