diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2013-08-01 19:36:42 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2013-08-01 19:42:34 +0200 |
commit | 6c4a60f96f7b4360a9f22b4685e6bc84c3d7912e (patch) | |
tree | 9da379063ea6410dde1518c18dab0f47f80ffa2b /tools | |
parent | a0d0f46756b7f2f1e55c7422f8f41dd1f7c18faf (diff) |
tools: improve gpu-trace
Use our old friend memcpy() to make temporary copy of
command buffer memory in client process.
No longer needs cooporation from target, which means the hacky
_viv_read_u32 can be removed again.
An added advantage is that this is *much* faster.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/etnaviv_gdb.py | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/tools/etnaviv_gdb.py b/tools/etnaviv_gdb.py index 13401c4..9b6f3e1 100644 --- a/tools/etnaviv_gdb.py +++ b/tools/etnaviv_gdb.py @@ -239,6 +239,39 @@ class GPUDisassemble(gdb.Command): ### gpu-trace ### from etnaviv.asm_common import format_instruction, disassemble +def indirect_memcpy(start_addr, end_addr): + ''' + Indirect memory copy operation from inferior. + + Allocate memory in the inferior process, and copy over + a range of memory using memcpy in the inferior. + Subsequently this memory is read by the gdb process. + This two-step process is needed because gdb refuses + to access the memory mapped by the Vivante kernel + driver. + ''' + inferior = gdb.selected_inferior() + size_t_type = gdb.lookup_type('size_t') # same size as pointer + # These don't have debug symbols, so we need to be very careful + # about the types passed in. Cast them all to size_t. + malloc = gdb.parse_and_eval('malloc') + free = gdb.parse_and_eval('free') + memcpy = gdb.parse_and_eval('memcpy') + + start_addr = gdb.Value(start_addr).cast(size_t_type) + size = gdb.Value(end_addr - start_addr).cast(size_t_type) + + try: + # allocate memory and cast result to size_t + ptr = malloc(size).cast(size_t_type) + # copy from client memory to client memory + memcpy(ptr, start_addr, size) + # read from client memory + return inferior.read_memory(ptr, size) + finally: # ensure free of temp buffer to prevent memory leak + free(ptr) + +import struct class CommitBreakpoint(gdb.Breakpoint): def __init__(self, state_map, do_stop): super(CommitBreakpoint, self).__init__('viv_commit') @@ -282,11 +315,14 @@ class CommitBreakpoint(gdb.Breakpoint): startOffset = int(commandBuffer['startOffset']) physical = int(commandBuffer['physical'].cast(self.size_t_type)) # GPU address logical = int(commandBuffer['logical'].cast(self.size_t_type)) # CPU address + + buffer = indirect_memcpy(logical + startOffset, logical + offset) + data = struct.unpack_from(b'%dL' % (len(buffer)/4), buffer) + print('viv_commit:') - # need this function from viv.c to work around gdb having no access to the mapped buffers - self.viv_read_u32 = gdb.lookup_symbol('_viv_read_u32')[0].value() + # "cast" byte-based buffer to uint32_t # iterate over buffer, one 32 bit word at a time - for rec in parse_command_buffer(self.memory_iterator(logical + startOffset, logical + offset)): + for rec in parse_command_buffer(data): if rec.state_info is not None: desc = self.format_state(rec.state_info.pos, rec.value, rec.state_info.format) else: |