Skip to content

Commit

Permalink
add debugging tools
Browse files Browse the repository at this point in the history
  • Loading branch information
taviso committed Aug 27, 2022
1 parent 027389b commit d435212
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ build
*.so
reference
symbols
stabs
2 changes: 2 additions & 0 deletions debug/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
basemap.s
*.dbg
44 changes: 44 additions & 0 deletions debug/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
ASFLAGS=--32 -gstabs
LDFLAGS=-m elf_i386 -shared
TARGET=wp
CFLAGS=-m32 -gstabs

.PHONY: clean objsize

all: $(TARGET:=.dbg)

wp:
test -f /opt/wp80/wpbin/wp
ln -s /opt/wp80/wpbin/wp wp

objsize: wp
$(eval TEXT_addr := $(shell objdump -j.text -h $(TARGET) | awk '/\.text/ { print $$4 }'))
$(eval TEXT_size := $(shell objdump -j.text -h $(TARGET) | awk '/\.text/ { print $$3 }'))
$(eval DATA_addr := $(shell objdump -j.data -h $(TARGET) | awk '/\.data/ { print $$4 }'))
$(eval DATA_size := $(shell objdump -j.data -h $(TARGET) | awk '/\.data/ { print $$3 }'))
$(eval BSS_addr := $(shell objdump -j.bss -h $(TARGET) | awk '/\.bss/ { print $$4 }'))
$(eval BSS_size := $(shell objdump -j.bss -h $(TARGET) | awk '/\.bss/ { print $$3 }'))

types.s: types.c
$(CC) -c $(CFLAGS) -S -o $@ $<

basemap.s:
@echo You may need to generate basemap.s with ida2stabs.py

%.o: ASFLAGS+=--defsym _textsize=0x$(TEXT_size)
%.o: ASFLAGS+=--defsym _datasize=0x$(DATA_size)
%.o: ASFLAGS+=--defsym _bsssize=0x$(BSS_size)
%.o: %.s | objsize basemap.s
as $(ASFLAGS) -o $@ $<


%.dbg: %.o types.o | objsize
ld $(LDFLAGS) -Tdata=$(DATA_addr) -Ttext=$(TEXT_addr) -Tbss=$(BSS_addr) -o $@ $^
strip --only-keep-debug $@

clean:
rm -f *.o
rm -f *.dbg
rm -f a.out
rm -f types.s
rm -f wp
7 changes: 7 additions & 0 deletions debug/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Stabs Debugging

This is a set of tools and macros to generate gdb compatible symbol files from an idb.

This allows names and parameter info while debugging.

There is an article documenting this available [here](https://lock.cmpxchg8b.com/symbols.html).
107 changes: 107 additions & 0 deletions debug/idb2stabs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Try to dump function types and parameters from an idb.
#
# Tavis Ormandy <taviso@gmail.com>, August 2022
#
# Note: I am not a python programmer, I usually use IDC! This may not be correct!
#

from idaapi import *

typemap = {
'char': '%char',
'int': '%int',
'size_t': '%size_t',
'void': '%void',
'_WORD': '%uint16_t',
'unsigned __int8': '%int8_t',
'unsigned __int16': '%uint16_t',
'__int16': '%int16_t',
'unsigned int': '%uint32_t',
'double': '%double',
'__int64': '%int64_t',
'uint16_t': '%uint16_t',
'__off_t': '%uint64_t',
'signed int': '%int32_t',
'__pid_t': '%uint32_t',
'_DWORD': '%uint32_t',
'time_t': '%uint32_t',
'__uid_t': '%uint32_t',
}

ptr = ptr_type_data_t()
tif = tinfo_t()
funcdata = func_type_data_t()
func = ida_funcs.get_next_func(0)

# Figure out how many *s we need
def derefstr(type):
ptr = ptr_type_data_t()
pstr = ""

while type.is_ptr():
type.get_ptr_details(ptr)
type = ptr.obj_type
pstr += "*"

return pstr

# Simplify any complex types
def simplify(type):
ptr = ptr_type_data_t()

while type.is_ptr():
type.get_ptr_details(ptr)
type = ptr.obj_type

type.clr_const()
type.clr_volatile()

if str(type) in typemap:
return typemap[str(type)]

return "%void"

print("# Automatically Generated by ida2py")

while func is not None:
fname = get_func_name(func.start_ea)

# Filter any characters here.
fname = fname.replace('.', '_')

if get_tinfo(tif, func.start_ea) is not True:
print("function %s, 0x%x, %%void" % (fname, func.start_ea))
func = ida_funcs.get_next_func(func.start_ea)
continue

if tif.get_func_details(funcdata) is not True:
print("get_func_details error")
break

print("function %s, 0x%x, %s %s"
% (fname,
func.start_ea,
derefstr(tif.get_rettype()),
simplify(tif.get_rettype())
))

for arg in range(funcdata.size()):
name = funcdata[arg].name
pstr = derefstr(funcdata[arg].type)
type = simplify(funcdata[arg].type)

if type == "%void" and pstr == "":
#print("Dont know type %s" % str(funcdata[arg].type))
break

# Handle unnamed parameters.
if name == "":
name = "arg" + str(arg)

print("\tparam %s, %s %s" % (
name,
pstr,
type
))

func = ida_funcs.get_next_func(func.start_ea)
120 changes: 120 additions & 0 deletions debug/stabs.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#
# vim: ft=asm
#
# This is a manually created symbol file template. If you want to create a
# symbol file to debug a binary without symbols, you can use this file to
# define stabs.
#
# Compile:
#
# $ as -gstabs symbols.s -o symbols.o
#
# Now you can do this in gdb:
#
# (gdb) add-symbol-file symbols.o
#

.altmacro

# Some of the common stabs types we can use.
.equ N_GSYM, 0x20
.equ N_FUN, 0x24
.equ N_STSYM, 0x26
.equ N_ROSYM, 0x2c
.equ N_RSYM, 0x40
.equ N_SLINE, 0x44
.equ N_DSLINE, 0x46
.equ N_BSLINE, 0x48
.equ N_FLINE, 0x4c
.equ N_SSYM, 0x60
.equ N_SO, 0x64
.equ N_LSYM, 0x80
.equ N_PSYM, 0xa0
.equ N_LBRAC, 0xc0
.equ N_RBRAC, 0xe0
.equ N_BCOMM, 0xe2
.equ N_ECOMM, 0xe4
.equ N_ECOML, 0xe8

# Set this to the size of a long.
.equ PARAM_SIZE, 4

# Make enough space to fill sections without confusing gdb.
.section .text
.fill _textsize, 1, 0

.section .data
.fill _datasize, 1, 0

.section .bss
.fill _bsssize, 1, 0

# Predefined types, prefix with * for a pointer
#
# -1 int, 32 bit signed integral type.
# -2 char, 8 bit type holding a character.
# -3 short, 16 bit signed integral type.
# -4 long, 32 bit signed integral type.
# -5 unsigned char, 8 bit unsigned integral type.
# -6 signed char, 8 bit signed integral type.
# -7 unsigned short, 16 bit unsigned integral type.
# -8 unsigned int, 32 bit unsigned integral type.
# -9 unsigned, 32 bit unsigned integral type.
# -10 unsigned long, 32 bit unsigned integral type.
# -11 void, type indicating the lack of a value.
# -12 float, IEEE single precision.
# -13 double, IEEE double precision.
# -14 long double, IEEE double precision.
# -16 boolean. 32 bit type.
# -17 short real. IEEE single precision.
# -18 real. IEEE double precision.
# -19 stringptr.
# -30 wchar. Wide character, 16 bits wide, unsigned.
# -31 long long, 64 bit signed integral type.
# -32 unsigned long long, 64 bit unsigned integral type.

.equ int, -1
.equ int32_t, -1
.equ char, -2
.equ int16_t, -3
.equ short, -3
.equ long, -4
.equ uint8_t, -5
.equ int8_t, -6
.equ uint16_t, -7
.equ uint32_t, -8
.equ unsigned, -9
.equ size_t, -10
.equ void, -11
.equ float, -12
.equ double, -13
.equ bool, -16
.equ uint64_t, -32
.equ int64_t, -31

# This is used to verify definitions are sorted.
.set _prevaddr, 0

# This is used to reset after an .include
.macro resetorder
.set _prevaddr, 0
.endm

# type is a number from the list above, or a custom type.
.macro function name, address, ptr=, type
.if _prevaddr > \address
.warning "Function \name was not in ascending numerical order."
.endif
.set _prevaddr, \address
.set _arg, 0
.stabs "\name:f\ptr\type", N_FUN, 0, 0, \address
.endm

.macro param name, ptr=, type
.set _arg, _arg + 1
.stabs "\name:p\ptr\type", N_PSYM, 0, 0, PARAM_SIZE+_arg*PARAM_SIZE
.endm

.macro variable name, address, ptr=, type
.stabs "\name:S\ptr\type", N_STSYM, 0, 0, \address
.endm
4 changes: 4 additions & 0 deletions debug/types.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
struct foo {
int bar;
int baz;
};
74 changes: 74 additions & 0 deletions debug/wp.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#
# vim: ft=asm
#

.include "stabs.s"

.include "basemap.s"

# WARNING: These definitions should be sorted by address.
resetorder

function main, 0x8128000, %int
param argc, %int
param argv, ** %char
param envp, ** %char

function pcline, 0x8129200, %int
param argc, %int
param argv, ** %char

function skipw, 0x8129250, %int
param argc, %int
param argv, ** %char

function writesyntax, 0x8129f30, %void

function seterminal, 0x812A0D0, %int
param str, * %char

function wopen51, 0x81cb030, %int
param fcb, * %void

function rddec, 0x81dac90, %bool
param numstr, ** %char
param num, * %uint16_t

function set_tname, 0x82013C0, %void
param name, * %char

function xy_mouse, 0x8204060, %void

function MessageBox, 0x823b710, %int
param type, %unsigned
param message, * %char

function GkWarning, 0x823b7d0, %int
param message, * %char

function GkYesNo, 0x0823b7f0, %int
param message, * %char

function GkOkCancel, 0x823b810, %int
param message, * %char

function wstrcat, 0x82bc600, * %char
param s1, * %char
param s2, * %char

function wstrcpy, 0x82bc6b0, * %char
param s1, * %char
param s2, * %char

function wstrlen, 0x82bc760, %size_t
param str, * %char

function wstrncmp, 0x82BC830, %size_t
param s1, * %char
param s2, * %char
param n, %size_t

function initthird, 0x82bcb50, %int

function thrSavePipes, 0x82bce30, %int
param pipestr, * %char

0 comments on commit d435212

Please sign in to comment.