angr.utils.go_runtime

Identification of Go runtime functions that never return.

angr has no built-in knowledge of the Go runtime, so the two families of stubs that the Go compiler emits at essentially every call site – the goroutine stack-growth stub (runtime.morestack) and the bounds-check panic stubs – are recovered as returning functions. That attaches a large amount of unreachable code to every Go function: a fake self-recursive tail after each morestack call site, and one dead panic branch per bounds check.

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_NORETURN_NAMES: frozenset[str] = frozenset({'os.Exit', 'runtime.Goexit', 'runtime.abort', 'runtime.badctxt', 'runtime.badmcall', 'runtime.badmcall2', 'runtime.badreflectcall', '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.mcall', 'runtime.morestack', 'runtime.morestack_noctxt', 'runtime.morestackc', '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.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.panicunsafestringlen1', 'runtime.panicunsafestringnilptr', 'runtime.panicunsafestringnilptr1', '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. runtime.morestack and friends do resume the caller, but at its entry point rather than at the return address, so they do not “return” in the sense CFG recovery cares about.

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.

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.find_go_noreturn_functions(project, kb=None, use_names=True)

Identify Go runtime functions in project that never return.

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:

dict[int, str]

Returns:

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