Compare commits

...

7 Commits
v0.8.1 ... main

9 changed files with 147 additions and 47 deletions

View File

@ -25,6 +25,26 @@ jobs:
- name: build and test
run: |
python3 ci/test-all-configs.py --${{matrix.compiler}} --default-config
test-linux-arm:
runs-on: ubuntu-22.04-arm
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]
shared: [--shared, ""]
steps:
- uses: actions/checkout@v4
- name: dependencies
run: |
sudo apt install gcc-10 g++-10 libgcc-10-dev libunwind8-dev
pip3 install colorama
- name: libdwarf
run: |
cd ..
cpptrace/ci/setup-prerequisites.sh
- name: build and test
run: |
python3 ci/test-all-configs.py --${{matrix.compiler}} --default-config
test-macos:
runs-on: macos-14
strategy:
@ -562,6 +582,32 @@ jobs:
- name: test opt
run: |
bazel test //... -c opt
unittest-linux-arm:
runs-on: ubuntu-24.04-arm
strategy:
fail-fast: false
matrix:
compiler: [g++-10, clang++-18]
stdlib: [libstdc++, libc++]
dwarf_version: [4, 5]
split_dwarf: [OFF, ON]
exclude:
- compiler: g++-10
stdlib: libc++
steps:
- uses: actions/checkout@v4
- name: dependencies
run: |
sudo apt install gcc-10 g++-10 libgcc-10-dev ninja-build libc++-dev
cd ..
cpptrace/ci/setup-prerequisites-unittest.sh
- name: build and test
run: |
python3 ci/unittest.py \
--slice=compiler:${{matrix.compiler}} \
--slice=stdlib:${{matrix.stdlib}} \
--slice=dwarf_version:${{matrix.dwarf_version}} \
--slice=split_dwarf:${{matrix.split_dwarf}}
unittest-macos:
runs-on: macos-14
steps:

View File

@ -1,6 +1,7 @@
# Changelog
- [Changelog](#changelog)
- [v0.8.2](#v082)
- [v0.8.1](#v081)
- [v0.8.0](#v080)
- [v0.7.5](#v075)
@ -27,6 +28,14 @@
- [v0.1.1](#v011)
- [v0.1](#v01)
# v0.8.2
Fixed:
- Fixed printing of internal error messages when an object file can't be loaded, mainly affecting MacOS https://github.com/jeremy-rifkin/cpptrace/issues/217
Other:
- Bumped zstd via FetchContent to 1.5.7
# v0.8.1
Fixed:

View File

@ -9,7 +9,7 @@ set(package_name "cpptrace")
project(
cpptrace
VERSION 0.8.1
VERSION 0.8.2
DESCRIPTION "Simple, portable, and self-contained stacktrace library for C++11 and newer "
HOMEPAGE_URL "https://github.com/jeremy-rifkin/cpptrace"
LANGUAGES C CXX

View File

@ -16,9 +16,6 @@ Cpptrace also has a C API, docs [here](docs/c-api.md).
- [30-Second Overview](#30-second-overview)
- [CMake FetchContent Usage](#cmake-fetchcontent-usage)
- [FAQ](#faq)
- [What about C++23 `<stacktrace>`?](#what-about-c23-stacktrace)
- [What does cpptrace have over other C++ stacktrace libraries?](#what-does-cpptrace-have-over-other-c-stacktrace-libraries)
- [Prerequisites](#prerequisites)
- [Basic Usage](#basic-usage)
- [`namespace cpptrace`](#namespace-cpptrace)
@ -57,6 +54,10 @@ Cpptrace also has a C API, docs [here](docs/c-api.md).
- [Summary of Library Configurations](#summary-of-library-configurations)
- [Testing Methodology](#testing-methodology)
- [Notes About the Library](#notes-about-the-library)
- [FAQ](#faq)
- [What about C++23 `<stacktrace>`?](#what-about-c23-stacktrace)
- [What does cpptrace have over other C++ stacktrace libraries?](#what-does-cpptrace-have-over-other-c-stacktrace-libraries)
- [I'm getting undefined standard library symbols like `std::__1::basic_string` on MacOS](#im-getting-undefined-standard-library-symbols-like-std__1basic_string-on-macos)
- [Contributing](#contributing)
- [License](#license)
@ -138,7 +139,7 @@ include(FetchContent)
FetchContent_Declare(
cpptrace
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
GIT_TAG v0.8.1 # <HASH or TAG>
GIT_TAG v0.8.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(cpptrace)
target_link_libraries(your_target cpptrace::cpptrace)
@ -163,33 +164,6 @@ On macOS it is recommended to generate a `.dSYM` file, see [Platform Logistics](
For other ways to use the library, such as through package managers, a system-wide installation, or on a platform
without internet access see [How to Include The Library](#how-to-include-the-library) below.
# FAQ
## What about C++23 `<stacktrace>`?
Some day C++23's `<stacktrace>` will be ubiquitous. And maybe one day the msvc implementation will be acceptable.
The original motivation for cpptrace was to support projects using older C++ standards and as the library has grown its
functionality has extended beyond the standard library's implementation.
Cpptrace provides functionality beyond what the standard library provides and what implementations provide, such as:
- Walking inlined function calls
- Providing a lightweight interface for "raw traces"
- Resolving function parameter types
- Providing traced exception objects
- Providing an API for signal-safe stacktrace generation
- Providing a way to retrieve stack traces from arbitrary exceptions, not just special cpptrace traced exception
objects. This is a feature coming to C++26, but cpptrace provides a solution for C++11.
## What does cpptrace have over other C++ stacktrace libraries?
Other C++ stacktrace libraries, such as boost stacktrace and backward-cpp, fall short when it comes to portability and
ease of use. In testing, I found neither to provide adaquate coverage of various environments. Even when they can be
made to work in an environment they require manual configuration from the end-user, possibly requiring manual
installation of third-party dependencies. This is a highly undesirable burden to impose on users, especially when it is
for a software package which just provides diagnostics as opposed to core functionality. Additionally, cpptrace provides
support for resolving inlined calls by default for DWARF symbols (boost does not do this, backward-cpp can do this but
only for some back-ends), better support for resolving full function signatures, and nicer API, among other features.
# Prerequisites
> [!IMPORTANT]
@ -465,6 +439,8 @@ thrown exception object, with minimal or no overhead in the non-throwing path:
```cpp
#include <cpptrace/from_current.hpp>
#include <iostream>
void foo() {
throw std::runtime_error("foo failed");
}
@ -929,7 +905,7 @@ include(FetchContent)
FetchContent_Declare(
cpptrace
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
GIT_TAG v0.8.1 # <HASH or TAG>
GIT_TAG v0.8.2 # <HASH or TAG>
)
FetchContent_MakeAvailable(cpptrace)
target_link_libraries(your_target cpptrace::cpptrace)
@ -945,7 +921,7 @@ information.
```sh
git clone https://github.com/jeremy-rifkin/cpptrace.git
git checkout v0.8.1
git checkout v0.8.2
mkdir cpptrace/build
cd cpptrace/build
cmake .. -DCMAKE_BUILD_TYPE=Release
@ -988,7 +964,7 @@ you when installing new libraries.
```ps1
git clone https://github.com/jeremy-rifkin/cpptrace.git
git checkout v0.8.1
git checkout v0.8.2
mkdir cpptrace/build
cd cpptrace/build
cmake .. -DCMAKE_BUILD_TYPE=Release
@ -1006,7 +982,7 @@ To install just for the local user (or any custom prefix):
```sh
git clone https://github.com/jeremy-rifkin/cpptrace.git
git checkout v0.8.1
git checkout v0.8.2
mkdir cpptrace/build
cd cpptrace/build
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/wherever
@ -1089,7 +1065,7 @@ make install
cd ~/scratch/cpptrace-test
git clone https://github.com/jeremy-rifkin/cpptrace.git
cd cpptrace
git checkout v0.8.1
git checkout v0.8.2
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=On -DCPPTRACE_USE_EXTERNAL_LIBDWARF=On -DCMAKE_PREFIX_PATH=~/scratch/cpptrace-test/resources -DCMAKE_INSTALL_PREFIX=~/scratch/cpptrace-test/resources
@ -1109,7 +1085,7 @@ cpptrace and its dependencies.
Cpptrace is available through conan at https://conan.io/center/recipes/cpptrace.
```
[requires]
cpptrace/0.8.1
cpptrace/0.8.2
[generators]
CMakeDeps
CMakeToolchain
@ -1318,6 +1294,51 @@ A couple things I'd like to improve in the future:
in dbghelp the library cannot accurately show const and volatile qualifiers or rvalue references (these appear as
pointers).
# FAQ
## What about C++23 `<stacktrace>`?
Some day C++23's `<stacktrace>` will be ubiquitous. And maybe one day the msvc implementation will be acceptable.
The original motivation for cpptrace was to support projects using older C++ standards and as the library has grown its
functionality has extended beyond the standard library's implementation.
Cpptrace provides functionality beyond what the standard library provides and what implementations provide, such as:
- Walking inlined function calls
- Providing a lightweight interface for "raw traces"
- Resolving function parameter types
- Providing traced exception objects
- Providing an API for signal-safe stacktrace generation
- Providing a way to retrieve stack traces from arbitrary exceptions, not just special cpptrace traced exception
objects. This is a feature coming to C++26, but cpptrace provides a solution for C++11.
## What does cpptrace have over other C++ stacktrace libraries?
Other C++ stacktrace libraries, such as boost stacktrace and backward-cpp, fall short when it comes to portability and
ease of use. In testing, I found neither to provide adaquate coverage of various environments. Even when they can be
made to work in an environment they require manual configuration from the end-user, possibly requiring manual
installation of third-party dependencies. This is a highly undesirable burden to impose on users, especially when it is
for a software package which just provides diagnostics as opposed to core functionality. Additionally, cpptrace provides
support for resolving inlined calls by default for DWARF symbols (boost does not do this, backward-cpp can do this but
only for some back-ends), better support for resolving full function signatures, and nicer API, among other features.
## I'm getting undefined standard library symbols like `std::__1::basic_string` on MacOS
If you see a linker error along the lines of the following on MacOS then it's highly likely you are mixing standard
library ABIs.
```
Undefined symbols for architecture arm64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find(char, unsigned long) const", referenced from:
cpptrace::detail::demangle(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool) in libcpptrace.a(demangle_with_cxxabi.cpp.o)
cpptrace::detail::snippet_manager::build_line_table() in libcpptrace.a(snippet.cpp.o)
```
This can happen when using apple clang to compile cpptrace and gcc to compile your code, or vice versa. The reason is
that apple clang defaults to libc++ and gcc defaults to libstdc++ and these two standard library implementations are not
ABI-compatible. To resolve this, ensure you are compiling both cpptrace and your code with the same standard library by
either using the same compiler for both or using `-stdlib=libc++`/`-stdlib=libstdc++` to control which standard library
is used.
# Contributing
I'm grateful for the help I've received with this library and I welcome contributions! For information on contributing

View File

@ -180,7 +180,7 @@ option(CPPTRACE_SKIP_UNIT "" OFF)
option(CPPTRACE_STD_FORMAT "" ON)
option(CPPTRACE_UNPREFIXED_TRY_CATCH "" OFF)
option(CPPTRACE_USE_EXTERNAL_GTEST "" OFF)
set(CPPTRACE_ZSTD_URL "https://github.com/facebook/zstd/releases/download/v1.5.6/zstd-1.5.6.tar.gz" CACHE STRING "")
set(CPPTRACE_ZSTD_URL "https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz" CACHE STRING "")
set(CPPTRACE_LIBDWARF_REPO "https://github.com/jeremy-rifkin/libdwarf-lite.git" CACHE STRING "")
set(CPPTRACE_LIBDWARF_TAG "fe09ca800b988e2ff21225ac5e7468ceade2a30e" CACHE STRING "") # v0.11.1
set(CPPTRACE_LIBDWARF_SHALLOW "1" CACHE STRING "")

View File

@ -78,7 +78,9 @@ namespace detail {
- reinterpret_cast<std::uintptr_t>(info.dli_fbase)
+ base.unwrap_value();
} else {
base.drop_error();
if(!should_absorb_trace_exceptions()) {
base.drop_error();
}
}
}
return frame;
@ -101,7 +103,9 @@ namespace detail {
- reinterpret_cast<std::uintptr_t>(info.dli_fbase)
+ base.unwrap_value();
} else {
base.drop_error();
if(!should_absorb_trace_exceptions()) {
base.drop_error();
}
}
}
return frame;
@ -146,7 +150,9 @@ namespace detail {
- reinterpret_cast<std::uintptr_t>(handle)
+ base.unwrap_value();
} else {
base.drop_error();
if(!should_absorb_trace_exceptions()) {
base.drop_error();
}
}
} else {
std::fprintf(stderr, "%s\n", std::system_error(GetLastError(), std::system_category()).what());

View File

@ -208,18 +208,19 @@ namespace cpptrace {
const auto yellow = color ? YELLOW : "";
const auto blue = color ? BLUE : "";
if(frame.is_inline) {
microfmt::print(stream, "{<{}}", 2 * sizeof(frame_ptr) + 2, "(inlined)");
} else {
microfmt::print(stream, "{<{}} ", 2 * sizeof(frame_ptr) + 2, "(inlined)");
} else if(options.addresses != address_mode::none) {
auto address = options.addresses == address_mode::raw ? frame.raw_address : frame.object_address;
microfmt::print(stream, "{}0x{>{}:0h}{}", blue, 2 * sizeof(frame_ptr), address, reset);
microfmt::print(stream, "{}0x{>{}:0h}{} ", blue, 2 * sizeof(frame_ptr), address, reset);
}
if(!frame.symbol.empty()) {
microfmt::print(stream, " in {}{}{}", yellow, frame.symbol, reset);
microfmt::print(stream, "in {}{}{}", yellow, frame.symbol, reset);
}
if(!frame.filename.empty()) {
microfmt::print(
stream,
" at {}{}{}",
"{}at {}{}{}",
frame.symbol.empty() ? "" : " ",
green,
options.paths == path_mode::full ? frame.filename : detail::basename(frame.filename, true),
reset

View File

@ -83,6 +83,8 @@ namespace detail {
}
}
// TODO: Symbol resolution code should probably handle when object addresses are 0
std::vector<stacktrace_frame> resolve_frames(const std::vector<object_frame>& frames) {
#if defined(CPPTRACE_GET_SYMBOLS_WITH_LIBDWARF) && defined(CPPTRACE_GET_SYMBOLS_WITH_DBGHELP)
std::vector<stacktrace_frame> trace = libdwarf::resolve_frames(frames);

View File

@ -96,6 +96,21 @@ TEST(FormatterTest, ObjectAddresses) {
);
}
TEST(FormatterTest, NoAddresses) {
auto formatter = cpptrace::formatter{}
.addresses(cpptrace::formatter::address_mode::none);
auto res = split(formatter.format(make_test_stacktrace()), "\n");
EXPECT_THAT(
res,
ElementsAre(
"Stack trace (most recent call first):",
"#0 in foo() at foo.cpp:20:30",
"#1 in bar() at bar.cpp:30:40",
"#2 in main at foo.cpp:40:25"
)
);
}
TEST(FormatterTest, PathShortening) {
cpptrace::stacktrace trace;
trace.frames.push_back({0x1, 0x1001, {20}, {30}, "/home/foo/foo.cpp", "foo()", false});