diff --git a/docs/gdbmi.rst b/docs/gdbmi.rst
index f2b4726066d8138d205e5bdbd2b7452e9d01e201..4523a5a49de10763d435417a88daad76b485c6da 100644
--- a/docs/gdbmi.rst
+++ b/docs/gdbmi.rst
@@ -1,6 +1,9 @@
 GDBMI
 =====
 
+The ``gdbmi`` module provides the low-level interface to gdb's
+`gdbmi <https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html>`_.
+
 .. automodule:: gdbmi
    :members:
    :undoc-members:
diff --git a/docs/hacking.rst b/docs/hacking.rst
index c207020cbeda1e057659531396dc09f5dc4bc596..8daffe9bfa41cdea6636e8144c523f36e28c18d7 100644
--- a/docs/hacking.rst
+++ b/docs/hacking.rst
@@ -7,6 +7,9 @@ looking to add their own parser plugin to the LRDP.
 .. toctree::
    :maxdepth: 2
 
+   writing_parsers
+   ramdump
    gdbmi
-   parser_util
    register
+   sizes
+   parser_util
diff --git a/docs/ramdump.rst b/docs/ramdump.rst
new file mode 100644
index 0000000000000000000000000000000000000000..cde677d5d9d8fab0cafb728a2d81aa015e13e241
--- /dev/null
+++ b/docs/ramdump.rst
@@ -0,0 +1,7 @@
+.. _`RamDump`:
+
+RamDump
+=======
+
+.. automodule:: ramdump
+   :members:
diff --git a/docs/register.rst b/docs/register.rst
index 222af996bf4afeb218d8ea8bedccfa3fadbc8b31..296c963192514f8d6872b8b54f764afc31f6aedd 100644
--- a/docs/register.rst
+++ b/docs/register.rst
@@ -1,3 +1,5 @@
+.. _`register`:
+
 register
 ========
 
diff --git a/docs/sizes.rst b/docs/sizes.rst
new file mode 100644
index 0000000000000000000000000000000000000000..e9d8112bf23731b77bccfb6ebfa784910b1b9829
--- /dev/null
+++ b/docs/sizes.rst
@@ -0,0 +1,8 @@
+.. _`Sizes`:
+
+Sizes
+=====
+
+.. automodule:: sizes
+   :members:
+   :undoc-members:
diff --git a/docs/writing_parsers.rst b/docs/writing_parsers.rst
new file mode 100644
index 0000000000000000000000000000000000000000..c71b3557f5c7af1ce27d0aedcdd4ee2a775a8e72
--- /dev/null
+++ b/docs/writing_parsers.rst
@@ -0,0 +1,7 @@
+.. _`Writing Parsers`:
+
+Writing Parsers
+===============
+
+.. autofunction:: parser_util.register_parser
+   :noindex:
diff --git a/linux-ramdump-parser-v2/gdbmi.py b/linux-ramdump-parser-v2/gdbmi.py
index 521abac9ba93fed613013b9b693eb07d80949d3d..981d14907c313e10f81fdb771d8774382add50af 100644
--- a/linux-ramdump-parser-v2/gdbmi.py
+++ b/linux-ramdump-parser-v2/gdbmi.py
@@ -48,6 +48,13 @@ class GdbMIException(Exception):
 
 
 class GdbMI(object):
+    """Interface to the ``gdbmi`` subprocess. This should generally be
+    used as a context manager (using Python's ``with`` statement),
+    like so::
+
+        >>> with GdbMI(gdb_path, elf) as g:
+                print('GDB Version: ' + g.version())
+    """
 
     def __init__(self, gdb_path, elf):
         self.gdb_path = gdb_path
@@ -56,6 +63,10 @@ class GdbMI(object):
         self._gdbmi = None
 
     def open(self):
+        """Open the connection to the ``gdbmi`` backend. Not needed if using
+        ``gdbmi`` as a context manager (recommended).
+
+        """
         self._gdbmi = subprocess.Popen(
             [self.gdb_path, '--interpreter=mi2', self.elf],
             stdin=subprocess.PIPE,
@@ -64,6 +75,10 @@ class GdbMI(object):
         self._flush_gdbmi()
 
     def close(self):
+        """Close the connection to the ``gdbmi`` backend. Not needed if using
+        ``gdbmi`` as a context manager (recommended).
+
+        """
         self._gdbmi.communicate('quit')
 
     def __enter__(self):
@@ -147,11 +162,13 @@ class GdbMI(object):
         >>> gdbmi.field_offset("struct ion_buffer", "heap")
         20
 
-        - `the_type': struct or type (note that if it's a struct you
-          should include the word "struct" (e.g.: "struct
-          ion_buffer"))
+        ``the_type``
+           struct or type (note that if it's a struct you should
+           include the word ``"struct"`` (e.g.: ``"struct
+           ion_buffer"``))
 
-        - `field': the field whose offset we want to return
+        ``field``
+           the field whose offset we want to return
 
         """
         cmd = 'print /x (int)&(({0} *)0)->{1}'.format(the_type, field)
@@ -159,6 +176,7 @@ class GdbMI(object):
         return gdb_hex_to_dec(result)
 
     def container_of(self, ptr, the_type, member):
+        """Like ``container_of`` from the kernel."""
         return ptr - self.field_offset(the_type, member)
 
     def sibling_field_addr(self, ptr, parent_type, member, sibling):
@@ -167,35 +185,40 @@ class GdbMI(object):
 
         Example:
 
-        Given:
+        Given a dump containing an instance of the following struct::
+
             struct pizza {
                 int price;
-                int *qty;
+                int qty;
             };
 
-            int quanitity = 42;
-            struct pizza mypizza = {.price = 10, .qty = &quanitity};
-
-        qtyp = dump.address_of('quantity')
-        price = dump.read_int(gdbmi.sibling_field_addr(qtyp, 'struct pizza', 'qty', 'price'))
+        If you have a pointer to qty, you can get a pointer to price with:
 
+        >>> addr = sibling_field_addr(qty, 'struct pizza', 'qty', 'price')
+        >>> price = dump.read_int(addr)
+        >>> price
+        10
         """
         return self.container_of(ptr, parent_type, member) + \
             self.field_offset(parent_type, sibling)
 
     def sizeof(self, the_type):
-        """Returns the size of the type specified by `the_type'."""
+        """Returns the size of the type specified by ``the_type``."""
         result = self._run_for_one('print /x sizeof({0})'.format(the_type))
         return gdb_hex_to_dec(result)
 
     def address_of(self, symbol):
-        """Returns the address of the specified symbol."""
+        """Returns the address of the specified symbol.
+
+        >>> hex(dump.address_of('linux_banner'))
+        '0xc0b0006a'
+        """
         result = self._run_for_one('print /x &{0}'.format(symbol))
         return int(result.split(' ')[-1], 16)
 
     def get_symbol_info(self, address):
         """Returns a GdbSymbol representing the nearest symbol found at
-        `address'."""
+        ``address``."""
         result = self._run_for_one('info symbol ' + hex(address))
         parts = result.split(' ')
         if len(parts) < 2:
@@ -205,11 +228,25 @@ class GdbMI(object):
         return GdbSymbol(symbol, section, address)
 
     def symbol_at(self, address):
-        """Get the symbol at the specified address (using `get_symbol_info')"""
+        """Get the symbol at the given address (using ``get_symbol_info``)"""
         return self.get_symbol_info(address).symbol
 
     def get_enum_lookup_table(self, enum, upperbound):
-        """Return a table translating enum values to human readable strings."""
+        """Return a table translating enum values to human readable
+        strings.
+
+        >>> dump.gdbmi.get_enum_lookup_table('ion_heap_type', 10)
+        ['ION_HEAP_TYPE_SYSTEM',
+         'ION_HEAP_TYPE_SYSTEM_CONTIG',
+         'ION_HEAP_TYPE_CARVEOUT',
+         'ION_HEAP_TYPE_CHUNK',
+         'ION_HEAP_TYPE_CUSTOM',
+         'ION_NUM_HEAPS',
+         '6',
+         '7',
+         '8',
+         '9']
+        """
         table = []
         for i in range(0, upperbound):
             result = self._run_for_first(
@@ -223,8 +260,13 @@ class GdbMI(object):
         return table
 
     def get_func_info(self, address):
-        """Returns the function info at a particular address, specifically line
-        and file."""
+        """Returns the function info at a particular address, specifically
+        line and file.
+
+        >>> dump.gdbmi.get_func_info(dump.gdbmi.address_of('panic'))
+        'Line 78 of \\"kernel/kernel/panic.c\\"'
+
+        """
         result = self._run_for_one('info line *0x{0:x}'.format(address))
         m = re.search(r'(Line \d+ of \\?\".*\\?\")', result)
         if m is not None:
diff --git a/linux-ramdump-parser-v2/parser_util.py b/linux-ramdump-parser-v2/parser_util.py
index 942f1e5ba3675b89b599610166189e7ddbc39ee9..bebcf1d89f24aa76865d72a480897539753df277 100644
--- a/linux-ramdump-parser-v2/parser_util.py
+++ b/linux-ramdump-parser-v2/parser_util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+# Copyright (c) 2013-2015, 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
@@ -39,35 +39,48 @@ def cleanupString(unclean_str):
 
 def register_parser(longopt, desc, shortopt=None, optional=False):
     """Decorator to register a parser class (a class that inherits from
-    RamParser) with the parsing framework. By using this decorator
+    ``RamParser``) with the parsing framework. By using this decorator
     your parser will automatically be hooked up to the command-line
     parsing code.
 
     This makes it very easy and clean to add a new parser:
 
-      o Drop a new file in parsers that defines a class that inherits
-        from RamParser
+      1. Drop a new file in the ``parsers/`` directory that defines a
+         class that inherits from ``RamParser``
 
-      o Decorate your class with @register_parser
+      2. Decorate your class with ``@register_parser``
 
-      o Define a `parse' method for your class
+      3. Define a ``parse`` method for your class
 
     All of the command line argument handling and invoking the parse
     method of your parser will then be handled automatically.
 
+    Example::
+
+       # file: parsers/my_banner.py
+       @register_parser('--banner', 'Print the kernel banner')
+       class BannerParser(RamParser):
+
+           def parse(self):
+               print self.ramdump.read_cstring('linux_banner', 256, False)
+
     Required arguments:
 
-    - longopt:: The longopt command line switch for this parser
+    ``longopt``
+       The longopt command line switch for this parser
 
-    - desc:: A short description of the parser (also shown in the
-      help-text associated with the longopt)
+    ``desc``
+       A short description of the parser (also shown in the help-text
+       associated with the longopt)
 
     Optional arguments:
 
-    - shortopt:: The shortopt command line switch for this parser
+    ``shortopt``
+       The shortopt command line switch for this parser
 
-    - optional:: Indicates the parser is optional and should not be run with
-      --everything
+    ``optional``
+       Indicates the parser is optional and should not be run with
+       --everything
 
     """
     def wrapper(cls):
@@ -79,11 +92,11 @@ def register_parser(longopt, desc, shortopt=None, optional=False):
 
 
 def get_parsers():
-    """Imports everyone under the `parsers' directory. It is expected that
+    """Imports everyone under the ``parsers`` directory. It is expected that
     the parsers under the parsers directory will be a collection of
     classes that subclass RamParser and use the register_parser
     decorator to register themselves with the parser
-    framework. Therefore, importing all the modules under `parsers'
+    framework. Therefore, importing all the modules under ``parsers``
     should have the side-effect of populating the (internal to
     parser_util) _parsers list with the discovered parsers.
 
@@ -111,7 +124,7 @@ def get_parsers():
 class RamParser(object):
 
     """Base class for implementing ramdump parsers. New parsers should inherit
-    from this class and define a `parse' method.
+    from this class and define a ``parse`` method.
 
     Interesting properties that will be set for usage in derived
     classes:
@@ -180,7 +193,7 @@ def _xxd_line(addr, data):
     )
 
 def xxd(address, data, file_object=None):
-    """Dumps data to `file_object' or stdout, in the format of `xxd'. data
+    """Dumps data to ``file_object`` or stdout, in the format of ``xxd``. data
     should be a list of integers.
 
     >>> xxd(0x1000, [0xde, 0xad, 0xbe, 0xef, 112, 105, 122, 122, 97, 0, 0, 42, 43, 44, 45, 90])
diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py
index 8a16f2dabb6bd28b30c30b2be3c4c8bbdf711234..357ba6dd16687c2bb2d53ff5f42aeaf6973ad6c5 100644
--- a/linux-ramdump-parser-v2/ramdump.py
+++ b/linux-ramdump-parser-v2/ramdump.py
@@ -46,6 +46,7 @@ extra_mem_file_names = ['EBI1CS1.BIN', 'DDRCS1.BIN', 'ebi1_cs1.bin', 'DDRCS0_1.B
 
 
 class RamDump():
+    """The main interface to the RAM dump"""
 
     class Unwinder ():
 
@@ -555,6 +556,13 @@ class RamDump():
         self.gdbmi.close()
 
     def open_file(self, file_name, mode='wb'):
+        """Open a file in the out directory.
+
+        Example:
+
+        >>> with self.ramdump.open_file('pizza.txt') as p:
+                p.write('Pizza is the best\\n')
+        """
         file_path = os.path.join(self.outdir, file_name)
         f = None
         try:
@@ -598,6 +606,13 @@ class RamDump():
         return True
 
     def get_config_val(self, config):
+        """Gets the value of a kernel config option.
+
+        Example:
+
+        >>> va_bits = int(dump.get_config_val("CONFIG_ARM64_VA_BITS"))
+        39
+        """
         return self.config_dict.get(config)
 
     def is_config_defined(self, config):
@@ -982,6 +997,13 @@ class RamDump():
         stream.close()
 
     def address_of(self, symbol):
+        """Returns the address of a symbol.
+
+        Example:
+
+        >>> hex(dump.address_of('linux_banner'))
+        '0xffffffc000c7a0a8L'
+        """
         try:
             return self.gdbmi.address_of(symbol)
         except gdbmi.GdbMIException:
@@ -1000,40 +1022,52 @@ class RamDump():
             pass
 
     def array_index(self, addr, the_type, index):
-        """Index into the array of type `the_type' located at `addr'.
-
-        I.e.:
-
-            Given:
+        """Index into the array of type ``the_type`` located at ``addr``.
 
-                int my_arr[3];
-                my_arr[2] = 42;
+        I.e., given::
 
+            int my_arr[3];
+            my_arr[2] = 42;
 
-            The following:
-
-                my_arr_addr = dump.address_of("my_arr")
-                dump.read_word(dump.array_index(my_arr_addr, "int", 2))
-
-        will return 42.
+        You could do the following:
 
+        >>> addr = dump.address_of("my_arr")
+        >>> dump.read_word(dump.array_index(addr, "int", 2))
+        42
         """
         offset = self.gdbmi.sizeof(the_type) * index
         return addr + offset
 
     def field_offset(self, the_type, field):
+        """Gets the offset of a field from the base of its containing struct.
+
+        This can be useful when reading struct fields, although you should
+        consider using :func:`~read_structure_field` if
+        you're reading a word-sized value.
+
+        Example:
+
+        >>> dump.field_offset('struct device', 'bus')
+        168
+        """
         try:
             return self.gdbmi.field_offset(the_type, field)
         except gdbmi.GdbMIException:
             pass
 
     def container_of(self, ptr, the_type, member):
+        """Like ``container_of`` in the kernel."""
         try:
             return self.gdbmi.container_of(ptr, the_type, member)
         except gdbmi.GdbMIException:
             pass
 
     def sibling_field_addr(self, ptr, parent_type, member, sibling):
+        """Gets the address of a sibling structure field.
+
+        Given the address of some field within a structure, returns the
+        address of the requested sibling field.
+        """
         try:
             return self.gdbmi.sibling_field_addr(ptr, parent_type, member, sibling)
         except gdbmi.GdbMIException:
@@ -1111,10 +1145,12 @@ class RamDump():
         return s[0] if s is not None else None
 
     def read_byte(self, addr_or_name, virtual=True, cpu=None):
+        """Reads a single byte."""
         s = self.read_string(addr_or_name, '<B', virtual, cpu)
         return s[0] if s is not None else None
 
     def read_bool(self, addr_or_name, virtual=True, cpu=None):
+        """Reads a bool."""
         s = self.read_string(addr_or_name, '<?', virtual, cpu)
         return s[0] if s is not None else None
 
@@ -1134,7 +1170,7 @@ class RamDump():
         return s[0] if s is not None else None
 
     def read_int(self, addr_or_name, virtual=True,  cpu=None):
-        """Alias for `read_u32'"""
+        """Alias for :func:`~read_u32`"""
         return self.read_u32(addr_or_name, virtual, cpu)
 
     def read_u16(self, addr_or_name, virtual=True, cpu=None):
@@ -1143,7 +1179,7 @@ class RamDump():
         return s[0] if s is not None else None
 
     def read_pointer(self, addr_or_name, virtual=True, cpu=None):
-        """Reads `addr_or_name' as a pointer variable.
+        """Reads ``addr_or_name`` as a pointer variable.
 
         The read length is either 32-bit or 64-bit depending on the
         architecture.  This returns the *value* of the pointer variable
@@ -1167,8 +1203,8 @@ class RamDump():
     def read_structure_cstring(self, addr_or_name, struct_name, field,
                                max_length=100):
         """reads a C string from a structure field.  The C string field will be
-        dereferenced before reading, so it should be a `char *', not a
-        `char []'.
+        dereferenced before reading, so it should be a ``char *``, not a
+        ``char []``.
         """
         virt = self.resolve_virt(addr_or_name)
         cstring_addr = virt + self.field_offset(struct_name, field)
@@ -1176,6 +1212,7 @@ class RamDump():
 
     def read_cstring(self, addr_or_name, max_length=100, virtual=True,
                      cpu=None):
+        """Reads a C string."""
         addr = addr_or_name
         if virtual:
             if cpu is not None:
@@ -1213,9 +1250,9 @@ class RamDump():
         return struct.unpack(format_string, s)
 
     def hexdump(self, addr_or_name, length, virtual=True, file_object=None):
-        """Returns a string with a hexdump (in the format of `xxd').
+        """Returns a string with a hexdump (in the format of ``xxd``).
 
-        `length' is in bytes.
+        ``length`` is in bytes.
 
         Example (intentionally not in doctest format since it would require
         a specific dump to be loaded to pass as a doctest):
@@ -1251,11 +1288,19 @@ class RamDump():
         return self.read_word(per_cpu_offset_addr_indexed)
 
     def get_num_cpus(self):
+        """Gets the number of CPUs in the system."""
         cpu_present_bits_addr = self.address_of('cpu_present_bits')
         cpu_present_bits = self.read_word(cpu_present_bits_addr)
         return bin(cpu_present_bits).count('1')
 
     def iter_cpus(self):
+        """Returns an iterator over all CPUs in the system.
+
+        Example:
+
+        >>> list(dump.iter_cpus())
+        [0, 1, 2, 3]
+        """
         return xrange(self.get_num_cpus())
 
     def thread_saved_field_common_32(self, task, reg_offset):