Skip to content

Commit

Permalink
karm-base: Added backtrace collection api.
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepy-monax committed Dec 6, 2024
1 parent 5e171fd commit 9ea85f7
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 3 deletions.
32 changes: 32 additions & 0 deletions src/impls/impl-posix/base.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,40 @@
#include <execinfo.h>
#include <karm-base/backtrace.h>
#include <karm-io/aton.h>
#include <stdio.h>
#include <stdlib.h>

#include <karm-base/_embed.h>

namespace Karm::_Embed {

// MARK: Backtrace -------------------------------------------------------------

Backtrace captureBacktrace() {
return forceCaptureBacktrace();
}

Backtrace forceCaptureBacktrace() {
Backtrace bt = Backtrace::CAPTURED;
void *buffer[64];
int count = backtrace(buffer, 64);
char **symbols = backtrace_symbols(buffer, count);

for (int i = 0; i < count; i++) {
char *symbol = symbols[i];
bt._frames.pushBack({
String(symbol),
String("unknown"),
0,
});
}

free(symbols);
return bt;
}

// MARK: Locks -----------------------------------------------------------------

void relaxe() {
#if defined(__x86_64__)
asm volatile("pause");
Expand Down
13 changes: 13 additions & 0 deletions src/impls/impl-posix/entry.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
#include <karm-base/backtrace.h>
#include <karm-base/panic.h>
#include <karm-sys/chan.h>
#include <stdio.h>
#include <stdlib.h>

void __panicHandler(Karm::PanicKind kind, char const *msg) {
fprintf(stderr, "%s: %s\n", kind == Karm::PanicKind::PANIC ? "panic" : "debug", msg);

// NOTE: We hare calling backinto the framework here, it might cause another
// panic, this is why we are keeping track of nested panics
static isize _panicDepth = 1;
_panicDepth++;
if (_panicDepth == 1) {
auto bt = Karm::Backtrace::capture();
if (bt.status() == Karm::Backtrace::Status::CAPTURED)
Sys::println("backtrace:\n{}", bt);
}

if (kind == Karm::PanicKind::PANIC) {
abort();
__builtin_unreachable();
}
_panicDepth--;
}
12 changes: 12 additions & 0 deletions src/libs/karm-base/_embed.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
#pragma once

namespace Karm {
struct Backtrace;
} // namespace Karm

namespace Karm::_Embed {

// MARK: Backtrace -------------------------------------------------------------

Backtrace captureBacktrace();

Backtrace forceCaptureBacktrace();

// MARK: Locks -----------------------------------------------------------------

void relaxe();

void enterCritical();
Expand Down
15 changes: 15 additions & 0 deletions src/libs/karm-base/backtrace.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "backtrace.h"

#include "_embed.h"

namespace Karm {

Backtrace Backtrace::capture() {
return _Embed::captureBacktrace();
}

Backtrace Backtrace::forceCapture() {
return _Embed::forceCaptureBacktrace();
}

} // namespace Karm
49 changes: 49 additions & 0 deletions src/libs/karm-base/backtrace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include "string.h"
#include "vec.h"

namespace Karm {

struct Backtrace {
struct Frame {
String desc;
String file;
usize line;

bool operator==(Frame const &other) const = default;

auto operator<=>(Frame const &other) const = default;
};

enum struct Status {
UNSUPPORTED,
DISABLED,
CAPTURED,
};

using enum Status;

Vec<Frame> _frames;
Status _status;

Backtrace(Status status) : _status(status) {}

static Backtrace capture();

static Backtrace forceCapture();

Slice<Frame> frames() const {
return _frames;
}

Status status() const {
return _status;
}

bool operator==(Backtrace const &other) const = default;

auto operator<=>(Backtrace const &other) const = default;
};

} // namespace Karm
6 changes: 3 additions & 3 deletions src/libs/karm-crypto/sha2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static inline void _sha256ComputeBlock(Array<u32, 8> &state, u8 const *buf) {
static inline Array<u32, 8> _sha256Internal(Array<u32, 8> const &init, Bytes bytes) {
Array<u32, 8> state = init;
auto [buf, len] = bytes;
usize padlen = len << 3;
u64 padlen = len << 3;

for (; len >= 64; len -= 64, buf += 64) {
_sha256ComputeBlock(state, buf);
Expand Down Expand Up @@ -223,7 +223,7 @@ static inline void _sha512ComputeBlock(Array<u64, 8> &state, u8 const *buf) {
static inline Array<u64, 8> _sha512Internal(Array<u64, 8> const &init, Bytes bytes) {
Array<u64, 8> state = init;
auto [buf, len] = bytes;
usize padlen = len << 3;
u64 padlen = len << 3;

for (; len >= 128; len -= 128, buf += 128) {
_sha512ComputeBlock(state, buf);
Expand Down Expand Up @@ -270,4 +270,4 @@ Array<u8, SHA384_BYTES> sha384(Bytes bytes) {
return Array<u8, SHA384_BYTES>::from(state.bytes());
}

} // namespace Karm::Crypto
} // namespace Karm::Crypto
23 changes: 23 additions & 0 deletions src/libs/karm-io/fmt.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <karm-base/backtrace.h>
#include <karm-base/box.h>
#include <karm-base/cow.h>
#include <karm-base/endian.h>
Expand Down Expand Up @@ -1018,4 +1019,26 @@ struct Formatter<Tuple<Ts...>> {
}
};

// MARK: Format backtrace ------------------------------------------------------

template <>
struct Formatter<Backtrace> {
Res<usize> format(Io::TextWriter &writer, Backtrace const &val) {
if (val.status() == Backtrace::DISABLED)
return writer.writeStr("(backtrace disabled)"s);

if (val.status() == Backtrace::UNSUPPORTED)
return writer.writeStr("(backtrace unsupported)"s);

usize index = 1;
usize written = 0;
for (auto const &frame : val.frames()) {
written += try$(Io::format(writer, "#{}: {} at {}:{}\n", index, frame.desc, frame.file, frame.line));
index++;
}

return Ok(written);
}
};

} // namespace Karm::Io

0 comments on commit 9ea85f7

Please sign in to comment.