angr.utils.go_runtime

Identification of Go runtime functions whose control flow CFG recovery cannot infer on its own.

angr has no built-in knowledge of the Go runtime, which gets two families of functions wrong:

  • Functions that never return to their call site, chiefly the bounds-check panic stubs emitted at essentially every index expression. Recovered as returning, they attach one dead panic branch per bounds check to every Go function.

  • Functions that never execute a ret but still resume their caller at the return address: runtime.morestack (called from the stack-check trampoline of every non-leaf function) and runtime.mcall. Both save the caller’s return address in g.sched and the scheduler later resumes it with gogo. Inferred from their bodies, they look non-returning, which cuts the argument-reload stub after every morestack call site off its function and stops recovery of every caller of runtime.gopark at the park.

Two identification strategies are provided, because the interesting targets are usually stripped:

  • by name, when symbols (or a .gopclntab-derived symbol table) are available;

  • by shape, which is what actually carries stripped binaries.

A false positive here silently deletes real code, so every shape-based rule below requires either overwhelming corroboration across the binary or an assembly signature that no compiler emits for ordinary code.

angr.utils.go_runtime.GO_CHECK_PANIC_NAMES: frozenset[str] = frozenset({'runtime.goPanicExtendIndex', 'runtime.goPanicExtendIndexU', 'runtime.goPanicExtendSlice3Acap', 'runtime.goPanicExtendSlice3AcapU', 'runtime.goPanicExtendSlice3Alen', 'runtime.goPanicExtendSlice3AlenU', 'runtime.goPanicExtendSlice3B', 'runtime.goPanicExtendSlice3BU', 'runtime.goPanicExtendSlice3C', 'runtime.goPanicExtendSlice3CU', 'runtime.goPanicExtendSliceAcap', 'runtime.goPanicExtendSliceAcapU', 'runtime.goPanicExtendSliceAlen', 'runtime.goPanicExtendSliceAlenU', 'runtime.goPanicExtendSliceB', 'runtime.goPanicExtendSliceBU', 'runtime.goPanicExtendSliceConvert', 'runtime.goPanicIndex', 'runtime.goPanicIndexU', 'runtime.goPanicSlice3Acap', 'runtime.goPanicSlice3AcapU', 'runtime.goPanicSlice3Alen', 'runtime.goPanicSlice3AlenU', 'runtime.goPanicSlice3B', 'runtime.goPanicSlice3BU', 'runtime.goPanicSlice3C', 'runtime.goPanicSlice3CU', 'runtime.goPanicSliceAcap', 'runtime.goPanicSliceAcapU', 'runtime.goPanicSliceAlen', 'runtime.goPanicSliceAlenU', 'runtime.goPanicSliceB', 'runtime.goPanicSliceBU', 'runtime.goPanicSliceConvert', 'runtime.panicBounds', 'runtime.panicBounds32', 'runtime.panicBounds64', 'runtime.panicExtendIndex', 'runtime.panicExtendIndexU', 'runtime.panicExtendSlice3Acap', 'runtime.panicExtendSlice3AcapU', 'runtime.panicExtendSlice3Alen', 'runtime.panicExtendSlice3AlenU', 'runtime.panicExtendSlice3B', 'runtime.panicExtendSlice3BU', 'runtime.panicExtendSlice3C', 'runtime.panicExtendSlice3CU', 'runtime.panicExtendSliceAcap', 'runtime.panicExtendSliceAcapU', 'runtime.panicExtendSliceAlen', 'runtime.panicExtendSliceAlenU', 'runtime.panicExtendSliceB', 'runtime.panicExtendSliceBU', 'runtime.panicExtendSliceConvert', 'runtime.panicIndex', 'runtime.panicIndexU', 'runtime.panicSlice3Acap', 'runtime.panicSlice3AcapU', 'runtime.panicSlice3Alen', 'runtime.panicSlice3AlenU', 'runtime.panicSlice3B', 'runtime.panicSlice3BU', 'runtime.panicSlice3C', 'runtime.panicSlice3CU', 'runtime.panicSliceAcap', 'runtime.panicSliceAcapU', 'runtime.panicSliceAlen', 'runtime.panicSliceAlenU', 'runtime.panicSliceB', 'runtime.panicSliceBU', 'runtime.panicSliceConvert', 'runtime.panicdivide', 'runtime.panicoverflow', 'runtime.panicshift', 'runtime.panicunsafeslicelen', 'runtime.panicunsafeslicelen1', 'runtime.panicunsafeslicenilptr', 'runtime.panicunsafeslicenilptr1', 'runtime.panicunsafestringlen', 'runtime.panicunsafestringlen1', 'runtime.panicunsafestringnilptr', 'runtime.panicunsafestringnilptr1'})

bounds/slice checks (per-kind stubs before go1.25, the panicBounds dispatcher after), integer division/shift checks, and the unsafe.Slice/String checks.

Type:

Panic helpers that only compiler-inserted checks call

angr.utils.go_runtime.GO_ASSERT_PANIC_NAMES: frozenset[str] = frozenset({'runtime.panicdottypeE', 'runtime.panicdottypeI', 'runtime.panicnildottype'})

the check that guards them is the assertion itself.

Type:

Failure stubs of type assertions (x.(T))

angr.utils.go_runtime.GO_NORETURN_NAMES: frozenset[str] = frozenset({'os.Exit', 'runtime.Goexit', 'runtime.abort', 'runtime.badctxt', 'runtime.badmcall', 'runtime.badmcall2', 'runtime.badreflectcall', 'runtime.execute', 'runtime.exit', 'runtime.exitThread', 'runtime.exitsyscall0', 'runtime.fatal', 'runtime.fatalpanic', 'runtime.fatalthrow', 'runtime.goPanicExtendIndex', 'runtime.goPanicExtendIndexU', 'runtime.goPanicExtendSlice3Acap', 'runtime.goPanicExtendSlice3AcapU', 'runtime.goPanicExtendSlice3Alen', 'runtime.goPanicExtendSlice3AlenU', 'runtime.goPanicExtendSlice3B', 'runtime.goPanicExtendSlice3BU', 'runtime.goPanicExtendSlice3C', 'runtime.goPanicExtendSlice3CU', 'runtime.goPanicExtendSliceAcap', 'runtime.goPanicExtendSliceAcapU', 'runtime.goPanicExtendSliceAlen', 'runtime.goPanicExtendSliceAlenU', 'runtime.goPanicExtendSliceB', 'runtime.goPanicExtendSliceBU', 'runtime.goPanicExtendSliceConvert', 'runtime.goPanicIndex', 'runtime.goPanicIndexU', 'runtime.goPanicSlice3Acap', 'runtime.goPanicSlice3AcapU', 'runtime.goPanicSlice3Alen', 'runtime.goPanicSlice3AlenU', 'runtime.goPanicSlice3B', 'runtime.goPanicSlice3BU', 'runtime.goPanicSlice3C', 'runtime.goPanicSlice3CU', 'runtime.goPanicSliceAcap', 'runtime.goPanicSliceAcapU', 'runtime.goPanicSliceAlen', 'runtime.goPanicSliceAlenU', 'runtime.goPanicSliceB', 'runtime.goPanicSliceBU', 'runtime.goPanicSliceConvert', 'runtime.goexit', 'runtime.goexit0', 'runtime.goexit1', 'runtime.gogo', 'runtime.gopanic', 'runtime.goschedImpl', 'runtime.main', 'runtime.morestackc', 'runtime.panicBounds', 'runtime.panicBounds32', 'runtime.panicBounds32X', 'runtime.panicBounds64', 'runtime.panicExtend', 'runtime.panicExtendIndex', 'runtime.panicExtendIndexU', 'runtime.panicExtendSlice3Acap', 'runtime.panicExtendSlice3AcapU', 'runtime.panicExtendSlice3Alen', 'runtime.panicExtendSlice3AlenU', 'runtime.panicExtendSlice3B', 'runtime.panicExtendSlice3BU', 'runtime.panicExtendSlice3C', 'runtime.panicExtendSlice3CU', 'runtime.panicExtendSliceAcap', 'runtime.panicExtendSliceAcapU', 'runtime.panicExtendSliceAlen', 'runtime.panicExtendSliceAlenU', 'runtime.panicExtendSliceB', 'runtime.panicExtendSliceBU', 'runtime.panicExtendSliceConvert', 'runtime.panicIndex', 'runtime.panicIndexU', 'runtime.panicSlice3Acap', 'runtime.panicSlice3AcapU', 'runtime.panicSlice3Alen', 'runtime.panicSlice3AlenU', 'runtime.panicSlice3B', 'runtime.panicSlice3BU', 'runtime.panicSlice3C', 'runtime.panicSlice3CU', 'runtime.panicSliceAcap', 'runtime.panicSliceAcapU', 'runtime.panicSliceAlen', 'runtime.panicSliceAlenU', 'runtime.panicSliceB', 'runtime.panicSliceBU', 'runtime.panicSliceConvert', 'runtime.panicdivide', 'runtime.panicdottypeE', 'runtime.panicdottypeI', 'runtime.panicfloat', 'runtime.panicmakeslicecap', 'runtime.panicmakeslicelen', 'runtime.panicmem', 'runtime.panicmemAddr', 'runtime.panicnildottype', 'runtime.panicoverflow', 'runtime.panicshift', 'runtime.panicunsafeslicelen', 'runtime.panicunsafeslicelen1', 'runtime.panicunsafeslicenilptr', 'runtime.panicunsafeslicenilptr1', 'runtime.panicunsafestringlen', 'runtime.panicunsafestringnilptr', 'runtime.panicwrap', 'runtime.park_m', 'runtime.schedule', 'runtime.sigpanic', 'runtime.sigpanic0', 'runtime.throw'})

Go runtime (and a few closely related standard library) functions that never transfer control back to the instruction following their call site, checked against the runtime sources of go1.4 to go1.27.

Deliberately excluded because they can fall through to their caller despite the suggestive names: runtime.mexit (returns when running on an OS-provided stack, and with it runtime.mstart0 and runtime.mstart), runtime.badsystemstack, runtime.badmorestackg0, runtime.badmorestackgsignal (all only print), runtime.systemstack, runtime.panicCheck1, runtime.panicCheck2, runtime.startpanic_m, runtime.dopanic_m, and the functions in GO_RESUMING_NAMES.

angr.utils.go_runtime.GO_RESUMING_NAMES: frozenset[str] = frozenset({'runtime.mcall', 'runtime.morestack', 'runtime.morestack_noctxt'})

Go runtime functions that never execute a ret, but whose callers are resumed at the return address: they save it in g.sched and the scheduler later continues there through gogo. Their bodies end in calls that do not return (abort, badmcall2), so they must be marked as returning explicitly.

angr.utils.go_runtime.GO_STACK_GROWTH_NAMES: frozenset[str] = frozenset({'runtime.morestack', 'runtime.morestack_noctxt', 'runtime.morestackc'})

morestack (and morestack_noctxt) grows the stack and resumes the caller after the call, which reloads its arguments and restarts itself; morestackc is called instead by //go:systemstack functions and throws.

Type:

The goroutine stack-growth stubs called from function preambles

angr.utils.go_runtime.has_go_hint(project)

Cheap test for “this might be a Go binary”, to keep the (much more expensive) LanguageDetector off the vast majority of binaries.

Return type:

bool

Parameters:

project (Project)

angr.utils.go_runtime.normalize_go_func_name(name)

Strip the ABI wrapper suffix the Go linker appends to duplicated symbols.

Return type:

str

Parameters:

name (str)

angr.utils.go_runtime.is_go_noreturn_name(name)
Return type:

bool

Parameters:

name (str)

angr.utils.go_runtime.is_go_resuming_name(name)
Return type:

bool

Parameters:

name (str)

angr.utils.go_runtime.is_go_stack_growth_name(name)
Return type:

bool

Parameters:

name (str)

class angr.utils.go_runtime.GoRuntimeFunctions

Bases: object

Go runtime functions identified in a binary, each mapped to a short description of the evidence.

Variables:
  • noreturn (dict[int, str]) – Functions that never return to their call site.

  • resuming (dict[int, str]) – Functions that never execute a ret but resume their caller at the return address.

  • stack_growth (dict[int, str]) – The stack-growth stubs that function preambles call (morestack and morestackc). Each is in noreturn or resuming as well.

noreturn: dict[int, str]
resuming: dict[int, str]
stack_growth: dict[int, str]
__init__(noreturn=<factory>, resuming=<factory>, stack_growth=<factory>)
Parameters:
Return type:

None

angr.utils.go_runtime.find_go_runtime_functions(project, kb=None, use_names=True)

Identify the Go runtime functions in project whose control flow CFG recovery must be told about.

The caller is responsible for having established that this is a Go binary.

Parameters:
  • use_names (bool) – Consult symbol names. Set to False to exercise the shape-based path that stripped binaries depend on.

  • project (Project)

Return type:

GoRuntimeFunctions

angr.utils.go_runtime.find_go_noreturn_functions(project, kb=None, use_names=True)

Identify Go runtime functions in project that never return. See find_go_runtime_functions().

Return type:

dict[int, str]

Returns:

A mapping from function address to a short description of the evidence.

Parameters: