Add ctrace documentation

This commit is contained in:
Jeremy 2024-02-07 00:11:48 -06:00
parent 78dd053f21
commit 68f919f292
No known key found for this signature in database
GPG Key ID: BE03111EB7ED6E2E
6 changed files with 175 additions and 6 deletions

View File

@ -11,6 +11,8 @@
Cpptrace is a simple, portable, and self-contained C++ stacktrace library supporting C++11 and greater on Linux, macOS,
and Windows including MinGW and Cygwin environments. The goal: Make stack traces simple for once.
Cpptrace also has a C API, docs [here](docs/c-api.md).
## Table of Contents <!-- omit in toc -->
- [30-Second Overview](#30-second-overview)
@ -220,7 +222,7 @@ namespace cpptrace {
### Raw Traces
Raw trace access: A vector of program counters. These are ideal for traces you want to resolve later.
Raw trace access: A vector of program counters. These are ideal for fast and cheap traces you want to resolve later.
Note it is important executables and shared libraries in memory aren't somehow unmapped otherwise libdl calls (and
`GetModuleFileName` in windows) will fail to figure out where the program counter corresponds to.

167
docs/c-api.md Normal file
View File

@ -0,0 +1,167 @@
# ctrace <!-- omit in toc -->
Cpptrace provides a C API under the name ctrace, documented below.
## Table of Contents <!-- omit in toc -->
- [Documentation](#documentation)
- [Stack Traces](#stack-traces)
- [Object Traces](#object-traces)
- [Raw Traces](#raw-traces)
- [Utilities](#utilities)
- [Utility types](#utility-types)
- [Configuration](#configuration)
- [Signal-Safe Tracing](#signal-safe-tracing)
## Documentation
All ctrace declarations are in the `ctrace.h` header:
```c
#include <cpptrace/ctrace.h>
```
### Stack Traces
Generate stack traces with `ctrace_generate_trace()`. Often `skip = 0` and `max_depth = SIZE_MAX` is what you want for
the parameters.
`ctrace_stacktrace_to_string` and `ctrace_print_stacktrace` can then be used for output.
`ctrace_free_stacktrace` must be called when you are done with the trace.
```c
typedef struct ctrace_stacktrace ctrace_stacktrace;
struct ctrace_stacktrace_frame {
ctrace_frame_ptr address;
uint32_t line;
uint32_t column;
const char* filename;
const char* symbol;
ctrace_bool is_inline;
};
struct ctrace_stacktrace {
ctrace_stacktrace_frame* frames;
size_t count;
};
ctrace_stacktrace ctrace_generate_trace(size_t skip, size_t max_depth);
ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color);
void ctrace_print_stacktrace(const ctrace_stacktrace* trace, FILE* to, ctrace_bool use_color);
void ctrace_free_stacktrace(ctrace_stacktrace* trace);
```
### Object Traces
Object traces contain the most basic information needed to construct a stack trace outside the currently running
executable. It contains the raw address, the address in the binary (ASLR and the object file's memory space and whatnot
is resolved), and the path to the object the instruction pointer is located in.
`ctrace_free_object_trace` must be called when you are done with the trace.
```c
typedef struct ctrace_object_trace ctrace_object_trace;
struct ctrace_object_frame {
ctrace_frame_ptr raw_address;
ctrace_frame_ptr obj_address;
const char* obj_path;
};
struct ctrace_object_trace {
ctrace_object_frame* frames;
size_t count;
};
ctrace_object_trace ctrace_generate_object_trace(size_t skip, size_t max_depth);
ctrace_stacktrace ctrace_resolve_object_trace(const ctrace_object_trace* trace);
void ctrace_free_object_trace(ctrace_object_trace* trace);
```
### Raw Traces
Raw traces are arrays of program counters. These are ideal for fast and cheap traces you want to resolve later.
Note it is important executables and shared libraries in memory aren't somehow unmapped otherwise libdl calls (and
`GetModuleFileName` in windows) will fail to figure out where the program counter corresponds to.
`ctrace_free_raw_trace` must be called when you are done with the trace.
```c
typedef struct ctrace_raw_trace ctrace_raw_trace;
ctrace_raw_trace ctrace_generate_raw_trace(size_t skip, size_t max_depth);
ctrace_stacktrace ctrace_resolve_raw_trace(const ctrace_raw_trace* trace);
void ctrace_free_raw_trace(ctrace_raw_trace* trace);
```
### Utilities
`ctrace_demangle`: Helper function for name demangling
`ctrace_stdin_fileno`, `ctrace_stderr_fileno`, `ctrace_stdout_fileno`: Returns the appropriate file descriptor for the
respective standard stream.
`ctrace_isatty`: Checks if a file descriptor corresponds to a tty device.
```c
ctrace_owning_string ctrace_demangle(const char* mangled);
int ctrace_stdin_fileno(void);
int ctrace_stderr_fileno(void);
int ctrace_stdout_fileno(void);
ctrace_bool ctrace_isatty(int fd);
```
### Utility types
For ABI reasons `ctrace_bool`s are used for bools. `ctrace_owning_string` is a wrapper type which indicates that a
string is owned and must be freed.
```c
typedef int8_t ctrace_bool;
typedef struct {
const char* data;
} ctrace_owning_string;
ctrace_owning_string ctrace_generate_owning_string(const char* raw_string);
void ctrace_free_owning_string(ctrace_owning_string* string);
```
### Configuration
`experimental::set_cache_mode`: Control time-memory tradeoffs within the library. By default speed is prioritized. If
using this function, set the cache mode at the very start of your program before any traces are performed. Note: This
API is not set in stone yet and could change in the future.
`ctrace_enable_inlined_call_resolution`: Configure whether the library will attempt to resolve inlined call information for
release builds. Default is true.
```c
typedef enum {
/* Only minimal lookup tables */
ctrace_prioritize_memory = 0,
/* Build lookup tables but don't keep them around between trace calls */
ctrace_hybrid = 1,
/* Build lookup tables as needed */
ctrace_prioritize_speed = 2
} ctrace_cache_mode;
void ctrace_set_cache_mode(ctrace_cache_mode mode);
void ctrace_enable_inlined_call_resolution(ctrace_bool enable);
```
### Signal-Safe Tracing
For more details on the signal-safe tracing interface please refer to the README and the
[signal-safe-tracing.md](signal-safe-tracing.md) guide.
```c
typedef struct ctrace_safe_object_frame ctrace_safe_object_frame;
struct ctrace_safe_object_frame {
ctrace_frame_ptr raw_address;
ctrace_frame_ptr relative_obj_address;
char object_path[CTRACE_PATH_MAX + 1];
};
size_t ctrace_safe_generate_raw_trace(ctrace_frame_ptr* buffer, size_t size, size_t skip, size_t max_depth);
void ctrace_get_safe_object_frame(ctrace_frame_ptr address, ctrace_safe_object_frame* out);
```

View File

@ -137,7 +137,7 @@ CTRACE_BEGIN_DEFINITIONS
/* ctrace::io: */
CPPTRACE_EXPORT ctrace_owning_string ctrace_stacktrace_to_string(const ctrace_stacktrace* trace, ctrace_bool use_color);
CPPTRACE_EXPORT void ctrace_stacktrace_print(const ctrace_stacktrace* trace, FILE* to, ctrace_bool use_color);
CPPTRACE_EXPORT void ctrace_print_stacktrace(const ctrace_stacktrace* trace, FILE* to, ctrace_bool use_color);
/* ctrace::utility: */
CPPTRACE_EXPORT ctrace_owning_string ctrace_demangle(const char* mangled);
@ -156,7 +156,7 @@ CTRACE_BEGIN_DEFINITIONS
ctrace_prioritize_speed = 2
} ctrace_cache_mode;
CPPTRACE_EXPORT void ctrace_set_cache_mode(ctrace_cache_mode mode);
CPPTRACE_EXPORT void enable_inlined_call_resolution(ctrace_bool enable);
CPPTRACE_EXPORT void ctrace_enable_inlined_call_resolution(ctrace_bool enable);
CTRACE_END_DEFINITIONS

View File

@ -317,7 +317,7 @@ extern "C" {
return ctrace::generate_owning_string(trace_string);
}
void ctrace_stacktrace_print(const ctrace_stacktrace* trace, FILE* to, ctrace_bool use_color) {
void ctrace_print_stacktrace(const ctrace_stacktrace* trace, FILE* to, ctrace_bool use_color) {
if(
use_color && (
(to == stdout && cpptrace::isatty(cpptrace::stdout_fileno)) ||
@ -420,7 +420,7 @@ extern "C" {
cpptrace::experimental::set_cache_mode(cache_mode);
}
void enable_inlined_call_resolution(ctrace_bool enable) {
void ctrace_enable_inlined_call_resolution(ctrace_bool enable) {
cpptrace::enable_inlined_call_resolution(enable);
}
}

View File

@ -7,7 +7,7 @@ void trace() {
ctrace_raw_trace raw_trace = ctrace_generate_raw_trace(1, INT_MAX);
ctrace_object_trace obj_trace = ctrace_resolve_raw_trace_to_object_trace(&raw_trace);
ctrace_stacktrace trace = ctrace_resolve_object_trace(&obj_trace);
ctrace_stacktrace_print(&trace, stdout, 1);
ctrace_print_stacktrace(&trace, stdout, 1);
ctrace_free_stacktrace(&trace);
ctrace_free_object_trace(&obj_trace);
ctrace_free_raw_trace(&raw_trace);