aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbenchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-12-16 16:42:59 +0000
committerbenchan@chromium.org <benchan@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-12-16 16:42:59 +0000
commitf044345c23c0324942b7375e7a09558267651523 (patch)
tree55a0847ef9681e390bad9c97458c352cc1da75ed
parentFix ContextDeathTest.X86BadFlags unit test on Mac OS X. (diff)
downloadbreakpad-f044345c23c0324942b7375e7a09558267651523.tar.xz
Refactor code in preparation of merging with the fork in Chromium OS.
This patch is part of a bigger patch that helps merging the breakpad code with the modified version in Chromium OS. Specifically, this patch makes the following changes: 1. Add a MemoryRange class for encapsulating and checking read access to a contiguous range of memory. 2. Add a MemoryMappedFile class for mapping a file into memory for read-only access. 3. Refactor other source code to use MemoryMappedFile. 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/332001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@895 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--Makefile.am11
-rw-r--r--Makefile.in96
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc21
-rw-r--r--src/common/basictypes.h39
-rw-r--r--src/common/linux/file_id.cc26
-rw-r--r--src/common/linux/file_id.h2
-rw-r--r--src/common/linux/memory_mapped_file.cc102
-rw-r--r--src/common/linux/memory_mapped_file.h86
-rw-r--r--src/common/linux/memory_mapped_file_unittest.cc192
-rw-r--r--src/common/memory_range.h151
-rw-r--r--src/common/memory_range_unittest.cc193
-rw-r--r--src/tools/linux/md2core/minidump-2-core.cc24
12 files changed, 878 insertions, 65 deletions
diff --git a/Makefile.am b/Makefile.am
index cfb57571..61921602 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
-# Copyright (c) 2010, Google Inc.
+# Copyright (c) 2011, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -72,7 +72,8 @@ src_client_linux_libbreakpad_client_a_SOURCES = \
src/common/md5.cc \
src/common/string_conversion.cc \
src/common/linux/file_id.cc \
- src/common/linux/guid_creator.cc
+ src/common/linux/guid_creator.cc \
+ src/common/linux/memory_mapped_file.cc
endif LINUX_HOST
if !DISABLE_PROCESSOR
@@ -312,6 +313,7 @@ src_client_linux_linux_client_unittest_LDADD = \
src/common/md5.o \
src/common/linux/file_id.o \
src/common/linux/guid_creator.o \
+ src/common/linux/memory_mapped_file.o \
src/common/string_conversion.o
src_client_linux_linux_client_unittest_DEPENDENCIES = src/client/linux/linux_dumper_unittest_helper src/client/linux/libbreakpad_client.a src/libbreakpad.a
@@ -331,9 +333,11 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
src/common/linux/dump_symbols.cc \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/file_id.cc \
+ src/common/linux/memory_mapped_file.cc \
src/tools/linux/dump_syms/dump_syms.cc
src_tools_linux_md2core_minidump_2_core_SOURCES = \
+ src/common/linux/memory_mapped_file.cc \
src/tools/linux/md2core/minidump-2-core.cc
src_tools_linux_symupload_minidump_upload_SOURCES = \
@@ -355,6 +359,7 @@ src_common_dumper_unittest_SOURCES = \
src/common/dwarf_line_to_module.cc \
src/common/dwarf_line_to_module_unittest.cc \
src/common/language.cc \
+ src/common/memory_range_unittest.cc \
src/common/module.cc \
src/common/module_unittest.cc \
src/common/stabs_reader.cc \
@@ -373,6 +378,8 @@ src_common_dumper_unittest_SOURCES = \
src/common/linux/dump_symbols_unittest.cc \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module_unittest.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/memory_mapped_file_unittest.cc \
src/common/linux/synth_elf.cc \
src/common/linux/synth_elf_unittest.cc \
src/common/linux/file_id.cc \
diff --git a/Makefile.in b/Makefile.in
index 4419d3a3..001ac84d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -15,7 +15,7 @@
@SET_MAKE@
-# Copyright (c) 2010, Google Inc.
+# Copyright (c) 2011, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -173,7 +173,8 @@ am__src_client_linux_libbreakpad_client_a_SOURCES_DIST = \
src/client/linux/minidump_writer/minidump_writer.cc \
src/client/minidump_file_writer.cc src/common/convert_UTF.c \
src/common/md5.cc src/common/string_conversion.cc \
- src/common/linux/file_id.cc src/common/linux/guid_creator.cc
+ src/common/linux/file_id.cc src/common/linux/guid_creator.cc \
+ src/common/linux/memory_mapped_file.cc
am__dirstamp = $(am__leading_dot)dirstamp
@LINUX_HOST_TRUE@am_src_client_linux_libbreakpad_client_a_OBJECTS = src/client/linux/crash_generation/crash_generation_client.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/client/linux/handler/exception_handler.$(OBJEXT) \
@@ -184,7 +185,8 @@ am__dirstamp = $(am__leading_dot)dirstamp
@LINUX_HOST_TRUE@ src/common/md5.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/common/string_conversion.$(OBJEXT) \
@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \
-@LINUX_HOST_TRUE@ src/common/linux/guid_creator.$(OBJEXT)
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.$(OBJEXT) \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.$(OBJEXT)
src_client_linux_libbreakpad_client_a_OBJECTS = \
$(am_src_client_linux_libbreakpad_client_a_OBJECTS)
src_libbreakpad_a_AR = $(AR) $(ARFLAGS)
@@ -421,9 +423,9 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/dwarf_cu_to_module_unittest.cc \
src/common/dwarf_line_to_module.cc \
src/common/dwarf_line_to_module_unittest.cc \
- src/common/language.cc src/common/module.cc \
- src/common/module_unittest.cc src/common/stabs_reader.cc \
- src/common/stabs_reader_unittest.cc \
+ src/common/language.cc src/common/memory_range_unittest.cc \
+ src/common/module.cc src/common/module_unittest.cc \
+ src/common/stabs_reader.cc src/common/stabs_reader_unittest.cc \
src/common/stabs_to_module.cc \
src/common/stabs_to_module_unittest.cc \
src/common/test_assembler.cc src/common/dwarf/bytereader.cc \
@@ -437,6 +439,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
src/common/linux/dump_symbols_unittest.cc \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/elf_symbols_to_module_unittest.cc \
+ src/common/linux/memory_mapped_file.cc \
+ src/common/linux/memory_mapped_file_unittest.cc \
src/common/linux/synth_elf.cc \
src/common/linux/synth_elf_unittest.cc \
src/common/linux/file_id.cc \
@@ -452,6 +456,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-language.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT) \
@@ -470,6 +475,8 @@ am__src_common_dumper_unittest_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-synth_elf_unittest.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-file_id.$(OBJEXT) \
@@ -881,6 +888,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
src/common/linux/dump_symbols.cc \
src/common/linux/elf_symbols_to_module.cc \
src/common/linux/file_id.cc \
+ src/common/linux/memory_mapped_file.cc \
src/tools/linux/dump_syms/dump_syms.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_dump_syms_dump_syms_OBJECTS = src/common/dwarf_cfi_to_module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_cu_to_module.$(OBJEXT) \
@@ -895,13 +903,16 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.$(OBJEXT) \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms.$(OBJEXT)
src_tools_linux_dump_syms_dump_syms_OBJECTS = \
$(am_src_tools_linux_dump_syms_dump_syms_OBJECTS)
src_tools_linux_dump_syms_dump_syms_LDADD = $(LDADD)
am__src_tools_linux_md2core_minidump_2_core_SOURCES_DIST = \
+ src/common/linux/memory_mapped_file.cc \
src/tools/linux/md2core/minidump-2-core.cc
-@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_OBJECTS = src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@am_src_tools_linux_md2core_minidump_2_core_OBJECTS = src/common/linux/memory_mapped_file.$(OBJEXT) \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.$(OBJEXT)
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)
@@ -1160,7 +1171,8 @@ lib_LIBRARIES = $(am__append_1) $(am__append_3)
@LINUX_HOST_TRUE@ src/common/md5.cc \
@LINUX_HOST_TRUE@ src/common/string_conversion.cc \
@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
-@LINUX_HOST_TRUE@ src/common/linux/guid_creator.cc
+@LINUX_HOST_TRUE@ src/common/linux/guid_creator.cc \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc
@DISABLE_PROCESSOR_FALSE@src_libbreakpad_a_SOURCES = \
@DISABLE_PROCESSOR_FALSE@ src/google_breakpad/common/breakpad_types.h \
@@ -1329,6 +1341,7 @@ TESTS_ENVIRONMENT =
@LINUX_HOST_TRUE@ src/common/md5.o \
@LINUX_HOST_TRUE@ src/common/linux/file_id.o \
@LINUX_HOST_TRUE@ src/common/linux/guid_creator.o \
+@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.o \
@LINUX_HOST_TRUE@ src/common/string_conversion.o
@LINUX_HOST_TRUE@src_client_linux_linux_client_unittest_DEPENDENCIES = src/client/linux/linux_dumper_unittest_helper src/client/linux/libbreakpad_client.a src/libbreakpad.a
@@ -1346,9 +1359,11 @@ TESTS_ENVIRONMENT =
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/dump_syms/dump_syms.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_md2core_minidump_2_core_SOURCES = \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/tools/linux/md2core/minidump-2-core.cc
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@src_tools_linux_symupload_minidump_upload_SOURCES = \
@@ -1370,6 +1385,7 @@ TESTS_ENVIRONMENT =
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf_line_to_module_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/language.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/memory_range_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/module_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/stabs_reader.cc \
@@ -1388,6 +1404,8 @@ TESTS_ENVIRONMENT =
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_symbols_to_module_unittest.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file.cc \
+@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/memory_mapped_file_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/synth_elf_unittest.cc \
@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/file_id.cc \
@@ -2129,6 +2147,9 @@ src/common/linux/file_id.$(OBJEXT): src/common/linux/$(am__dirstamp) \
src/common/linux/guid_creator.$(OBJEXT): \
src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/memory_mapped_file.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
src/client/linux/$(am__dirstamp):
@$(MKDIR_P) src/client/linux
@: > src/client/linux/$(am__dirstamp)
@@ -2394,6 +2415,9 @@ src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT):
src/common/src_common_dumper_unittest-language.$(OBJEXT): \
src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(am__dirstamp)
+src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT): \
+ src/common/$(am__dirstamp) \
+ src/common/$(DEPDIR)/$(am__dirstamp)
src/common/src_common_dumper_unittest-module.$(OBJEXT): \
src/common/$(am__dirstamp) \
src/common/$(DEPDIR)/$(am__dirstamp)
@@ -2454,6 +2478,12 @@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT): \
src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT): \
src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.$(OBJEXT): \
+ src/common/linux/$(am__dirstamp) \
+ src/common/linux/$(DEPDIR)/$(am__dirstamp)
src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT): \
src/common/linux/$(am__dirstamp) \
src/common/linux/$(DEPDIR)/$(am__dirstamp)
@@ -2900,12 +2930,15 @@ mostlyclean-compile:
-rm -f src/common/linux/file_id.$(OBJEXT)
-rm -f src/common/linux/guid_creator.$(OBJEXT)
-rm -f src/common/linux/http_upload.$(OBJEXT)
+ -rm -f src/common/linux/memory_mapped_file.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-dump_symbols_unittest.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-elf_symbols_to_module.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-file_id.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-file_id_unittest.$(OBJEXT)
+ -rm -f src/common/linux/src_common_dumper_unittest-memory_mapped_file.$(OBJEXT)
+ -rm -f src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-synth_elf.$(OBJEXT)
-rm -f src/common/linux/src_common_dumper_unittest-synth_elf_unittest.$(OBJEXT)
-rm -f src/common/md5.$(OBJEXT)
@@ -2919,6 +2952,7 @@ mostlyclean-compile:
-rm -f src/common/src_common_dumper_unittest-dwarf_line_to_module.$(OBJEXT)
-rm -f src/common/src_common_dumper_unittest-dwarf_line_to_module_unittest.$(OBJEXT)
-rm -f src/common/src_common_dumper_unittest-language.$(OBJEXT)
+ -rm -f src/common/src_common_dumper_unittest-memory_range_unittest.$(OBJEXT)
-rm -f src/common/src_common_dumper_unittest-module.$(OBJEXT)
-rm -f src/common/src_common_dumper_unittest-module_unittest.$(OBJEXT)
-rm -f src/common/src_common_dumper_unittest-stabs_reader.$(OBJEXT)
@@ -3092,6 +3126,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-dwarf_line_to_module_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-language.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-module_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/$(DEPDIR)/src_common_dumper_unittest-stabs_reader.Po@am__quote@
@@ -3124,12 +3159,15 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/file_id.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/guid_creator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/http_upload.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/memory_mapped_file.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-elf_symbols_to_module_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-file_id_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/address_map_unittest.Po@am__quote@
@@ -3598,6 +3636,20 @@ src/common/src_common_dumper_unittest-language.obj: src/common/language.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-language.obj `if test -f 'src/common/language.cc'; then $(CYGPATH_W) 'src/common/language.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/language.cc'; fi`
+src/common/src_common_dumper_unittest-memory_range_unittest.o: src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-memory_range_unittest.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo -c -o src/common/src_common_dumper_unittest-memory_range_unittest.o `test -f 'src/common/memory_range_unittest.cc' || echo '$(srcdir)/'`src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/memory_range_unittest.cc' object='src/common/src_common_dumper_unittest-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_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-memory_range_unittest.o `test -f 'src/common/memory_range_unittest.cc' || echo '$(srcdir)/'`src/common/memory_range_unittest.cc
+
+src/common/src_common_dumper_unittest-memory_range_unittest.obj: src/common/memory_range_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-memory_range_unittest.obj -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo -c -o src/common/src_common_dumper_unittest-memory_range_unittest.obj `if test -f 'src/common/memory_range_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_range_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-memory_range_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/memory_range_unittest.cc' object='src/common/src_common_dumper_unittest-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_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/src_common_dumper_unittest-memory_range_unittest.obj `if test -f 'src/common/memory_range_unittest.cc'; then $(CYGPATH_W) 'src/common/memory_range_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/memory_range_unittest.cc'; fi`
+
src/common/src_common_dumper_unittest-module.o: src/common/module.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/src_common_dumper_unittest-module.o -MD -MP -MF src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo -c -o src/common/src_common_dumper_unittest-module.o `test -f 'src/common/module.cc' || echo '$(srcdir)/'`src/common/module.cc
@am__fastdepCXX_TRUE@ $(am__mv) src/common/$(DEPDIR)/src_common_dumper_unittest-module.Tpo src/common/$(DEPDIR)/src_common_dumper_unittest-module.Po
@@ -3850,6 +3902,34 @@ src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj:
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-elf_symbols_to_module_unittest.obj `if test -f 'src/common/linux/elf_symbols_to_module_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/elf_symbols_to_module_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/elf_symbols_to_module_unittest.cc'; fi`
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.o: src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.o `test -f 'src/common/linux/memory_mapped_file.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/memory_mapped_file.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.o `test -f 'src/common/linux/memory_mapped_file.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file.cc
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj: src/common/linux/memory_mapped_file.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj `if test -f 'src/common/linux/memory_mapped_file.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/memory_mapped_file.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file.obj `if test -f 'src/common/linux/memory_mapped_file.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file.cc'; fi`
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o: src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o `test -f 'src/common/linux/memory_mapped_file_unittest.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/memory_mapped_file_unittest.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.o `test -f 'src/common/linux/memory_mapped_file_unittest.cc' || echo '$(srcdir)/'`src/common/linux/memory_mapped_file_unittest.cc
+
+src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj: src/common/linux/memory_mapped_file_unittest.cc
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj `if test -f 'src/common/linux/memory_mapped_file_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file_unittest.cc'; fi`
+@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-memory_mapped_file_unittest.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/common/linux/memory_mapped_file_unittest.cc' object='src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-memory_mapped_file_unittest.obj `if test -f 'src/common/linux/memory_mapped_file_unittest.cc'; then $(CYGPATH_W) 'src/common/linux/memory_mapped_file_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/memory_mapped_file_unittest.cc'; fi`
+
src/common/linux/src_common_dumper_unittest-synth_elf.o: src/common/linux/synth_elf.cc
@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-synth_elf.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo -c -o src/common/linux/src_common_dumper_unittest-synth_elf.o `test -f 'src/common/linux/synth_elf.cc' || echo '$(srcdir)/'`src/common/linux/synth_elf.cc
@am__fastdepCXX_TRUE@ $(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-synth_elf.Po
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index ab3a5ea5..f4ab5b1f 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -56,6 +56,7 @@
#include "client/linux/minidump_writer/line_reader.h"
#include "common/linux/file_id.h"
#include "common/linux/linux_libc_support.h"
+#include "common/linux/memory_mapped_file.h"
#include "third_party/lss/linux_syscall_support.h"
static const char kMappedFileUnsafePrefix[] = "/dev/";
@@ -237,24 +238,12 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
filename[filename_len] = '\0';
bool filename_modified = HandleDeletedFileInMapping(filename);
- int fd = sys_open(filename, O_RDONLY, 0);
- if (fd < 0)
- return false;
- struct kernel_stat st;
- if (sys_fstat(fd, &st) != 0) {
- sys_close(fd);
- return false;
- }
-#if defined(__x86_64)
-#define sys_mmap2 sys_mmap
-#endif
- void* base = sys_mmap2(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- sys_close(fd);
- if (base == MAP_FAILED)
+ MemoryMappedFile mapped_file(filename);
+ if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
return false;
- bool success = FileID::ElfFileIdentifierFromMappedFile(base, identifier);
- sys_munmap(base, st.st_size);
+ bool success =
+ FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
if (success && member && filename_modified) {
mappings_[mapping_id]->name[filename_len -
sizeof(kDeletedSuffix) + 1] = '\0';
diff --git a/src/common/basictypes.h b/src/common/basictypes.h
new file mode 100644
index 00000000..694f7022
--- /dev/null
+++ b/src/common/basictypes.h
@@ -0,0 +1,39 @@
+// 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.
+
+#ifndef COMMON_BASICTYPES_H_
+#define COMMON_BASICTYPES_H_
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+#endif // COMMON_BASICTYPES_H_
diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc
index 13f4f3ad..bffef621 100644
--- a/src/common/linux/file_id.cc
+++ b/src/common/linux/file_id.cc
@@ -37,21 +37,17 @@
#include <arpa/inet.h>
#include <assert.h>
#include <elf.h>
-#include <fcntl.h>
#if defined(__ANDROID__)
#include "client/linux/android_link.h"
#else
#include <link.h>
#endif
-#include <stdio.h>
#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include <algorithm>
#include "common/linux/linux_libc_support.h"
+#include "common/linux/memory_mapped_file.h"
#include "third_party/lss/linux_syscall_support.h"
namespace google_breakpad {
@@ -231,7 +227,7 @@ static bool HashElfTextSection(const void *elf_mapped_base,
}
// static
-bool FileID::ElfFileIdentifierFromMappedFile(void* base,
+bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
uint8_t identifier[kMDGUIDSize]) {
// Look for a build id note first.
if (FindElfBuildIDNote(base, identifier))
@@ -242,23 +238,11 @@ bool FileID::ElfFileIdentifierFromMappedFile(void* base,
}
bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
- int fd = open(path_, O_RDONLY);
- if (fd < 0)
- return false;
- struct stat st;
- if (fstat(fd, &st) != 0) {
- close(fd);
- return false;
- }
- void* base = mmap(NULL, st.st_size,
- PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
- close(fd);
- if (base == MAP_FAILED)
+ MemoryMappedFile mapped_file(path_);
+ if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
return false;
- bool success = ElfFileIdentifierFromMappedFile(base, identifier);
- munmap(base, st.st_size);
- return success;
+ return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
}
// static
diff --git a/src/common/linux/file_id.h b/src/common/linux/file_id.h
index 4d5b52dc..70a6b3f5 100644
--- a/src/common/linux/file_id.h
+++ b/src/common/linux/file_id.h
@@ -57,7 +57,7 @@ class FileID {
// Load the identifier for the elf file mapped into memory at |base| into
// |identifier|. Return false if the identifier could not be created for the
// file.
- static bool ElfFileIdentifierFromMappedFile(void* base,
+ static bool ElfFileIdentifierFromMappedFile(const void* base,
uint8_t identifier[kMDGUIDSize]);
// Convert the |identifier| data to a NULL terminated string. The string will
diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc
new file mode 100644
index 00000000..6f450bd3
--- /dev/null
+++ b/src/common/linux/memory_mapped_file.cc
@@ -0,0 +1,102 @@
+// 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.
+
+// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile.
+// See memory_mapped_file.h for details.
+
+#include "common/linux/memory_mapped_file.h"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "common/memory_range.h"
+#include "third_party/lss/linux_syscall_support.h"
+
+namespace google_breakpad {
+
+MemoryMappedFile::MemoryMappedFile() {}
+
+MemoryMappedFile::MemoryMappedFile(const char* path) {
+ Map(path);
+}
+
+MemoryMappedFile::~MemoryMappedFile() {
+ Unmap();
+}
+
+bool MemoryMappedFile::Map(const char* path) {
+ Unmap();
+
+ int fd = sys_open(path, O_RDONLY, 0);
+ if (fd == -1) {
+ return false;
+ }
+
+#if defined(__x86_64__)
+ struct kernel_stat st;
+ if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
+#else
+ struct kernel_stat64 st;
+ if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) {
+#endif
+ sys_close(fd);
+ return false;
+ }
+
+ // If the file size is zero, simply use an empty MemoryRange and return
+ // true. Don't bother to call mmap() even though mmap() can handle an
+ // empty file on some platforms.
+ if (st.st_size == 0) {
+ sys_close(fd);
+ return true;
+ }
+
+#if defined(__x86_64__)
+ void* data = sys_mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+#else
+ void* data = sys_mmap2(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+#endif
+ sys_close(fd);
+ if (data == MAP_FAILED) {
+ return false;
+ }
+
+ content_.Set(data, st.st_size);
+ return true;
+}
+
+void MemoryMappedFile::Unmap() {
+ if (content_.data()) {
+ sys_munmap(const_cast<u_int8_t*>(content_.data()), content_.length());
+ content_.Set(NULL, 0);
+ }
+}
+
+} // namespace google_breakpad
diff --git a/src/common/linux/memory_mapped_file.h b/src/common/linux/memory_mapped_file.h
new file mode 100644
index 00000000..6abd5b0c
--- /dev/null
+++ b/src/common/linux/memory_mapped_file.h
@@ -0,0 +1,86 @@
+// 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.
+
+// memory_mapped_file.h: Define the google_breakpad::MemoryMappedFile
+// class, which maps a file into memory for read-only access.
+
+#ifndef COMMON_LINUX_MEMORY_MAPPED_FILE_H_
+#define COMMON_LINUX_MEMORY_MAPPED_FILE_H_
+
+#include "common/basictypes.h"
+#include "common/memory_range.h"
+
+namespace google_breakpad {
+
+// A utility class for mapping a file into memory for read-only access of
+// the file content. Its implementation avoids calling into libc functions
+// by directly making system calls for open, close, mmap, and munmap.
+class MemoryMappedFile {
+ public:
+ MemoryMappedFile();
+
+ // Constructor that calls Map() to map a file at |path| into memory.
+ // If Map() fails, the object behaves as if it is default constructed.
+ explicit MemoryMappedFile(const char* path);
+
+ ~MemoryMappedFile();
+
+ // Maps a file at |path| into memory, which can then be accessed via
+ // content() as a MemoryRange object or via data(), and returns true on
+ // success. Mapping an empty file will succeed but with data() and size()
+ // returning NULL and 0, respectively. An existing mapping is unmapped
+ // before a new mapping is created.
+ bool Map(const char* path);
+
+ // Unmaps the memory for the mapped file. It's a no-op if no file is
+ // mapped.
+ void Unmap();
+
+ // Returns a MemoryRange object that covers the memory for the mapped
+ // file. The MemoryRange object is empty if no file is mapped.
+ const MemoryRange& content() const { return content_; }
+
+ // Returns a pointer to the beginning of the memory for the mapped file.
+ // or NULL if no file is mapped or the mapped file is empty.
+ const void* data() const { return content_.data(); }
+
+ // Returns the size in bytes of the mapped file, or zero if no file
+ // is mapped.
+ size_t size() const { return content_.length(); }
+
+ private:
+ // Mapped file content as a MemoryRange object.
+ MemoryRange content_;
+
+ DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_MEMORY_MAPPED_FILE_H_
diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc
new file mode 100644
index 00000000..8a3129fb
--- /dev/null
+++ b/src/common/linux/memory_mapped_file_unittest.cc
@@ -0,0 +1,192 @@
+// 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.
+
+// memory_mapped_file_unittest.cc:
+// Unit tests for google_breakpad::MemoryMappedFile.
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "breakpad_googletest_includes.h"
+#include "common/linux/eintr_wrapper.h"
+#include "common/linux/memory_mapped_file.h"
+#include "common/tests/auto_tempdir.h"
+
+using google_breakpad::AutoTempDir;
+using google_breakpad::MemoryMappedFile;
+using std::string;
+
+namespace {
+
+bool WriteFile(const string& path, const void* buffer, size_t buffer_size) {
+ int fd =
+ HANDLE_EINTR(open(path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU));
+ if (fd == -1) {
+ perror("open");
+ return false;
+ }
+
+ bool ok = true;
+ if (buffer && buffer_size > 0) {
+ if (HANDLE_EINTR(write(fd, buffer, buffer_size) != buffer_size)) {
+ perror("write");
+ ok = false;
+ }
+ }
+ close(fd);
+ return ok;
+}
+
+class MemoryMappedFileTest : public testing::Test {
+ protected:
+ void ExpectNoMappedData(const MemoryMappedFile& mapped_file) {
+ EXPECT_TRUE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() == NULL);
+ EXPECT_EQ(0, mapped_file.size());
+ }
+};
+
+} // namespace
+
+TEST_F(MemoryMappedFileTest, DefaultConstructor) {
+ MemoryMappedFile mapped_file;
+ ExpectNoMappedData(mapped_file);
+}
+
+TEST_F(MemoryMappedFileTest, UnmapWithoutMap) {
+ MemoryMappedFile mapped_file;
+ mapped_file.Unmap();
+}
+
+TEST_F(MemoryMappedFileTest, MapNonexistentFile) {
+ {
+ MemoryMappedFile mapped_file("nonexistent-file");
+ ExpectNoMappedData(mapped_file);
+ }
+ {
+ MemoryMappedFile mapped_file;
+ EXPECT_FALSE(mapped_file.Map("nonexistent-file"));
+ ExpectNoMappedData(mapped_file);
+ }
+}
+
+TEST_F(MemoryMappedFileTest, MapEmptyFile) {
+ AutoTempDir temp_dir;
+ string test_file = temp_dir.path() + "/empty_file";
+ ASSERT_TRUE(WriteFile(test_file, NULL, 0));
+
+ {
+ MemoryMappedFile mapped_file(test_file.c_str());
+ ExpectNoMappedData(mapped_file);
+ }
+ {
+ MemoryMappedFile mapped_file;
+ EXPECT_TRUE(mapped_file.Map(test_file.c_str()));
+ ExpectNoMappedData(mapped_file);
+ }
+}
+
+TEST_F(MemoryMappedFileTest, MapNonEmptyFile) {
+ char data[256];
+ size_t data_size = sizeof(data);
+ for (size_t i = 0; i < data_size; ++i) {
+ data[i] = i;
+ }
+
+ AutoTempDir temp_dir;
+ string test_file = temp_dir.path() + "/test_file";
+ ASSERT_TRUE(WriteFile(test_file, data, data_size));
+
+ {
+ MemoryMappedFile mapped_file(test_file.c_str());
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
+ }
+ {
+ MemoryMappedFile mapped_file;
+ EXPECT_TRUE(mapped_file.Map(test_file.c_str()));
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
+ }
+}
+
+TEST_F(MemoryMappedFileTest, RemapAfterMap) {
+ char data1[256];
+ size_t data1_size = sizeof(data1);
+ for (size_t i = 0; i < data1_size; ++i) {
+ data1[i] = i;
+ }
+
+ char data2[50];
+ size_t data2_size = sizeof(data2);
+ for (size_t i = 0; i < data2_size; ++i) {
+ data2[i] = 255 - i;
+ }
+
+ AutoTempDir temp_dir;
+ string test_file1 = temp_dir.path() + "/test_file1";
+ string test_file2 = temp_dir.path() + "/test_file2";
+ ASSERT_TRUE(WriteFile(test_file1, data1, data1_size));
+ ASSERT_TRUE(WriteFile(test_file2, data2, data2_size));
+
+ {
+ MemoryMappedFile mapped_file(test_file1.c_str());
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data1_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
+
+ mapped_file.Map(test_file2.c_str());
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data2_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
+ }
+ {
+ MemoryMappedFile mapped_file;
+ EXPECT_TRUE(mapped_file.Map(test_file1.c_str()));
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data1_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
+
+ mapped_file.Map(test_file2.c_str());
+ EXPECT_FALSE(mapped_file.content().IsEmpty());
+ EXPECT_TRUE(mapped_file.data() != NULL);
+ EXPECT_EQ(data2_size, mapped_file.size());
+ EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
+ }
+}
diff --git a/src/common/memory_range.h b/src/common/memory_range.h
new file mode 100644
index 00000000..0c81d1ee
--- /dev/null
+++ b/src/common/memory_range.h
@@ -0,0 +1,151 @@
+// 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.
+
+// memory_range.h: Define the google_breakpad::MemoryRange class, which
+// is a lightweight wrapper with a pointer and a length to encapsulate
+// a contiguous range of memory.
+
+#ifndef COMMON_MEMORY_RANGE_H_
+#define COMMON_MEMORY_RANGE_H_
+
+#include <stddef.h>
+
+#include "google_breakpad/common/breakpad_types.h"
+
+namespace google_breakpad {
+
+// A lightweight wrapper with a pointer and a length to encapsulate a
+// contiguous range of memory. It provides helper methods for checked
+// 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) {}
+
+ MemoryRange(const void* data, size_t length) {
+ Set(data, length);
+ }
+
+ // Returns true if this memory range contains no data.
+ bool IsEmpty() const {
+ // Set() guarantees that |length_| is zero if |data_| is NULL.
+ return length_ == 0;
+ }
+
+ // Resets to an empty range.
+ void Reset() {
+ data_ = NULL;
+ length_ = 0;
+ }
+
+ // Sets this memory range to point to |data| and its length to |length|.
+ void Set(const void* data, size_t length) {
+ data_ = reinterpret_cast<const u_int8_t*>(data);
+ // Always set |length_| to zero if |data_| is NULL.
+ length_ = data ? length : 0;
+ }
+
+ // Returns true if this range covers a subrange of |sub_length| bytes
+ // at |sub_offset| bytes of this memory range, or false otherwise.
+ bool Covers(size_t sub_offset, size_t sub_length) const {
+ // The following checks verify that:
+ // 1. sub_offset is within [ 0 .. length_ - 1 ]
+ // 2. sub_offset + sub_length is within
+ // [ sub_offset .. length_ ]
+ return sub_offset < length_ &&
+ sub_offset + sub_length >= sub_offset &&
+ sub_offset + sub_length <= length_;
+ }
+
+ // Returns a raw data pointer to a subrange of |sub_length| bytes at
+ // |sub_offset| bytes of this memory range, or NULL if the subrange
+ // is out of bounds.
+ const void* GetData(size_t sub_offset, size_t sub_length) const {
+ return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL;
+ }
+
+ // Same as the two-argument version of GetData() but uses sizeof(DataType)
+ // as the subrange length and returns an |DataType| pointer for convenience.
+ template <typename DataType>
+ const DataType* GetData(size_t sub_offset) const {
+ return reinterpret_cast<const DataType*>(
+ GetData(sub_offset, sizeof(DataType)));
+ }
+
+ // Returns a raw pointer to the |element_index|-th element of an array
+ // of elements of length |element_size| starting at |sub_offset| bytes
+ // of this memory range, or NULL if the element is out of bounds.
+ const void* GetArrayElement(size_t element_offset,
+ size_t element_size,
+ unsigned element_index) const {
+ size_t sub_offset = element_offset + element_index * element_size;
+ return GetData(sub_offset, element_size);
+ }
+
+ // Same as the three-argument version of GetArrayElement() but deduces
+ // the element size using sizeof(ElementType) and returns an |ElementType|
+ // pointer for convenience.
+ template <typename ElementType>
+ const ElementType* GetArrayElement(size_t element_offset,
+ unsigned element_index) const {
+ return reinterpret_cast<const ElementType*>(
+ GetArrayElement(element_offset, sizeof(ElementType), element_index));
+ }
+
+ // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of
+ // this memory range, or an empty range if the subrange is out of bounds.
+ MemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
+ return Covers(sub_offset, sub_length) ?
+ MemoryRange(data_ + sub_offset, sub_length) : MemoryRange();
+ }
+
+ // Returns a pointer to the beginning of this memory range.
+ const u_int8_t* data() const { return data_; }
+
+ // Returns the length, in bytes, of this memory range.
+ size_t length() const { return length_; }
+
+ private:
+ // Pointer to the beginning of this memory range.
+ const u_int8_t* data_;
+
+ // Length, in bytes, of this memory range.
+ size_t length_;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_MEMORY_RANGE_H_
diff --git a/src/common/memory_range_unittest.cc b/src/common/memory_range_unittest.cc
new file mode 100644
index 00000000..f0831e85
--- /dev/null
+++ b/src/common/memory_range_unittest.cc
@@ -0,0 +1,193 @@
+// 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.
+
+// memory_range_unittest.cc: Unit tests for google_breakpad::MemoryRange.
+
+#include "breakpad_googletest_includes.h"
+#include "common/memory_range.h"
+
+using google_breakpad::MemoryRange;
+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(MemoryRangeTest, DefaultConstructor) {
+ MemoryRange range;
+ EXPECT_EQ(NULL, range.data());
+ EXPECT_EQ(0, range.length());
+}
+
+TEST(MemoryRangeTest, ConstructorWithDataAndLength) {
+ MemoryRange range(kBuffer, kBufferSize);
+ EXPECT_EQ(kBufferPointer, range.data());
+ EXPECT_EQ(kBufferSize, range.length());
+}
+
+TEST(MemoryRangeTest, Reset) {
+ MemoryRange 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(MemoryRangeTest, Set) {
+ MemoryRange 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(MemoryRangeTest, SubrangeOfEmptyMemoryRange) {
+ MemoryRange range;
+ MemoryRange subrange = range.Subrange(0, 10);
+ EXPECT_EQ(NULL, subrange.data());
+ EXPECT_EQ(0, subrange.length());
+}
+
+TEST(MemoryRangeTest, SubrangeAndGetData) {
+ MemoryRange 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);
+
+ MemoryRange 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(MemoryRangeTest, GetDataWithTemplateType) {
+ MemoryRange 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(MemoryRangeTest, GetArrayElement) {
+ MemoryRange 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(MemoryRangeTest, GetArrayElmentWithTemplateType) {
+ MemoryRange 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);
+}
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc
index efec22e4..ddefecc0 100644
--- a/src/tools/linux/md2core/minidump-2-core.cc
+++ b/src/tools/linux/md2core/minidump-2-core.cc
@@ -35,13 +35,10 @@
#include <elf.h>
#include <errno.h>
-#include <fcntl.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
#include <sys/user.h>
#include <unistd.h>
@@ -50,6 +47,7 @@
#include <vector>
#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 "third_party/lss/linux_syscall_support.h"
@@ -77,6 +75,8 @@
#define ELF_ARCH EM_MIPS
#endif
+using google_breakpad::MemoryMappedFile;
+
static const MDRVA kInvalidMDRVA = static_cast<MDRVA>(-1);
static bool verbose;
@@ -970,21 +970,13 @@ main(int argc, char** argv) {
if (argc != argi + 1)
return usage(argv[0]);
- const int fd = open(argv[argi], O_RDONLY);
- if (fd < 0)
- return usage(argv[0]);
-
- struct stat st;
- fstat(fd, &st);
-
- const void* bytes = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
- close(fd);
- if (bytes == MAP_FAILED) {
- perror("Failed to mmap dump file");
+ MemoryMappedFile mapped_file(argv[argi]);
+ if (!mapped_file.data()) {
+ fprintf(stderr, "Failed to mmap dump file\n");
return 1;
}
- MMappedRange dump(bytes, st.st_size);
+ MMappedRange dump(mapped_file.data(), mapped_file.size());
const MDRawHeader* header =
(const MDRawHeader*) dump.GetObject(0, sizeof(MDRawHeader));
@@ -1187,7 +1179,5 @@ main(int argc, char** argv) {
}
}
- munmap(const_cast<void*>(bytes), st.st_size);
-
return 0;
}