Skip to content

Instantly share code, notes, and snippets.

@dramforever
Last active March 3, 2022 09:06
Show Gist options
  • Save dramforever/292c4c876a17771b05ac4e68e0dd70c7 to your computer and use it in GitHub Desktop.
Save dramforever/292c4c876a17771b05ac4e68e0dd70c7 to your computer and use it in GitHub Desktop.
Stack trace

Usage:

$ ./stack-trace <number> [libunwind] [fp_chain]
$ # Example (Call pattern is different for different numbers)
$ ./stack-trace 52 libunwind fp_chain
CFLAGS += -fno-omit-frame-pointer -funwind-tables
LDFLAGS += -lunwind
.PHONY: all
all: stack-trace
.PHONY: clean
clean:
rm stack-trace
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
void print_stack_trace_libunwind() {
printf("=== Stack trace from libunwind ===\n");
unw_cursor_t cursor; unw_context_t uc;
unw_word_t pc, sp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &pc);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
printf("Program counter: 0x%016" PRIxPTR "\n", (uintptr_t) pc);
printf("Stack pointer: 0x%016" PRIxPTR "\n", (uintptr_t) sp);
printf("\n");
}
printf("=== End ===\n\n");
}
void print_stack_trace_fp_chain() {
printf("=== Stack trace from fp chain ===\n");
uintptr_t *fp;
asm("mv %0, fp" : "=r"(fp) : : );
// When should this stop?
while (fp) {
printf("Return address: 0x%016" PRIxPTR "\n", fp[-1]);
printf("Old stack pointer: 0x%016" PRIxPTR "\n", fp[-2]);
printf("\n");
fp = (uintptr_t *) fp[-2];
}
printf("=== End ===\n\n");
}
int use_libunwind = 0, use_fp_chain = 0;
void flip(unsigned n);
void flap(unsigned n);
void flip(unsigned n) {
if (n == 0) {
if (use_libunwind)
print_stack_trace_libunwind();
if (use_fp_chain)
print_stack_trace_fp_chain();
} else if ((n & 1) == 0) {
flip(n >> 1);
} else if ((n & 1) == 1) {
flap(n >> 1);
}
printf("flip %u\n", n);
}
void flap(unsigned n) {
if ((n & 1) == 0) {
flip(n >> 1);
} else if ((n & 1) == 1) {
flap(n >> 1);
}
printf("flap %u\n", n);
}
int main(int argc, char *argv[]) {
unsigned input;
sscanf(argv[1], "%u", &input);
for (int i = 2; i < argc; i ++) {
if (strcmp(argv[i], "libunwind") == 0)
use_libunwind = 1;
if (strcmp(argv[i], "fp_chain") == 0)
use_fp_chain = 1;
}
flip(input);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment