Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
49c5104
Add package "stack-trace"
kotovalexarian Jun 22, 2022
dc07e1d
Add function "kernaux_stack_trace_snprint"
kotovalexarian Jun 22, 2022
a9c427a
Add copyrights
kotovalexarian Jun 22, 2022
d1d7300
Add assertions
kotovalexarian Jun 22, 2022
5e53c46
Get ptr
kotovalexarian Jun 22, 2022
dc8265f
Implement stack trace loop
kotovalexarian Jun 22, 2022
8bb757f
Print stack trace
kotovalexarian Jun 22, 2022
5072252
Example values
kotovalexarian Jun 22, 2022
6dfc257
Add "tests/test_stack_trace"
kotovalexarian Jun 22, 2022
8008290
Better output
kotovalexarian Jun 22, 2022
3966851
Remove symbol names
kotovalexarian Jun 22, 2022
fe16489
Merge branch 'master' into stacktrace
kotovalexarian Jun 23, 2022
71fa111
Merge branch 'master' into stacktrace
kotovalexarian Jun 23, 2022
f000646
Merge branch 'master' into stacktrace
kotovalexarian Jun 24, 2022
1072c66
Merge branch 'master' into stacktrace
kotovalexarian Jun 24, 2022
8c4f763
Merge branch 'master' into stacktrace
kotovalexarian Jun 24, 2022
033b5ee
Merge branch 'master' into stacktrace
kotovalexarian Jun 25, 2022
c7bd123
Merge branch 'master' into stacktrace
kotovalexarian Jun 25, 2022
4020a88
Merge branch 'master' into stacktrace
kotovalexarian Jun 25, 2022
0001d0a
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
a0c9489
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
55d93fc
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
7335e4b
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
9795b1a
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
8dd2d78
Merge branch 'master' into stacktrace
kotovalexarian Jun 27, 2022
e1bc890
Merge branch 'master' into stacktrace
kotovalexarian Jun 29, 2022
1f1e581
Merge branch 'master' into stacktrace
kotovalexarian Jun 30, 2022
0078a40
Merge branch 'master' into stacktrace
kotovalexarian Jun 30, 2022
c528285
Merge branch 'master' into stacktrace
kotovalexarian Nov 29, 2022
87fe9ea
Use macro "KERNAUX_ASM"
kotovalexarian Nov 29, 2022
da6795c
Improve code
kotovalexarian Nov 29, 2022
bbd4442
Add empty line
kotovalexarian Nov 29, 2022
33adf6d
Improve code
kotovalexarian Nov 29, 2022
f1aa369
Improve code
kotovalexarian Nov 29, 2022
246b245
Merge branch 'master' into stacktrace
kotovalexarian Nov 30, 2022
a0f124c
Merge branch 'master' into stacktrace
kotovalexarian Nov 30, 2022
78b7659
Merge branch 'master' into stacktrace
kotovalexarian Dec 2, 2022
174bb97
Merge branch 'master' into stacktrace
kotovalexarian Dec 3, 2022
b956778
Merge branch 'master' into stacktrace
kotovalexarian Dec 3, 2022
80eef3b
Rewrite API
kotovalexarian Dec 3, 2022
40e4df8
Remove old test
kotovalexarian Dec 3, 2022
afb456e
Fix cppcheck
kotovalexarian Dec 3, 2022
5f8f740
Write test
kotovalexarian Dec 3, 2022
c0a1459
Fix error
kotovalexarian Dec 3, 2022
a483715
Debug output
kotovalexarian Dec 3, 2022
534a442
Debug output
kotovalexarian Dec 3, 2022
5257cd1
Fix test
kotovalexarian Dec 3, 2022
6a7941e
Debug output
kotovalexarian Dec 3, 2022
d1f2dce
Remove unnecessary debug output
kotovalexarian Dec 3, 2022
7b052cd
Add test case
kotovalexarian Dec 3, 2022
2868c17
Add test case
kotovalexarian Dec 3, 2022
f62581a
Fix cppcheck
kotovalexarian Dec 3, 2022
6c5d7d0
Rename func
kotovalexarian Dec 3, 2022
03589f4
Rename field
kotovalexarian Dec 3, 2022
025667f
Fix error
kotovalexarian Dec 3, 2022
eae451e
Fix bug
kotovalexarian Dec 3, 2022
1395896
Protect from segfault
kotovalexarian Dec 3, 2022
1bd8bef
Merge branch 'master' into stacktrace
kotovalexarian Dec 11, 2022
d48e9ed
Merge branch 'master' into stacktrace
kotovalexarian Dec 12, 2022
a1d5c3c
Merge branch 'master' into stacktrace
kotovalexarian Dec 15, 2022
829d820
Merge branch 'master' into stacktrace
kotovalexarian Dec 17, 2022
b4ccd39
Merge branch 'master' into stacktrace
kotovalexarian Dec 17, 2022
664e294
Merge branch 'master' into stacktrace
kotovalexarian Dec 21, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions COPYING
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Copyright (c) 2011 Nicholas J. Kain
Copyright (c) 2011-2015 Rich Felker
Copyright (c) 2014-2019 Marco Paland
Copyright (c) 2017-2022 Embedded Artistry LLC
Copyright (c) 2022-2022 mintsuki
Copyright (c) 2022 Alexander Monakov

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@
2022-12-05 Alex Kotov <kotovalexarian@gmail.com>

libkernaux 0.6.1 released

2022-06-22 Alex Kotov <kotovalexarian@gmail.com>

* include/kernaux/stack_trace.h: Added
3 changes: 3 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ endif
if WITH_PRINTF_FMT
libkernaux_la_SOURCES += src/printf_fmt.c
endif
if WITH_STACK_TRACE
libkernaux_la_SOURCES += src/stack_trace.c
endif
if WITH_UNITS
libkernaux_la_SOURCES += src/units.c
endif
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ zero). Work-in-progress APIs can change at any time.
* [Assertions](/include/kernaux/assert.h) (*non-breaking since* **0.4.0**)
* [Example: Assert](/examples/assert.c)
* [Example: Panic](/examples/panic.c)
* Stack trace *(planned)*
* [Stack trace](/include/kernaux/stack_trace.h) *(work in progress)*
* Generic types
* [Display](/include/kernaux/generic/display.h) (*non-breaking since* **?.?.?**)
* [Example](/examples/generic_display.c)
Expand Down Expand Up @@ -173,6 +173,7 @@ explicitly included, use `--without-all`.
* `--with[out]-multiboot2` - Multiboot 2 utils
* `--with[out]-ntoa` - itoa/ftoa
* `--with[out]-printf` - printf
* `--with[out]-stack-trace` - stack trace



Expand Down
12 changes: 9 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ AC_ARG_WITH( [ntoa], AS_HELP_STRING([--without-ntoa], [wit
AC_ARG_WITH( [pfa], AS_HELP_STRING([--without-pfa], [without Page Frame Allocator]))
AC_ARG_WITH( [printf], AS_HELP_STRING([--without-printf], [without printf]))
AC_ARG_WITH( [printf-fmt], AS_HELP_STRING([--without-printf-fmt], [without printf format parser]))
AC_ARG_WITH( [stack-trace], AS_HELP_STRING([--without-stack-trace], [without stack trace]))
AC_ARG_WITH( [units], AS_HELP_STRING([--without-units], [without measurement units utils]))

dnl Packages (disabled by default)
Expand Down Expand Up @@ -123,6 +124,7 @@ if test -z "$with_ntoa"; then with_ntoa=no; fi
if test -z "$with_pfa"; then with_pfa=no; fi
if test -z "$with_printf"; then with_printf=no; fi
if test -z "$with_printf_fmt"; then with_printf_fmt=no; fi
if test -z "$with_stack_trace"; then with_stack_trace=no; fi
if test -z "$with_units"; then with_units=no; fi
])
AS_IF([test "$with_all" = no], do_without_all)
Expand Down Expand Up @@ -165,6 +167,7 @@ AS_IF([test "$with_ntoa" = no ], [with_ntoa=no], [wit
AS_IF([test "$with_pfa" = no ], [with_pfa=no], [with_pfa=yes])
AS_IF([test "$with_printf" = no ], [with_printf=no], [with_printf=yes])
AS_IF([test "$with_printf_fmt" = no ], [with_printf_fmt=no], [with_printf_fmt=yes])
AS_IF([test "$with_stack_trace" = no ], [with_stack_trace=no], [with_stack_trace=yes])
AS_IF([test "$with_units" = no ], [with_units=no], [with_units=yes])

dnl Packages (disabled by default)
Expand All @@ -181,9 +184,9 @@ AS_IF([test "$enable_fixtures" = yes -a "$enable_freestanding" = yes], AC_MSG_ER
AS_IF([test "$enable_checks" = yes -a "$with_libc" = yes], AC_MSG_ERROR([can not use package `libc' with tests]))
AS_IF([test "$enable_fixtures" = yes -a "$with_libc" = yes], AC_MSG_ERROR([can not use package `libc' with fixtures]))

AS_IF([test "$with_printf" = yes -a "$with_ntoa" = no], AC_MSG_ERROR([package `printf' requires package `ntoa']))
AS_IF([test "$with_printf" = yes -a "$with_printf_fmt" = no], AC_MSG_ERROR([package `printf' requires package `printf-fmt']))
AS_IF([test "$with_units" = yes -a "$with_ntoa" = no], AC_MSG_ERROR([package `units' requires package `ntoa']))
AS_IF([test "$with_printf" = yes -a "$with_ntoa" = no], AC_MSG_ERROR([package `printf' requires package `ntoa']))
AS_IF([test "$with_printf" = yes -a "$with_printf_fmt" = no], AC_MSG_ERROR([package `printf' requires package `printf-fmt']))
AS_IF([test "$with_units" = yes -a "$with_ntoa" = no], AC_MSG_ERROR([package `units' requires package `ntoa']))



Expand Down Expand Up @@ -228,6 +231,7 @@ AM_CONDITIONAL([WITH_NTOA], [test "$with_ntoa" = yes])
AM_CONDITIONAL([WITH_PFA], [test "$with_pfa" = yes])
AM_CONDITIONAL([WITH_PRINTF], [test "$with_printf" = yes])
AM_CONDITIONAL([WITH_PRINTF_FMT], [test "$with_printf_fmt" = yes])
AM_CONDITIONAL([WITH_STACK_TRACE], [test "$with_stack_trace" = yes])
AM_CONDITIONAL([WITH_UNITS], [test "$with_units" = yes])

dnl Packages (disabled by default)
Expand Down Expand Up @@ -280,6 +284,7 @@ AS_IF([test "$with_ntoa" = yes], [AC_DEFINE([WITH_NTOA],
AS_IF([test "$with_pfa" = yes], [AC_DEFINE([WITH_PFA], [1], [with Page Frame Allocator])])
AS_IF([test "$with_printf" = yes], [AC_DEFINE([WITH_PRINTF], [1], [with printf])])
AS_IF([test "$with_printf_fmt" = yes], [AC_DEFINE([WITH_PRINTF_FMT], [1], [with printf format parser])])
AS_IF([test "$with_stack_trace" = yes], [AC_DEFINE([WITH_STACK_TRACE], [1], [with stack trace])])
AS_IF([test "$with_units", = yes], [AC_DEFINE([WITH_UNITS], [1], [with measurement units utils])])

dnl Packages (disabled by default)
Expand Down Expand Up @@ -312,6 +317,7 @@ AS_IF([test "$with_ntoa" = no], [AC_SUBST([comment_line_ntoa], [
AS_IF([test "$with_pfa" = no], [AC_SUBST([comment_line_pfa], [//])])
AS_IF([test "$with_printf" = no], [AC_SUBST([comment_line_printf], [//])])
AS_IF([test "$with_printf_fmt" = no], [AC_SUBST([comment_line_printf_fmt], [//])])
AS_IF([test "$with_stack_trace" = no], [AC_SUBST([comment_line_stack_trace], [//])])
AS_IF([test "$with_units" = no], [AC_SUBST([comment_line_units], [//])])


Expand Down
1 change: 1 addition & 0 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ nobase_include_HEADERS = \
kernaux/pfa.h \
kernaux/printf.h \
kernaux/printf_fmt.h \
kernaux/stack_trace.h \
kernaux/units.h \
kernaux/version.h
1 change: 1 addition & 0 deletions include/kernaux.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
#include <kernaux/pfa.h>
#include <kernaux/printf.h>
#include <kernaux/printf_fmt.h>
#include <kernaux/stack_trace.h>
#include <kernaux/units.h>
#include <kernaux/version.h>
29 changes: 29 additions & 0 deletions include/kernaux/stack_trace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef KERNAUX_INCLUDED_STACK_TRACE
#define KERNAUX_INCLUDED_STACK_TRACE

#ifdef __cplusplus
extern "C" {
#endif

#include <kernaux/macro.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef struct KernAux_StackTrace_Frame {
const void *KERNAUX_PRIVATE_FIELD(cur_ptr);
} *KernAux_StackTrace_Frame;

struct KernAux_StackTrace_Frame KernAux_StackTrace_Frame_create();

bool KernAux_StackTrace_Frame_has_next(KernAux_StackTrace_Frame frame);
void KernAux_StackTrace_Frame_use_next(KernAux_StackTrace_Frame frame);

const void *KernAux_StackTrace_Frame_get_ptr(KernAux_StackTrace_Frame frame);

#ifdef __cplusplus
}
#endif

#endif
76 changes: 76 additions & 0 deletions src/stack_trace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* The code was inspired by the Limine bootloader.
*
* Copyright (c) 2020-2022 mintsuki
* Copyright (c) 2022 Alex Kotov
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <kernaux/assert.h>
#include <kernaux/macro.h>
#include <kernaux/stack_trace.h>

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

struct KernAux_StackTrace_Frame KernAux_StackTrace_Frame_create()
{
struct KernAux_StackTrace_Frame frame = { .cur_ptr = NULL };

#if defined(ASM_I386)
const size_t *cur_ptr;
KERNAUX_ASM("movl %%ebp, %0" : "=g" (cur_ptr) :: "memory");
frame.cur_ptr = cur_ptr;
#elif defined(ASM_X86_64)
const size_t *cur_ptr;
KERNAUX_ASM("movq %%rbp, %0" : "=g" (cur_ptr) :: "memory");
frame.cur_ptr = cur_ptr;
#endif

return frame;
}

bool KernAux_StackTrace_Frame_has_next(const KernAux_StackTrace_Frame frame)
{
KERNAUX_ASSERT(frame);

if (!frame->cur_ptr) return false;

#if defined(ASM_X86)
const size_t *const cur_ptr = frame->cur_ptr;
return cur_ptr[1];
#else
return false;
#endif
}

void KernAux_StackTrace_Frame_use_next(const KernAux_StackTrace_Frame frame)
{
KERNAUX_ASSERT(frame);

if (!frame->cur_ptr) return;

#if defined(ASM_X86)
const size_t *const cur_ptr = frame->cur_ptr;
frame->cur_ptr = (const void*)cur_ptr[0];
#endif
}

const void *KernAux_StackTrace_Frame_get_ptr(
const KernAux_StackTrace_Frame frame
) {
KERNAUX_ASSERT(frame);

if (!frame->cur_ptr) return NULL;

#if defined(ASM_X86)
const size_t *const cur_ptr = frame->cur_ptr;
return (const void*)cur_ptr[1];
#else
return NULL;
#endif
}
1 change: 1 addition & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@
/test_printf_fmt_gen.c
/test_printf_gen
/test_printf_gen.c
/test_stack_trace
/test_units_human
12 changes: 12 additions & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,18 @@ CLEANFILES += test_printf_gen.c
test_printf_gen.c: $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/fixtures/printf.yml $(top_srcdir)/fixtures/printf_orig.yml
$(PYTHON) $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/fixtures/printf.yml $(top_srcdir)/fixtures/printf_orig.yml test_printf_gen.c

####################
# test_stack_trace #
####################

if WITH_STACK_TRACE
TESTS += test_stack_trace
test_stack_trace_LDADD = $(top_builddir)/libkernaux.la
test_stack_trace_SOURCES = \
main.c \
test_stack_trace.c
endif

####################
# test_units_human #
####################
Expand Down
81 changes: 81 additions & 0 deletions tests/test_stack_trace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <kernaux/stack_trace.h>

#include <assert.h>
#include <stdio.h>
#include <string.h>

#define MIN_SIZE 20
#define MAX_SIZE (MIN_SIZE + 5)

static size_t min_count = 0;
static const void *min_addresses[MIN_SIZE];

static size_t max_count = 0;
static const void *max_addresses[MAX_SIZE];

#define PREPARE(descr, lower, upper) \
do { \
printf("%s:\n", (descr)); \
\
lower##_count = 0; \
memset(lower##_addresses, 0, sizeof(lower##_addresses)); \
\
for ( \
struct KernAux_StackTrace_Frame frame = \
KernAux_StackTrace_Frame_create(); \
KernAux_StackTrace_Frame_has_next(&frame); \
KernAux_StackTrace_Frame_use_next(&frame) \
) { \
assert(lower##_count < upper##_SIZE); \
lower##_addresses[lower##_count] = \
KernAux_StackTrace_Frame_get_ptr(&frame); \
printf(" %llu: 0x%p\n", \
(unsigned long long)lower##_count, \
lower##_addresses[lower##_count]); \
++lower##_count; \
} \
\
assert(lower##_count >= 2); \
putchar('\n'); \
} while (0)

static void test1();

static void test5_1();
static void test5_2();
static void test5_3();
static void test5_4();
static void test5_5();

void test_main()
{
PREPARE("test_main (initial)", min, MIN);

PREPARE("test_main (compare)", max, MAX);
assert(max_count == min_count);
for (size_t index = 1; index < max_count; ++index) {
assert(max_addresses[index] == min_addresses[index]);
}

test1();
for (size_t index = 2; index < max_count; ++index) {
assert(max_addresses[index] == min_addresses[index - 1]);
}

test5_1();
for (size_t index = 6; index < max_count; ++index) {
assert(max_addresses[index] == min_addresses[index - 5]);
}
}

void test1() { PREPARE("test1", max, MAX); }

void test5_1() { test5_2(); }
void test5_2() { test5_3(); }
void test5_3() { test5_4(); }
void test5_4() { test5_5(); }
void test5_5() { PREPARE("test5_5", max, MAX); }