forked from OSchip/llvm-project
Added a "sources.py" which adds a command that can print out the source files contained in one or more modules.
Added "mach_o.py" which is a mach-o parser that can dump mach-o file contents and also extract sections. It uses the "file_extract" module and the "dict_utils" module. llvm-svn: 189959
This commit is contained in:
parent
5cba070ce2
commit
6a23d21289
|
@ -0,0 +1,61 @@
|
|||
|
||||
class LookupDictionary(dict):
|
||||
"""
|
||||
a dictionary which can lookup value by key, or keys by value
|
||||
"""
|
||||
def __init__(self, items=[]):
|
||||
"""items can be a list of pair_lists or a dictionary"""
|
||||
dict.__init__(self, items)
|
||||
|
||||
def get_keys_for_value(self, value, fail_value = None):
|
||||
"""find the key(s) as a list given a value"""
|
||||
list_result = [item[0] for item in self.items() if item[1] == value]
|
||||
if len(list_result) > 0:
|
||||
return list_result
|
||||
return fail_value
|
||||
|
||||
def get_first_key_for_value(self, value, fail_value = None):
|
||||
"""return the first key of this dictionary given the value"""
|
||||
list_result = [item[0] for item in self.items() if item[1] == value]
|
||||
if len(list_result) > 0:
|
||||
return list_result[0]
|
||||
return fail_value
|
||||
|
||||
def get_value(self, key, fail_value = None):
|
||||
"""find the value given a key"""
|
||||
if key in self:
|
||||
return self[key]
|
||||
return fail_value
|
||||
|
||||
|
||||
class Enum(LookupDictionary):
|
||||
|
||||
def __init__(self, initial_value=0, items=[]):
|
||||
"""items can be a list of pair_lists or a dictionary"""
|
||||
LookupDictionary.__init__(self, items)
|
||||
self.value = initial_value
|
||||
|
||||
def set_value(self, v):
|
||||
v_typename = typeof(v).__name__
|
||||
if v_typename == 'str':
|
||||
if str in self:
|
||||
v = self[v]
|
||||
else:
|
||||
v = 0
|
||||
else:
|
||||
self.value = v
|
||||
|
||||
def get_enum_value(self):
|
||||
return self.value
|
||||
|
||||
def get_enum_name(self):
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
s = self.get_first_key_for_value (self.value, None)
|
||||
if s == None:
|
||||
s = "%#8.8x" % self.value
|
||||
return s
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
|
@ -0,0 +1,221 @@
|
|||
#! /usr/bin/env python
|
||||
|
||||
import string
|
||||
import struct
|
||||
import sys
|
||||
|
||||
class FileExtract:
|
||||
'''Decode binary data from a file'''
|
||||
|
||||
def __init__(self, f, b = '='):
|
||||
'''Initialize with an open binary file and optional byte order'''
|
||||
|
||||
self.file = f
|
||||
self.byte_order = b
|
||||
self.offsets = list()
|
||||
|
||||
def set_byte_order(self, b):
|
||||
'''Set the byte order, valid values are "big", "little", "swap", "native", "<", ">", "@", "="'''
|
||||
if b == 'big':
|
||||
self.byte_order = '>'
|
||||
elif b == 'little':
|
||||
self.byte_order = '<'
|
||||
elif b == 'swap':
|
||||
# swap what ever the current byte order is
|
||||
self.byte_order = swap_unpack_char()
|
||||
elif b == 'native':
|
||||
self.byte_order = '='
|
||||
elif b == '<' or b == '>' or b == '@' or b == '=':
|
||||
self.byte_order = b
|
||||
else:
|
||||
print "error: invalid byte order specified: '%s'" % b
|
||||
|
||||
def is_in_memory(self):
|
||||
return False
|
||||
|
||||
def seek(self, offset, whence = 0):
|
||||
if self.file:
|
||||
return self.file.seek(offset, whence)
|
||||
raise ValueError
|
||||
|
||||
def tell(self):
|
||||
if self.file:
|
||||
return self.file.tell()
|
||||
raise ValueError
|
||||
|
||||
def read_size (self, byte_size):
|
||||
s = self.file.read(byte_size)
|
||||
if len(s) != byte_size:
|
||||
return None
|
||||
return s
|
||||
|
||||
def push_offset_and_seek(self, offset):
|
||||
'''Push the current file offset and seek to "offset"'''
|
||||
self.offsets.append(self.file.tell())
|
||||
self.file.seek(offset, 0)
|
||||
|
||||
def pop_offset_and_seek(self):
|
||||
'''Pop a previously pushed file offset, or do nothing if there were no previously pushed offsets'''
|
||||
if len(self.offsets) > 0:
|
||||
self.file.seek(self.offsets.pop())
|
||||
|
||||
def get_sint8(self, fail_value=0):
|
||||
'''Extract a single int8_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(1)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'b', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint8(self, fail_value=0):
|
||||
'''Extract a single uint8_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(1)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'B', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint16(self, fail_value=0):
|
||||
'''Extract a single int16_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(2)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'h', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint16(self, fail_value=0):
|
||||
'''Extract a single uint16_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(2)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'H', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint32(self, fail_value=0):
|
||||
'''Extract a single int32_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(4)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'i', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint32(self, fail_value=0):
|
||||
'''Extract a single uint32_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(4)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'I', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_sint64(self, fail_value=0):
|
||||
'''Extract a single int64_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(8)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'q', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_uint64(self, fail_value=0):
|
||||
'''Extract a single uint64_t from the binary file at the current file position, returns a single integer'''
|
||||
s = self.read_size(8)
|
||||
if s:
|
||||
v, = struct.unpack(self.byte_order + 'Q', s)
|
||||
return v
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_fixed_length_c_string(self, n, fail_value='', isprint_only_with_space_padding=False):
|
||||
'''Extract a single fixed length C string from the binary file at the current file position, returns a single C string'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
cstr, = struct.unpack(self.byte_order + ("%i" % n) + 's', s)
|
||||
# Strip trialing NULLs
|
||||
cstr = string.strip(cstr, "\0")
|
||||
if isprint_only_with_space_padding:
|
||||
for c in cstr:
|
||||
if c in string.printable or ord(c) == 0:
|
||||
continue
|
||||
return fail_value
|
||||
return cstr
|
||||
else:
|
||||
return fail_value
|
||||
|
||||
def get_c_string(self):
|
||||
'''Extract a single NULL terminated C string from the binary file at the current file position, returns a single C string'''
|
||||
cstr = ''
|
||||
byte = self.get_uint8()
|
||||
while byte != 0:
|
||||
cstr += "%c" % byte
|
||||
byte = self.get_uint8()
|
||||
return cstr
|
||||
|
||||
def get_n_sint8(self, n, fail_value=0):
|
||||
'''Extract "n" int8_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'b', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint8(self, n, fail_value=0):
|
||||
'''Extract "n" uint8_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'B', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint16(self, n, fail_value=0):
|
||||
'''Extract "n" int16_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(2*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'h', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint16(self, n, fail_value=0):
|
||||
'''Extract "n" uint16_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(2*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'H', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint32(self, n, fail_value=0):
|
||||
'''Extract "n" int32_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(4*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'i', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint32(self, n, fail_value=0):
|
||||
'''Extract "n" uint32_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(4*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'I', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_sint64(self, n, fail_value=0):
|
||||
'''Extract "n" int64_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(8*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'q', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
||||
|
||||
def get_n_uint64(self, n, fail_value=0):
|
||||
'''Extract "n" uint64_t integers from the binary file at the current file position, returns a list of integers'''
|
||||
s = self.read_size(8*n)
|
||||
if s:
|
||||
return struct.unpack(self.byte_order + ("%u" % n) + 'Q', s)
|
||||
else:
|
||||
return (fail_value,) * n
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import lldb
|
||||
import shlex
|
||||
|
||||
def dump_module_sources(module, result):
|
||||
if module:
|
||||
print >> result, "Module: %s" % (module.file)
|
||||
for compile_unit in module.compile_units:
|
||||
if compile_unit.file:
|
||||
print >> result, " %s" % (compile_unit.file)
|
||||
|
||||
def info_sources(debugger, command, result, dict):
|
||||
description='''This command will dump all compile units in any modules that are listed as arguments, or for all modules if no arguments are supplied.'''
|
||||
module_names = shlex.split(command)
|
||||
target = debugger.GetSelectedTarget()
|
||||
if module_names:
|
||||
for module_name in module_names:
|
||||
dump_module_sources(target.module[module_name], result)
|
||||
else:
|
||||
for module in target.modules:
|
||||
dump_module_sources(module, result)
|
||||
|
||||
|
||||
def __lldb_init_module (debugger, dict):
|
||||
# Add any commands contained in this module to LLDB
|
||||
debugger.HandleCommand('command script add -f sources.info_sources info_sources')
|
||||
print 'The "info_sources" command has been installed, type "help info_sources" or "info_sources --help" for detailed help.'
|
Loading…
Reference in New Issue