Last active
February 17, 2024 12:40
-
-
Save caltuntas/b84eda2937acfcfef2097a192a9d5995 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
docker build . -t musl-unwinder | |
docker run -dit \ | |
--name musl-unwinder \ | |
--ulimit core=-1 --privileged \ | |
--security-opt seccomp=unconfined \ | |
--entrypoint '/bin/sh' \ | |
musl-unwinder | |
docker exec -it musl-unwinder sh |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM alpine:3.18.0 | |
RUN apk --no-cache add \ | |
gdb \ | |
lldb \ | |
build-base \ | |
libc-dev \ | |
elfutils \ | |
file \ | |
binutils \ | |
coreutils \ | |
gcc \ | |
py3-lldb \ | |
make | |
COPY main.c Makefile muslunwinder.py /tmp | |
CMD ["/bin/sh"] | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
int number=0; | |
int mul(int num, int times) { | |
printf("Multiplying numbers: %d,%d\n", num, times); | |
if (number > 10) { | |
abort(); | |
} | |
return num * times; | |
} | |
int sub(int num, int sub) { | |
printf("Subtracting numbers: %d,%d\n", num, sub); | |
int a = num - sub; | |
int b = 2; | |
return mul(a,b); | |
} | |
int add(int a, int b) { | |
printf("Adding numbers: %d,%d\n", a, b); | |
int c = a + b; | |
int d = 5; | |
return sub(c, d); | |
} | |
int main(int argc, char* argv[]) { | |
number=atoi(argv[1]); | |
printf("Number: %d\n", number); | |
int result = add(3, 7); | |
printf("Result: %d\n", result); | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CC=gcc | |
CFLAGS=-g -O2 | |
main: main.c | |
$(CC) $(CFLAGS) -o main main.c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import gdb | |
from gdb.unwinder import Unwinder | |
def debug(pc, current_rsp, offset, addr, frame_id, func): | |
print('=============debug===========') | |
print('{:<20}:{:<8}'.format('function',func)) | |
print('{:<20}:{:<8}'.format('pc', str(pc))) | |
print('{:<20}:{:<8}'.format('current_rsp', str(current_rsp))) | |
print('{:<20}:{:<8}'.format('offset', str(offset))) | |
print('{:<20}:{:<8}'.format('return address', hex(addr))) | |
print('{:<20}:{:<8}'.format('frame_id', str(frame_id))) | |
u64_ptr = gdb.lookup_type('unsigned long long').pointer() | |
class FrameID: | |
def __init__(self, sp, pc): | |
self.sp = sp | |
self.pc = pc | |
def __str__(self): | |
return f'sp: {self.sp}, pc: {self.pc}' | |
class MuslUnwinder(Unwinder): | |
def __init__(self): | |
super().__init__("musl_unwinder") | |
def is_musl_frame(self,pc): | |
obj = gdb.execute("info symbol 0x%x" % pc, False, True) | |
return "musl" in obj | |
def dereference(self,adr): | |
deref = gdb.parse_and_eval("0x%x" % adr).cast(u64_ptr).dereference() | |
return deref | |
def __call__(self, pending_frame): | |
pc = pending_frame.read_register("pc") | |
if not self.is_musl_frame(pc): | |
return None | |
asm = gdb.execute("disassemble 0x%x" % pc, False, True) | |
lines = asm.splitlines() | |
func = None | |
args_bytes = 0 | |
locals_bytes = 0 | |
rbp_bytes = 0 | |
for line in lines: | |
m = re.match('Dump of assembler code for function (.*):', line) | |
if m: | |
func = m.group(1) | |
elif re.match('.*push[ ]*%', line): | |
args_bytes += 8 | |
if "rbp" in line: | |
rbp_bytes += 8 | |
elif m := re.match('.*sub[ ]*\\$0x([A-Fa-f0-9]+),%rsp', line): | |
locals_bytes = int(m.group(1), 16) | |
break | |
offset = locals_bytes + args_bytes | |
current_rsp = pending_frame.read_register("rsp") | |
current_rbp = pending_frame.read_register("rbp") | |
rsp = current_rsp + offset + 8 | |
return_addr = self.dereference(current_rsp + offset) | |
frame_id = FrameID(rsp, pc) | |
unwind_info = pending_frame.create_unwind_info(frame_id) | |
unwind_info.add_saved_register("rsp", rsp) | |
unwind_info.add_saved_register("rip", return_addr) | |
if rbp_bytes > 0: | |
saved_rbp = self.dereference(current_rsp+locals_bytes+rbp_bytes) | |
unwind_info.add_saved_register("rbp", saved_rbp) | |
else: | |
unwind_info.add_saved_register("rbp", current_rbp) | |
if gdb.parameter("verbose"): | |
debug(pc, current_rsp, offset, return_addr, frame_id, func) | |
return unwind_info | |
gdb.execute('set disassembly-flavor att') | |
gdb.unwinder.register_unwinder(None, MuslUnwinder(), replace=True) | |
gdb.invalidate_cached_frames() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment