diff --git a/linux-ramdump-parser-v2/boards.py b/linux-ramdump-parser-v2/boards.py index 70d20b8d6400337358fc5231f725dffd4584ebda..79c385f49f1e66e6a61788c434c3d8a56f4f3bad 100755 --- a/linux-ramdump-parser-v2/boards.py +++ b/linux-ramdump-parser-v2/boards.py @@ -401,6 +401,20 @@ class BoardCalifornium(Board): self.imem_file_name = 'OCIMEM.BIN' +class BoardCobalt(Board): + def __init__(self, socid): + super(BoardCobalt, self).__init__() + self.socid = socid + self.board_num = "cobalt" + self.cpu = 'CORTEXA53' + self.ram_start = 0x80000000 + self.smem_addr = 0x6000000 + self.phys_offset = 0x80000000 + self.imem_start = 0x14680000 + self.kaslr_addr = 0x146bf6d0 + self.wdog_addr = 0x146BF658 + self.imem_file_name = 'OCIMEM.BIN' + class Board8998(Board): def __init__(self, socid): super(Board8998, self).__init__() @@ -411,6 +425,33 @@ class Board8998(Board): self.smem_addr = 0x6000000 self.phys_offset = 0x80000000 self.imem_start = 0x14680000 + self.kaslr_addr = 0x146bf6d0 + self.wdog_addr = 0x146BF658 + self.imem_file_name = 'OCIMEM.BIN' + +class Board660(Board): + def __init__(self, socid): + super(Board660, self).__init__() + self.socid = socid + self.board_num = "660" + self.cpu = 'CORTEXA53' + self.ram_start = 0x80000000 + self.smem_addr = 0x6000000 + self.phys_offset = 0x80000000 + self.imem_start = 0x14680000 + self.wdog_addr = 0x146BF658 + self.imem_file_name = 'OCIMEM.BIN' + +class Board630(Board): + def __init__(self, socid): + super(Board630, self).__init__() + self.socid = socid + self.board_num = "630" + self.cpu = 'CORTEXA53' + self.ram_start = 0x80000000 + self.smem_addr = 0x6000000 + self.phys_offset = 0x80000000 + self.imem_start = 0x14680000 self.wdog_addr = 0x146BF658 self.imem_file_name = 'OCIMEM.BIN' @@ -613,8 +654,16 @@ boards.append(Board8920(socid=320)) boards.append(BoardCalifornium(socid=279)) +boards.append(BoardCobalt(socid=292)) boards.append(Board8998(socid=292)) +boards.append(Board660(socid=317)) +boards.append(Board660(socid=324)) +boards.append(Board660(socid=325)) +boards.append(Board660(socid=326)) + +boards.append(Board630(socid=318)) +boards.append(Board630(socid=327)) def get_supported_boards(): """ Called by other part of the code to get a list of boards """ diff --git a/linux-ramdump-parser-v2/cachedumplib.py b/linux-ramdump-parser-v2/cachedumplib.py index 2fc1c439607a5daa86790c959b9e14276ad8d251..d6568940a26e451978584a2a60658f8b70be809f 100755 --- a/linux-ramdump-parser-v2/cachedumplib.py +++ b/linux-ramdump-parser-v2/cachedumplib.py @@ -454,6 +454,43 @@ lookuptable[("8998", 0x65, 0x14)] = L1_ICache_KRYO2XX_GOLD() lookuptable[("8998", 0x66, 0x14)] = L1_ICache_KRYO2XX_GOLD() lookuptable[("8998", 0x67, 0x14)] = L1_ICache_KRYO2XX_GOLD() +# "sdm660" +lookuptable[("660", 0x80, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("660", 0x81, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("660", 0x82, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("660", 0x83, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("660", 0x84, 0x14)] = L1_DCache_KRYO2XX_GOLD() +lookuptable[("660", 0x85, 0x14)] = L1_DCache_KRYO2XX_GOLD() +lookuptable[("660", 0x86, 0x14)] = L1_DCache_KRYO2XX_GOLD() +lookuptable[("660", 0x87, 0x14)] = L1_DCache_KRYO2XX_GOLD() + +lookuptable[("660", 0x60, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("660", 0x61, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("660", 0x62, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("660", 0x63, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("660", 0x64, 0x14)] = L1_ICache_KRYO2XX_GOLD() +lookuptable[("660", 0x65, 0x14)] = L1_ICache_KRYO2XX_GOLD() +lookuptable[("660", 0x66, 0x14)] = L1_ICache_KRYO2XX_GOLD() +lookuptable[("660", 0x67, 0x14)] = L1_ICache_KRYO2XX_GOLD() + +# "sdm630" +lookuptable[("630", 0x80, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x81, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x82, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x83, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x84, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x85, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x86, 0x14)] = L1_DCache_KRYO2XX_SILVER() +lookuptable[("630", 0x87, 0x14)] = L1_DCache_KRYO2XX_SILVER() + +lookuptable[("630", 0x60, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x61, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x62, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x63, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x64, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x65, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x66, 0x14)] = L1_ICache_KYRO2XX_SILVER() +lookuptable[("630", 0x67, 0x14)] = L1_ICache_KYRO2XX_SILVER() # 8994 diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py index b6b3655926ee614384e910a0f315ae5dd3eef7ea..8d0e7b12a0dda3dbf16ee153041eaa6882df97c4 100755 --- a/linux-ramdump-parser-v2/debug_image_v2.py +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -335,9 +335,13 @@ class DebugImage_v2(): qtf_dir = os.path.join(out_dir, 'qtf') workspace = os.path.join(qtf_dir, 'qtf.workspace') qtf_out = os.path.join(out_dir, 'qtf.txt') - chipset = 'msm' + str(ram_dump.hw_id) + chipset = 'msm' + ram_dump.hw_id hlos = 'LA' + #Temp change to handle descripancy between tools usage + if chipset == 'msmcobalt': + chipset = 'msm8998' + # Resolve any port collisions with other running qtf_server instances for tries in range(max_tries): port = random.randint(12000, 13000) @@ -448,8 +452,7 @@ class DebugImage_v2(): 'msm_dump_table_ids', MAX_NUM_ENTRIES) self.dump_data_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( 'msm_dump_data_ids', MAX_NUM_ENTRIES) - cpu_present_bits = ram_dump.read_word('cpu_present_bits') - cpus = bin(cpu_present_bits).count('1') + cpus = ram_dump.get_num_cpus() # per cpu entries for i in range(1, cpus): diff --git a/linux-ramdump-parser-v2/parsers/cpr3_info.py b/linux-ramdump-parser-v2/parsers/cpr3_info.py index ca5d9ddf472c73945a904408f1bb9ad753790d20..3f0be291fd8be868fddc4b8d6db41acc46d26b2b 100644 --- a/linux-ramdump-parser-v2/parsers/cpr3_info.py +++ b/linux-ramdump-parser-v2/parsers/cpr3_info.py @@ -430,9 +430,19 @@ class CPR3Info(RamParser): else: cpr_mode = "closed-loop" - tmp = "" - if cpr_controller_name is None: + thread_addr = self.ramdump.read_word( + ctrl_addr + + self.ramdump.field_offset( + 'struct cpr3_controller', 'thread')) + if thread_addr is None: return + thread_ctrl_addr = self.ramdump.read_word( + thread_addr + + self.ramdump.field_offset('struct cpr3_thread', 'ctrl')) + + if cpr_controller_name is None or thread_ctrl_addr != ctrl_addr: + return + tmp = "" tmp += "=" * 80 + "\n" tmp += 'CPR3 controller state: %s\n' % cpr_controller_name tmp += "=" * 80 + "\n" @@ -464,10 +474,6 @@ class CPR3Info(RamParser): self.output.append("\nCPR aggregated voltages:\n") self.dump_cpr3_corner_info(aggr_corner_addr, 0, 0, 0) - thread_addr = self.ramdump.read_word( - ctrl_addr + - self.ramdump.field_offset( - 'struct cpr3_controller', 'thread')) thread_count = self.ramdump.read_int( ctrl_addr + self.ramdump.field_offset( diff --git a/linux-ramdump-parser-v2/parsers/irqstate.py b/linux-ramdump-parser-v2/parsers/irqstate.py index b9f8d3e754e8a5683c688bde66651a3c531f3a14..66215d42ec56054c6a596021eab924f064e66744 100755 --- a/linux-ramdump-parser-v2/parsers/irqstate.py +++ b/linux-ramdump-parser-v2/parsers/irqstate.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -20,9 +20,7 @@ class IrqParse(RamParser): print_out_str( '=========================== IRQ STATE ===============================') per_cpu_offset_addr = ram_dump.address_of('__per_cpu_offset') - cpu_present_bits_addr = ram_dump.address_of('cpu_present_bits') - cpu_present_bits = ram_dump.read_word(cpu_present_bits_addr) - cpus = bin(cpu_present_bits).count('1') + cpus = ram_dump.get_num_cpus() irq_desc = ram_dump.address_of('irq_desc') foo, irq_desc_size = ram_dump.unwind_lookup(irq_desc, 1) h_irq_offset = ram_dump.field_offset('struct irq_desc', 'handle_irq') @@ -72,6 +70,50 @@ class IrqParse(RamParser): print_out_str( '{0:4} {1} {2:30} {3:10}'.format(irqnum, irq_stats_str, name, chip_name)) + def shift_to_maxindex(self, shift): + radix_tree_map_shift = 6 + radix_tree_map_size = 1 << radix_tree_map_shift + return (radix_tree_map_size << shift) - 1 + + def is_internal_node(self, addr): + radix_tree_entry_mask = 0x3 + radix_tree_internal_node = 0x1 + return (addr & radix_tree_entry_mask) == radix_tree_internal_node + + def entry_to_node(self, addr): + return addr & 0xfffffffffffffffe + + def radix_tree_lookup_element_v2(self, ram_dump, root_addr, index): + rnode_offset = ram_dump.field_offset('struct radix_tree_root', 'rnode') + rnode_shift_offset = ram_dump.field_offset('struct radix_tree_node', 'shift') + slots_offset = ram_dump.field_offset('struct radix_tree_node', 'slots') + pointer_size = ram_dump.sizeof('struct radix_tree_node *') + maxindex = 0 + # if CONFIG_BASE_SMALL=0: radix_tree_map_shift = 6 + radix_tree_map_shift = 6 + radix_tree_map_mask = 0x3f + + rnode_addr = ram_dump.read_word(root_addr + rnode_offset) + if self.is_internal_node(rnode_addr): + node_addr = self.entry_to_node(rnode_addr) + shift = ram_dump.read_byte(node_addr + rnode_shift_offset) + maxindex = self.shift_to_maxindex(shift) + + if index > maxindex: + return None + + while self.is_internal_node(rnode_addr): + parent_addr = self.entry_to_node(rnode_addr) + parent_shift = ram_dump.read_byte(parent_addr + rnode_shift_offset) + offset = (index >> parent_shift) & radix_tree_map_mask + rnode_addr = ram_dump.read_word(parent_addr + slots_offset + + (offset * pointer_size)) + + if rnode_addr is 0: + return None + + return rnode_addr + def radix_tree_lookup_element(self, ram_dump, root_addr, index): rnode_offset = ram_dump.field_offset('struct radix_tree_root', 'rnode') if (ram_dump.kernel_version[0], ram_dump.kernel_version[1]) >= (3, 18): @@ -142,11 +184,19 @@ class IrqParse(RamParser): if nr_irqs > 50000: return + major, minor, patch = ram_dump.kernel_version for i in range(0, nr_irqs): - irq_desc = self.radix_tree_lookup_element( - ram_dump, irq_desc_tree, i) + + if (major, minor) >= (4, 9): + irq_desc = self.radix_tree_lookup_element_v2( + ram_dump, irq_desc_tree, i) + else: + irq_desc = self.radix_tree_lookup_element( + ram_dump, irq_desc_tree, i) + if irq_desc is None: continue + irqnum = ram_dump.read_int(irq_desc + irq_data_offset + irq_num_offset) irqcount = ram_dump.read_int(irq_desc + irq_count_offset) action = ram_dump.read_word(irq_desc + irq_action_offset) diff --git a/linux-ramdump-parser-v2/parsers/rtb.py b/linux-ramdump-parser-v2/parsers/rtb.py index 602012d80005ce9b72f56515dd176d4df25553de..ca1b770bff3386867075fff42fb8ea47683e0f37 100755 --- a/linux-ramdump-parser-v2/parsers/rtb.py +++ b/linux-ramdump-parser-v2/parsers/rtb.py @@ -17,10 +17,11 @@ from parser_util import register_parser, RamParser # struct msm_rtb_layout { # unsigned char sentinel[3]; # unsigned char log_type; -# void *caller; # unsigned long idx; +# void *caller; # void *data; -# void *time +# void *timestamp; +# void *cycle_count; #} __attribute__ ((__packed__)); print_table = { @@ -63,6 +64,12 @@ class RTB(RamParser): timestamp = format(timestamp,'.6f') return timestamp + def get_cycle_count(self, rtb_ptr): + cycle_count = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'cycle_count') + if cycle_count == None: + return 0 + return cycle_count + def print_none(self, rtbout, rtb_ptr, logtype): rtbout.write('{0} No data\n'.format(logtype).encode('ascii', 'ignore')) @@ -82,8 +89,9 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} from address {2:x}({3}) called from addr {4:x} {5} {6}\n'.format( - timestamp, logtype, data, physical, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} from address {3:x}({4}) called from addr {5:x} {6} {7}\n'.format( + timestamp, cycle_count, logtype, data, physical, caller, func, line).encode('ascii', 'ignore')) def print_logbuf(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') @@ -91,8 +99,9 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} log end {2:x} called from addr {3:x} {4} {5}\n'.format( - timestamp, logtype, data, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} log end {3:x} called from addr {4:x} {5} {6}\n'.format( + timestamp, cycle_count, logtype, data, caller, func, line).encode('ascii', 'ignore')) def print_hotplug(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') @@ -100,8 +109,9 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} cpu data {2:x} called from addr {3:x} {4} {5}\n'.format( - timestamp, logtype, data, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} cpu data {3:x} called from addr {4:x} {5} {6}\n'.format( + timestamp, cycle_count, logtype, data, caller, func, line).encode('ascii', 'ignore')) def print_ctxid(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') @@ -109,14 +119,16 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} context id {2:x} called from addr {3:x} {4} {5}\n'.format( - timestamp, logtype, data, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} context id {3:x} called from addr {4:x} {5} {6}\n'.format( + timestamp, cycle_count, logtype, data, caller, func, line).encode('ascii', 'ignore')) def print_timestamp(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') caller = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'caller') - rtbout.write('[{0}] Timestamp: {1:x}{2:x}\n'.format( - logtype, data, caller).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] : [{1}] Timestamp: {2:x}{3:x}\n'.format( + cycle_count, logtype, data, caller).encode('ascii', 'ignore')) def print_cp_rw(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') @@ -124,8 +136,9 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} from offset {2:x} called from addr {3:x} {4} {5}\n'.format( - timestamp, logtype, data, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} from offset {3:x} called from addr {4:x} {5} {6}\n'.format( + timestamp, cycle_count, logtype, data, caller, func, line).encode('ascii', 'ignore')) def print_irq(self, rtbout, rtb_ptr, logtype): data = self.ramdump.read_structure_field(rtb_ptr, 'struct msm_rtb_layout', 'data') @@ -133,8 +146,9 @@ class RTB(RamParser): func = self.get_fun_name(caller) line = self.get_caller(caller) timestamp = self.get_timestamp(rtb_ptr) - rtbout.write('[{0}] : {1} interrupt {2:x} handled from addr {3:x} {4} {5}\n'.format( - timestamp, logtype, data, caller, func, line).encode('ascii', 'ignore')) + cycle_count = self.get_cycle_count(rtb_ptr) + rtbout.write('[{0}] [{1}] : {2} interrupt {3:x} handled from addr {4:x} {5} {6}\n'.format( + timestamp, cycle_count, logtype, data, caller, func, line).encode('ascii', 'ignore')) def next_rtb_entry(self, index, step_size, mask): unused_buffer_size = (mask + 1) % step_size diff --git a/linux-ramdump-parser-v2/parsers/slabinfo.py b/linux-ramdump-parser-v2/parsers/slabinfo.py index 460c08ea5cc108e9dd060dc098c8a1d028180707..e65fb1504c95cc409ba78f931414868eff9a9fa1 100644 --- a/linux-ramdump-parser-v2/parsers/slabinfo.py +++ b/linux-ramdump-parser-v2/parsers/slabinfo.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -284,9 +284,7 @@ class Slabinfo(RamParser): def validate_slab_cache(self, slab_out, input_slabname, map_fn): slab_name_found = False original_slab = self.ramdump.address_of('slab_caches') - cpu_present_bits_addr = self.ramdump.address_of('cpu_present_bits') - cpu_present_bits = self.ramdump.read_word(cpu_present_bits_addr) - cpus = bin(cpu_present_bits).count('1') + cpus = self.ramdump.get_num_cpus() offsetof = struct_member_offset(self.ramdump) self.initializeOffset() slab_list_offset = g_offsetof.kmemcache_list diff --git a/linux-ramdump-parser-v2/parsers/slabsummary.py b/linux-ramdump-parser-v2/parsers/slabsummary.py index 34b43dc496f544a81a855ea6370c0cdba9d955a8..abe47dc90570ab320d1e25775b6e0fa12163187a 100644 --- a/linux-ramdump-parser-v2/parsers/slabsummary.py +++ b/linux-ramdump-parser-v2/parsers/slabsummary.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -10,7 +10,7 @@ # GNU General Public License for more details. import math - +import operator from mm import pfn_to_page from parser_util import register_parser, RamParser @@ -55,10 +55,10 @@ class Slabinfo_summary(RamParser): # Currently with assumption there is only one numa node def print_slab_summary(self, slab_out): total_freeobjects = 0 + slab_summary = {} + nCounter = 0 original_slab = self.ramdump.address_of('slab_caches') - cpu_present_bits_addr = self.ramdump.address_of('cpu_present_bits') - cpu_present_bits = self.ramdump.read_word(cpu_present_bits_addr) - cpus = bin(cpu_present_bits).count('1') + cpus = self.ramdump.get_num_cpus() slab_list_offset = self.ramdump.field_offset( 'struct kmem_cache', 'list') slab_name_offset = self.ramdump.field_offset( @@ -130,11 +130,18 @@ class Slabinfo_summary(RamParser): slab_size = int(math.pow(2, page_order + PAGE_SHIFT)) slab_size = slab_size / 1024 slab = self.ramdump.read_word(slab + slab_list_offset) + slab_summary[nCounter] = [ + slab_name, obj_size, + total_allocated, nr_total_objects, + (objsize_w_metadata * nr_total_objects)/1024, + num_slabs, slab_size] + nCounter += 1 + sorted_summary = sorted(slab_summary.values(), + key=operator.itemgetter(4), reverse=True) + for val in sorted_summary: slab_out.write(format_string.format( - slab_name, obj_size, total_allocated, - nr_total_objects, - (objsize_w_metadata * nr_total_objects)/1024, - num_slabs, slab_size)) + val[0], val[1], val[2], val[3], val[4], + val[5], val[6])) def parse(self): slab_out = self.ramdump.open_file('slabsummary.txt') diff --git a/linux-ramdump-parser-v2/parsers/timerlist.py b/linux-ramdump-parser-v2/parsers/timerlist.py index c1b7318bd7cbc147bf3766f51a9bec9af0797327..80510a01f43caa7044c5b4751280b22bd9e109d9 100755 --- a/linux-ramdump-parser-v2/parsers/timerlist.py +++ b/linux-ramdump-parser-v2/parsers/timerlist.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -99,6 +99,34 @@ class TimerList(RamParser) : def get_timer_list(self): self.output_file.write("Timer List Dump\n\n") + tvec_base_deferral_addr = self.ramdump.address_of('tvec_base_deferrable') + if tvec_base_deferral_addr: + timer_jiffies_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'timer_jiffies') + next_timer_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'next_timer') + + timer_jiffies = self.ramdump.read_word(timer_jiffies_addr) + next_timer = self.ramdump.read_word(next_timer_addr) + active_timers_offset = self.ramdump.field_offset('struct tvec_base', 'active_timers') + if active_timers_offset is not None: + active_timers_addr = tvec_base_deferral_addr + self.ramdump.field_offset('struct tvec_base', 'active_timers') + active_timers = self.ramdump.read_word(active_timers_addr) + else: + active_timers = "NA" + + title = "(deferrable_base: {0:x} ".format(tvec_base_deferral_addr) + title += "timer_jiffies: {0} next_timer: {1} active_timers: {2})\n".format(timer_jiffies, next_timer, active_timers) + self.output_file.write("-" * len(title) + "\n") + self.output_file.write(title) + self.output_file.write("-" * len(title) + "\n\n") + + for vec in sorted(self.vectors): + self.output = [] + if self.timer_42: + self.iterate_vec_v2(vec, tvec_base_deferral_addr) + else: + self.iterate_vec(vec, tvec_base_deferral_addr) + self.print_vec(vec) + tvec_bases_addr = self.ramdump.address_of('tvec_bases') for cpu in range(0, self.ramdump.get_num_cpus()): diff --git a/linux-ramdump-parser-v2/parsers/workqueue.py b/linux-ramdump-parser-v2/parsers/workqueue.py index 21c7b920fb72f79a9c3aa65598684d2783e42331..86e23124cb24216a6877879e1893188088b2f040 100644 --- a/linux-ramdump-parser-v2/parsers/workqueue.py +++ b/linux-ramdump-parser-v2/parsers/workqueue.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2015, 2017 The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -212,9 +212,7 @@ class Workqueues(RamParser): worker_pool_size = ram_dump.sizeof('struct worker_pool') pending_work_offset = ram_dump.field_offset( 'struct worker_pool', 'worklist') - cpu_present_bits_addr = ram_dump.address_of('cpu_present_bits') - cpu_present_bits = ram_dump.read_word(cpu_present_bits_addr) - cpus = bin(cpu_present_bits).count('1') + cpus = ram_dump.get_num_cpus() s = '<' for a in range(0, 64): diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py index a4a7bf1d9724698c81ccee86576f0324be89f1a0..289b850cde1e491610f1cf7cf64e97879c37c92d 100755 --- a/linux-ramdump-parser-v2/ramdump.py +++ b/linux-ramdump-parser-v2/ramdump.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -547,6 +547,12 @@ class RamDump(): self.ebi_start = self.ebi_files[0][1] if self.phys_offset is None: self.get_hw_id() + + if self.kaslr_offset is None: + self.get_kaslr_offset() + if self.kaslr_offset is not None: + self.gdbmi.kaslr_offset = self.kaslr_offset + if options.phys_offset is not None: print_out_str( '[!!!] Phys offset was set to {0:x}'.format(\ @@ -577,7 +583,8 @@ class RamDump(): self.kimage_vaddr = self.va_start + self.kasan_shadow_size + \ modules_vsize - + if self.kaslr_offset is not None: + self.kimage_vaddr = self.kimage_vaddr + self.kaslr_offset self.modules_end = self.page_offset self.kimage_voffset = self.address_of("kimage_voffset") if self.kimage_voffset is not None: @@ -803,7 +810,7 @@ class RamDump(): return False def create_t32_launcher(self): - out_path = self.outdir + out_path = os.path.abspath(self.outdir) t32_host_system = self.t32_host_system or platform.system() @@ -822,10 +829,14 @@ class RamDump(): launch_config.write('PBI=SIM\n') launch_config.write('\n') launch_config.write('SCREEN=\n') - launch_config.write('FONT=SMALL\n') + if t32_host_system != 'Linux': + launch_config.write('FONT=SMALL\n') + else: + launch_config.write('FONT=LARGE\n') launch_config.write('HEADER=Trace32-ScorpionSimulator\n') launch_config.write('\n') - launch_config.write('PRINTER=WINDOWS\n') + if t32_host_system != 'Linux': + launch_config.write('PRINTER=WINDOWS\n') launch_config.write('\n') launch_config.write('RCL=NETASSIST\n') launch_config.write('PACKLEN=1024\n') @@ -927,7 +938,8 @@ class RamDump(): startup_script.close() if t32_host_system != 'Linux': - t32_bat = open(out_path + '/launch_t32.bat', 'wb') + launch_file = os.path.join(out_path, 'launch_t32.bat') + t32_bat = open(launch_file, 'wb') if self.arm64: t32_binary = 'C:\\T32\\bin\\windows64\\t32MARM64.exe' elif is_cortex_a53: @@ -936,22 +948,23 @@ class RamDump(): t32_binary = 'c:\\t32\\t32MARM.exe' t32_bat.write(('start '+ t32_binary + ' -c ' + out_path + '/t32_config.t32, ' + out_path + '/t32_startup_script.cmm').encode('ascii', 'ignore')) + t32_bat.close() else: - t32_bat = open(out_path + '/launch_t32.sh', 'wb') + launch_file = os.path.join(out_path, 'launch_t32.sh') + t32_sh = open(launch_file, 'wb') if self.arm64: t32_binary = '/opt/t32/bin/pc_linux64/t32marm64-qt' elif is_cortex_a53: t32_binary = '/opt/t32/bin/pc_linux64/t32marm-qt' else: t32_binary = '/opt/t32/bin/pc_linux64/t32marm-qt' - t32_bat.write('#!/bin/sh\n\n') - t32_bat.write('cd $(dirname $0)\n') - t32_bat.write('{} -c t32_config.t32, t32_startup_script.cmm &\n'.format(t32_binary)) - os.chmod(out_path + '/launch_t32.sh', stat.S_IRWXU) + t32_sh.write('#!/bin/sh\n\n') + t32_sh.write('{0} -c {1}/t32_config.t32, {1}/t32_startup_script.cmm &\n'.format(t32_binary, out_path)) + t32_sh.close() + os.chmod(launch_file, stat.S_IRWXU) - t32_bat.close() print_out_str( - '--- Created a T32 Simulator launcher (run {0}/launch_t32.bat)'.format(out_path)) + '--- Created a T32 Simulator launcher (run {})'.format(launch_file)) def read_tz_offset(self): if self.tz_addr == 0: @@ -961,6 +974,18 @@ class RamDump(): else: return self.read_word(self.tz_addr, False) + def get_kaslr_offset(self): + if(self.kaslr_addr is None): + print_out_str('!!!! Kaslr addr is not provided.') + else: + kaslr_magic = self.read_u32(self.kaslr_addr, False) + if kaslr_magic != 0xdead4ead: + print_out_str('!!!! Kaslr magic does not match.') + self.kaslr_offset = None + else: + self.kaslr_offset = self.read_u64(self.kaslr_addr + 4, False) + print_out_str("The kaslr_offset extracted is: " + str(hex(self.kaslr_offset))) + def get_hw_id(self, add_offset=True): socinfo_format = -1 socinfo_id = -1 @@ -1047,6 +1072,10 @@ class RamDump(): self.hw_id = board.board_num self.cpu_type = board.cpu self.imem_fname = board.imem_file_name + if hasattr(board, 'kaslr_addr'): + self.kaslr_addr = board.kaslr_addr + else: + self.kaslr_addr = None return True def resolve_virt(self, virt_or_name): @@ -1370,8 +1399,14 @@ class RamDump(): def get_num_cpus(self): """Gets the number of CPUs in the system.""" + major, minor, patch = self.kernel_version cpu_present_bits_addr = self.address_of('cpu_present_bits') cpu_present_bits = self.read_word(cpu_present_bits_addr) + + if (major, minor) >= (4, 5): + cpu_present_bits_addr = self.address_of('__cpu_present_mask') + bits_offset = self.field_offset('struct cpumask', 'bits') + cpu_present_bits = self.read_word(cpu_present_bits_addr + bits_offset) return bin(cpu_present_bits).count('1') def iter_cpus(self): diff --git a/linux-ramdump-parser-v2/watchdog_v2.py b/linux-ramdump-parser-v2/watchdog_v2.py index dba99d615f277bc521011a4f76643fce2c763767..c9e856e8513de3c531534ae985cd0a2777c9d9cd 100755 --- a/linux-ramdump-parser-v2/watchdog_v2.py +++ b/linux-ramdump-parser-v2/watchdog_v2.py @@ -15,6 +15,7 @@ import re from scandump_reader import Scandump_v2 from print_out import print_out_str from bitops import is_set +from parser_util import register_parser, RamParser # name from tz dump, corresponding T32 register, whether or not to # print_out_str (the function name) @@ -836,3 +837,48 @@ class TZRegDump_v2(): self.sec_regs = TZCpuCtx_v2(self.version, sc_secure, self.neon_regs, ram_dump) return True + + +@register_parser('--watchdog', 'Extracts NS Watchdog related info') +class Watchdog(RamParser): + def parse(self): + get_wdog_timing(self.ramdump) + + +def get_wdog_timing(ramdump): + jiffies = ramdump.read_word('jiffies') + last_jiffies_update = ramdump.read_word('last_jiffies_update') + tick_do_timer_cpu = ramdump.read_word('tick_do_timer_cpu') + wdog_data_addr = ramdump.read_word('wdog_data') + pet_timer_off = ramdump.field_offset( + 'struct msm_watchdog_data', 'pet_timer') + timer_expires_off = ramdump.field_offset('struct timer_list', 'expires') + pet_timer_expires = ramdump.read_word( + wdog_data_addr + pet_timer_off + timer_expires_off) + last_pet_off = ramdump.field_offset('struct msm_watchdog_data', 'last_pet') + wdog_last_pet = ramdump.read_word(wdog_data_addr + last_pet_off) + timer_expired_off = ramdump.field_offset( + 'struct msm_watchdog_data', 'timer_expired') + pet_timer_expired = ramdump.read_word(wdog_data_addr + timer_expired_off) + pet_time_off = ramdump.field_offset('struct msm_watchdog_data', 'pet_time') + bark_time_off = ramdump.field_offset( + 'struct msm_watchdog_data', 'bark_time') + pet_time = ramdump.read_int(wdog_data_addr + pet_time_off) + bark_time = ramdump.read_int(wdog_data_addr + bark_time_off) + print_out_str('Non-secure Watchdog data') + print_out_str('Pet time: {0}s'.format(pet_time/1000.0)) + print_out_str('Bark time: {0}s'.format(bark_time/1000.0)) + print_out_str('Watchdog last pet: {0}'.format(wdog_last_pet/1000000000.0)) + if pet_timer_expired == 1: + print_out_str('Watchdog pet timer expired') + else: + print_out_str('Watchdog pet timer not expired') + if jiffies > pet_timer_expires: + print_out_str('Current jiffies crossed pet_timer expires jiffies') + print_out_str('pet_timer_expires: {0}'.format(pet_timer_expires)) + print_out_str('Current jiffies : {0}'.format(jiffies)) + print_out_str( + 'Timestamp of last timer interrupt(last_jiffies_update): {0}'.format( + last_jiffies_update/1000000000.0)) + print_out_str('Core which updates jiffies(tick_do_timer_cpu): {0}'.format( + tick_do_timer_cpu))