Skip to content
Snippets Groups Projects
Commit 1f3a3492 authored by pompolic's avatar pompolic
Browse files

Extract function length from progspace

Finally, instead of having to hardcode a constant, the length of
the code to disassemble in search of a RET instruction is discovered
at runtime.
parent 750b8c6b
No related branches found
No related tags found
No related merge requests found
...@@ -44,7 +44,7 @@ class BreakpointManager: ...@@ -44,7 +44,7 @@ class BreakpointManager:
def set_h_rule_breakpoints(self): def set_h_rule_breakpoints(self):
for func in self.H_RULE_FUNCTIONS: for func in self.H_RULE_FUNCTIONS:
func_retq = self.locate_retq(func[0], func[1]) func_retq = self.locate_retq(func)
self.h_rule_breakpoints.append(HRuleBreakpoint("*" + hex(func_retq))) self.h_rule_breakpoints.append(HRuleBreakpoint("*" + hex(func_retq)))
def set_hammer_retq_breakpoints(self): def set_hammer_retq_breakpoints(self):
...@@ -61,17 +61,18 @@ class BreakpointManager: ...@@ -61,17 +61,18 @@ class BreakpointManager:
bp.delete() bp.delete()
# Helper functions for finding the return instructions of particular functions of interest # Helper functions for finding the return instructions of particular functions of interest
#TODO: rename "symbol" to "fn_name"
def locate_retqs(self, symbol, length): def locate_retqs(self, symbol):
arch = gdb.selected_frame().architecture() arch = gdb.selected_frame().architecture()
sym = gdb.lookup_symbol(symbol)[0] sym = gdb.lookup_symbol(symbol)[0]
sym_address = int(sym.value().address) sym_address = int(sym.value().address)
instructions = arch.disassemble(sym_address, sym_address+length) sym_block = sym.symtab.objfile.progspace.block_for_pc(sym_address)
instructions = arch.disassemble(sym_address, sym_block.end)
results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ] results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ]
return results return results
def locate_retq(self, symbol, length): def locate_retq(self, symbol):
results = self.locate_retqs(symbol, length) results = self.locate_retqs(symbol)
return results[0] return results[0]
# TODO: these can probably be removed # TODO: these can probably be removed
...@@ -80,8 +81,8 @@ class BreakpointManager: ...@@ -80,8 +81,8 @@ class BreakpointManager:
arch = gdb.selected_frame().architecture() arch = gdb.selected_frame().architecture()
h_p_p_sym = gdb.lookup_symbol("h_packrat_parse")[0] h_p_p_sym = gdb.lookup_symbol("h_packrat_parse")[0]
h_p_p_address = int(h_p_p_sym.value().address) h_p_p_address = int(h_p_p_sym.value().address)
# Same as with perform_lowlevel_parse, +450 is arbitrary h_p_p_block = h_p_p_sym.symtab.objfile.progspace.block_for_pc(h_p_p_address)
instructions = arch.disassemble(h_p_p_address, h_p_p_address+450) instructions = arch.disassemble(h_p_p_address, h_p_p_block.end)
results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ] results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ]
return results[0] return results[0]
...@@ -89,8 +90,8 @@ class BreakpointManager: ...@@ -89,8 +90,8 @@ class BreakpointManager:
arch = gdb.selected_frame().architecture() arch = gdb.selected_frame().architecture()
i_p_sym = gdb.lookup_symbol("init_parser")[0] i_p_sym = gdb.lookup_symbol("init_parser")[0]
i_p_address = int(i_p_sym.value().address) i_p_address = int(i_p_sym.value().address)
# Same as with perform_lowlevel_parse, +16000 is arbitrary i_p_block = i_p_sym.symtab.objfile.progspace.block_for_pc(i_p_address)
instructions = arch.disassemble(i_p_address, i_p_address+16000) instructions = arch.disassemble(i_p_address, i_p_block.end)
results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ] results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ]
return results[0] return results[0]
...@@ -98,7 +99,7 @@ class BreakpointManager: ...@@ -98,7 +99,7 @@ class BreakpointManager:
arch = gdb.selected_frame().architecture() arch = gdb.selected_frame().architecture()
p_l_p_sym = gdb.lookup_symbol("perform_lowlevel_parse")[0] p_l_p_sym = gdb.lookup_symbol("perform_lowlevel_parse")[0]
p_l_p_address = int(p_l_p_sym.value().address) p_l_p_address = int(p_l_p_sym.value().address)
# The choice of disassembling only 400 instructions from the start is arbitrary. (This function is 310 bytes long on this particular machine.) There is probably a way to find out where a function ends. p_l_p_block = p_l_p_sym.symtab.objfile.progspace.block_for_pc(p_l_p_address)
instructions = arch.disassemble(p_l_p_address, p_l_p_address+400) instructions = arch.disassemble(p_l_p_address, p_l_p_block.end)
results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ] results = [ ins["addr"] for ins in instructions if ins["asm"].startswith("ret") ]
return results[0] return results[0]
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
# TODO: The parameter given to h_do_parse is not shown in the backtrace, which is confusing # TODO: The parameter given to h_do_parse is not shown in the backtrace, which is confusing
# Tuples of symbol name, length in bytes # List of names of functions with H_RULEs declared, used by BreakpointManager
H_RULE_FUNCTIONS = [ ("init_runlengthdecode_parser", 314), ("init_LZW_parser", 1221) ] H_RULE_FUNCTIONS = [ "init_runlengthdecode_parser", "init_LZW_parser" ]
class Parser: class Parser:
def __init__(self, name, address): def __init__(self, name, address):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment