Skip to content

Instantly share code, notes, and snippets.

@burke
Last active October 14, 2015 21:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save burke/c43e712ee2541aee87aa to your computer and use it in GitHub Desktop.
Save burke/c43e712ee2541aee87aa to your computer and use it in GitHub Desktop.
#!/bin/bash
if [[ $# -ne 1 ]]; then
>&2 echo "usage: $0 <pid>"
exit 1
fi
pid=$1
tmpfile="$(mktemp)"
cat > "${tmpfile}" <<'EOF'
python
def get_rstring(addr):
s = addr.cast(string_t.pointer())
if s['basic']['flags'] & (1 << 13):
return s['as']['heap']['ptr'].string()
else:
return s['as']['ary'].string()
def get_lineno(iseq, pos):
if pos != 0:
pos -= 1
t = iseq['line_info_table']
t_size = iseq['line_info_size']
if t_size == 0:
return 0
elif t_size == 1:
return t[0]['line_no']
for i in range(0, int(t_size)):
if pos == t[i]['position']:
return t[i]['line_no']
elif t[i]['position'] > pos:
return t[i-1]['line_no']
return t[t_size-1]['line_no']
try:
control_frame_t = gdb.lookup_type('rb_control_frame_t')
string_t = gdb.lookup_type('struct RString')
except gdb.error:
raise gdb.GdbError ("ruby extension requires symbols")
th = gdb.parse_and_eval('ruby_current_thread')
last_cfp = th['cfp']
start_cfp = (th['stack'] + th['stack_size']).cast(control_frame_t.pointer()) - 2
size = start_cfp - last_cfp + 1
cfp = start_cfp
call_stack = []
for i in range(0, int(size)):
if cfp['iseq'] != 0 and cfp['iseq'].dereference().address != 0:
if cfp['pc'] != 0 and cfp['pc'].dereference().address != 0:
s = "{}:{}:in `{}'".format(get_rstring(cfp['iseq']['location']['path']),
get_lineno(cfp['iseq'], cfp['pc'] - cfp['iseq']['iseq_encoded']),
get_rstring(cfp['iseq']['location']['label']))
call_stack.append(s)
else:
print("???pc???")
else:
print("???cfp???")
cfp -= 1
print("===== ruby stack =====")
for i in reversed(call_stack):
print(i)
end
detach
quit
EOF
out="$(mktemp)"
trap "rm -f ${tmpfile} ${out}" EXIT
sudo gdb --batch -q -x "${tmpfile}" -p "${pid}" > "${out}" 2>&1
if [[ $? -eq 0 ]]; then
stack="$(awk 'p{print} /===== ruby stack =====/{p=1}' < "${out}")"
if [[ "$(echo "${stack}" | wc -c)" -lt 10 ]]; then
cat "${out}"
exit 1
fi
echo "${stack}"
exit 0
fi
cat "${out}"
exit 1
@burke
Copy link
Author

burke commented Oct 14, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment