From 3d023a3472e6a0eb1cc09407ff8ad4d2917c0704 Mon Sep 17 00:00:00 2001 From: "thestig@chromium.org" Date: Wed, 23 Apr 2014 20:52:28 +0000 Subject: [PATCH] Linux: Check the CRC32 of the debug link file in the symbol dumper. R=mark@chromium.org Review URL: https://breakpad.appspot.com/1644002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1320 4c0a9323-5329-0410-9bdc-e9ce6186880e --- Makefile.am | 3 ++ Makefile.in | 30 ++++++++++++- src/common/linux/crc32.cc | 70 +++++++++++++++++++++++++++++ src/common/linux/crc32.h | 53 ++++++++++++++++++++++ src/common/linux/dump_symbols.cc | 75 ++++++++++++++++++++++---------- 5 files changed, 206 insertions(+), 25 deletions(-) create mode 100644 src/common/linux/crc32.cc create mode 100644 src/common/linux/crc32.h diff --git a/Makefile.am b/Makefile.am index 410e4c54..0e3f5f09 100644 --- a/Makefile.am +++ b/Makefile.am @@ -462,6 +462,7 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \ src/common/dwarf/bytereader.cc \ src/common/dwarf/dwarf2diehandler.cc \ src/common/dwarf/dwarf2reader.cc \ + src/common/linux/crc32.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elfutils.cc \ @@ -510,6 +511,7 @@ src_common_dumper_unittest_SOURCES = \ src/common/dwarf/dwarf2reader.cc \ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ src/common/dwarf/dwarf2reader_die_unittest.cc \ + src/common/linux/crc32.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols_unittest.cc \ src/common/linux/elf_core_dump.cc \ @@ -1115,6 +1117,7 @@ EXTRA_DIST = \ src/client/windows/sender/crash_report_sender.vcproj \ src/common/convert_UTF.c \ src/common/convert_UTF.h \ + src/common/linux/crc32.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols.h \ src/common/linux/elf_symbols_to_module.cc \ diff --git a/Makefile.in b/Makefile.in index 95162002..53688170 100644 --- a/Makefile.in +++ b/Makefile.in @@ -610,7 +610,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ src/common/dwarf/dwarf2reader.cc \ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ src/common/dwarf/dwarf2reader_die_unittest.cc \ - src/common/linux/dump_symbols.cc \ + src/common/linux/crc32.cc src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols_unittest.cc \ src/common/linux/elf_core_dump.cc \ src/common/linux/elf_core_dump_unittest.cc \ @@ -654,6 +654,7 @@ am__src_common_dumper_unittest_SOURCES_DIST = \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT) \ @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_core_dump.$(OBJEXT) \ @@ -1211,7 +1212,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \ src/common/module.cc src/common/stabs_reader.cc \ src/common/stabs_to_module.cc src/common/dwarf/bytereader.cc \ src/common/dwarf/dwarf2diehandler.cc \ - src/common/dwarf/dwarf2reader.cc \ + src/common/dwarf/dwarf2reader.cc src/common/linux/crc32.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/elf_symbols_to_module.cc \ src/common/linux/elfutils.cc src/common/linux/file_id.cc \ @@ -1229,6 +1230,7 @@ am__src_tools_linux_dump_syms_dump_syms_SOURCES_DIST = \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.$(OBJEXT) \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.$(OBJEXT) \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.$(OBJEXT) \ @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/elfutils.$(OBJEXT) \ @@ -2022,6 +2024,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/bytereader.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2diehandler.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \ @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/elfutils.cc \ @@ -2070,6 +2073,7 @@ TESTS = $(check_PROGRAMS) $(check_SCRIPTS) @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_cfi_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/dwarf/dwarf2reader_die_unittest.cc \ +@DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/crc32.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/dump_symbols_unittest.cc \ @DISABLE_TOOLS_FALSE@@LINUX_HOST_TRUE@ src/common/linux/elf_core_dump.cc \ @@ -2712,6 +2716,7 @@ EXTRA_DIST = \ src/client/windows/sender/crash_report_sender.vcproj \ src/common/convert_UTF.c \ src/common/convert_UTF.h \ + src/common/linux/crc32.cc \ src/common/linux/dump_symbols.cc \ src/common/linux/dump_symbols.h \ src/common/linux/elf_symbols_to_module.cc \ @@ -3387,6 +3392,9 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_cfi_unittest.$(OBJEXT): src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.$(OBJEXT): \ src/common/dwarf/$(am__dirstamp) \ src/common/dwarf/$(DEPDIR)/$(am__dirstamp) +src/common/linux/src_common_dumper_unittest-crc32.$(OBJEXT): \ + src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) src/common/linux/src_common_dumper_unittest-dump_symbols.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -3893,6 +3901,8 @@ src/common/dwarf/dwarf2diehandler.$(OBJEXT): \ src/common/dwarf/dwarf2reader.$(OBJEXT): \ src/common/dwarf/$(am__dirstamp) \ src/common/dwarf/$(DEPDIR)/$(am__dirstamp) +src/common/linux/crc32.$(OBJEXT): src/common/linux/$(am__dirstamp) \ + src/common/linux/$(DEPDIR)/$(am__dirstamp) src/common/linux/dump_symbols.$(OBJEXT): \ src/common/linux/$(am__dirstamp) \ src/common/linux/$(DEPDIR)/$(am__dirstamp) @@ -4062,6 +4072,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_cfi_unittest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/dwarf/$(DEPDIR)/src_common_dumper_unittest-dwarf2reader_die_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/crc32.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/dump_symbols.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_core_dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/elf_symbols_to_module.Po@am__quote@ @@ -4074,6 +4085,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/safe_readlink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-elf_core_dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_client_linux_linux_client_unittest_shlib-linux_libc_support_unittest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.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_core_dump.Po@am__quote@ @@ -4978,6 +4990,20 @@ src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj: src/c @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/dwarf/src_common_dumper_unittest-dwarf2reader_die_unittest.obj `if test -f 'src/common/dwarf/dwarf2reader_die_unittest.cc'; then $(CYGPATH_W) 'src/common/dwarf/dwarf2reader_die_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/dwarf/dwarf2reader_die_unittest.cc'; fi` +src/common/linux/src_common_dumper_unittest-crc32.o: src/common/linux/crc32.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-crc32.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo -c -o src/common/linux/src_common_dumper_unittest-crc32.o `test -f 'src/common/linux/crc32.cc' || echo '$(srcdir)/'`src/common/linux/crc32.cc +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/crc32.cc' object='src/common/linux/src_common_dumper_unittest-crc32.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-crc32.o `test -f 'src/common/linux/crc32.cc' || echo '$(srcdir)/'`src/common/linux/crc32.cc + +src/common/linux/src_common_dumper_unittest-crc32.obj: src/common/linux/crc32.cc +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-crc32.obj -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo -c -o src/common/linux/src_common_dumper_unittest-crc32.obj `if test -f 'src/common/linux/crc32.cc'; then $(CYGPATH_W) 'src/common/linux/crc32.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/crc32.cc'; fi` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-crc32.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/common/linux/crc32.cc' object='src/common/linux/src_common_dumper_unittest-crc32.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/common/linux/src_common_dumper_unittest-crc32.obj `if test -f 'src/common/linux/crc32.cc'; then $(CYGPATH_W) 'src/common/linux/crc32.cc'; else $(CYGPATH_W) '$(srcdir)/src/common/linux/crc32.cc'; fi` + src/common/linux/src_common_dumper_unittest-dump_symbols.o: src/common/linux/dump_symbols.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_common_dumper_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/common/linux/src_common_dumper_unittest-dump_symbols.o -MD -MP -MF src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo -c -o src/common/linux/src_common_dumper_unittest-dump_symbols.o `test -f 'src/common/linux/dump_symbols.cc' || echo '$(srcdir)/'`src/common/linux/dump_symbols.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Tpo src/common/linux/$(DEPDIR)/src_common_dumper_unittest-dump_symbols.Po diff --git a/src/common/linux/crc32.cc b/src/common/linux/crc32.cc new file mode 100644 index 00000000..8df636ce --- /dev/null +++ b/src/common/linux/crc32.cc @@ -0,0 +1,70 @@ +// Copyright 2014 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. + +#include "common/linux/crc32.h" + +namespace google_breakpad { + +// This implementation is based on the sample implementation in RFC 1952. + +// CRC32 polynomial, in reversed form. +// See RFC 1952, or http://en.wikipedia.org/wiki/Cyclic_redundancy_check +static const uint32_t kCrc32Polynomial = 0xEDB88320; +static uint32_t kCrc32Table[256] = { 0 }; + +#define arraysize(f) (sizeof(f) / sizeof(*f)) + +static void EnsureCrc32TableInited() { + if (kCrc32Table[arraysize(kCrc32Table) - 1]) + return; // already inited + for (uint32_t i = 0; i < arraysize(kCrc32Table); ++i) { + uint32_t c = i; + for (size_t j = 0; j < 8; ++j) { + if (c & 1) { + c = kCrc32Polynomial ^ (c >> 1); + } else { + c >>= 1; + } + } + kCrc32Table[i] = c; + } +} + +uint32_t UpdateCrc32(uint32_t start, const void* buf, size_t len) { + EnsureCrc32TableInited(); + + uint32_t c = start ^ 0xFFFFFFFF; + const uint8_t* u = static_cast(buf); + for (size_t i = 0; i < len; ++i) { + c = kCrc32Table[(c ^ u[i]) & 0xFF] ^ (c >> 8); + } + return c ^ 0xFFFFFFFF; +} + +} // namespace google_breakpad diff --git a/src/common/linux/crc32.h b/src/common/linux/crc32.h new file mode 100644 index 00000000..e3d9db92 --- /dev/null +++ b/src/common/linux/crc32.h @@ -0,0 +1,53 @@ +// Copyright 2014 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_LINUX_CRC32_H_ +#define COMMON_LINUX_CRC32_H_ + +#include + +#include + +namespace google_breakpad { + +// Updates a CRC32 checksum with |len| bytes from |buf|. |initial| holds the +// checksum result from the previous update; for the first call, it should be 0. +uint32_t UpdateCrc32(uint32_t initial, const void* buf, size_t len); + +// Computes a CRC32 checksum using |len| bytes from |buf|. +inline uint32_t ComputeCrc32(const void* buf, size_t len) { + return UpdateCrc32(0, buf, len); +} +inline uint32_t ComputeCrc32(const std::string& str) { + return ComputeCrc32(str.c_str(), str.size()); +} + +} // namespace google_breakpad + +#endif // COMMON_LINUX_CRC32_H_ diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 75dcfd4c..b03bea87 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -57,6 +57,8 @@ #include "common/dwarf_cfi_to_module.h" #include "common/dwarf_cu_to_module.h" #include "common/dwarf_line_to_module.h" +#include "common/linux/crc32.h" +#include "common/linux/eintr_wrapper.h" #include "common/linux/elfutils.h" #include "common/linux/elfutils-inl.h" #include "common/linux/elf_symbols_to_module.h" @@ -141,7 +143,7 @@ class MmapWrapper { private: bool is_set_; - void *base_; + void* base_; size_t size_; }; @@ -204,8 +206,8 @@ class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { void StartCompilationUnit(const string& compilation_dir) { compilation_dir_ = compilation_dir; } - void ReadProgram(const char *program, uint64 length, - Module *module, std::vector *lines) { + void ReadProgram(const char* program, uint64 length, + Module* module, std::vector* lines) { DwarfLineToModule handler(module, compilation_dir_, lines); dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); parser.Start(); @@ -369,7 +371,7 @@ bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper, obj_file.c_str(), strerror(errno)); return false; } - void *obj_base = mmap(NULL, st.st_size, + void* obj_base = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); if (obj_base == MAP_FAILED) { fprintf(stderr, "Failed to mmap ELF file '%s': %s\n", @@ -405,19 +407,19 @@ bool ElfEndianness(const typename ElfClass::Ehdr* elf_header, // Read the .gnu_debuglink and get the debug file name. If anything goes // wrong, return an empty string. -template string ReadDebugLink(const char* debuglink, - size_t debuglink_size, + const size_t debuglink_size, + const bool big_endian, const string& obj_file, const std::vector& debug_dirs) { - size_t debuglink_len = strlen(debuglink) + 5; // '\0' + CRC32. - debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round to nearest 4 bytes. + size_t debuglink_len = strlen(debuglink) + 5; // Include '\0' + CRC32. + debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes. // Sanity check. if (debuglink_len != debuglink_size) { fprintf(stderr, "Mismatched .gnu_debuglink string / section size: " "%zx %zx\n", debuglink_len, debuglink_size); - return ""; + return string(); } bool found = false; @@ -428,10 +430,39 @@ string ReadDebugLink(const char* debuglink, const string& debug_dir = *it; debuglink_path = debug_dir + "/" + debuglink; debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); - if (debuglink_fd >= 0) { - found = true; - break; + if (debuglink_fd < 0) + continue; + + FDWrapper debuglink_fd_wrapper(debuglink_fd); + + // The CRC is the last 4 bytes in |debuglink|. + const dwarf2reader::Endianness endianness = big_endian ? + dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; + dwarf2reader::ByteReader byte_reader(endianness); + uint32_t expected_crc = + byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]); + + uint32_t actual_crc = 0; + while (true) { + const size_t kReadSize = 4096; + char buf[kReadSize]; + ssize_t bytes_read = HANDLE_EINTR(read(debuglink_fd, &buf, kReadSize)); + if (bytes_read < 0) { + fprintf(stderr, "Error reading debug ELF file %s.\n", + debuglink_path.c_str()); + return string(); + } + if (bytes_read == 0) + break; + actual_crc = google_breakpad::UpdateCrc32(actual_crc, buf, bytes_read); } + if (actual_crc != expected_crc) { + fprintf(stderr, "Error reading debug ELF file - CRC32 mismatch: %s\n", + debuglink_path.c_str()); + continue; + } + found = true; + break; } if (!found) { @@ -441,13 +472,9 @@ string ReadDebugLink(const char* debuglink, const string debug_dir = *it; fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink); } - return ""; + return string(); } - FDWrapper debuglink_fd_wrapper(debuglink_fd); - // TODO(thestig) check the CRC-32 at the end of the .gnu_debuglink - // section. - return debuglink_path; } @@ -545,7 +572,7 @@ bool LoadSymbols(const string& obj_file, module->SetLoadAddress(loading_addr); info->set_loading_addr(loading_addr, obj_file); - Word debug_section_type = + Word debug_section_type = elf_header->e_machine == EM_MIPS ? SHT_MIPS_DWARF : SHT_PROGBITS; const Shdr* sections = GetOffset(elf_header, elf_header->e_shoff); @@ -657,10 +684,12 @@ bool LoadSymbols(const string& obj_file, const char* debuglink_contents = GetOffset(elf_header, gnu_debuglink_section->sh_offset); - string debuglink_file - = ReadDebugLink(debuglink_contents, - gnu_debuglink_section->sh_size, - obj_file, info->debug_dirs()); + string debuglink_file = + ReadDebugLink(debuglink_contents, + gnu_debuglink_section->sh_size, + big_endian, + obj_file, + info->debug_dirs()); info->set_debuglink_file(debuglink_file); } else { fprintf(stderr, ".gnu_debuglink section found in '%s', " @@ -759,7 +788,7 @@ string FormatIdentifier(unsigned char identifier[16]) { // last slash, or the whole filename if there are no slashes. string BaseFileName(const string &filename) { // Lots of copies! basename's behavior is less than ideal. - char *c_filename = strdup(filename.c_str()); + char* c_filename = strdup(filename.c_str()); string base = basename(c_filename); free(c_filename); return base;