Replace MMappedRange with MinidumpMemoryRange.

This patch is part of a bigger patch that helps merging the breakpad code
with the modified version in Chromium OS.

The MemoryRange class was added in r895 (http://breakpad.appspot.com/332001),
which is largely based on MMappedRange but generalized to be used in other
code. However, MemoryRange does not support minidump data structures. This
patch adds a MinidumpMemoryRange class that extends MemoryRange to handle
minidump data structures, which can then replace MMappedRange.

As with MemoryRange, MinidumpMemoryRange is unit tested.

BUG=455
TEST=Tested the following:
1. Build on 32-bit and 64-bit Linux with gcc 4.4.3 and gcc 4.6.
2. Build on Mac OS X 10.6.8 with gcc 4.2 and clang 3.0 (with latest gmock).
3. All unit tests pass.
4. Run minidump-2-core to covnert a minidump file to a core file.
Review URL: http://breakpad.appspot.com/335001

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@898 4c0a9323-5329-0410-9bdc-e9ce6186880e
diff --git a/Makefile.am b/Makefile.am
index 47e7676..6a6ca3f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -255,7 +255,8 @@
 
 if !DISABLE_TOOLS
 check_PROGRAMS += \
-	src/common/dumper_unittest
+	src/common/dumper_unittest \
+	src/tools/linux/md2core/minidump_2_core_unittest
 endif
 endif LINUX_HOST
 
@@ -399,6 +400,19 @@
 	-I$(top_srcdir)/src/testing/gtest \
 	-I$(top_srcdir)/src/testing
 endif
+
+src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
+	src/testing/gtest/src/gtest-all.cc \
+	src/testing/gtest/src/gtest_main.cc \
+	src/testing/src/gmock-all.cc \
+	src/tools/linux/md2core/minidump_memory_range_unittest.cc
+src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \
+	-I$(top_srcdir)/src \
+	-I$(top_srcdir)/src/testing/include \
+	-I$(top_srcdir)/src/testing/gtest/include \
+	-I$(top_srcdir)/src/testing/gtest \
+	-I$(top_srcdir)/src/testing
+
 endif LINUX_HOST
 
 if !DISABLE_PROCESSOR
diff --git a/Makefile.in b/Makefile.in
index 785233c..7fdae4f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -114,7 +114,8 @@
 @LINUX_HOST_TRUE@	src/client/linux/linux_client_unittest
 
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__append_9 = \
-@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dumper_unittest
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/common/dumper_unittest \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/md2core/minidump_2_core_unittest
 
 @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__append_10 = \
 @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@	src/processor/stackwalker_selftest
@@ -377,7 +378,8 @@
 @DISABLE_PROCESSOR_FALSE@	src/processor/stackwalker_x86_unittest$(EXEEXT) \
 @DISABLE_PROCESSOR_FALSE@	src/processor/synth_minidump_unittest$(EXEEXT)
 @LINUX_HOST_TRUE@am__EXEEXT_5 = src/client/linux/linux_client_unittest$(EXEEXT)
-@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_6 = src/common/dumper_unittest$(EXEEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am__EXEEXT_6 = src/common/dumper_unittest$(EXEEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)
 @DISABLE_PROCESSOR_FALSE@@SELFTEST_TRUE@am__EXEEXT_7 = src/processor/stackwalker_selftest$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
 am__src_client_linux_linux_client_unittest_SOURCES_DIST =  \
@@ -924,6 +926,17 @@
 src_tools_linux_md2core_minidump_2_core_OBJECTS =  \
 	$(am_src_tools_linux_md2core_minidump_2_core_OBJECTS)
 src_tools_linux_md2core_minidump_2_core_LDADD = $(LDADD)
+am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST =  \
+	src/testing/gtest/src/gtest-all.cc \
+	src/testing/gtest/src/gtest_main.cc \
+	src/testing/src/gmock-all.cc \
+	src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT) \
+@LINUX_HOST_TRUE@	src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT) \
+@LINUX_HOST_TRUE@	src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT) \
+@LINUX_HOST_TRUE@	src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT)
+src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS = $(am_src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS)
+src_tools_linux_md2core_minidump_2_core_unittest_LDADD = $(LDADD)
 am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST =  \
 	src/common/linux/http_upload.cc \
 	src/tools/linux/symupload/minidump_upload.cc
@@ -995,6 +1008,7 @@
 	$(src_processor_synth_minidump_unittest_SOURCES) \
 	$(src_tools_linux_dump_syms_dump_syms_SOURCES) \
 	$(src_tools_linux_md2core_minidump_2_core_SOURCES) \
+	$(src_tools_linux_md2core_minidump_2_core_unittest_SOURCES) \
 	$(src_tools_linux_symupload_minidump_upload_SOURCES) \
 	$(src_tools_linux_symupload_sym_upload_SOURCES)
 DIST_SOURCES =  \
@@ -1032,6 +1046,7 @@
 	$(am__src_processor_synth_minidump_unittest_SOURCES_DIST) \
 	$(am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST) \
 	$(am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST) \
+	$(am__src_tools_linux_md2core_minidump_2_core_unittest_SOURCES_DIST) \
 	$(am__src_tools_linux_symupload_minidump_upload_SOURCES_DIST) \
 	$(am__src_tools_linux_symupload_sym_upload_SOURCES_DIST)
 DATA = $(dist_doc_DATA)
@@ -1434,6 +1449,19 @@
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing/gtest \
 @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing
 
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
+@LINUX_HOST_TRUE@	src/testing/gtest/src/gtest-all.cc \
+@LINUX_HOST_TRUE@	src/testing/gtest/src/gtest_main.cc \
+@LINUX_HOST_TRUE@	src/testing/src/gmock-all.cc \
+@LINUX_HOST_TRUE@	src/tools/linux/md2core/minidump_memory_range_unittest.cc
+
+@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS = \
+@LINUX_HOST_TRUE@	-I$(top_srcdir)/src \
+@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing/include \
+@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing/gtest/include \
+@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing/gtest \
+@LINUX_HOST_TRUE@	-I$(top_srcdir)/src/testing
+
 @DISABLE_PROCESSOR_FALSE@src_processor_address_map_unittest_SOURCES = \
 @DISABLE_PROCESSOR_FALSE@	src/processor/address_map_unittest.cc
 
@@ -2897,6 +2925,21 @@
 src/tools/linux/md2core/minidump-2-core$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp)
 	@rm -f src/tools/linux/md2core/minidump-2-core$(EXEEXT)
 	$(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_LDADD) $(LIBS)
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT):  \
+	src/testing/gtest/src/$(am__dirstamp) \
+	src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT):  \
+	src/testing/gtest/src/$(am__dirstamp) \
+	src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp)
+src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT):  \
+	src/testing/src/$(am__dirstamp) \
+	src/testing/src/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT):  \
+	src/tools/linux/md2core/$(am__dirstamp) \
+	src/tools/linux/md2core/$(DEPDIR)/$(am__dirstamp)
+src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT): $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_DEPENDENCIES) src/tools/linux/md2core/$(am__dirstamp)
+	@rm -f src/tools/linux/md2core/minidump_2_core_unittest$(EXEEXT)
+	$(CXXLINK) $(src_tools_linux_md2core_minidump_2_core_unittest_OBJECTS) $(src_tools_linux_md2core_minidump_2_core_unittest_LDADD) $(LIBS)
 src/common/linux/http_upload.$(OBJEXT):  \
 	src/common/linux/$(am__dirstamp) \
 	src/common/linux/$(DEPDIR)/$(am__dirstamp)
@@ -3082,6 +3125,8 @@
 	-rm -f src/testing/gtest/src/src_processor_static_range_map_unittest-gtest-all.$(OBJEXT)
 	-rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest-all.$(OBJEXT)
 	-rm -f src/testing/gtest/src/src_processor_synth_minidump_unittest-gtest_main.$(OBJEXT)
+	-rm -f src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.$(OBJEXT)
+	-rm -f src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.$(OBJEXT)
 	-rm -f src/testing/src/src_client_linux_linux_client_unittest-gmock-all.$(OBJEXT)
 	-rm -f src/testing/src/src_common_dumper_unittest-gmock-all.$(OBJEXT)
 	-rm -f src/testing/src/src_common_test_assembler_unittest-gmock-all.$(OBJEXT)
@@ -3102,6 +3147,7 @@
 	-rm -f src/testing/src/src_processor_static_map_unittest-gmock-all.$(OBJEXT)
 	-rm -f src/testing/src/src_processor_static_range_map_unittest-gmock-all.$(OBJEXT)
 	-rm -f src/testing/src/src_processor_synth_minidump_unittest-gmock-all.$(OBJEXT)
+	-rm -f src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.$(OBJEXT)
 	-rm -f src/third_party/libdisasm/ia32_implicit.$(OBJEXT)
 	-rm -f src/third_party/libdisasm/ia32_insn.$(OBJEXT)
 	-rm -f src/third_party/libdisasm/ia32_invariant.$(OBJEXT)
@@ -3118,6 +3164,7 @@
 	-rm -f src/third_party/libdisasm/x86_operand_list.$(OBJEXT)
 	-rm -f src/tools/linux/dump_syms/dump_syms.$(OBJEXT)
 	-rm -f src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
+	-rm -f src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.$(OBJEXT)
 	-rm -f src/tools/linux/symupload/minidump_upload.$(OBJEXT)
 	-rm -f src/tools/linux/symupload/sym_upload.$(OBJEXT)
 
@@ -3285,6 +3332,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_static_range_map_unittest-gtest-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gtest_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_client_linux_linux_client_unittest-gmock-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_common_dumper_unittest-gmock-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_common_test_assembler_unittest-gmock-all.Po@am__quote@
@@ -3305,6 +3354,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_static_map_unittest-gmock-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_static_range_map_unittest-gmock-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_synth_minidump_unittest-gmock-all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_implicit.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_insn.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/ia32_invariant.Po@am__quote@
@@ -3321,6 +3371,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote@src/third_party/libdisasm/$(DEPDIR)/x86_operand_list.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/dump_syms/$(DEPDIR)/dump_syms.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/minidump-2-core.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/minidump_upload.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@src/tools/linux/symupload/$(DEPDIR)/sym_upload.Po@am__quote@
 
@@ -5077,6 +5128,62 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/processor/synth_minidump.cc' object='src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_synth_minidump_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_synth_minidump_unittest-synth_minidump.obj `if test -f 'src/processor/synth_minidump.cc'; then $(CYGPATH_W) 'src/processor/synth_minidump.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/synth_minidump.cc'; fi`
+
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc
+
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi`
+
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.o `test -f 'src/testing/gtest/src/gtest_main.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest_main.cc
+
+src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj: src/testing/gtest/src/gtest_main.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Tpo src/testing/gtest/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/gtest/src/gtest_main.cc' object='src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_tools_linux_md2core_minidump_2_core_unittest-gtest_main.obj `if test -f 'src/testing/gtest/src/gtest_main.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest_main.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest_main.cc'; fi`
+
+src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/src/gmock-all.cc' object='src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc
+
+src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj: src/testing/src/gmock-all.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/testing/src/gmock-all.cc' object='src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_tools_linux_md2core_minidump_2_core_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi`
+
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o: src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@	$(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.o `test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc' || echo '$(srcdir)/'`src/tools/linux/md2core/minidump_memory_range_unittest.cc
+
+src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj: src/tools/linux/md2core/minidump_memory_range_unittest.cc
+@am__fastdepCXX_TRUE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj -MD -MP -MF src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@	$(am__mv) src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Tpo src/tools/linux/md2core/$(DEPDIR)/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='src/tools/linux/md2core/minidump_memory_range_unittest.cc' object='src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_tools_linux_md2core_minidump_2_core_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/tools/linux/md2core/src_tools_linux_md2core_minidump_2_core_unittest-minidump_memory_range_unittest.obj `if test -f 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; then $(CYGPATH_W) 'src/tools/linux/md2core/minidump_memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tools/linux/md2core/minidump_memory_range_unittest.cc'; fi`
 install-dist_docDATA: $(dist_doc_DATA)
 	@$(NORMAL_INSTALL)
 	test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)"
diff --git a/src/common/memory_range.h b/src/common/memory_range.h
index 0c81d1e..86bd08c 100644
--- a/src/common/memory_range.h
+++ b/src/common/memory_range.h
@@ -45,12 +45,6 @@
 // access of a subrange of the memory. Its implemementation does not
 // allocate memory or call into libc functions, and is thus safer to use
 // in a crashed environment.
-//
-// TODO(benchan): This class is largely based on the MMappedRange class
-// in tools/linux/md2core/minidump-2-core.cc, but generalized for use in
-// other code. Provide a variant of MemoryRange with methods for handling
-// Minidump data structures in order to replace MMappedRange in
-// minidump-2-core.cc.
 class MemoryRange {
  public:
   MemoryRange() : data_(NULL), length_(0) {}
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc
index ddefecc..0a0343f 100644
--- a/src/tools/linux/md2core/minidump-2-core.cc
+++ b/src/tools/linux/md2core/minidump-2-core.cc
@@ -48,9 +48,10 @@
 
 #include "client/linux/minidump_writer/minidump_extension_linux.h"
 #include "common/linux/memory_mapped_file.h"
-#include "google_breakpad/common/minidump_format.h"
 #include "google_breakpad/common/minidump_cpu_x86.h"
+#include "google_breakpad/common/minidump_format.h"
 #include "third_party/lss/linux_syscall_support.h"
+#include "tools/linux/md2core/minidump_memory_range.h"
 
 
 #if __WORDSIZE == 64
@@ -76,6 +77,7 @@
 #endif
 
 using google_breakpad::MemoryMappedFile;
+using google_breakpad::MinidumpMemoryRange;
 
 static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1);
 static bool verbose;
@@ -106,63 +108,6 @@
   return true;
 }
 
-// A range of a mmaped file.
-class MMappedRange {
- public:
-  MMappedRange(const void* data, size_t length)
-      : data_(reinterpret_cast<const uint8_t*>(data)),
-        length_(length) {
-  }
-
-  // Get an object of |length| bytes at |offset| and return a pointer to it
-  // unless it's out of bounds.
-  const void* GetObject(size_t offset, size_t length) const {
-    if (offset + length < offset)
-      return NULL;
-    if (offset + length > length_)
-      return NULL;
-    return data_ + offset;
-  }
-
-  // Get element |index| of an array of objects of length |length| starting at
-  // |offset| bytes. Return NULL if out of bounds.
-  const void* GetArrayElement(size_t offset, size_t length,
-                              unsigned index) const {
-    const size_t element_offset = offset + index * length;
-    return GetObject(element_offset, length);
-  }
-
-  // Get a zero-terminated string. This method only works correctly for ASCII
-  // characters and does not convert between UTF-16 and UTF-8.
-  const std::string GetString(size_t offset) const {
-    const MDString* s = (const MDString*) GetObject(offset, sizeof(MDString));
-    const u_int16_t* buf = &s->buffer[0];
-    std::string str;
-    for (unsigned i = 0; i < s->length && buf[i]; ++i) {
-      str.push_back(buf[i]);
-    }
-    return str;
-  }
-
-  // Return a new range which is a subset of this range.
-  MMappedRange Subrange(const MDLocationDescriptor& location) const {
-    if (location.rva > length_ ||
-        location.rva + location.data_size < location.rva ||
-        location.rva + location.data_size > length_) {
-      return MMappedRange(NULL, 0);
-    }
-
-    return MMappedRange(data_ + location.rva, location.data_size);
-  }
-
-  const uint8_t* data() const { return data_; }
-  size_t length() const { return length_; }
-
- private:
-  const uint8_t* const data_;
-  const size_t length_;
-};
-
 /* Dynamically determines the byte sex of the system. Returns non-zero
  * for big-endian machines.
  */
@@ -290,9 +235,9 @@
 }
 
 static void
-ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) {
-  const MDRawContextX86* rawregs =
-      (const MDRawContextX86*) range.GetObject(0, sizeof(MDRawContextX86));
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+                     const MinidumpMemoryRange& range) {
+  const MDRawContextX86* rawregs = range.GetData<MDRawContextX86>(0);
 
   thread->regs.ebx = rawregs->ebx;
   thread->regs.ecx = rawregs->ecx;
@@ -336,9 +281,9 @@
 }
 #elif defined(__x86_64__)
 static void
-ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) {
-  const MDRawContextAMD64* rawregs =
-      (const MDRawContextAMD64*) range.GetObject(0, sizeof(MDRawContextAMD64));
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+                     const MinidumpMemoryRange& range) {
+  const MDRawContextAMD64* rawregs = range.GetData<MDRawContextAMD64>(0);
 
   thread->regs.r15 = rawregs->r15;
   thread->regs.r14 = rawregs->r14;
@@ -384,10 +329,9 @@
 #endif
 
 static void
-ParseThreadList(CrashedProcess* crashinfo, MMappedRange range,
-                const MMappedRange& full_file) {
-  const uint32_t num_threads =
-      *(const uint32_t*) range.GetObject(0, sizeof(uint32_t));
+ParseThreadList(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
+                const MinidumpMemoryRange& full_file) {
+  const uint32_t num_threads = *range.GetData<uint32_t>(0);
   if (verbose) {
     fprintf(stderr,
             "MD_THREAD_LIST_STREAM:\n"
@@ -399,11 +343,11 @@
     CrashedProcess::Thread thread;
     memset(&thread, 0, sizeof(thread));
     const MDRawThread* rawthread =
-        (MDRawThread*) range.GetArrayElement(sizeof(uint32_t),
-                                             sizeof(MDRawThread), i);
+        range.GetArrayElement<MDRawThread>(sizeof(uint32_t), i);
     thread.tid = rawthread->thread_id;
     thread.stack_addr = rawthread->stack.start_of_memory_range;
-    MMappedRange stack_range = full_file.Subrange(rawthread->stack.memory);
+    MinidumpMemoryRange stack_range =
+        full_file.Subrange(rawthread->stack.memory);
     thread.stack = stack_range.data();
     thread.stack_length = rawthread->stack.memory.data_size;
 
@@ -415,10 +359,9 @@
 }
 
 static void
-ParseSystemInfo(CrashedProcess* crashinfo, MMappedRange range,
-                const MMappedRange &full_file) {
-  const MDRawSystemInfo* sysinfo =
-    (MDRawSystemInfo*) range.GetObject(0, sizeof(MDRawSystemInfo));
+ParseSystemInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
+                const MinidumpMemoryRange& full_file) {
+  const MDRawSystemInfo* sysinfo = range.GetData<MDRawSystemInfo>(0);
   if (!sysinfo) {
     fprintf(stderr, "Failed to access MD_SYSTEM_INFO_STREAM\n");
     _exit(1);
@@ -442,7 +385,8 @@
 #else
 #error "This code has not been ported to your platform yet"
 #endif
-  if (!strstr(full_file.GetString(sysinfo->csd_version_rva).c_str(), "Linux")) {
+  if (!strstr(full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str(),
+              "Linux")) {
     fprintf(stderr, "This minidump was not generated by Linux.\n");
     _exit(1);
   }
@@ -478,13 +422,13 @@
       fputs("\n", stderr);
     }
     fprintf(stderr, "OS: %s\n",
-            full_file.GetString(sysinfo->csd_version_rva).c_str());
+            full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str());
     fputs("\n\n", stderr);
   }
 }
 
 static void
-ParseCPUInfo(CrashedProcess* crashinfo, MMappedRange range) {
+ParseCPUInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   if (verbose) {
     fputs("MD_LINUX_CPU_INFO:\n", stderr);
     fwrite(range.data(), range.length(), 1, stderr);
@@ -493,7 +437,8 @@
 }
 
 static void
-ParseProcessStatus(CrashedProcess* crashinfo, MMappedRange range) {
+ParseProcessStatus(CrashedProcess* crashinfo,
+                   const MinidumpMemoryRange& range) {
   if (verbose) {
     fputs("MD_LINUX_PROC_STATUS:\n", stderr);
     fwrite(range.data(), range.length(), 1, stderr);
@@ -502,7 +447,7 @@
 }
 
 static void
-ParseLSBRelease(CrashedProcess* crashinfo, MMappedRange range) {
+ParseLSBRelease(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   if (verbose) {
     fputs("MD_LINUX_LSB_RELEASE:\n", stderr);
     fwrite(range.data(), range.length(), 1, stderr);
@@ -511,7 +456,7 @@
 }
 
 static void
-ParseMaps(CrashedProcess* crashinfo, MMappedRange range) {
+ParseMaps(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   if (verbose) {
     fputs("MD_LINUX_MAPS:\n", stderr);
     fwrite(range.data(), range.length(), 1, stderr);
@@ -557,7 +502,7 @@
 }
 
 static void
-ParseEnvironment(CrashedProcess* crashinfo, MMappedRange range) {
+ParseEnvironment(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   if (verbose) {
     fputs("MD_LINUX_ENVIRON:\n", stderr);
     char *env = new char[range.length()];
@@ -595,7 +540,7 @@
 }
 
 static void
-ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) {
+ParseAuxVector(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   // Some versions of Chrome erroneously used the MD_LINUX_AUXV stream value
   // when dumping /proc/$x/maps
   if (range.length() > 17) {
@@ -616,7 +561,7 @@
 }
 
 static void
-ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) {
+ParseCmdLine(CrashedProcess* crashinfo, const MinidumpMemoryRange& range) {
   // The command line is supposed to use NUL bytes to separate arguments.
   // As Chrome rewrites its own command line and (incorrectly) substitutes
   // spaces, this is often not the case in our minidump files.
@@ -664,10 +609,9 @@
 }
 
 static void
-ParseDSODebugInfo(CrashedProcess* crashinfo, MMappedRange range,
-                  const MMappedRange &full_file) {
-  const MDRawDebug* debug =
-    (MDRawDebug*) range.GetObject(0, sizeof(MDRawDebug));
+ParseDSODebugInfo(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
+                  const MinidumpMemoryRange& full_file) {
+  const MDRawDebug* debug = range.GetData<MDRawDebug>(0);
   if (!debug) {
     return;
   }
@@ -694,14 +638,13 @@
   if (debug->map != kInvalidMDRVA) {
     for (int i = 0; i < debug->dso_count; ++i) {
       const MDRawLinkMap* link_map =
-        (MDRawLinkMap*) full_file.GetArrayElement(debug->map,
-                                                  sizeof(MDRawLinkMap), i);
+          full_file.GetArrayElement<MDRawLinkMap>(debug->map, i);
       if (link_map) {
         if (verbose) {
           fprintf(stderr,
                   "#%03d: %p, %p, \"%s\"\n",
                   i, link_map->addr, link_map->ld,
-                  full_file.GetString(link_map->name).c_str());
+                  full_file.GetAsciiMDString(link_map->name).c_str());
         }
         crashinfo->link_map.push_back(*link_map);
       }
@@ -713,9 +656,9 @@
 }
 
 static void
-ParseExceptionStream(CrashedProcess* crashinfo, MMappedRange range) {
-  const MDRawExceptionStream* exp =
-      (MDRawExceptionStream*) range.GetObject(0, sizeof(MDRawExceptionStream));
+ParseExceptionStream(CrashedProcess* crashinfo,
+                     const MinidumpMemoryRange& range) {
+  const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0);
   crashinfo->crashing_tid = exp->thread_id;
   crashinfo->fatal_signal = (int) exp->exception_record.exception_code;
 }
@@ -763,18 +706,16 @@
 }
 
 static void
-ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range,
-                  const MMappedRange &full_file) {
+ParseModuleStream(CrashedProcess* crashinfo, const MinidumpMemoryRange& range,
+                  const MinidumpMemoryRange& full_file) {
   if (verbose) {
     fputs("MD_MODULE_LIST_STREAM:\n", stderr);
   }
-  const uint32_t num_mappings =
-      *(const uint32_t*) range.GetObject(0, sizeof(uint32_t));
+  const uint32_t num_mappings = *range.GetData<uint32_t>(0);
   for (unsigned i = 0; i < num_mappings; ++i) {
     CrashedProcess::Mapping mapping;
-    const MDRawModule* rawmodule =
-        (MDRawModule*) range.GetArrayElement(sizeof(uint32_t),
-                                             MD_MODULE_SIZE, i);
+    const MDRawModule* rawmodule = reinterpret_cast<const MDRawModule*>(
+        range.GetArrayElement(sizeof(uint32_t), MD_MODULE_SIZE, i));
     mapping.start_address = rawmodule->base_of_image;
     mapping.end_address = rawmodule->size_of_image + rawmodule->base_of_image;
 
@@ -785,9 +726,8 @@
       crashinfo->mappings[mapping.start_address] = mapping;
     }
 
-    const MDCVInfoPDB70* record =
-      (const MDCVInfoPDB70*)full_file.GetObject(rawmodule->cv_record.rva,
-                                                MDCVInfoPDB70_minsize);
+    const MDCVInfoPDB70* record = reinterpret_cast<const MDCVInfoPDB70*>(
+        full_file.GetData(rawmodule->cv_record.rva, MDCVInfoPDB70_minsize));
     char guid[40];
     sprintf(guid, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
             record->signature.data1, record->signature.data2,
@@ -796,7 +736,8 @@
             record->signature.data4[2], record->signature.data4[3],
             record->signature.data4[4], record->signature.data4[5],
             record->signature.data4[6], record->signature.data4[7]);
-    std::string filename = full_file.GetString(rawmodule->module_name_rva);
+    std::string filename =
+        full_file.GetAsciiMDString(rawmodule->module_name_rva);
     size_t slash = filename.find_last_of('/');
     std::string basename = slash == std::string::npos ?
       filename : filename.substr(slash + 1);
@@ -869,7 +810,7 @@
 
 static void
 AugmentMappings(CrashedProcess* crashinfo,
-                const MMappedRange &full_file) {
+                const MinidumpMemoryRange& full_file) {
   // For each thread, find the memory mapping that matches the thread's stack.
   // Then adjust the mapping to include the stack dump.
   for (unsigned i = 0; i < crashinfo->threads.size(); ++i) {
@@ -903,7 +844,7 @@
     link_map.l_ld = (ElfW(Dyn)*)iter->ld;
     link_map.l_prev = prev;
     prev = (struct link_map*)(start_addr + data.size());
-    std::string filename = full_file.GetString(iter->name);
+    std::string filename = full_file.GetAsciiMDString(iter->name);
 
     // Look up signature for this filename. If available, change filename
     // to point to GUID, instead.
@@ -976,10 +917,9 @@
     return 1;
   }
 
-  MMappedRange dump(mapped_file.data(), mapped_file.size());
+  MinidumpMemoryRange dump(mapped_file.data(), mapped_file.size());
 
-  const MDRawHeader* header =
-      (const MDRawHeader*) dump.GetObject(0, sizeof(MDRawHeader));
+  const MDRawHeader* header = dump.GetData<MDRawHeader>(0);
 
   CrashedProcess crashinfo;
 
@@ -988,8 +928,7 @@
   bool ok = false;
   for (unsigned i = 0; i < header->stream_count; ++i) {
     const MDRawDirectory* dirent =
-        (const MDRawDirectory*) dump.GetArrayElement(
-            header->stream_directory_rva, sizeof(MDRawDirectory), i);
+        dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i);
     switch (dirent->stream_type) {
       case MD_SYSTEM_INFO_STREAM:
         ParseSystemInfo(&crashinfo, dump.Subrange(dirent->location), dump);
@@ -1006,8 +945,7 @@
 
   for (unsigned i = 0; i < header->stream_count; ++i) {
     const MDRawDirectory* dirent =
-        (const MDRawDirectory*) dump.GetArrayElement(
-            header->stream_directory_rva, sizeof(MDRawDirectory), i);
+        dump.GetArrayElement<MDRawDirectory>(header->stream_directory_rva, i);
     switch (dirent->stream_type) {
       case MD_THREAD_LIST_STREAM:
         ParseThreadList(&crashinfo, dump.Subrange(dirent->location), dump);
diff --git a/src/tools/linux/md2core/minidump_memory_range.h b/src/tools/linux/md2core/minidump_memory_range.h
new file mode 100644
index 0000000..b0d8255
--- /dev/null
+++ b/src/tools/linux/md2core/minidump_memory_range.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_memory_range.h: Define the google_breakpad::MinidumpMemoryRange
+// class, which adds methods for handling minidump specific data structures
+// on top of google_breakpad::MemoryRange. See common/memory_range.h for
+// more details on MemoryRange.
+
+#ifndef TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
+#define TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
+
+#include <string>
+
+#include "common/memory_range.h"
+#include "google_breakpad/common/minidump_format.h"
+
+namespace google_breakpad {
+
+// A derived class of MemoryRange with added methods for handling minidump
+// specific data structures. To avoid virtual functions, it is not designed
+// to be used polymorphically.
+class MinidumpMemoryRange : public MemoryRange {
+ public:
+  MinidumpMemoryRange() {}
+
+  MinidumpMemoryRange(const void* data, size_t length)
+      : MemoryRange(data, length) {}
+
+  // Returns a subrange of |length| bytes at |offset| bytes of this memory
+  // range, or an empty range if the subrange is out of bounds.
+  // This methods overrides the base implemementation in order to return
+  // an instance of MinidumpMemoryRange instead of MemoryRange.
+  MinidumpMemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
+    if (Covers(sub_offset, sub_length))
+      return MinidumpMemoryRange(data() + sub_offset, sub_length);
+    return MinidumpMemoryRange();
+  }
+
+  // Returns a subrange that covers the offset and length specified by
+  // |location|, or an empty range if the subrange is out of bounds.
+  MinidumpMemoryRange Subrange(const MDLocationDescriptor& location) const {
+    return MinidumpMemoryRange::Subrange(location.rva, location.data_size);
+  }
+
+  // Gets a STL string from a MDString at |sub_offset| bytes of this memory
+  // range. This method only works correctly for ASCII characters and does
+  // not convert between UTF-16 and UTF-8.
+  const std::string GetAsciiMDString(size_t sub_offset) const {
+    std::string str;
+    const MDString* md_str = GetData<MDString>(sub_offset);
+    if (md_str) {
+      const u_int16_t* buffer = &md_str->buffer[0];
+      for (u_int32_t i = 0; i < md_str->length && buffer[i]; ++i) {
+        str.push_back(buffer[i]);
+      }
+    }
+    return str;
+  }
+};
+
+}  // namespace google_breakpad
+
+#endif  // TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
diff --git a/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
new file mode 100644
index 0000000..bf94ad5
--- /dev/null
+++ b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2011, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// minidump_memory_range_unittest.cc:
+// Unit tests for google_breakpad::MinidumpMemoryRange.
+
+#include "breakpad_googletest_includes.h"
+#include "tools/linux/md2core/minidump_memory_range.h"
+
+using google_breakpad::MinidumpMemoryRange;
+using testing::Message;
+
+namespace {
+
+const u_int32_t kBuffer[10] = { 0 };
+const size_t kBufferSize = sizeof(kBuffer);
+const u_int8_t* kBufferPointer = reinterpret_cast<const u_int8_t*>(kBuffer);
+
+// Test vectors for verifying Covers, GetData, and Subrange.
+const struct {
+  bool valid;
+  size_t offset;
+  size_t length;
+} kSubranges[] = {
+  { true, 0, 0 },
+  { true, 0, 2 },
+  { true, 0, kBufferSize },
+  { true, 2, 0 },
+  { true, 2, 4 },
+  { true, 2, kBufferSize - 2 },
+  { true, kBufferSize - 1, 1 },
+  { false, kBufferSize, 0 },
+  { false, kBufferSize, -1 },
+  { false, kBufferSize + 1, 0 },
+  { false, -1, 2 },
+  { false, 1, kBufferSize },
+  { false, kBufferSize - 1, 2 },
+  { false, 0, -1 },
+  { false, 1, -1 },
+};
+const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]);
+
+// Test vectors for verifying GetArrayElement.
+const struct {
+  size_t offset;
+  size_t size;
+  size_t index;
+  const void* const pointer;
+} kElements[] = {
+  // Valid array elemenets
+  { 0, 1, 0, kBufferPointer },
+  { 0, 1, 1, kBufferPointer + 1 },
+  { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 },
+  { 0, 2, 1, kBufferPointer + 2 },
+  { 0, 4, 2, kBufferPointer + 8 },
+  { 0, 4, 9, kBufferPointer + 36 },
+  { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 },
+  // Invalid array elemenets
+  { 0, 1, kBufferSize, NULL },
+  { 0, 4, 10, NULL },
+  { kBufferSize - 1, 1, 1, NULL },
+  { kBufferSize - 1, 2, 0, NULL },
+  { kBufferSize, 1, 0, NULL },
+};
+const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]);
+
+}  // namespace
+
+TEST(MinidumpMemoryRangeTest, DefaultConstructor) {
+  MinidumpMemoryRange range;
+  EXPECT_EQ(NULL, range.data());
+  EXPECT_EQ(0, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  EXPECT_EQ(kBufferPointer, range.data());
+  EXPECT_EQ(kBufferSize, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, Reset) {
+  MinidumpMemoryRange range;
+  range.Reset();
+  EXPECT_EQ(NULL, range.data());
+  EXPECT_EQ(0, range.length());
+
+  range.Set(kBuffer, kBufferSize);
+  EXPECT_EQ(kBufferPointer, range.data());
+  EXPECT_EQ(kBufferSize, range.length());
+
+  range.Reset();
+  EXPECT_EQ(NULL, range.data());
+  EXPECT_EQ(0, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, Set) {
+  MinidumpMemoryRange range;
+  range.Set(kBuffer, kBufferSize);
+  EXPECT_EQ(kBufferPointer, range.data());
+  EXPECT_EQ(kBufferSize, range.length());
+
+  range.Set(NULL, 0);
+  EXPECT_EQ(NULL, range.data());
+  EXPECT_EQ(0, range.length());
+}
+
+TEST(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) {
+  MinidumpMemoryRange range;
+  MinidumpMemoryRange subrange = range.Subrange(0, 10);
+  EXPECT_EQ(NULL, subrange.data());
+  EXPECT_EQ(0, subrange.length());
+}
+
+TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  for (size_t i = 0; i < kNumSubranges; ++i) {
+    bool valid = kSubranges[i].valid;
+    size_t sub_offset = kSubranges[i].offset;
+    size_t sub_length = kSubranges[i].length;
+    SCOPED_TRACE(Message() << "offset=" << sub_offset
+                 << ", length=" << sub_length);
+
+    MinidumpMemoryRange subrange = range.Subrange(sub_offset, sub_length);
+    if (valid) {
+      EXPECT_TRUE(range.Covers(sub_offset, sub_length));
+      EXPECT_EQ(kBufferPointer + sub_offset,
+                range.GetData(sub_offset, sub_length));
+      EXPECT_EQ(kBufferPointer + sub_offset, subrange.data());
+      EXPECT_EQ(sub_length, subrange.length());
+    } else {
+      EXPECT_FALSE(range.Covers(sub_offset, sub_length));
+      EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length));
+      EXPECT_EQ(NULL, subrange.data());
+      EXPECT_EQ(0, subrange.length());
+    }
+  }
+}
+
+TEST(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  for (size_t i = 0; i < kNumSubranges; ++i) {
+    bool valid = kSubranges[i].valid;
+    size_t sub_offset = kSubranges[i].offset;
+    size_t sub_length = kSubranges[i].length;
+    SCOPED_TRACE(Message() << "offset=" << sub_offset
+                 << ", length=" << sub_length);
+
+    MDLocationDescriptor location;
+    location.rva = sub_offset;
+    location.data_size = sub_length;
+    MinidumpMemoryRange subrange = range.Subrange(location);
+    if (valid) {
+      EXPECT_TRUE(range.Covers(sub_offset, sub_length));
+      EXPECT_EQ(kBufferPointer + sub_offset,
+                range.GetData(sub_offset, sub_length));
+      EXPECT_EQ(kBufferPointer + sub_offset, subrange.data());
+      EXPECT_EQ(sub_length, subrange.length());
+    } else {
+      EXPECT_FALSE(range.Covers(sub_offset, sub_length));
+      EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length));
+      EXPECT_EQ(NULL, subrange.data());
+      EXPECT_EQ(0, subrange.length());
+    }
+  }
+}
+
+TEST(MinidumpMemoryRangeTest, GetDataWithTemplateType) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  const char* char_pointer = range.GetData<char>(0);
+  EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
+  const int* int_pointer = range.GetData<int>(0);
+  EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
+}
+
+TEST(MinidumpMemoryRangeTest, GetArrayElement) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  for (size_t i = 0; i < kNumElements; ++i) {
+    size_t element_offset = kElements[i].offset;
+    size_t element_size = kElements[i].size;
+    unsigned element_index = kElements[i].index;
+    const void* const element_pointer = kElements[i].pointer;
+    SCOPED_TRACE(Message() << "offset=" << element_offset
+                 << ", size=" << element_size
+                 << ", index=" << element_index);
+    EXPECT_EQ(element_pointer, range.GetArrayElement(
+        element_offset, element_size, element_index));
+  }
+}
+
+TEST(MinidumpMemoryRangeTest, GetArrayElmentWithTemplateType) {
+  MinidumpMemoryRange range(kBuffer, kBufferSize);
+  const char* char_pointer = range.GetArrayElement<char>(0, 0);
+  EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
+  const int* int_pointer = range.GetArrayElement<int>(0, 0);
+  EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
+}
+
+TEST(MinidumpMemoryRangeTest, GetAsciiMDString) {
+  u_int8_t buffer[100] = { 0 };
+
+  MDString* md_str = reinterpret_cast<MDString*>(buffer);
+  md_str->length = 4;
+  md_str->buffer[0] = 'T';
+  md_str->buffer[1] = 'e';
+  md_str->buffer[2] = 's';
+  md_str->buffer[3] = 't';
+  md_str->buffer[4] = '\0';
+
+  size_t str2_offset =
+      sizeof(MDString) + (md_str->length + 1) * sizeof(u_int16_t);
+
+  md_str = reinterpret_cast<MDString*>(buffer + str2_offset);
+  md_str->length = 9;  // Test length larger than actual string
+  md_str->buffer[0] = 'S';
+  md_str->buffer[1] = 't';
+  md_str->buffer[2] = 'r';
+  md_str->buffer[3] = 'i';
+  md_str->buffer[4] = 'n';
+  md_str->buffer[5] = 'g';
+  md_str->buffer[6] = '\0';
+  md_str->buffer[7] = '1';
+  md_str->buffer[8] = '2';
+
+  MinidumpMemoryRange range(buffer, sizeof(buffer));
+  EXPECT_EQ("Test", range.GetAsciiMDString(0));
+  EXPECT_EQ("String", range.GetAsciiMDString(str2_offset));
+
+  // Test out-of-bounds cases.
+  EXPECT_EQ("", range.GetAsciiMDString(
+      sizeof(buffer) - sizeof(MDString) + 1));
+  EXPECT_EQ("", range.GetAsciiMDString(sizeof(buffer)));
+}