---
name: "backtrace"
section: "9"
platform: "macos"
package: "xnu"
version: "12377.121.6"
release: "macOS 26.5"
platforms: ["macos"]
url: "https://new.carta.tech/backtrace/9"
---

# backtrace(9)

gather the PC and return addresses of a thread's kernel or user call stack

## NAME

**backtrace**, **backtrace\_packed**, **backtrace\_user**, – gather the PC and return addresses of a thread's kernel or user call stack

## SYNOPSIS

**#include \<kern/backtrace.h\>**

*unsigned* *int*\

**backtrace**(*uintptr\_t \*bt*, *unsigned int btlen*, *struct backtrace\_control \*ctl*, *backtrace\_info\_t \*info\_out*);

*size\_t*\

**backtrace\_packed**(*backtrace\_pack\_t packing*, *uintptr\_t \*bt*, *size\_t btlen*, *struct backtrace\_control \*ctl*, *backtrace\_info\_t \*info\_out*);

*unsigned* *int*\

**backtrace\_user**(*uintptr\_t \*bt*, *unsigned int btlen*, *struct backtrace\_control \*ctl*, *struct backtrace\_user\_info \*info\_out*);

## DESCRIPTION

The **backtrace**, **backtrace\_packed**, and **backtrace\_user** functions fill a buffer with the current PC and return addresses of a thread's kernel and user call stack, respectively. This is only possible when frame pointers are pushed to the stack, alongside the return addresses. [clang(1)](/clang/1.md), disables this behavior with the **-fomit-frame-pointer** flag, so it will prevent these functions from working. Furthermore, leaf functions and inlined function calls can also prevent backtracing from reporting the source-level function control flow. **backtrace\_user**() operates on user call stacks, while **backtrace**() captures the current kernel call stack. **backtrace\_packed**() writes a more compact representation of the return addresses to a buffer, which can be unpacked with [backtrace\_unpack(9)](/backtrace_unpack/9.md). Calling **backtrace\_user**() on a kernel thread (which lacks a user context) is undefined.

Up to *btlen* instruction addresses( or *btsize* bytes for **backtrace\_packed**()) are written to the buffer at *bt*. These functions also accept *ctl* and *info\_out* arguments, described in BACKTRACE\_CONTROL and BACKTRACE\_INFO, respectively. **backtrace\_packed**() takes a *backtrace\_pack\_t* to control which packing scheme to use.

**backtrace**() records the kernel PC and call stack of the current thread.

**backtrace\_packed**() records the kernel PC and call stack of the current thread in a buffer in a compact representation. See [backtrace\_pack(9)](/backtrace_pack/9.md) for a description of the supported formats.

**backtrace\_user**() records the user PC and call stack of the current thread, which must be associated with a user space task.

## RETURN VALUES

The **backtrace** functions return the number of PC and return address elements( or bytes for **backtrace\_packed**()) written to the provided buffer. If there is space, the buffer is terminated with a NULL entry( except for **backtrace\_packed**()). The *info\_out* argument will be set with information about the provided call stack. **backtrace\_user**() will set *btui\_error* to an error of the [copyin(9)](/copyin/9.md) routine if an error occurred during call stack traversal.

## BACKTRACE\_CONTROL

The **backtrace** functions accept a *struct* *backtrace\_control* control argument to alter their behavior, with the following fields:

- *btc\_flags*

  These flags control the backtracer's behavior:

  - BTF\_KERN\_INTERRUPTED

    For **backtrace**() only, record the PC and return addresses of the interrupted call stack.

- *btc\_frame\_addr*

  Start backtracing from the provided frame address.

- *btc\_user\_thread*

  Capture the backtrace of the provided thread pointer. This must be either the current thread or a different thread that is suspended and unable to run in user space.

- *btc\_user\_copy*

  For **backtrace\_user**() only, the function to use instead of [copyin(9)](/copyin/9.md) to copy data from the thread's user space virtual address space into the kernel.

- *btc\_user\_copy\_context*

  Additional data that's passed to the custom copy routine to act as private context.

## BACKTRACE\_INFO

The **backtrace** functions report additional information through a *backtrace\_info\_t* flags out-parameter, with the following options:

- BTI\_64\_BIT

  The PC and call stack return addresses are 64-bit quantities.

- BTI\_TRUNCATED

  The backtrace has been truncated and does not terminate with the base frame.

The **backtrace\_user**() variant uses an out-parameter structure *struct* *backtrace\_user\_info* to return additional context:

- *btui\_info*

  The *backtrace\_info\_t* flags, described above.

- *btui\_error*

  Any error encountered while copying data.

- *btui\_async\_start\_index*

  For Swift continuations (async stacks), the location where the continuation hint was found and where it logically branches from the standard call stack.

- *btui\_async\_frame\_addr*

  The frame address of the Swift continuation to pass in to a subsequent call to **backtrace\_user**() (as the control structure's frame address field) to follow the corresponding async stack.

- *btui\_next\_frame\_addr*

  In the case of a truncated backtrace due to lack of space in the destination buffer, the next frame address to resume the backtrace operation.

## EXAMPLE

```
uintptr_t bt[8] = {};
enum backtrace_info bti = BTI_NONE;
unsigned int len = backtrace(bt, sizeof(bt) / sizeof(bt[0]), NULL, &bti);
for (unsigned int i = 0; i < len; i++)  {
	printf("%d: 0x%lx\n", i, bt[i]);
}
if (bti & BTI_TRUNCATED) {
	printf("[... TRUNCATED ...]\n");
}
```

## SEE ALSO

[backtrace(3)](/backtrace/3.md), [backtrace\_pack(9)](/backtrace_pack/9.md), and [copyin(9)](/copyin/9.md)
