Skip to content

Commit

Permalink
feat(r2): load symbols from file if possible
Browse files Browse the repository at this point in the history
refactor r2._cmd() to allow optional r_core passed
  • Loading branch information
chinggg committed Oct 20, 2022
1 parent 8a73925 commit becf881
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
4 changes: 2 additions & 2 deletions examples/extensions/r2/deflat_r2.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
# see source code at examples/src/linux/fla_test.c
ql = R2Qiling(['rootfs/x86_linux/bin/test_fla_argv', '1'], 'rootfs/x86_linux', verbose=QL_VERBOSE.DEFAULT)
r2 = ql.r2
# now r2 has only rbuf but no symbol info
fcn = r2.get_fcn_at(0x08049190)
# now we can use r2 parsed symbol name instead of address
fcn = r2.get_fcn_at(r2.where('target_function'))
print(fcn)
r2.deflat(fcn)
ql.run()
Expand Down
24 changes: 20 additions & 4 deletions qiling/extensions/r2/r2.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ def __init__(self, ql: 'R2Qiling', baseaddr=(1 << 64) - 1, loadaddr=0):
self._r2c = libr.r_core.r_core_new()
self._r2i = ctypes.cast(self._r2c.contents.io, ctypes.POINTER(libr.r_io.struct_r_io_t))
self._setup_mem(ql)
if ql.code is None: # ql is initialized with file
self._load_symbol_from_file(ql.path)

def _qlarch2r(self, archtype: QL_ARCH) -> str:
return {
Expand Down Expand Up @@ -251,13 +253,27 @@ def _setup_mem(self, ql: 'R2Qiling'):
self._cmd(f"e,asm.arch={arch},asm.bits={ql.arch.bits}")
self._cmd("oba") # load bininfo and update flags

def _cmd(self, cmd: str) -> str:
def _load_symbol_from_file(self, path: str):
r2c = libr.r_core.r_core_new()
path = path.encode()
fh = libr.r_core.r_core_file_open(r2c, path, UC_PROT_READ | UC_PROT_EXEC, self.loadaddr)
libr.r_core.r_core_bin_load(r2c, path, self.baseaddr)
symbols = self._cmdj("isj", r2c)
for sym in symbols:
name = sym['name'] # name is shoter, but starting with . causes error
name = sym['flagname'] if name.startswith('.') else name
if name: # add each symbol as flag if symbol name is not empty
self._cmd(f"f {name} {sym['size']} @ {sym['vaddr']}")
libr.r_core_free(r2c)

def _cmd(self, cmd: str, r2c = None) -> str:
r2c = r2c or self._r2c
r = libr.r_core.r_core_cmd_str(
self._r2c, ctypes.create_string_buffer(cmd.encode("utf-8")))
r2c, ctypes.create_string_buffer(cmd.encode("utf-8")))
return ctypes.string_at(r).decode('utf-8')

def _cmdj(self, cmd: str) -> Union[Dict, List[Dict]]:
return json.loads(self._cmd(cmd))
def _cmdj(self, cmd: str, r2c = None) -> Union[Dict, List[Dict]]:
return json.loads(self._cmd(cmd, r2c))

@property
def offset(self) -> int:
Expand Down

0 comments on commit becf881

Please sign in to comment.