Skip to content

Instantly share code, notes, and snippets.

@dpoggi
Last active August 29, 2015 14:15
Show Gist options
  • Save dpoggi/f91c1412400766e369e4 to your computer and use it in GitHub Desktop.
Save dpoggi/f91c1412400766e369e4 to your computer and use it in GitHub Desktop.
Stack Unwinding (thanks HN!)
*.o
*.obj
*.out
unwind
CC = clang
CFLAGS = -m64 -fPIC -std=gnu99 -W -Wall
SOURCES = $(wildcard *.c)
TARGET = unwind
.PHONY: all
all: $(TARGET)
$(TARGET): $(SOURCES)
.PHONY: clean
clean:
$(RM) $(TARGET)
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
struct frameptr_t { struct frameptr_t *next; };
struct frameptr_t *get_frameptr(void) {
struct frameptr_t *ebp;
#if __x86_64__
asm volatile("movq %%rbp, %0;" : "=r" (ebp));
#else
asm volatile("movl %%ebp, %0;" : "=r" (ebp));
#endif
return ebp->next;
}
void unwind(size_t depth, char *addr, size_t size) {
size_t i;
struct frameptr_t *ebp;
ptrdiff_t offset;
ebp = get_frameptr();
offset = addr - (char *)ebp;
for (i = 0; i < depth; i++) ebp = ebp->next;
for (i = 0; i < size; i++) addr[i] = ((char *)ebp + offset)[i];
}
#define UNWIND(d, v) unwind(d, (char *)&v, sizeof(v))
void test_unwind(int x) {
x = 42;
printf("x now:\t\t\t%d\n", x);
UNWIND(1, x);
printf("x as it was passed:\t%d\n", x);
}
int main(int argc, const char *argv[]) {
int x;
if (argc < 2) {
fprintf(stderr, "Error: need at least one integer argument.\n");
exit(1);
}
x = atoi(argv[1]);
test_unwind(x);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment