diff --git a/linux-ramdump-parser-v2/iommulib.py b/linux-ramdump-parser-v2/iommulib.py
new file mode 100644
index 0000000000000000000000000000000000000000..fc941e20e5bd4ab73aa84f19c62a300015b7991a
--- /dev/null
+++ b/linux-ramdump-parser-v2/iommulib.py
@@ -0,0 +1,107 @@
+# Copyright (c) 2014, 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
+# only version 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+import rb_tree
+import linux_list as llist
+
+class Domain(object):
+    def __init__(self, domain_num, pg_table, redirect, ctx_list, client_name):
+        self.domain_num = domain_num
+        self.pg_table = pg_table
+        self.redirect = redirect
+        self.ctx_list = ctx_list
+        self.client_name = client_name
+
+class IommuLib(object):
+    def __init__(self, ramdump):
+        self.ramdump = ramdump
+        self.domain_list = []
+
+        root = self.ramdump.read_word('domain_root')
+        if root is None:
+            return
+        rb_walker = rb_tree.RbTreeWalker(self.ramdump)
+        rb_walker.walk(root, self._iommu_domain_func, self.domain_list)
+
+    def _iommu_list_func(self, node, ctx_list):
+        ctx_drvdata_name_ptr = self.ramdump.read_word(
+            node + self.ramdump.field_offset('struct msm_iommu_ctx_drvdata', 'name'))
+        ctxdrvdata_num_offset = self.ramdump.field_offset(
+            'struct msm_iommu_ctx_drvdata', 'num')
+        num = self.ramdump.read_word(node + ctxdrvdata_num_offset)
+        if ctx_drvdata_name_ptr != 0:
+            name = self.ramdump.read_cstring(ctx_drvdata_name_ptr, 100)
+            ctx_list.append((num, name))
+
+    def _iommu_domain_func(self, node, domain_list):
+        domain_num = self.ramdump.read_word(self.ramdump.sibling_field_addr(
+            node, 'struct msm_iova_data', 'node', 'domain_num'))
+        domain = self.ramdump.read_word(self.ramdump.sibling_field_addr(
+            node, 'struct msm_iova_data', 'node', 'domain'))
+        priv_ptr = self.ramdump.read_word(
+            domain + self.ramdump.field_offset('struct iommu_domain', 'priv'))
+
+        client_name_offset = self.ramdump.field_offset(
+            'struct msm_iommu_priv', 'client_name')
+
+        if client_name_offset is not None:
+            client_name_ptr = self.ramdump.read_word(
+                priv_ptr + self.ramdump.field_offset(
+                    'struct msm_iommu_priv', 'client_name'))
+            if client_name_ptr != 0:
+                client_name = self.ramdump.read_cstring(client_name_ptr, 100)
+            else:
+                client_name = '(null)'
+        else:
+            client_name = 'unknown'
+
+        list_attached_offset = self.ramdump.field_offset(
+                'struct msm_iommu_priv', 'list_attached')
+
+        if list_attached_offset is not None:
+            list_attached = self.ramdump.read_word(priv_ptr + list_attached_offset)
+        else:
+            list_attached = None
+
+        priv_pt_offset = self.ramdump.field_offset('struct msm_iommu_priv', 'pt')
+        pgtable_offset = self.ramdump.field_offset('struct msm_iommu_pt', 'fl_table')
+        redirect_offset = self.ramdump.field_offset('struct msm_iommu_pt', 'redirect')
+
+        if priv_pt_offset is not None:
+            pg_table = self.ramdump.read_word(
+                priv_ptr + priv_pt_offset + pgtable_offset)
+            redirect = self.ramdump.read_word(
+                priv_ptr + priv_pt_offset + redirect_offset)
+        else:
+            # On some builds we are unable to look up the offsets so hardcode
+            # the offsets.
+            pg_table = self.ramdump.read_word(priv_ptr + 0)
+            redirect = self.ramdump.read_word(priv_ptr + self.ramdump.sizeof('void *'))
+
+            # Note: On some code bases we don't have this pg_table and redirect in the priv structure (see msm_iommu_sec.c). It only
+            # contains list_attached. If this is the case we can detect that by checking whether
+            # pg_table == redirect (prev == next pointers of the attached
+            # list).
+            if pg_table == redirect:
+                # This is a secure domain. We don't have access to the page
+                # tables.
+                pg_table = 0
+                redirect = None
+
+        ctx_list = []
+        if list_attached is not None and list_attached != 0:
+            list_walker = llist.ListWalker(
+                self.ramdump, list_attached,
+                self.ramdump.field_offset('struct msm_iommu_ctx_drvdata', 'attached_elm'))
+            list_walker.walk(list_attached, self._iommu_list_func, extra=ctx_list)
+
+        domain_list.append(
+            Domain(domain_num, pg_table, redirect, ctx_list, client_name))
diff --git a/linux-ramdump-parser-v2/linux_list.py b/linux-ramdump-parser-v2/linux_list.py
index cb526a30a5ba0a3752a538a1f6b5df3619048fda..3a3295c24a36111896f20e4bef2d1622a8c24800 100644
--- a/linux-ramdump-parser-v2/linux_list.py
+++ b/linux-ramdump-parser-v2/linux_list.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-2014, 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
@@ -17,50 +17,32 @@ struct list_head {
 };
 '''
 
-
-def get_list_offsets(ram_dump):
-    next_offset = ram_dump.field_offset('struct list_head', 'next')
-    prev_offset = ram_dump.field_offset('struct list_head', 'prev')
-    return next_offset, prev_offset
-
-
 class ListWalker(object):
 
     '''
     ram_dump: Reference to the ram dump
     node_addr: The address of the first element of the list
     list_elem_offset: The offset of the list_head in the structure that this list is container for.
-    next_offset: The offset for the next pointer in the list
-    prev_offset: The offset for the prev pointer in the list
     '''
 
-    def __init__(self, ram_dump, node_addr, list_elem_offset, next_offset, prev_offset):
-        self.LIST_OFFSETS = [
-            ('((struct list_head *)0x0)', 'next', 0, 0),
-            ('((struct list_head *)0x0)', 'prev', 0, 0),
-        ]
-        self.LIST_NEXT_IDX = 0
-        self.LIST_PREV_IDX = 1
+    def __init__(self, ram_dump, node_addr, list_elem_offset):
 
         self.ram_dump = ram_dump
-        self.next_offset = next_offset
-        self.prev_offset = prev_offset
         self.list_elem_offset = list_elem_offset
-
         self.last_node = node_addr
         self.seen_nodes = []
 
-    def walk(self, node_addr, func):
+    def walk(self, node_addr, func, extra=None):
         if node_addr != 0:
-            func(node_addr - self.list_elem_offset)
+            func(node_addr - self.list_elem_offset, extra)
 
-            next_node_addr = node_addr + self.next_offset
+            next_node_addr = node_addr + self.ram_dump.field_offset('struct list_head', 'next')
             next_node = self.ram_dump.read_word(next_node_addr)
 
             if next_node != self.last_node:
                 if next_node in self.seen_nodes:
                     print_out_str(
-                        '[!] WARNING: Cycle found in attach list for IOMMU domain. List is corrupted!')
+                        '[!] WARNING: Cycle found in list. List is corrupted!')
                 else:
                     self.seen_nodes.append(node_addr)
-                    self.walk(next_node, func)
+                    self.walk(next_node, func, extra)
diff --git a/linux-ramdump-parser-v2/parsers/iommu.py b/linux-ramdump-parser-v2/parsers/iommu.py
index bb3e2657a22d3642e993be0b4ba47fc4251f5ec9..0216ee9a597c86e811da9aa8329a74566932c016 100644
--- a/linux-ramdump-parser-v2/parsers/iommu.py
+++ b/linux-ramdump-parser-v2/parsers/iommu.py
@@ -11,27 +11,14 @@
 
 import math
 
-import rb_tree
-import linux_list as llist
 from print_out import print_out_str
 from parser_util import register_parser, RamParser
 from sizes import SZ_4K, SZ_64K, SZ_1M, SZ_16M, get_order, order_size_strings
-
-IOMMU_DOMAIN_VAR = 'domain_root'
-
+from iommulib import IommuLib
 
 @register_parser('--print-iommu-pg-tables', 'Print IOMMU page tables')
 class IOMMU(RamParser):
 
-    class Domain(object):
-
-        def __init__(self):
-            self.domain_num = -1
-            self.pg_table = 0
-            self.redirect = 0
-            self.ctx_name = ''
-            self.client_name = ''
-
     class FlatMapping(object):
 
         def __init__(self, virt, phys=-1, type='[]', size=SZ_4K, mapped=False):
@@ -61,7 +48,6 @@ class IOMMU(RamParser):
     def __init__(self, *args):
         super(IOMMU, self).__init__(*args)
         self.out_file = None
-        self.domain_list = []
         self.NUM_FL_PTE = 4096
         self.NUM_SL_PTE = 256
 
@@ -90,37 +76,9 @@ class IOMMU(RamParser):
         self.SL_CACHEABLE = (1 << 3)
         self.SL_TEX0 = (1 << 6)
         self.SL_NG = (1 << 11)
-        self.ctxdrvdata_name_offset = 0
-        self.ctxdrvdata_num_offset = 0
-        self.ctx_list = []
 
         self.node_offset = self.ramdump.field_offset(
             'struct msm_iova_data', 'node')
-        self.domain_num_offset = self.ramdump.field_offset(
-            'struct msm_iova_data', 'domain_num')
-        self.domain_offset = self.ramdump.field_offset(
-            'struct msm_iova_data', 'domain')
-        self.priv_offset = self.ramdump.field_offset(
-            'struct iommu_domain', 'priv')
-        self.ctxdrvdata_attached_offset = self.ramdump.field_offset(
-            'struct msm_iommu_ctx_drvdata', 'attached_elm')
-        self.ctxdrvdata_name_offset = self.ramdump.field_offset(
-            'struct msm_iommu_ctx_drvdata', 'name')
-        self.ctxdrvdata_num_offset = self.ramdump.field_offset(
-            'struct msm_iommu_ctx_drvdata', 'num')
-        self.priv_pt_offset = self.ramdump.field_offset(
-            'struct msm_iommu_priv', 'pt')
-        self.list_attached_offset = self.ramdump.field_offset(
-            'struct msm_iommu_priv', 'list_attached')
-        self.client_name_offset = self.ramdump.field_offset(
-            'struct msm_iommu_priv', 'client_name')
-        self.pgtable_offset = self.ramdump.field_offset(
-            'struct msm_iommu_pt', 'fl_table')
-        self.redirect_offset = self.ramdump.field_offset(
-            'struct msm_iommu_pt', 'redirect')
-
-        self.list_next_offset, self.list_prev_offset = llist.get_list_offsets(
-            self.ramdump)
 
     def fl_offset(va):
         return (((va) & 0xFFF00000) >> 20)
@@ -128,76 +86,6 @@ class IOMMU(RamParser):
     def sl_offset(va):
         return (((va) & 0xFF000) >> 12)
 
-    def list_func(self, node):
-        ctx_drvdata_name_ptr = self.ramdump.read_word(
-            node + self.ctxdrvdata_name_offset)
-        num = self.ramdump.read_word(node + self.ctxdrvdata_num_offset)
-
-        if ctx_drvdata_name_ptr != 0:
-            name = self.ramdump.read_cstring(ctx_drvdata_name_ptr, 100)
-            self.ctx_list.append((num, name))
-
-    def iommu_domain_func(self, node):
-
-        domain_num_addr = (node - self.node_offset) + self.domain_num_offset
-        domain_num = self.ramdump.read_word(domain_num_addr)
-
-        domain_addr = (node - self.node_offset) + self.domain_offset
-        domain = self.ramdump.read_word(domain_addr)
-
-        priv_ptr = self.ramdump.read_word(domain + self.priv_offset)
-
-        if self.client_name_offset is not None:
-            client_name_ptr = self.ramdump.read_word(
-                priv_ptr + self.client_name_offset)
-            if client_name_ptr != 0:
-                client_name = self.ramdump.read_cstring(client_name_ptr, 100)
-            else:
-                client_name = '(null)'
-        else:
-            client_name = 'unknown'
-
-        if self.list_attached_offset is not None:
-            list_attached = self.ramdump.read_word(
-                priv_ptr + self.list_attached_offset)
-        else:
-            list_attached = None
-
-        if self.priv_pt_offset is not None:
-            pg_table = self.ramdump.read_word(
-                priv_ptr + self.priv_pt_offset + self.pgtable_offset)
-            redirect = self.ramdump.read_word(
-                priv_ptr + self.priv_pt_offset + self.redirect_offset)
-        else:
-            # On some builds we are unable to look up the offsets so hardcode
-            # the offsets.
-            pg_table = self.ramdump.read_word(priv_ptr + 0)
-            redirect = self.ramdump.read_word(priv_ptr + 4)
-
-            # Note: On some code bases we don't have this pg_table and redirect in the priv structure (see msm_iommu_sec.c). It only
-            # contains list_attached. If this is the case we can detect that by checking whether
-            # pg_table == redirect (prev == next pointers of the attached
-            # list).
-            if pg_table == redirect:
-                # This is a secure domain. We don't have access to the page
-                # tables.
-                pg_table = 0
-                redirect = None
-
-        if list_attached is not None and list_attached != 0:
-            list_walker = llist.ListWalker(
-                self.ramdump, list_attached, self.ctxdrvdata_attached_offset, self.list_next_offset, self.list_prev_offset)
-            list_walker.walk(list_attached, self.list_func)
-
-        dom = self.Domain()
-        dom.domain_num = domain_num
-        dom.pg_table = pg_table
-        dom.redirect = redirect
-        dom.ctx_list = self.ctx_list
-        dom.client_name = client_name
-        self.ctx_list = []
-        self.domain_list.append(dom)
-
     def print_sl_page_table(self, pg_table):
         sl_pte = pg_table
         for i in range(0, self.NUM_SL_PTE):
@@ -415,17 +303,13 @@ class IOMMU(RamParser):
                                     (mapping.virt_start, mapping.virt_end, mapping.virt_size()))
 
     def parse(self):
-        iommu_domains_rb_root = self.ramdump.addr_lookup(IOMMU_DOMAIN_VAR)
-        if iommu_domains_rb_root is None:
+        ilib = IommuLib(self.ramdump)
+        self.domain_list = ilib.domain_list
+        if self.domain_list is None:
             print_out_str(
                 '[!] WARNING: IOMMU domains was not found in this build. No IOMMU page tables will be generated')
             return
 
-        iommu_domains_rb_root_addr = self.ramdump.read_word(
-            iommu_domains_rb_root)
-        rb_walker = rb_tree.RbTreeWalker(self.ramdump)
-        rb_walker.walk(iommu_domains_rb_root_addr, self.iommu_domain_func)
-
         for d in self.domain_list:
             self.out_file = self.ramdump.open_file(
                 'msm_iommu_domain_%02d.txt' % (d.domain_num))
diff --git a/linux-ramdump-parser-v2/rb_tree.py b/linux-ramdump-parser-v2/rb_tree.py
index b7a5d3387746ce33eaf0682f288ee92608a1be0d..0eacfd08588a1afea2cef13a572fc1352fd5f628 100644
--- a/linux-ramdump-parser-v2/rb_tree.py
+++ b/linux-ramdump-parser-v2/rb_tree.py
@@ -30,21 +30,25 @@ class RbTreeWalker(object):
         self.left_offset = self.ram_dump.field_offset(
             'struct rb_node', 'rb_left')
 
-    def _walk(self, node, func, seen):
+    def _walk(self, node, func, seen, extra):
         if node != 0:
             left_node_addr = node + self.left_offset
             left_node = self.ram_dump.read_word(left_node_addr)
             if left_node not in seen:
                 seen.append(left_node)
-                self._walk(left_node, func, seen)
+                self._walk(left_node, func, seen, extra)
 
-            func(node)
+            func(node, extra)
 
             right_node_addr = node + self.right_offset
             right_node = self.ram_dump.read_word(right_node_addr)
             if right_node not in seen:
                 seen.append(right_node)
-                self._walk(right_node, func, seen)
+                self._walk(right_node, func, seen, extra)
 
-    def walk(self, node, func):
-        self._walk(node, func, [])
+    def walk(self, node, func, extra=None):
+        """Walks the RbTree, calling `func' on each iteration. `func' receives
+        two arguments: the current `struct rb_node', and `extra'.
+
+        """
+        self._walk(node, func, [], extra)