From 3f3ce9a46b350ee77bc70c2ca10745e8b7f29191 Mon Sep 17 00:00:00 2001
From: Kumar Harsh <harkumar@codeaurora.org>
Date: Thu, 1 Nov 2018 15:14:31 +0530
Subject: [PATCH] ldrp_V2 : Format event log data

This change formats the event log data. Timestamp is
converted to secs format. Since event log buffer is
circular in nature, added changes to sort the logs
in ascending timestamp order.

Any truncated log string is removed and not added
to the final output. Error handling is added in case
event zone is not part of persistent ram zone so
atleast console logs are extracted properly.

Change-Id: Id284df1646872b179e1cdfd3fe9ee68e7397c398
Signed-off-by: Kumar Harsh <harkumar@codeaurora.org>
---
 linux-ramdump-parser-v2/parsers/pstore.py | 81 +++++++++++++++++++----
 1 file changed, 67 insertions(+), 14 deletions(-)

diff --git a/linux-ramdump-parser-v2/parsers/pstore.py b/linux-ramdump-parser-v2/parsers/pstore.py
index d05cfef..70858f2 100644
--- a/linux-ramdump-parser-v2/parsers/pstore.py
+++ b/linux-ramdump-parser-v2/parsers/pstore.py
@@ -12,31 +12,82 @@
 from parser_util import cleanupString
 from parser_util import register_parser, RamParser
 from print_out import print_out_str
+import re
+import collections
 
 @register_parser('--pstore', 'Extract event logs from pstore')
 class PStore(RamParser):
 
     def calculate_percpu_eventbuf_size(self, base_addr):
-        event_zone_addr = self.ramdump.read_u64(base_addr +
-                          (self.ramdump.field_offset('struct ramoops_context', 'eprzs')))
-        event_zone_addr = self.ramdump.read_u64(event_zone_addr)
-        start_addr = self.ramdump.read_u32(event_zone_addr +
-                     (self.ramdump.field_offset('struct persistent_ram_zone', 'paddr')))
-        percpu_size = self.ramdump.read_u32(event_zone_addr +
-                      (self.ramdump.field_offset('struct persistent_ram_zone', 'size')))
+        try:
+            event_zone_addr = self.ramdump.read_u64(base_addr +
+                              self.ramdump.field_offset('struct ramoops_context', 'eprzs'))
+            event_zone_addr = self.ramdump.read_u64(event_zone_addr)
+            start_addr = self.ramdump.read_u32(event_zone_addr +
+                         self.ramdump.field_offset('struct persistent_ram_zone', 'paddr'))
+            percpu_size = self.ramdump.read_u32(event_zone_addr +
+                          self.ramdump.field_offset('struct persistent_ram_zone', 'size'))
+        except:
+            return None, None
         return start_addr, percpu_size
 
-    def print_pstore(self, pstore_out, addr, size):
+    def print_console_logs(self, pstore_out, addr, size):
         pstore = self.ramdump.read_physical(addr, size)
         pstore_out.write(cleanupString(pstore.decode('ascii', 'ignore')) + '\n')
 
+    def sort_event_data(self, event_data, pstore_out):
+        '''
+        Event log buffer is circular, so this function
+        sorts the logs in ascending timestamp manner
+        '''
+        ordered_event_data = collections.OrderedDict(sorted(event_data.items()))
+        for ts, log in ordered_event_data.iteritems():
+            pstore_out.write(log)
+
+    def print_event_logs(self, pstore_out, addr, size):
+        '''
+        This function tries to format the event logs before logging them to
+        the core specific rtb file. Raw Data will be in the format given below
+        io_read: type=readl cpu=1 ts:58270610802 data=0xffffff8009de8614
+                 caller=qcom_geni_serial_start_tx+0x114/0x150
+        io_write: type=writel cpu=1 ts:58270618875 data=0xffffff8009de880c
+                 caller=qcom_geni_serial_start_tx+0x130/0x150
+
+        Timestamp is extracted from raw data and converted to secs format and cpu
+        field is removed since it is redundant.
+
+        Final Formatting will be as shown below
+        [644.279442] io_write : writel from address 0xffffff8009673120(None) called
+                     from qcom_cpufreq_hw_target_index+0x60/0x64
+        '''
+        pstore = self.ramdump.read_physical(addr, size)
+        event_log_data = cleanupString(pstore.decode('ascii', 'ignore'))
+        event_data = event_log_data.split('\n')
+        formatted_event_data = {}
+        for line in event_data:
+            expr = r'.*(io_.*):.*type=(.*)cpu=(.*)ts:(.*)data=(.*)caller=(.*).*'
+            regEx = re.search(expr, line)
+            if regEx:
+                event_type = regEx.group(2).strip()
+                timestamp = regEx.group(4).strip()
+                timestamp = round(float(timestamp)/10**9,9)
+                timestamp = format(timestamp,'.9f')
+                data = regEx.group(5).strip()
+                caller = regEx.group(6).strip()
+                log_string = "[{0}] {1} : {2} from address {3} called from {4}\n".format(timestamp,
+                              regEx.group(1), event_type, data, caller)
+                formatted_event_data[timestamp] = log_string
+            else:
+                continue
+        self.sort_event_data(formatted_event_data, pstore_out)
+
     def calculate_console_size(self, base_addr):
         console_zone_addr = self.ramdump.read_u64(base_addr +
-                            (self.ramdump.field_offset('struct ramoops_context', 'cprz')))
+                            self.ramdump.field_offset('struct ramoops_context', 'cprz'))
         start_addr = self.ramdump.read_u32(console_zone_addr +
-                     (self.ramdump.field_offset('struct persistent_ram_zone', 'paddr')))
+                     self.ramdump.field_offset('struct persistent_ram_zone', 'paddr'))
         console_size = self.ramdump.read_u32(console_zone_addr +
-                       (self.ramdump.field_offset('struct persistent_ram_zone', 'size')))
+                       self.ramdump.field_offset('struct persistent_ram_zone', 'size'))
         return start_addr, console_size
 
     def extract_console_logs(self, base_addr):
@@ -45,7 +96,7 @@ class PStore(RamParser):
         '''
         start_addr, console_size = self.calculate_console_size(base_addr)
         pstore_out = self.ramdump.open_file('console_logs.txt')
-        self.print_pstore(pstore_out, start_addr, console_size)
+        self.print_console_logs(pstore_out, start_addr, console_size)
         pstore_out.close()
 
     def extract_io_event_logs(self, base_addr):
@@ -55,11 +106,13 @@ class PStore(RamParser):
         files.
         '''
         start_addr, percpu_size = self.calculate_percpu_eventbuf_size(base_addr)
+        if start_addr is None:
+            return
         nr_cpus = self.ramdump.get_num_cpus()
         for cpu in range(0,nr_cpus):
-            pstore_out = self.ramdump.open_file('rtb_core_{}.txt'.format(cpu))
+            pstore_out = self.ramdump.open_file('msm_rtb{0}.txt'.format(cpu))
             cpu_offset = percpu_size*cpu
-            self.print_pstore(pstore_out, start_addr+cpu_offset, percpu_size)
+            self.print_event_logs(pstore_out, start_addr+cpu_offset, percpu_size)
             pstore_out.close()
 
     def parse(self):
-- 
GitLab