commit 3d39248bb3adb5421a787c1549c467e3635057af
parent e952359b927844a2176aeffb9d82adad69ba647b
Author: Mykyta Holubakha <hilobakho@gmail.com>
Date: Sun, 25 Apr 2021 15:42:54 +0300
rt: add functions to walk stack frames
Co-authored-by: Drew DeVault <sir@cmpwn.com>
Signed-off-by: Mykyta Holubakha <hilobakho@gmail.com>
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
6 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/rt/+aarch64/backtrace.ha b/rt/+aarch64/backtrace.ha
@@ -0,0 +1,19 @@
+fn getfp() **void;
+
+// Details for a stack frame. Contents are architecture-specific.
+export type frame = struct {
+ fp: nullable *frame,
+ lr: nullable *void,
+};
+
+// Returns the caller's stack frame. Call [[nextframe]] to walk the stack.
+export fn backtrace() frame = *(getfp(): *frame);
+
+// Returns the frame above the current frame, if any.
+export fn nextframe(fp: *frame) (frame | void) = {
+ return match (fp.fp) {
+ null => void,
+ fp: *frame => *fp,
+ };
+};
+
diff --git a/rt/+aarch64/getfp.s b/rt/+aarch64/getfp.s
@@ -0,0 +1,5 @@
+.global rt.getfp
+.type rt.getfp,@function
+rt.getfp:
+ mov x0, x29
+ ret
diff --git a/rt/+x86_64/backtrace.ha b/rt/+x86_64/backtrace.ha
@@ -0,0 +1,20 @@
+fn getfp() **void;
+
+// Details for a stack frame. Contents are architecture-specific.
+export type frame = struct {
+ addr: *void
+};
+
+// Returns the current stack frame. See [[nextframe]] to walk the stack.
+export fn backtrace() frame = frame {
+ addr = getfp()
+};
+
+// Returns the frame above the current frame, if any.
+export fn nextframe(sframe: frame) (frame | void) = {
+ let addr = sframe.addr: *nullable *void;
+ return match (*addr) {
+ null => void,
+ a: *void => frame { addr = a }
+ };
+};
diff --git a/rt/+x86_64/getfp.s b/rt/+x86_64/getfp.s
@@ -0,0 +1,5 @@
+.global rt.getfp
+.type rt.getfp,@function
+rt.getfp:
+ mov (%rbp),%rax
+ ret
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -29,6 +29,7 @@ gensrcs_rt() {
'$(PLATFORM)/stat.ha' \
'$(PLATFORM)/socket.ha' \
'$(ARCH)/jmp.ha' \
+ '$(ARCH)/backtrace.ha' \
ensure.ha \
jmp.ha \
malloc.ha \
@@ -66,6 +67,7 @@ ${stdlib}_asm=\$($cache)/rt/syscall.o \\
\$($cache)/rt/setjmp.o \\
\$($cache)/rt/longjmp.o \\
\$($cache)/rt/restore.o \\
+ \$($cache)/rt/getfp.o \\
\$($cache)/rt/start.o
\$($cache)/rt/syscall.o: \$(STDLIB)/rt/\$(PLATFORM)/syscall\$(ARCH).s
@@ -88,6 +90,11 @@ ${stdlib}_asm=\$($cache)/rt/syscall.o \\
@mkdir -p \$($cache)/rt
@\$(AS) -o \$@ \$<
+\$($cache)/rt/getfp.o: \$(STDLIB)/rt/\$(ARCH)/getfp.s
+ @printf 'AS \t\$@\n'
+ @mkdir -p \$($cache)/rt
+ @\$(AS) -o \$@ \$<
+
\$($cache)/rt/rt.a: \$($cache)/rt/rt.o \$(${stdlib}_asm)
@printf 'AR\t\$@\n'
@\$(AR) -csr \$@ \$($cache)/rt/rt.o \$(${stdlib}_asm)
diff --git a/stdlib.mk b/stdlib.mk
@@ -16,6 +16,7 @@ stdlib_rt_srcs= \
$(STDLIB)/rt/$(PLATFORM)/stat.ha \
$(STDLIB)/rt/$(PLATFORM)/socket.ha \
$(STDLIB)/rt/$(ARCH)/jmp.ha \
+ $(STDLIB)/rt/$(ARCH)/backtrace.ha \
$(STDLIB)/rt/ensure.ha \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
@@ -40,6 +41,7 @@ stdlib_asm=$(HARECACHE)/rt/syscall.o \
$(HARECACHE)/rt/setjmp.o \
$(HARECACHE)/rt/longjmp.o \
$(HARECACHE)/rt/restore.o \
+ $(HARECACHE)/rt/getfp.o \
$(HARECACHE)/rt/start.o
$(HARECACHE)/rt/syscall.o: $(STDLIB)/rt/$(PLATFORM)/syscall$(ARCH).s
@@ -62,6 +64,11 @@ $(HARECACHE)/rt/restore.o: $(STDLIB)/rt/$(ARCH)/restore.s
@mkdir -p $(HARECACHE)/rt
@$(AS) -o $@ $<
+$(HARECACHE)/rt/getfp.o: $(STDLIB)/rt/$(ARCH)/getfp.s
+ @printf 'AS \t$@\n'
+ @mkdir -p $(HARECACHE)/rt
+ @$(AS) -o $@ $<
+
$(HARECACHE)/rt/rt.a: $(HARECACHE)/rt/rt.o $(stdlib_asm)
@printf 'AR\t$@\n'
@$(AR) -csr $@ $(HARECACHE)/rt/rt.o $(stdlib_asm)
@@ -905,6 +912,7 @@ testlib_rt_srcs= \
$(STDLIB)/rt/$(PLATFORM)/stat.ha \
$(STDLIB)/rt/$(PLATFORM)/socket.ha \
$(STDLIB)/rt/$(ARCH)/jmp.ha \
+ $(STDLIB)/rt/$(ARCH)/backtrace.ha \
$(STDLIB)/rt/ensure.ha \
$(STDLIB)/rt/jmp.ha \
$(STDLIB)/rt/malloc.ha \
@@ -933,6 +941,7 @@ testlib_asm=$(TESTCACHE)/rt/syscall.o \
$(TESTCACHE)/rt/setjmp.o \
$(TESTCACHE)/rt/longjmp.o \
$(TESTCACHE)/rt/restore.o \
+ $(TESTCACHE)/rt/getfp.o \
$(TESTCACHE)/rt/start.o
$(TESTCACHE)/rt/syscall.o: $(STDLIB)/rt/$(PLATFORM)/syscall$(ARCH).s
@@ -955,6 +964,11 @@ $(TESTCACHE)/rt/restore.o: $(STDLIB)/rt/$(ARCH)/restore.s
@mkdir -p $(TESTCACHE)/rt
@$(AS) -o $@ $<
+$(TESTCACHE)/rt/getfp.o: $(STDLIB)/rt/$(ARCH)/getfp.s
+ @printf 'AS \t$@\n'
+ @mkdir -p $(TESTCACHE)/rt
+ @$(AS) -o $@ $<
+
$(TESTCACHE)/rt/rt.a: $(TESTCACHE)/rt/rt.o $(testlib_asm)
@printf 'AR\t$@\n'
@$(AR) -csr $@ $(TESTCACHE)/rt/rt.o $(testlib_asm)