scripts/symbolize.py: print ELF sections after MMU region information

When processing a user TA abort dump, list the ELF sections that are
mapped in each MMU region. For example (the lines modified by this
patch are prefixed with >>):

   User TA undef-abort at address 0x10574e
    fsr 0x00000000  ttbr0 0x0e07a06a  ttbr1 0x0e07406a  cidr 0x1
    cpu #0          cpsr 0x60000030
    r0 0x20000013      r4 0x0013a6bc    r8 0x00000000   r12 0x0e07dd88
    r1 0x00000033      r5 0x00121fd3    r9 0x00000000    sp 0x001026cc
    r2 0x0010581f      r6 0x00102590   r10 0x00000000    lr 0x00105823
    r3 0x00000043      r7 0x001026cc   r11 0x00000000    pc 0x0010574e
   Status of TA 5b9e0e40-2636-11e1-ad9e-0002a5d5c51b (0xe073b70) (active)
    arch: arm  load address: 0x103000  ctx-idr: 1
    stack: 0x100000 10240
    region 0: va 0x100000 pa 0xe21e000 size 0x3000 flags rw-
>>  region 1: va 0x103000 pa 0xe100000 size 0x2e000 flags r-x .ta_head .text .rodata
>>  region 2: va 0x131000 pa 0xe12e000 size 0xa000 flags r-- .rodata .ARM.extab .ARM.exidx .got .dynsym .rel.got .dynamic .dynstr .hash .rel.dyn
>>  region 3: va 0x13b000 pa 0xe138000 size 0xe6000 flags rw- .data .bss
    region 4: va 0 pa 0 size 0 flags ---
    region 5: va 0 pa 0 size 0 flags ---
    region 6: va 0 pa 0 size 0 flags ---
    region 7: va 0 pa 0 size 0 flags ---
   User TA undef-abort at address 0x10574e undef_instr+6 .text+10030
   Call stack:
    0x0010574e undef_instr at optee_test/ta/os_test/os_test.c:880
    0x00105823 ta_entry_bad_mem_access at optee_test/ta/os_test/os_test.c:917
    0x00105e75 TA_InvokeCommandEntryPoint at optee_test/ta/os_test/ta_entry.c:101
    0x00121fb7 entry_invoke_command at optee_os/lib/libutee/arch/arm/user_ta_entry.c:207
    0x00122013 __utee_entry at optee_os/lib/libutee/arch/arm/user_ta_entry.c:235

Suggested-by: Zeng Tao <prime.zeng@hisilicon.com>
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/scripts/symbolize.py b/scripts/symbolize.py
index 9599b6f..772ba2e 100755
--- a/scripts/symbolize.py
+++ b/scripts/symbolize.py
@@ -40,6 +40,8 @@
 CALL_STACK_RE = re.compile('Call stack:')
 STACK_ADDR_RE = re.compile(r':  (?P<addr>0x[0-9a-f]+)')
 ABORT_ADDR_RE = re.compile('-abort at address (?P<addr>0x[0-9a-f]+)')
+REGION_RE = re.compile('region [0-9]+: va (?P<addr>0x[0-9a-f]+) '
+                       'pa 0x[0-9a-f]+ size (?P<size>0x[0-9a-f]+)')
 
 epilog = '''
 This scripts reads an OP-TEE abort message from stdin and adds debug
@@ -157,7 +159,7 @@
         cmd = self.arch_prefix('nm')
         if not reladdr or not elf or not cmd:
             return ''
-        ireladdr = int(reladdr, 0)
+        ireladdr = int(reladdr, 16)
         nm = subprocess.Popen([cmd, '--numeric-sort', '--print-size', elf],
                                stdin = subprocess.PIPE,
                                stdout = subprocess.PIPE)
@@ -193,7 +195,7 @@
         cmd = self.arch_prefix('objdump')
         if not reladdr or not elf or not cmd:
             return ''
-        iaddr = int(reladdr, 0)
+        iaddr = int(reladdr, 16)
         objdump = subprocess.Popen([cmd, '--section-headers', elf],
                                     stdin = subprocess.PIPE,
                                     stdout = subprocess.PIPE)
@@ -232,6 +234,44 @@
             ret += line[post:]
         return ret
 
+    # Return all ELF sections with the ALLOC flag
+    def read_sections(self):
+        if self._sections:
+            return
+        elf = self.get_elf(self._bin)
+        cmd = self.arch_prefix('objdump')
+        if not elf or not cmd:
+            return
+        objdump = subprocess.Popen([cmd, '--section-headers', elf],
+                                    stdin = subprocess.PIPE,
+                                    stdout = subprocess.PIPE)
+        for line in iter(objdump.stdout.readline, ''):
+            try:
+                _, name, size, vma, _, _, _ = line.split()
+            except:
+                if 'ALLOC' in line:
+                    self._sections.append([name, int(vma, 16), int(size, 16)])
+
+    def overlaps(self, section, addr, size):
+        sec_addr = section[1]
+        sec_size = section[2]
+        if not size or not sec_size:
+            return False
+        return (addr <= (sec_addr + sec_size - 1)) and ((addr + size - 1) >= sec_addr)
+
+    def sections_in_region(self, addr, size):
+        ret = ''
+        addr = self.subtract_load_addr(addr)
+        if not addr:
+            return ''
+        iaddr = int(addr, 16)
+        isize = int(size, 16)
+        self.read_sections()
+        for s in self._sections:
+            if self.overlaps(s, iaddr, isize):
+                ret += ' ' + s[0]
+        return ret
+
     def reset(self):
         self._call_stack_found = False
         self._load_addr = '0'
@@ -240,6 +280,7 @@
             self._addr2line = None
         self._arch = None
         self._saved_abort_line = ''
+        self._sections = []
 
     def write(self, line):
             if self._call_stack_found:
@@ -259,6 +300,13 @@
                     return
                 else:
                     self.reset()
+            match = re.search(REGION_RE, line)
+            if match:
+                addr = match.group('addr')
+                size = match.group('size')
+                self._out.write(line.strip() +
+                                self.sections_in_region(addr, size) + '\n');
+                return
             match = re.search(CALL_STACK_RE, line)
             if match:
                 self._call_stack_found = True