diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common/linux')
47 files changed, 0 insertions, 8072 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc deleted file mode 100644 index 8df636ce4..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc +++ /dev/null @@ -1,70 +0,0 @@ -// 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<const uint8_t*>(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/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h deleted file mode 100644 index e3d9db92b..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h +++ /dev/null @@ -1,53 +0,0 @@ -// 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 <stdint.h> - -#include <string> - -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/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc deleted file mode 100644 index cd99bee66..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc +++ /dev/null @@ -1,1159 +0,0 @@ -// 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. - -// Restructured in 2009 by: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// dump_symbols.cc: implement google_breakpad::WriteSymbolFile: -// Find all the debugging info in a file and dump it as a Breakpad symbol file. - -#include "common/linux/dump_symbols.h" - -#include <assert.h> -#include <elf.h> -#include <errno.h> -#include <fcntl.h> -#include <link.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <iostream> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "common/arm_ex_reader.h" -#include "common/dwarf/bytereader-inl.h" -#include "common/dwarf/dwarf2diehandler.h" -#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" -#include "common/linux/file_id.h" -#include "common/memory.h" -#include "common/module.h" -#include "common/scoped_ptr.h" -#ifndef NO_STABS_SUPPORT -#include "common/stabs_reader.h" -#include "common/stabs_to_module.h" -#endif -#include "common/using_std_string.h" - -#ifndef SHT_ARM_EXIDX -// bionic and older glibc don't define this -# define SHT_ARM_EXIDX (SHT_LOPROC + 1) -#endif - -// This namespace contains helper functions. -namespace { - -using google_breakpad::DumpOptions; -using google_breakpad::DwarfCFIToModule; -using google_breakpad::DwarfCUToModule; -using google_breakpad::DwarfLineToModule; -using google_breakpad::ElfClass; -using google_breakpad::ElfClass32; -using google_breakpad::ElfClass64; -using google_breakpad::FileID; -using google_breakpad::FindElfSectionByName; -using google_breakpad::GetOffset; -using google_breakpad::IsValidElf; -using google_breakpad::kDefaultBuildIdSize; -using google_breakpad::Module; -using google_breakpad::PageAllocator; -#ifndef NO_STABS_SUPPORT -using google_breakpad::StabsToModule; -#endif -using google_breakpad::scoped_ptr; -using google_breakpad::wasteful_vector; - -// Define AARCH64 ELF architecture if host machine does not include this define. -#ifndef EM_AARCH64 -#define EM_AARCH64 183 -#endif - -// Define SHT_ANDROID_REL and SHT_ANDROID_RELA if not defined by the host. -// Sections with this type contain Android packed relocations. -#ifndef SHT_ANDROID_REL -#define SHT_ANDROID_REL (SHT_LOOS + 1) -#endif -#ifndef SHT_ANDROID_RELA -#define SHT_ANDROID_RELA (SHT_LOOS + 2) -#endif - -// -// FDWrapper -// -// Wrapper class to make sure opened file is closed. -// -class FDWrapper { - public: - explicit FDWrapper(int fd) : - fd_(fd) {} - ~FDWrapper() { - if (fd_ != -1) - close(fd_); - } - int get() { - return fd_; - } - int release() { - int fd = fd_; - fd_ = -1; - return fd; - } - private: - int fd_; -}; - -// -// MmapWrapper -// -// Wrapper class to make sure mapped regions are unmapped. -// -class MmapWrapper { - public: - MmapWrapper() : is_set_(false) {} - ~MmapWrapper() { - if (is_set_ && base_ != NULL) { - assert(size_ > 0); - munmap(base_, size_); - } - } - void set(void *mapped_address, size_t mapped_size) { - is_set_ = true; - base_ = mapped_address; - size_ = mapped_size; - } - void release() { - assert(is_set_); - is_set_ = false; - base_ = NULL; - size_ = 0; - } - - private: - bool is_set_; - void* base_; - size_t size_; -}; - -// Find the preferred loading address of the binary. -template<typename ElfClass> -typename ElfClass::Addr GetLoadingAddress( - const typename ElfClass::Phdr* program_headers, - int nheader) { - typedef typename ElfClass::Phdr Phdr; - - // For non-PIC executables (e_type == ET_EXEC), the load address is - // the start address of the first PT_LOAD segment. (ELF requires - // the segments to be sorted by load address.) For PIC executables - // and dynamic libraries (e_type == ET_DYN), this address will - // normally be zero. - for (int i = 0; i < nheader; ++i) { - const Phdr& header = program_headers[i]; - if (header.p_type == PT_LOAD) - return header.p_vaddr; - } - return 0; -} - -#ifndef NO_STABS_SUPPORT -template<typename ElfClass> -bool LoadStabs(const typename ElfClass::Ehdr* elf_header, - const typename ElfClass::Shdr* stab_section, - const typename ElfClass::Shdr* stabstr_section, - const bool big_endian, - Module* module) { - // A callback object to handle data from the STABS reader. - StabsToModule handler(module); - // Find the addresses of the STABS data, and create a STABS reader object. - // On Linux, STABS entries always have 32-bit values, regardless of the - // address size of the architecture whose code they're describing, and - // the strings are always "unitized". - const uint8_t* stabs = - GetOffset<ElfClass, uint8_t>(elf_header, stab_section->sh_offset); - const uint8_t* stabstr = - GetOffset<ElfClass, uint8_t>(elf_header, stabstr_section->sh_offset); - google_breakpad::StabsReader reader(stabs, stab_section->sh_size, - stabstr, stabstr_section->sh_size, - big_endian, 4, true, &handler); - // Read the STABS data, and do post-processing. - if (!reader.Process()) - return false; - handler.Finalize(); - return true; -} -#endif // NO_STABS_SUPPORT - -// A line-to-module loader that accepts line number info parsed by -// dwarf2reader::LineInfo and populates a Module and a line vector -// with the results. -class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { - public: - // Create a line-to-module converter using BYTE_READER. - explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader) - : byte_reader_(byte_reader) { } - void StartCompilationUnit(const string& compilation_dir) { - compilation_dir_ = compilation_dir; - } - void ReadProgram(const uint8_t *program, uint64 length, - Module* module, std::vector<Module::Line>* lines) { - DwarfLineToModule handler(module, compilation_dir_, lines); - dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); - parser.Start(); - } - private: - string compilation_dir_; - dwarf2reader::ByteReader *byte_reader_; -}; - -template<typename ElfClass> -bool LoadDwarf(const string& dwarf_filename, - const typename ElfClass::Ehdr* elf_header, - const bool big_endian, - bool handle_inter_cu_refs, - Module* module) { - typedef typename ElfClass::Shdr Shdr; - - const dwarf2reader::Endianness endianness = big_endian ? - dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; - dwarf2reader::ByteReader byte_reader(endianness); - - // Construct a context for this file. - DwarfCUToModule::FileContext file_context(dwarf_filename, - module, - handle_inter_cu_refs); - - // Build a map of the ELF file's sections. - const Shdr* sections = - GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); - int num_sections = elf_header->e_shnum; - const Shdr* section_names = sections + elf_header->e_shstrndx; - for (int i = 0; i < num_sections; i++) { - const Shdr* section = §ions[i]; - string name = GetOffset<ElfClass, char>(elf_header, - section_names->sh_offset) + - section->sh_name; - const uint8_t *contents = GetOffset<ElfClass, uint8_t>(elf_header, - section->sh_offset); - file_context.AddSectionToSectionMap(name, contents, section->sh_size); - } - - // Parse all the compilation units in the .debug_info section. - DumperLineToModule line_to_module(&byte_reader); - dwarf2reader::SectionMap::const_iterator debug_info_entry = - file_context.section_map().find(".debug_info"); - assert(debug_info_entry != file_context.section_map().end()); - const std::pair<const uint8_t *, uint64>& debug_info_section = - debug_info_entry->second; - // This should never have been called if the file doesn't have a - // .debug_info section. - assert(debug_info_section.first); - uint64 debug_info_length = debug_info_section.second; - for (uint64 offset = 0; offset < debug_info_length;) { - // Make a handler for the root DIE that populates MODULE with the - // data that was found. - DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); - DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter); - // Make a Dwarf2Handler that drives the DIEHandler. - dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); - // Make a DWARF parser for the compilation unit at OFFSET. - dwarf2reader::CompilationUnit reader(dwarf_filename, - file_context.section_map(), - offset, - &byte_reader, - &die_dispatcher); - // Process the entire compilation unit; get the offset of the next. - offset += reader.Start(); - } - return true; -} - -// Fill REGISTER_NAMES with the register names appropriate to the -// machine architecture given in HEADER, indexed by the register -// numbers used in DWARF call frame information. Return true on -// success, or false if HEADER's machine architecture is not -// supported. -template<typename ElfClass> -bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header, - std::vector<string>* register_names) { - switch (elf_header->e_machine) { - case EM_386: - *register_names = DwarfCFIToModule::RegisterNames::I386(); - return true; - case EM_ARM: - *register_names = DwarfCFIToModule::RegisterNames::ARM(); - return true; - case EM_AARCH64: - *register_names = DwarfCFIToModule::RegisterNames::ARM64(); - return true; - case EM_MIPS: - *register_names = DwarfCFIToModule::RegisterNames::MIPS(); - return true; - case EM_X86_64: - *register_names = DwarfCFIToModule::RegisterNames::X86_64(); - return true; - default: - return false; - } -} - -template<typename ElfClass> -bool LoadDwarfCFI(const string& dwarf_filename, - const typename ElfClass::Ehdr* elf_header, - const char* section_name, - const typename ElfClass::Shdr* section, - const bool eh_frame, - const typename ElfClass::Shdr* got_section, - const typename ElfClass::Shdr* text_section, - const bool big_endian, - Module* module) { - // Find the appropriate set of register names for this file's - // architecture. - std::vector<string> register_names; - if (!DwarfCFIRegisterNames<ElfClass>(elf_header, ®ister_names)) { - fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';" - " cannot convert DWARF call frame information\n", - dwarf_filename.c_str(), elf_header->e_machine); - return false; - } - - const dwarf2reader::Endianness endianness = big_endian ? - dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; - - // Find the call frame information and its size. - const uint8_t *cfi = - GetOffset<ElfClass, uint8_t>(elf_header, section->sh_offset); - size_t cfi_size = section->sh_size; - - // Plug together the parser, handler, and their entourages. - DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name); - DwarfCFIToModule handler(module, register_names, &module_reporter); - dwarf2reader::ByteReader byte_reader(endianness); - - byte_reader.SetAddressSize(ElfClass::kAddrSize); - - // Provide the base addresses for .eh_frame encoded pointers, if - // possible. - byte_reader.SetCFIDataBase(section->sh_addr, cfi); - if (got_section) - byte_reader.SetDataBase(got_section->sh_addr); - if (text_section) - byte_reader.SetTextBase(text_section->sh_addr); - - dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename, - section_name); - dwarf2reader::CallFrameInfo parser(cfi, cfi_size, - &byte_reader, &handler, &dwarf_reporter, - eh_frame); - parser.Start(); - return true; -} - -template<typename ElfClass> -bool LoadARMexidx(const typename ElfClass::Ehdr* elf_header, - const typename ElfClass::Shdr* exidx_section, - const typename ElfClass::Shdr* extab_section, - uint32_t loading_addr, - Module* module) { - // To do this properly we need to know: - // * the bounds of the .ARM.exidx section in the mapped image - // * the bounds of the .ARM.extab section in the mapped image - // * the vma of the last byte in the text section associated with the .exidx - // The first two are easy. The third is a bit tricky. If we can't - // figure out what it is, just pass in zero. - const char *exidx_img - = GetOffset<ElfClass, char>(elf_header, exidx_section->sh_offset); - size_t exidx_size = exidx_section->sh_size; - const char *extab_img - = GetOffset<ElfClass, char>(elf_header, extab_section->sh_offset); - size_t extab_size = extab_section->sh_size; - - // The sh_link field of the exidx section gives the section number - // for the associated text section. - uint32_t exidx_text_last_svma = 0; - int exidx_text_sno = exidx_section->sh_link; - typedef typename ElfClass::Shdr Shdr; - // |sections| points to the section header table - const Shdr* sections - = GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); - const int num_sections = elf_header->e_shnum; - if (exidx_text_sno >= 0 && exidx_text_sno < num_sections) { - const Shdr* exidx_text_shdr = §ions[exidx_text_sno]; - if (exidx_text_shdr->sh_size > 0) { - exidx_text_last_svma - = exidx_text_shdr->sh_addr + exidx_text_shdr->sh_size - 1; - } - } - - arm_ex_to_module::ARMExToModule handler(module); - arm_ex_reader::ExceptionTableInfo - parser(exidx_img, exidx_size, extab_img, extab_size, exidx_text_last_svma, - &handler, - reinterpret_cast<const char*>(elf_header), - loading_addr); - parser.Start(); - return true; -} - -bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper, - void** elf_header) { - int obj_fd = open(obj_file.c_str(), O_RDONLY); - if (obj_fd < 0) { - fprintf(stderr, "Failed to open ELF file '%s': %s\n", - obj_file.c_str(), strerror(errno)); - return false; - } - FDWrapper obj_fd_wrapper(obj_fd); - struct stat st; - if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) { - fprintf(stderr, "Unable to fstat ELF file '%s': %s\n", - obj_file.c_str(), strerror(errno)); - return false; - } - 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", - obj_file.c_str(), strerror(errno)); - return false; - } - map_wrapper->set(obj_base, st.st_size); - *elf_header = obj_base; - if (!IsValidElf(*elf_header)) { - fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str()); - return false; - } - return true; -} - -// Get the endianness of ELF_HEADER. If it's invalid, return false. -template<typename ElfClass> -bool ElfEndianness(const typename ElfClass::Ehdr* elf_header, - bool* big_endian) { - if (elf_header->e_ident[EI_DATA] == ELFDATA2LSB) { - *big_endian = false; - return true; - } - if (elf_header->e_ident[EI_DATA] == ELFDATA2MSB) { - *big_endian = true; - return true; - } - - fprintf(stderr, "bad data encoding in ELF header: %d\n", - elf_header->e_ident[EI_DATA]); - return false; -} - -// Given |left_abspath|, find the absolute path for |right_path| and see if the -// two absolute paths are the same. -bool IsSameFile(const char* left_abspath, const string& right_path) { - char right_abspath[PATH_MAX]; - if (!realpath(right_path.c_str(), right_abspath)) - return false; - return strcmp(left_abspath, right_abspath) == 0; -} - -// Read the .gnu_debuglink and get the debug file name. If anything goes -// wrong, return an empty string. -string ReadDebugLink(const uint8_t *debuglink, - const size_t debuglink_size, - const bool big_endian, - const string& obj_file, - const std::vector<string>& debug_dirs) { - // Include '\0' + CRC32 (4 bytes). - size_t debuglink_len = strlen(reinterpret_cast<const char *>(debuglink)) + 5; - 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 string(); - } - - char obj_file_abspath[PATH_MAX]; - if (!realpath(obj_file.c_str(), obj_file_abspath)) { - fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str()); - return string(); - } - - std::vector<string> searched_paths; - string debuglink_path; - std::vector<string>::const_iterator it; - for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { - const string& debug_dir = *it; - debuglink_path = debug_dir + "/" + - reinterpret_cast<const char *>(debuglink); - - // There is the annoying case of /path/to/foo.so having foo.so as the - // debug link file name. Thus this may end up opening /path/to/foo.so again, - // and there is a small chance of the two files having the same CRC. - if (IsSameFile(obj_file_abspath, debuglink_path)) - continue; - - searched_paths.push_back(debug_dir); - int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); - 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 debug file. - return debuglink_path; - } - - // Not found case. - fprintf(stderr, "Failed to find debug ELF file for '%s' after trying:\n", - obj_file.c_str()); - for (it = searched_paths.begin(); it < searched_paths.end(); ++it) { - const string& debug_dir = *it; - fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink); - } - return string(); -} - -// -// LoadSymbolsInfo -// -// Holds the state between the two calls to LoadSymbols() in case it's necessary -// to follow the .gnu_debuglink section and load debug information from a -// different file. -// -template<typename ElfClass> -class LoadSymbolsInfo { - public: - typedef typename ElfClass::Addr Addr; - - explicit LoadSymbolsInfo(const std::vector<string>& dbg_dirs) : - debug_dirs_(dbg_dirs), - has_loading_addr_(false) {} - - // Keeps track of which sections have been loaded so sections don't - // accidentally get loaded twice from two different files. - void LoadedSection(const string §ion) { - if (loaded_sections_.count(section) == 0) { - loaded_sections_.insert(section); - } else { - fprintf(stderr, "Section %s has already been loaded.\n", - section.c_str()); - } - } - - // The ELF file and linked debug file are expected to have the same preferred - // loading address. - void set_loading_addr(Addr addr, const string &filename) { - if (!has_loading_addr_) { - loading_addr_ = addr; - loaded_file_ = filename; - return; - } - - if (addr != loading_addr_) { - fprintf(stderr, - "ELF file '%s' and debug ELF file '%s' " - "have different load addresses.\n", - loaded_file_.c_str(), filename.c_str()); - assert(false); - } - } - - // Setters and getters - const std::vector<string>& debug_dirs() const { - return debug_dirs_; - } - - string debuglink_file() const { - return debuglink_file_; - } - void set_debuglink_file(string file) { - debuglink_file_ = file; - } - - private: - const std::vector<string>& debug_dirs_; // Directories in which to - // search for the debug ELF file. - - string debuglink_file_; // Full path to the debug ELF file. - - bool has_loading_addr_; // Indicate if LOADING_ADDR_ is valid. - - Addr loading_addr_; // Saves the preferred loading address from the - // first call to LoadSymbols(). - - string loaded_file_; // Name of the file loaded from the first call to - // LoadSymbols(). - - std::set<string> loaded_sections_; // Tracks the Loaded ELF sections - // between calls to LoadSymbols(). -}; - -template<typename ElfClass> -bool LoadSymbols(const string& obj_file, - const bool big_endian, - const typename ElfClass::Ehdr* elf_header, - const bool read_gnu_debug_link, - LoadSymbolsInfo<ElfClass>* info, - const DumpOptions& options, - Module* module) { - typedef typename ElfClass::Addr Addr; - typedef typename ElfClass::Phdr Phdr; - typedef typename ElfClass::Shdr Shdr; - typedef typename ElfClass::Word Word; - - Addr loading_addr = GetLoadingAddress<ElfClass>( - GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff), - elf_header->e_phnum); - module->SetLoadAddress(loading_addr); - info->set_loading_addr(loading_addr, obj_file); - - Word debug_section_type = - elf_header->e_machine == EM_MIPS ? SHT_MIPS_DWARF : SHT_PROGBITS; - const Shdr* sections = - GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); - const Shdr* section_names = sections + elf_header->e_shstrndx; - const char* names = - GetOffset<ElfClass, char>(elf_header, section_names->sh_offset); - const char *names_end = names + section_names->sh_size; - bool found_debug_info_section = false; - bool found_usable_info = false; - - // Reject files that contain Android packed relocations. The pre-packed - // version of the file should be symbolized; the packed version is only - // intended for use on the target system. - if (FindElfSectionByName<ElfClass>(".rel.dyn", SHT_ANDROID_REL, - sections, names, - names_end, elf_header->e_shnum)) { - fprintf(stderr, "%s: file contains a \".rel.dyn\" section " - "with type SHT_ANDROID_REL\n", obj_file.c_str()); - fprintf(stderr, "Files containing Android packed relocations " - "may not be symbolized.\n"); - return false; - } - if (FindElfSectionByName<ElfClass>(".rela.dyn", SHT_ANDROID_RELA, - sections, names, - names_end, elf_header->e_shnum)) { - fprintf(stderr, "%s: file contains a \".rela.dyn\" section " - "with type SHT_ANDROID_RELA\n", obj_file.c_str()); - fprintf(stderr, "Files containing Android packed relocations " - "may not be symbolized.\n"); - return false; - } - - if (options.symbol_data != ONLY_CFI) { -#ifndef NO_STABS_SUPPORT - // Look for STABS debugging information, and load it if present. - const Shdr* stab_section = - FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - if (stab_section) { - const Shdr* stabstr_section = stab_section->sh_link + sections; - if (stabstr_section) { - found_debug_info_section = true; - found_usable_info = true; - info->LoadedSection(".stab"); - if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section, - big_endian, module)) { - fprintf(stderr, "%s: \".stab\" section found, but failed to load" - " STABS debugging information\n", obj_file.c_str()); - } - } - } -#endif // NO_STABS_SUPPORT - - // Look for DWARF debugging information, and load it if present. - const Shdr* dwarf_section = - FindElfSectionByName<ElfClass>(".debug_info", debug_section_type, - sections, names, names_end, - elf_header->e_shnum); - if (dwarf_section) { - found_debug_info_section = true; - found_usable_info = true; - info->LoadedSection(".debug_info"); - if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian, - options.handle_inter_cu_refs, module)) { - fprintf(stderr, "%s: \".debug_info\" section found, but failed to load " - "DWARF debugging information\n", obj_file.c_str()); - } - } - - // See if there are export symbols available. - const Shdr* symtab_section = - FindElfSectionByName<ElfClass>(".symtab", SHT_SYMTAB, - sections, names, names_end, - elf_header->e_shnum); - const Shdr* strtab_section = - FindElfSectionByName<ElfClass>(".strtab", SHT_STRTAB, - sections, names, names_end, - elf_header->e_shnum); - if (symtab_section && strtab_section) { - info->LoadedSection(".symtab"); - - const uint8_t* symtab = - GetOffset<ElfClass, uint8_t>(elf_header, - symtab_section->sh_offset); - const uint8_t* strtab = - GetOffset<ElfClass, uint8_t>(elf_header, - strtab_section->sh_offset); - bool result = - ELFSymbolsToModule(symtab, - symtab_section->sh_size, - strtab, - strtab_section->sh_size, - big_endian, - ElfClass::kAddrSize, - module); - found_usable_info = found_usable_info || result; - } else { - // Look in dynsym only if full symbol table was not available. - const Shdr* dynsym_section = - FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM, - sections, names, names_end, - elf_header->e_shnum); - const Shdr* dynstr_section = - FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB, - sections, names, names_end, - elf_header->e_shnum); - if (dynsym_section && dynstr_section) { - info->LoadedSection(".dynsym"); - - const uint8_t* dynsyms = - GetOffset<ElfClass, uint8_t>(elf_header, - dynsym_section->sh_offset); - const uint8_t* dynstrs = - GetOffset<ElfClass, uint8_t>(elf_header, - dynstr_section->sh_offset); - bool result = - ELFSymbolsToModule(dynsyms, - dynsym_section->sh_size, - dynstrs, - dynstr_section->sh_size, - big_endian, - ElfClass::kAddrSize, - module); - found_usable_info = found_usable_info || result; - } - } - } - - if (options.symbol_data != NO_CFI) { - // Dwarf Call Frame Information (CFI) is actually independent from - // the other DWARF debugging information, and can be used alone. - const Shdr* dwarf_cfi_section = - FindElfSectionByName<ElfClass>(".debug_frame", debug_section_type, - sections, names, names_end, - elf_header->e_shnum); - if (dwarf_cfi_section) { - // Ignore the return value of this function; even without call frame - // information, the other debugging information could be perfectly - // useful. - info->LoadedSection(".debug_frame"); - bool result = - LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame", - dwarf_cfi_section, false, 0, 0, big_endian, - module); - found_usable_info = found_usable_info || result; - } - - // Linux C++ exception handling information can also provide - // unwinding data. - const Shdr* eh_frame_section = - FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - if (eh_frame_section) { - // Pointers in .eh_frame data may be relative to the base addresses of - // certain sections. Provide those sections if present. - const Shdr* got_section = - FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - const Shdr* text_section = - FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - info->LoadedSection(".eh_frame"); - // As above, ignore the return value of this function. - bool result = - LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame", - eh_frame_section, true, - got_section, text_section, big_endian, module); - found_usable_info = found_usable_info || result; - } - } - - // ARM has special unwind tables that can be used. - const Shdr* arm_exidx_section = - FindElfSectionByName<ElfClass>(".ARM.exidx", SHT_ARM_EXIDX, - sections, names, names_end, - elf_header->e_shnum); - const Shdr* arm_extab_section = - FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - // Load information from these sections even if there is - // .debug_info, because some functions (e.g., hand-written or - // script-generated assembly) could have exidx entries but no DWARF. - // (For functions with both, the DWARF info that has already been - // parsed will take precedence.) - if (arm_exidx_section && arm_extab_section && options.symbol_data != NO_CFI) { - info->LoadedSection(".ARM.exidx"); - info->LoadedSection(".ARM.extab"); - bool result = LoadARMexidx<ElfClass>(elf_header, - arm_exidx_section, arm_extab_section, - loading_addr, module); - found_usable_info = found_usable_info || result; - } - - if (!found_debug_info_section) { - fprintf(stderr, "%s: file contains no debugging information" - " (no \".stab\" or \".debug_info\" sections)\n", - obj_file.c_str()); - - // Failed, but maybe there's a .gnu_debuglink section? - if (read_gnu_debug_link) { - const Shdr* gnu_debuglink_section - = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS, - sections, names, - names_end, elf_header->e_shnum); - if (gnu_debuglink_section) { - if (!info->debug_dirs().empty()) { - const uint8_t *debuglink_contents = - GetOffset<ElfClass, uint8_t>(elf_header, - gnu_debuglink_section->sh_offset); - 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', " - "but no debug path specified.\n", obj_file.c_str()); - } - } else { - fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n", - obj_file.c_str()); - } - } else { - // Return true if some usable information was found, since the caller - // doesn't want to use .gnu_debuglink. - return found_usable_info; - } - - // No debug info was found, let the user try again with .gnu_debuglink - // if present. - return false; - } - - return true; -} - -// Return the breakpad symbol file identifier for the architecture of -// ELF_HEADER. -template<typename ElfClass> -const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) { - typedef typename ElfClass::Half Half; - Half arch = elf_header->e_machine; - switch (arch) { - case EM_386: return "x86"; - case EM_ARM: return "arm"; - case EM_AARCH64: return "arm64"; - case EM_MIPS: return "mips"; - case EM_PPC64: return "ppc64"; - case EM_PPC: return "ppc"; - case EM_S390: return "s390"; - case EM_SPARC: return "sparc"; - case EM_SPARCV9: return "sparcv9"; - case EM_X86_64: return "x86_64"; - default: return NULL; - } -} - -// Return the non-directory portion of FILENAME: the portion after the -// 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()); - string base = basename(c_filename); - free(c_filename); - return base; -} - -template<typename ElfClass> -bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header, - const string& debuglink_file, - const string& obj_filename, - const char* obj_file_architecture, - const bool obj_file_is_big_endian) { - const char* debug_architecture = - ElfArchitecture<ElfClass>(debug_elf_header); - if (!debug_architecture) { - fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", - debuglink_file.c_str(), debug_elf_header->e_machine); - return false; - } - if (strcmp(obj_file_architecture, debug_architecture)) { - fprintf(stderr, "%s with ELF machine architecture %s does not match " - "%s with ELF architecture %s\n", - debuglink_file.c_str(), debug_architecture, - obj_filename.c_str(), obj_file_architecture); - return false; - } - bool debug_big_endian; - if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian)) - return false; - if (debug_big_endian != obj_file_is_big_endian) { - fprintf(stderr, "%s and %s does not match in endianness\n", - obj_filename.c_str(), debuglink_file.c_str()); - return false; - } - return true; -} - -template<typename ElfClass> -bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, - const string& obj_filename, - scoped_ptr<Module>& module) { - PageAllocator allocator; - wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize); - if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) { - fprintf(stderr, "%s: unable to generate file identifier\n", - obj_filename.c_str()); - return false; - } - - const char *architecture = ElfArchitecture<ElfClass>(elf_header); - if (!architecture) { - fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n", - obj_filename.c_str(), elf_header->e_machine); - return false; - } - - string name = BaseFileName(obj_filename); - string os = "Linux"; - // Add an extra "0" at the end. PDB files on Windows have an 'age' - // number appended to the end of the file identifier; this isn't - // really used or necessary on other platforms, but be consistent. - string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0"; - // This is just the raw Build ID in hex. - string code_id = FileID::ConvertIdentifierToString(identifier); - - module.reset(new Module(name, os, architecture, id, code_id)); - - return true; -} - -template<typename ElfClass> -bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, - const string& obj_filename, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - Module** out_module) { - typedef typename ElfClass::Ehdr Ehdr; - - *out_module = NULL; - - scoped_ptr<Module> module; - if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, module)) { - return false; - } - - // Figure out what endianness this file is. - bool big_endian; - if (!ElfEndianness<ElfClass>(elf_header, &big_endian)) - return false; - - LoadSymbolsInfo<ElfClass> info(debug_dirs); - if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header, - !debug_dirs.empty(), &info, - options, module.get())) { - const string debuglink_file = info.debuglink_file(); - if (debuglink_file.empty()) - return false; - - // Load debuglink ELF file. - fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); - MmapWrapper debug_map_wrapper; - Ehdr* debug_elf_header = NULL; - if (!LoadELF(debuglink_file, &debug_map_wrapper, - reinterpret_cast<void**>(&debug_elf_header)) || - !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file, - obj_filename, - module->architecture().c_str(), - big_endian)) { - return false; - } - - if (!LoadSymbols<ElfClass>(debuglink_file, big_endian, - debug_elf_header, false, &info, - options, module.get())) { - return false; - } - } - - *out_module = module.release(); - return true; -} - -} // namespace - -namespace google_breakpad { - -// Not explicitly exported, but not static so it can be used in unit tests. -bool ReadSymbolDataInternal(const uint8_t* obj_file, - const string& obj_filename, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - Module** module) { - if (!IsValidElf(obj_file)) { - fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str()); - return false; - } - - int elfclass = ElfClass(obj_file); - if (elfclass == ELFCLASS32) { - return ReadSymbolDataElfClass<ElfClass32>( - reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dirs, - options, module); - } - if (elfclass == ELFCLASS64) { - return ReadSymbolDataElfClass<ElfClass64>( - reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dirs, - options, module); - } - - return false; -} - -bool WriteSymbolFile(const string &obj_file, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - std::ostream &sym_stream) { - Module* module; - if (!ReadSymbolData(obj_file, debug_dirs, options, &module)) - return false; - - bool result = module->Write(sym_stream, options.symbol_data); - delete module; - return result; -} - -// Read the selected object file's debugging information, and write out the -// header only to |stream|. Return true on success; if an error occurs, report -// it and return false. -bool WriteSymbolFileHeader(const string& obj_file, - std::ostream &sym_stream) { - MmapWrapper map_wrapper; - void* elf_header = NULL; - if (!LoadELF(obj_file, &map_wrapper, &elf_header)) { - fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str()); - return false; - } - - if (!IsValidElf(elf_header)) { - fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str()); - return false; - } - - int elfclass = ElfClass(elf_header); - scoped_ptr<Module> module; - if (elfclass == ELFCLASS32) { - if (!InitModuleForElfClass<ElfClass32>( - reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, module)) { - fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); - return false; - } - } else if (elfclass == ELFCLASS64) { - if (!InitModuleForElfClass<ElfClass64>( - reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, module)) { - fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); - return false; - } - } else { - fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str()); - return false; - } - - return module->Write(sym_stream, ALL_SYMBOL_DATA); -} - -bool ReadSymbolData(const string& obj_file, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - Module** module) { - MmapWrapper map_wrapper; - void* elf_header = NULL; - if (!LoadELF(obj_file, &map_wrapper, &elf_header)) - return false; - - return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header), - obj_file, debug_dirs, options, module); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h deleted file mode 100644 index 1f204cbad..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h +++ /dev/null @@ -1,86 +0,0 @@ -// -*- mode: c++ -*- - -// 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. - -// dump_symbols.h: Read debugging information from an ELF file, and write -// it out as a Breakpad symbol file. - -#ifndef COMMON_LINUX_DUMP_SYMBOLS_H__ -#define COMMON_LINUX_DUMP_SYMBOLS_H__ - -#include <iostream> -#include <string> -#include <vector> - -#include "common/symbol_data.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -class Module; - -struct DumpOptions { - DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs) - : symbol_data(symbol_data), - handle_inter_cu_refs(handle_inter_cu_refs) { - } - - SymbolData symbol_data; - bool handle_inter_cu_refs; -}; - -// Find all the debugging information in OBJ_FILE, an ELF executable -// or shared library, and write it to SYM_STREAM in the Breakpad symbol -// file format. -// If OBJ_FILE has been stripped but contains a .gnu_debuglink section, -// then look for the debug file in DEBUG_DIRS. -// SYMBOL_DATA allows limiting the type of symbol data written. -bool WriteSymbolFile(const string &obj_file, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - std::ostream &sym_stream); - -// Read the selected object file's debugging information, and write out the -// header only to |stream|. Return true on success; if an error occurs, report -// it and return false. -bool WriteSymbolFileHeader(const string& obj_file, - std::ostream &sym_stream); - -// As above, but simply return the debugging information in MODULE -// instead of writing it to a stream. The caller owns the resulting -// Module object and must delete it when finished. -bool ReadSymbolData(const string& obj_file, - const std::vector<string>& debug_dirs, - const DumpOptions& options, - Module** module); - -} // namespace google_breakpad - -#endif // COMMON_LINUX_DUMP_SYMBOLS_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc deleted file mode 100644 index bb7b20076..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc +++ /dev/null @@ -1,204 +0,0 @@ -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -// dump_symbols_unittest.cc: -// Unittests for google_breakpad::DumpSymbols - -#include <elf.h> -#include <link.h> -#include <stdio.h> - -#include <sstream> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/linux/elf_gnu_compat.h" -#include "common/linux/elfutils.h" -#include "common/linux/dump_symbols.h" -#include "common/linux/synth_elf.h" -#include "common/module.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -bool ReadSymbolDataInternal(const uint8_t* obj_file, - const string& obj_filename, - const std::vector<string>& debug_dir, - const DumpOptions& options, - Module** module); - -using google_breakpad::synth_elf::ELF; -using google_breakpad::synth_elf::Notes; -using google_breakpad::synth_elf::StringTable; -using google_breakpad::synth_elf::SymbolTable; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Section; -using std::stringstream; -using std::vector; -using ::testing::Test; -using ::testing::Types; - -template<typename ElfClass> -class DumpSymbols : public Test { - public: - void GetElfContents(ELF& elf) { - string contents; - ASSERT_TRUE(elf.GetContents(&contents)); - ASSERT_LT(0U, contents.size()); - - elfdata_v.clear(); - elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end()); - elfdata = &elfdata_v[0]; - } - - vector<uint8_t> elfdata_v; - uint8_t* elfdata; -}; - -typedef Types<ElfClass32, ElfClass64> ElfClasses; - -TYPED_TEST_CASE(DumpSymbols, ElfClasses); - -TYPED_TEST(DumpSymbols, Invalid) { - Elf32_Ehdr header; - memset(&header, 0, sizeof(header)); - Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); - EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header), - "foo", - vector<string>(), - options, - &module)); -} - -TYPED_TEST(DumpSymbols, SimplePublic) { - ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian); - // Zero out text section for simplicity. - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - - // Add a public symbol. - StringTable table(kLittleEndian); - SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table); - syms.AddSymbol("superfunc", - (typename TypeParam::Addr)0x1000, - (typename TypeParam::Addr)0x10, - // ELF32_ST_INFO works for 32-or 64-bit. - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - SHN_UNDEF + 1); - int index = elf.AddSection(".dynstr", table, SHT_STRTAB); - elf.AddSection(".dynsym", syms, - SHT_DYNSYM, // type - SHF_ALLOC, // flags - 0, // addr - index, // link - sizeof(typename TypeParam::Sym)); // entsize - - elf.Finish(); - this->GetElfContents(elf); - - Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); - EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, - "foo", - vector<string>(), - options, - &module)); - - stringstream s; - module->Write(s, ALL_SYMBOL_DATA); - const string expected = - string("MODULE Linux ") + TypeParam::kMachineName - + " 000000000000000000000000000000000 foo\n" - "INFO CODE_ID 00000000000000000000000000000000\n" - "PUBLIC 1000 0 superfunc\n"; - EXPECT_EQ(expected, s.str()); - delete module; -} - -TYPED_TEST(DumpSymbols, SimpleBuildID) { - ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian); - // Zero out text section for simplicity. - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - - // Add a Build ID - const uint8_t kExpectedIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13}; - Notes notes(kLittleEndian); - notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, - sizeof(kExpectedIdentifierBytes)); - elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE); - - // Add a public symbol. - StringTable table(kLittleEndian); - SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table); - syms.AddSymbol("superfunc", - (typename TypeParam::Addr)0x1000, - (typename TypeParam::Addr)0x10, - // ELF32_ST_INFO works for 32-or 64-bit. - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - SHN_UNDEF + 1); - int index = elf.AddSection(".dynstr", table, SHT_STRTAB); - elf.AddSection(".dynsym", syms, - SHT_DYNSYM, // type - SHF_ALLOC, // flags - 0, // addr - index, // link - sizeof(typename TypeParam::Sym)); // entsize - - elf.Finish(); - this->GetElfContents(elf); - - Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); - EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, - "foo", - vector<string>(), - options, - &module)); - - stringstream s; - module->Write(s, ALL_SYMBOL_DATA); - const string expected = - string("MODULE Linux ") + TypeParam::kMachineName - + " 030201000504070608090A0B0C0D0E0F0 foo\n" - "INFO CODE_ID 000102030405060708090A0B0C0D0E0F10111213\n" - "PUBLIC 1000 0 superfunc\n"; - EXPECT_EQ(expected, s.str()); - delete module; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h deleted file mode 100644 index 3f1d18481..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2010 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_EINTR_WRAPPER_H_ -#define COMMON_LINUX_EINTR_WRAPPER_H_ - -#include <errno.h> - -// This provides a wrapper around system calls which may be interrupted by a -// signal and return EINTR. See man 7 signal. -// - -#define HANDLE_EINTR(x) ({ \ - __typeof__(x) eintr_wrapper_result; \ - do { \ - eintr_wrapper_result = (x); \ - } while (eintr_wrapper_result == -1 && errno == EINTR); \ - eintr_wrapper_result; \ -}) - -#define IGNORE_EINTR(x) ({ \ - __typeof__(x) eintr_wrapper_result; \ - do { \ - eintr_wrapper_result = (x); \ - if (eintr_wrapper_result == -1 && errno == EINTR) { \ - eintr_wrapper_result = 0; \ - } \ - } while (0); \ - eintr_wrapper_result; \ -}) - -#endif // COMMON_LINUX_EINTR_WRAPPER_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc deleted file mode 100644 index 0e7db7b1f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc +++ /dev/null @@ -1,179 +0,0 @@ -// 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. - -// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump. -// See elf_core_dump.h for details. - -#include "common/linux/elf_core_dump.h" - -#include <stddef.h> -#include <string.h> - -namespace google_breakpad { - -// Implementation of ElfCoreDump::Note. - -ElfCoreDump::Note::Note() {} - -ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {} - -bool ElfCoreDump::Note::IsValid() const { - return GetHeader() != NULL; -} - -const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const { - return content_.GetData<Nhdr>(0); -} - -ElfCoreDump::Word ElfCoreDump::Note::GetType() const { - const Nhdr* header = GetHeader(); - // 0 is not being used as a NOTE type. - return header ? header->n_type : 0; -} - -MemoryRange ElfCoreDump::Note::GetName() const { - const Nhdr* header = GetHeader(); - if (header) { - return content_.Subrange(sizeof(Nhdr), header->n_namesz); - } - return MemoryRange(); -} - -MemoryRange ElfCoreDump::Note::GetDescription() const { - const Nhdr* header = GetHeader(); - if (header) { - return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz), - header->n_descsz); - } - return MemoryRange(); -} - -ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const { - MemoryRange next_content; - const Nhdr* header = GetHeader(); - if (header) { - size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz); - next_offset = AlignedSize(next_offset + header->n_descsz); - next_content = - content_.Subrange(next_offset, content_.length() - next_offset); - } - return Note(next_content); -} - -// static -size_t ElfCoreDump::Note::AlignedSize(size_t size) { - size_t mask = sizeof(Word) - 1; - return (size + mask) & ~mask; -} - - -// Implementation of ElfCoreDump. - -ElfCoreDump::ElfCoreDump() {} - -ElfCoreDump::ElfCoreDump(const MemoryRange& content) - : content_(content) { -} - -void ElfCoreDump::SetContent(const MemoryRange& content) { - content_ = content; -} - -bool ElfCoreDump::IsValid() const { - const Ehdr* header = GetHeader(); - return (header && - header->e_ident[0] == ELFMAG0 && - header->e_ident[1] == ELFMAG1 && - header->e_ident[2] == ELFMAG2 && - header->e_ident[3] == ELFMAG3 && - header->e_ident[4] == kClass && - header->e_version == EV_CURRENT && - header->e_type == ET_CORE); -} - -const ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const { - return content_.GetData<Ehdr>(0); -} - -const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const { - const Ehdr* header = GetHeader(); - if (header) { - return reinterpret_cast<const Phdr*>(content_.GetArrayElement( - header->e_phoff, header->e_phentsize, index)); - } - return NULL; -} - -const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType( - Word type) const { - for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { - const Phdr* program = GetProgramHeader(i); - if (program->p_type == type) { - return program; - } - } - return NULL; -} - -unsigned ElfCoreDump::GetProgramHeaderCount() const { - const Ehdr* header = GetHeader(); - return header ? header->e_phnum : 0; -} - -bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) { - for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) { - const Phdr* program = GetProgramHeader(i); - if (program->p_type != PT_LOAD) - continue; - - size_t offset_in_segment = virtual_address - program->p_vaddr; - if (virtual_address >= program->p_vaddr && - offset_in_segment < program->p_filesz) { - const void* data = - content_.GetData(program->p_offset + offset_in_segment, length); - if (data) { - memcpy(buffer, data, length); - return true; - } - } - } - return false; -} - -ElfCoreDump::Note ElfCoreDump::GetFirstNote() const { - MemoryRange note_content; - const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE); - if (program_header) { - note_content = content_.Subrange(program_header->p_offset, - program_header->p_filesz); - } - return Note(note_content); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h deleted file mode 100644 index d03c7a88d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h +++ /dev/null @@ -1,148 +0,0 @@ -// 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. - -// elf_core_dump.h: Define the google_breakpad::ElfCoreDump class, which -// encapsulates an ELF core dump file mapped into memory. - -#ifndef COMMON_LINUX_ELF_CORE_DUMP_H_ -#define COMMON_LINUX_ELF_CORE_DUMP_H_ - -#include <elf.h> -#include <link.h> -#include <stddef.h> - -#include "common/memory_range.h" - -namespace google_breakpad { - -// A class encapsulating an ELF core dump file mapped into memory, which -// provides methods for accessing program headers and the note section. -class ElfCoreDump { - public: - // ELF types based on the value of __WORDSIZE. - typedef ElfW(Ehdr) Ehdr; - typedef ElfW(Nhdr) Nhdr; - typedef ElfW(Phdr) Phdr; - typedef ElfW(Word) Word; - typedef ElfW(Addr) Addr; -#if __WORDSIZE == 32 - static const int kClass = ELFCLASS32; -#elif __WORDSIZE == 64 - static const int kClass = ELFCLASS64; -#else -#error "Unsupported __WORDSIZE for ElfCoreDump." -#endif - - // A class encapsulating the note content in a core dump, which provides - // methods for accessing the name and description of a note. - class Note { - public: - Note(); - - // Constructor that takes the note content from |content|. - explicit Note(const MemoryRange& content); - - // Returns true if this note is valid, i,e. a note header is found in - // |content_|, or false otherwise. - bool IsValid() const; - - // Returns the note header, or NULL if no note header is found in - // |content_|. - const Nhdr* GetHeader() const; - - // Returns the note type, or 0 if no note header is found in |content_|. - Word GetType() const; - - // Returns a memory range covering the note name, or an empty range - // if no valid note name is found in |content_|. - MemoryRange GetName() const; - - // Returns a memory range covering the note description, or an empty - // range if no valid note description is found in |content_|. - MemoryRange GetDescription() const; - - // Returns the note following this note, or an empty note if no valid - // note is found after this note. - Note GetNextNote() const; - - private: - // Returns the size in bytes round up to the word alignment, specified - // for the note section, of a given size in bytes. - static size_t AlignedSize(size_t size); - - // Note content. - MemoryRange content_; - }; - - ElfCoreDump(); - - // Constructor that takes the core dump content from |content|. - explicit ElfCoreDump(const MemoryRange& content); - - // Sets the core dump content to |content|. - void SetContent(const MemoryRange& content); - - // Returns true if a valid ELF header in the core dump, or false otherwise. - bool IsValid() const; - - // Returns the ELF header in the core dump, or NULL if no ELF header - // is found in |content_|. - const Ehdr* GetHeader() const; - - // Returns the |index|-th program header in the core dump, or NULL if no - // ELF header is found in |content_| or |index| is out of bounds. - const Phdr* GetProgramHeader(unsigned index) const; - - // Returns the first program header of |type| in the core dump, or NULL if - // no ELF header is found in |content_| or no program header of |type| is - // found. - const Phdr* GetFirstProgramHeaderOfType(Word type) const; - - // Returns the number of program headers in the core dump, or 0 if no - // ELF header is found in |content_|. - unsigned GetProgramHeaderCount() const; - - // Copies |length| bytes of data starting at |virtual_address| in the core - // dump to |buffer|. |buffer| should be a valid pointer to a buffer of at - // least |length| bytes. Returns true if the data to be copied is found in - // the core dump, or false otherwise. - bool CopyData(void* buffer, Addr virtual_address, size_t length); - - // Returns the first note found in the note section of the core dump, or - // an empty note if no note is found. - Note GetFirstNote() const; - - private: - // Core dump content. - MemoryRange content_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_ELF_CORE_DUMP_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc deleted file mode 100644 index 9b41dceee..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc +++ /dev/null @@ -1,256 +0,0 @@ -// 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. - -// elf_core_dump_unittest.cc: Unit tests for google_breakpad::ElfCoreDump. - -#include <sys/procfs.h> - -#include <set> -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/linux/elf_core_dump.h" -#include "common/linux/memory_mapped_file.h" -#include "common/tests/file_utils.h" -#include "common/linux/tests/crash_generator.h" -#include "common/using_std_string.h" - -using google_breakpad::AutoTempDir; -using google_breakpad::CrashGenerator; -using google_breakpad::ElfCoreDump; -using google_breakpad::MemoryMappedFile; -using google_breakpad::MemoryRange; -using google_breakpad::WriteFile; -using std::set; - -TEST(ElfCoreDumpTest, DefaultConstructor) { - ElfCoreDump core; - EXPECT_FALSE(core.IsValid()); - EXPECT_EQ(NULL, core.GetHeader()); - EXPECT_EQ(0U, core.GetProgramHeaderCount()); - EXPECT_EQ(NULL, core.GetProgramHeader(0)); - EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); - EXPECT_FALSE(core.GetFirstNote().IsValid()); -} - -TEST(ElfCoreDumpTest, TestElfHeader) { - ElfCoreDump::Ehdr header; - memset(&header, 0, sizeof(header)); - - AutoTempDir temp_dir; - string core_path = temp_dir.path() + "/core"; - const char* core_file = core_path.c_str(); - MemoryMappedFile mapped_core_file; - ElfCoreDump core; - - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header) - 1)); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - EXPECT_EQ(NULL, core.GetHeader()); - EXPECT_EQ(0U, core.GetProgramHeaderCount()); - EXPECT_EQ(NULL, core.GetProgramHeader(0)); - EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); - EXPECT_FALSE(core.GetFirstNote().IsValid()); - - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_ident[0] = ELFMAG0; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_ident[1] = ELFMAG1; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_ident[2] = ELFMAG2; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_ident[3] = ELFMAG3; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_ident[4] = ElfCoreDump::kClass; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_version = EV_CURRENT; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_FALSE(core.IsValid()); - - header.e_type = ET_CORE; - ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); - ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); - core.SetContent(mapped_core_file.content()); - EXPECT_TRUE(core.IsValid()); -} - -TEST(ElfCoreDumpTest, ValidCoreFile) { - CrashGenerator crash_generator; - if (!crash_generator.HasDefaultCorePattern()) { - fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped " - "due to non-default core pattern"); - return; - } - - const unsigned kNumOfThreads = 3; - const unsigned kCrashThread = 1; - const int kCrashSignal = SIGABRT; - ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread, - kCrashSignal, NULL)); - pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread); - set<pid_t> expected_thread_ids; - for (unsigned i = 0; i < kNumOfThreads; ++i) { - expected_thread_ids.insert(crash_generator.GetThreadId(i)); - } - -#if defined(__ANDROID__) - struct stat st; - if (stat(crash_generator.GetCoreFilePath().c_str(), &st) != 0) { - fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped " - "due to no core file being generated"); - return; - } -#endif - - MemoryMappedFile mapped_core_file; - ASSERT_TRUE( - mapped_core_file.Map(crash_generator.GetCoreFilePath().c_str(), 0)); - - ElfCoreDump core; - core.SetContent(mapped_core_file.content()); - EXPECT_TRUE(core.IsValid()); - - // Based on write_note_info() in linux/kernel/fs/binfmt_elf.c, notes are - // ordered as follows (NT_PRXFPREG and NT_386_TLS are i386 specific): - // Thread Name Type - // ------------------------------------------------------------------- - // 1st thread CORE NT_PRSTATUS - // process-wide CORE NT_PRPSINFO - // process-wide CORE NT_AUXV - // 1st thread CORE NT_FPREGSET - // 1st thread LINUX NT_PRXFPREG - // 1st thread LINUX NT_386_TLS - // - // 2nd thread CORE NT_PRSTATUS - // 2nd thread CORE NT_FPREGSET - // 2nd thread LINUX NT_PRXFPREG - // 2nd thread LINUX NT_386_TLS - // - // 3rd thread CORE NT_PRSTATUS - // 3rd thread CORE NT_FPREGSET - // 3rd thread LINUX NT_PRXFPREG - // 3rd thread LINUX NT_386_TLS - - size_t num_nt_prpsinfo = 0; - size_t num_nt_prstatus = 0; - size_t num_pr_fpvalid = 0; -#if defined(__i386__) || defined(__x86_64__) - size_t num_nt_fpregset = 0; -#endif -#if defined(__i386__) - size_t num_nt_prxfpreg = 0; -#endif - set<pid_t> actual_thread_ids; - ElfCoreDump::Note note = core.GetFirstNote(); - while (note.IsValid()) { - MemoryRange name = note.GetName(); - MemoryRange description = note.GetDescription(); - EXPECT_FALSE(name.IsEmpty()); - EXPECT_FALSE(description.IsEmpty()); - - switch (note.GetType()) { - case NT_PRPSINFO: { - EXPECT_TRUE(description.data() != NULL); - EXPECT_EQ(sizeof(elf_prpsinfo), description.length()); - ++num_nt_prpsinfo; - break; - } - case NT_PRSTATUS: { - EXPECT_TRUE(description.data() != NULL); - EXPECT_EQ(sizeof(elf_prstatus), description.length()); - const elf_prstatus* status = description.GetData<elf_prstatus>(0); - actual_thread_ids.insert(status->pr_pid); - if (num_nt_prstatus == 0) { - EXPECT_EQ(expected_crash_thread_id, status->pr_pid); - EXPECT_EQ(kCrashSignal, status->pr_info.si_signo); - } - ++num_nt_prstatus; - if (status->pr_fpvalid) - ++num_pr_fpvalid; - break; - } -#if defined(__i386__) || defined(__x86_64__) - case NT_FPREGSET: { - EXPECT_TRUE(description.data() != NULL); - EXPECT_EQ(sizeof(user_fpregs_struct), description.length()); - ++num_nt_fpregset; - break; - } -#endif -#if defined(__i386__) - case NT_PRXFPREG: { - EXPECT_TRUE(description.data() != NULL); - EXPECT_EQ(sizeof(user_fpxregs_struct), description.length()); - ++num_nt_prxfpreg; - break; - } -#endif - default: - break; - } - note = note.GetNextNote(); - } - - EXPECT_TRUE(expected_thread_ids == actual_thread_ids); - EXPECT_EQ(1U, num_nt_prpsinfo); - EXPECT_EQ(kNumOfThreads, num_nt_prstatus); -#if defined(__i386__) || defined(__x86_64__) - EXPECT_EQ(num_pr_fpvalid, num_nt_fpregset); -#endif -#if defined(__i386__) - EXPECT_EQ(num_pr_fpvalid, num_nt_prxfpreg); -#endif -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h deleted file mode 100644 index f870cbc7d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h +++ /dev/null @@ -1,46 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2013, 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. - -// Original author: Lei Zhang <thestig@google.com> - -// elf_gnu_compat.h: #defines unique to glibc's elf.h. - -#ifndef COMMON_LINUX_ELF_GNU_COMPAT_H_ -#define COMMON_LINUX_ELF_GNU_COMPAT_H_ - -#include <elf.h> - -// A note type on GNU systems corresponding to the .note.gnu.build-id section. -#ifndef NT_GNU_BUILD_ID -#define NT_GNU_BUILD_ID 3 -#endif - -#endif // COMMON_LINUX_ELF_GNU_COMPAT_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc deleted file mode 100644 index 562875e11..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc +++ /dev/null @@ -1,178 +0,0 @@ -// -*- mode: c++ -*- - -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -#include "common/linux/elf_symbols_to_module.h" - -#include <cxxabi.h> -#include <elf.h> -#include <string.h> - -#include "common/byte_cursor.h" -#include "common/module.h" - -namespace google_breakpad { - -class ELFSymbolIterator { -public: - // The contents of an ELF symbol, adjusted for the host's endianness, - // word size, and so on. Corresponds to the data in Elf32_Sym / Elf64_Sym. - struct Symbol { - // True if this iterator has reached the end of the symbol array. When - // this is set, the other members of this structure are not valid. - bool at_end; - - // The number of this symbol within the list. - size_t index; - - // The current symbol's name offset. This is the offset within the - // string table. - size_t name_offset; - - // The current symbol's value, size, info and shndx fields. - uint64_t value; - uint64_t size; - unsigned char info; - uint16_t shndx; - }; - - // Create an ELFSymbolIterator walking the symbols in BUFFER. Treat the - // symbols as big-endian if BIG_ENDIAN is true, as little-endian - // otherwise. Assume each symbol has a 'value' field whose size is - // VALUE_SIZE. - // - ELFSymbolIterator(const ByteBuffer *buffer, bool big_endian, - size_t value_size) - : value_size_(value_size), cursor_(buffer, big_endian) { - // Actually, weird sizes could be handled just fine, but they're - // probably mistakes --- expressed in bits, say. - assert(value_size == 4 || value_size == 8); - symbol_.index = 0; - Fetch(); - } - - // Move to the next symbol. This function's behavior is undefined if - // at_end() is true when it is called. - ELFSymbolIterator &operator++() { Fetch(); symbol_.index++; return *this; } - - // Dereferencing this iterator produces a reference to an Symbol structure - // that holds the current symbol's values. The symbol is owned by this - // SymbolIterator, and will be invalidated at the next call to operator++. - const Symbol &operator*() const { return symbol_; } - const Symbol *operator->() const { return &symbol_; } - -private: - // Read the symbol at cursor_, and set symbol_ appropriately. - void Fetch() { - // Elf32_Sym and Elf64_Sym have different layouts. - unsigned char other; - if (value_size_ == 4) { - // Elf32_Sym - cursor_ - .Read(4, false, &symbol_.name_offset) - .Read(4, false, &symbol_.value) - .Read(4, false, &symbol_.size) - .Read(1, false, &symbol_.info) - .Read(1, false, &other) - .Read(2, false, &symbol_.shndx); - } else { - // Elf64_Sym - cursor_ - .Read(4, false, &symbol_.name_offset) - .Read(1, false, &symbol_.info) - .Read(1, false, &other) - .Read(2, false, &symbol_.shndx) - .Read(8, false, &symbol_.value) - .Read(8, false, &symbol_.size); - } - symbol_.at_end = !cursor_; - } - - // The size of symbols' value field, in bytes. - size_t value_size_; - - // A byte cursor traversing buffer_. - ByteCursor cursor_; - - // Values for the symbol this iterator refers to. - Symbol symbol_; -}; - -const char *SymbolString(ptrdiff_t offset, ByteBuffer& strings) { - if (offset < 0 || (size_t) offset >= strings.Size()) { - // Return the null string. - offset = 0; - } - return reinterpret_cast<const char *>(strings.start + offset); -} - -bool ELFSymbolsToModule(const uint8_t *symtab_section, - size_t symtab_size, - const uint8_t *string_section, - size_t string_size, - const bool big_endian, - size_t value_size, - Module *module) { - ByteBuffer symbols(symtab_section, symtab_size); - // Ensure that the string section is null-terminated. - if (string_section[string_size - 1] != '\0') { - const void* null_terminator = memrchr(string_section, '\0', string_size); - string_size = reinterpret_cast<const uint8_t*>(null_terminator) - - string_section; - } - ByteBuffer strings(string_section, string_size); - - // The iterator walking the symbol table. - ELFSymbolIterator iterator(&symbols, big_endian, value_size); - - while(!iterator->at_end) { - if (ELF32_ST_TYPE(iterator->info) == STT_FUNC && - iterator->shndx != SHN_UNDEF) { - Module::Extern *ext = new Module::Extern(iterator->value); - ext->name = SymbolString(iterator->name_offset, strings); -#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle. - int status = 0; - char* demangled = - abi::__cxa_demangle(ext->name.c_str(), NULL, NULL, &status); - if (demangled) { - if (status == 0) - ext->name = demangled; - free(demangled); - } -#endif - module->AddExtern(ext); - } - ++iterator; - } - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h deleted file mode 100644 index 2e7c09715..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h +++ /dev/null @@ -1,58 +0,0 @@ -// -*- mode: c++ -*- - -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -// elf_symbols_to_module.h: Exposes ELFSymbolsToModule, a function -// for reading ELF symbol tables and inserting exported symbol names -// into a google_breakpad::Module as Extern definitions. - -#ifndef BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_ -#define BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_ - -#include <stddef.h> -#include <stdint.h> - -namespace google_breakpad { - -class Module; - -bool ELFSymbolsToModule(const uint8_t *symtab_section, - size_t symtab_size, - const uint8_t *string_section, - size_t string_size, - const bool big_endian, - size_t value_size, - Module *module); - -} // namespace google_breakpad - - -#endif // BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc deleted file mode 100644 index 8984449ab..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc +++ /dev/null @@ -1,370 +0,0 @@ -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -// elf_symbols_to_module_unittest.cc: -// Unittests for google_breakpad::ELFSymbolsToModule - -#include <elf.h> - -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/linux/elf_symbols_to_module.h" -#include "common/linux/synth_elf.h" -#include "common/module.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" - -using google_breakpad::Module; -using google_breakpad::synth_elf::StringTable; -using google_breakpad::test_assembler::Endianness; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using ::testing::Test; -using ::testing::TestWithParam; -using std::vector; - -class ELFSymbolsToModuleTestFixture { -public: - ELFSymbolsToModuleTestFixture(Endianness endianness, - size_t value_size) : module("a", "b", "c", "d"), - section(endianness), - table(endianness), - value_size(value_size) {} - - bool ProcessSection() { - string section_contents, table_contents; - section.GetContents(§ion_contents); - table.GetContents(&table_contents); - - bool ret = ELFSymbolsToModule(reinterpret_cast<const uint8_t*>(section_contents.data()), - section_contents.size(), - reinterpret_cast<const uint8_t*>(table_contents.data()), - table_contents.size(), - section.endianness() == kBigEndian, - value_size, - &module); - module.GetExterns(&externs, externs.end()); - return ret; - } - - Module module; - Section section; - StringTable table; - string section_contents; - // 4 or 8 (bytes) - size_t value_size; - - vector<Module::Extern *> externs; -}; - -class ELFSymbolsToModuleTest32 : public ELFSymbolsToModuleTestFixture, - public TestWithParam<Endianness> { -public: - ELFSymbolsToModuleTest32() : ELFSymbolsToModuleTestFixture(GetParam(), 4) {} - - void AddElf32Sym(const string& name, uint32_t value, - uint32_t size, unsigned info, uint16_t shndx) { - section - .D32(table.Add(name)) - .D32(value) - .D32(size) - .D8(info) - .D8(0) // other - .D16(shndx); - } -}; - -TEST_P(ELFSymbolsToModuleTest32, NoFuncs) { - ProcessSection(); - - ASSERT_EQ((size_t)0, externs.size()); -} - -TEST_P(ELFSymbolsToModuleTest32, OneFunc) { - const string kFuncName = "superfunc"; - const uint32_t kFuncAddr = 0x1000; - const uint32_t kFuncSize = 0x10; - - AddElf32Sym(kFuncName, kFuncAddr, kFuncSize, - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -TEST_P(ELFSymbolsToModuleTest32, NameOutOfBounds) { - const string kFuncName = ""; - const uint32_t kFuncAddr = 0x1000; - const uint32_t kFuncSize = 0x10; - - table.Add("Foo"); - table.Add("Bar"); - // Can't use AddElf32Sym because it puts in a valid string offset. - section - .D32((uint32_t)table.Here().Value() + 1) - .D32(kFuncAddr) - .D32(kFuncSize) - .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC)) - .D8(0) // other - .D16(SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -TEST_P(ELFSymbolsToModuleTest32, NonTerminatedStringTable) { - const string kFuncName = ""; - const uint32_t kFuncAddr = 0x1000; - const uint32_t kFuncSize = 0x10; - - table.Add("Foo"); - table.Add("Bar"); - // Add a non-null-terminated string to the end of the string table - Label l; - table - .Mark(&l) - .Append("Unterminated"); - // Can't use AddElf32Sym because it puts in a valid string offset. - section - .D32((uint32_t)l.Value()) - .D32(kFuncAddr) - .D32(kFuncSize) - .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC)) - .D8(0) // other - .D16(SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -TEST_P(ELFSymbolsToModuleTest32, MultipleFuncs) { - const string kFuncName1 = "superfunc"; - const uint32_t kFuncAddr1 = 0x10001000; - const uint32_t kFuncSize1 = 0x10; - const string kFuncName2 = "awesomefunc"; - const uint32_t kFuncAddr2 = 0x20002000; - const uint32_t kFuncSize2 = 0x2f; - const string kFuncName3 = "megafunc"; - const uint32_t kFuncAddr3 = 0x30003000; - const uint32_t kFuncSize3 = 0x3c; - - AddElf32Sym(kFuncName1, kFuncAddr1, kFuncSize1, - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - AddElf32Sym(kFuncName2, kFuncAddr2, kFuncSize2, - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 2); - AddElf32Sym(kFuncName3, kFuncAddr3, kFuncSize3, - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 3); - - ProcessSection(); - - ASSERT_EQ((size_t)3, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName1, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address); - Module::Extern *extern2 = externs[1]; - EXPECT_EQ(kFuncName2, extern2->name); - EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address); - Module::Extern *extern3 = externs[2]; - EXPECT_EQ(kFuncName3, extern3->name); - EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address); -} - -TEST_P(ELFSymbolsToModuleTest32, SkipStuff) { - const string kFuncName = "superfunc"; - const uint32_t kFuncAddr = 0x1000; - const uint32_t kFuncSize = 0x10; - - // Should skip functions in SHN_UNDEF - AddElf32Sym("skipme", 0xFFFF, 0x10, - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - SHN_UNDEF); - AddElf32Sym(kFuncName, kFuncAddr, kFuncSize, - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - // Should skip non-STT_FUNC entries. - AddElf32Sym("skipmetoo", 0xAAAA, 0x10, - ELF32_ST_INFO(STB_GLOBAL, STT_FILE), - SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -// Run all the 32-bit tests with both endianness -INSTANTIATE_TEST_CASE_P(Endian, - ELFSymbolsToModuleTest32, - ::testing::Values(kLittleEndian, kBigEndian)); - -// Similar tests, but with 64-bit values. Ostensibly this could be -// shoehorned into the parameterization by using ::testing::Combine, -// but that would make it difficult to get the types right since these -// actual test cases aren't parameterized. This could also be written -// as a type-parameterized test, but combining that with a value-parameterized -// test seemed really ugly, and also makes it harder to test 64-bit -// values. -class ELFSymbolsToModuleTest64 : public ELFSymbolsToModuleTestFixture, - public TestWithParam<Endianness> { -public: - ELFSymbolsToModuleTest64() : ELFSymbolsToModuleTestFixture(GetParam(), 8) {} - - void AddElf64Sym(const string& name, uint64_t value, - uint64_t size, unsigned info, uint16_t shndx) { - section - .D32(table.Add(name)) - .D8(info) - .D8(0) // other - .D16(shndx) - .D64(value) - .D64(size); - } -}; - -TEST_P(ELFSymbolsToModuleTest64, NoFuncs) { - ProcessSection(); - - ASSERT_EQ((size_t)0, externs.size()); -} - -TEST_P(ELFSymbolsToModuleTest64, OneFunc) { - const string kFuncName = "superfunc"; - const uint64_t kFuncAddr = 0x1000200030004000ULL; - const uint64_t kFuncSize = 0x1000; - - AddElf64Sym(kFuncName, kFuncAddr, kFuncSize, - ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -TEST_P(ELFSymbolsToModuleTest64, MultipleFuncs) { - const string kFuncName1 = "superfunc"; - const uint64_t kFuncAddr1 = 0x1000100010001000ULL; - const uint64_t kFuncSize1 = 0x1000; - const string kFuncName2 = "awesomefunc"; - const uint64_t kFuncAddr2 = 0x2000200020002000ULL; - const uint64_t kFuncSize2 = 0x2f00; - const string kFuncName3 = "megafunc"; - const uint64_t kFuncAddr3 = 0x3000300030003000ULL; - const uint64_t kFuncSize3 = 0x3c00; - - AddElf64Sym(kFuncName1, kFuncAddr1, kFuncSize1, - ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - AddElf64Sym(kFuncName2, kFuncAddr2, kFuncSize2, - ELF64_ST_INFO(STB_LOCAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 2); - AddElf64Sym(kFuncName3, kFuncAddr3, kFuncSize3, - ELF64_ST_INFO(STB_LOCAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 3); - - ProcessSection(); - - ASSERT_EQ((size_t)3, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName1, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address); - Module::Extern *extern2 = externs[1]; - EXPECT_EQ(kFuncName2, extern2->name); - EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address); - Module::Extern *extern3 = externs[2]; - EXPECT_EQ(kFuncName3, extern3->name); - EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address); -} - -TEST_P(ELFSymbolsToModuleTest64, SkipStuff) { - const string kFuncName = "superfunc"; - const uint64_t kFuncAddr = 0x1000100010001000ULL; - const uint64_t kFuncSize = 0x1000; - - // Should skip functions in SHN_UNDEF - AddElf64Sym("skipme", 0xFFFF, 0x10, - ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), - SHN_UNDEF); - AddElf64Sym(kFuncName, kFuncAddr, kFuncSize, - ELF64_ST_INFO(STB_GLOBAL, STT_FUNC), - // Doesn't really matter, just can't be SHN_UNDEF. - SHN_UNDEF + 1); - // Should skip non-STT_FUNC entries. - AddElf64Sym("skipmetoo", 0xAAAA, 0x10, - ELF64_ST_INFO(STB_GLOBAL, STT_FILE), - SHN_UNDEF + 1); - - ProcessSection(); - - ASSERT_EQ((size_t)1, externs.size()); - Module::Extern *extern1 = externs[0]; - EXPECT_EQ(kFuncName, extern1->name); - EXPECT_EQ((Module::Address)kFuncAddr, extern1->address); -} - -// Run all the 64-bit tests with both endianness -INSTANTIATE_TEST_CASE_P(Endian, - ELFSymbolsToModuleTest64, - ::testing::Values(kLittleEndian, kBigEndian)); diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h deleted file mode 100644 index e56b37a9f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2012, 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_ELFUTILS_INL_H__ -#define COMMON_LINUX_ELFUTILS_INL_H__ - -#include "common/linux/linux_libc_support.h" -#include "elfutils.h" - -namespace google_breakpad { - -template<typename ElfClass, typename T> -const T* GetOffset(const typename ElfClass::Ehdr* elf_header, - typename ElfClass::Off offset) { - return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) + - offset); -} - -template<typename ElfClass> -const typename ElfClass::Shdr* FindElfSectionByName( - const char* name, - typename ElfClass::Word section_type, - const typename ElfClass::Shdr* sections, - const char* section_names, - const char* names_end, - int nsection) { - assert(name != NULL); - assert(sections != NULL); - assert(nsection > 0); - - int name_len = my_strlen(name); - if (name_len == 0) - return NULL; - - for (int i = 0; i < nsection; ++i) { - const char* section_name = section_names + sections[i].sh_name; - if (sections[i].sh_type == section_type && - names_end - section_name >= name_len + 1 && - my_strcmp(name, section_name) == 0) { - return sections + i; - } - } - return NULL; -} - -} // namespace google_breakpad - -#endif // COMMON_LINUX_ELFUTILS_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc deleted file mode 100644 index a79391c13..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright (c) 2012, 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/elfutils.h" - -#include <assert.h> -#include <string.h> - -#include "common/linux/linux_libc_support.h" -#include "common/linux/elfutils-inl.h" - -namespace google_breakpad { - -namespace { - -template<typename ElfClass> -void FindElfClassSection(const char *elf_base, - const char *section_name, - typename ElfClass::Word section_type, - const void **section_start, - size_t *section_size) { - typedef typename ElfClass::Ehdr Ehdr; - typedef typename ElfClass::Shdr Shdr; - - assert(elf_base); - assert(section_start); - assert(section_size); - - assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); - - const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); - assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); - - const Shdr* sections = - GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff); - const Shdr* section_names = sections + elf_header->e_shstrndx; - const char* names = - GetOffset<ElfClass, char>(elf_header, section_names->sh_offset); - const char *names_end = names + section_names->sh_size; - - const Shdr* section = - FindElfSectionByName<ElfClass>(section_name, section_type, - sections, names, names_end, - elf_header->e_shnum); - - if (section != NULL && section->sh_size > 0) { - *section_start = elf_base + section->sh_offset; - *section_size = section->sh_size; - } -} - -template<typename ElfClass> -void FindElfClassSegment(const char *elf_base, - typename ElfClass::Word segment_type, - const void **segment_start, - size_t *segment_size) { - typedef typename ElfClass::Ehdr Ehdr; - typedef typename ElfClass::Phdr Phdr; - - assert(elf_base); - assert(segment_start); - assert(segment_size); - - assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0); - - const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); - assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); - - const Phdr* phdrs = - GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff); - - for (int i = 0; i < elf_header->e_phnum; ++i) { - if (phdrs[i].p_type == segment_type) { - *segment_start = elf_base + phdrs[i].p_offset; - *segment_size = phdrs[i].p_filesz; - return; - } - } -} - -} // namespace - -bool IsValidElf(const void* elf_base) { - return my_strncmp(reinterpret_cast<const char*>(elf_base), - ELFMAG, SELFMAG) == 0; -} - -int ElfClass(const void* elf_base) { - const ElfW(Ehdr)* elf_header = - reinterpret_cast<const ElfW(Ehdr)*>(elf_base); - - return elf_header->e_ident[EI_CLASS]; -} - -bool FindElfSection(const void *elf_mapped_base, - const char *section_name, - uint32_t section_type, - const void **section_start, - size_t *section_size, - int *elfclass) { - assert(elf_mapped_base); - assert(section_start); - assert(section_size); - - *section_start = NULL; - *section_size = 0; - - if (!IsValidElf(elf_mapped_base)) - return false; - - int cls = ElfClass(elf_mapped_base); - if (elfclass) { - *elfclass = cls; - } - - const char* elf_base = - static_cast<const char*>(elf_mapped_base); - - if (cls == ELFCLASS32) { - FindElfClassSection<ElfClass32>(elf_base, section_name, section_type, - section_start, section_size); - return *section_start != NULL; - } else if (cls == ELFCLASS64) { - FindElfClassSection<ElfClass64>(elf_base, section_name, section_type, - section_start, section_size); - return *section_start != NULL; - } - - return false; -} - -bool FindElfSegment(const void *elf_mapped_base, - uint32_t segment_type, - const void **segment_start, - size_t *segment_size, - int *elfclass) { - assert(elf_mapped_base); - assert(segment_start); - assert(segment_size); - - *segment_start = NULL; - *segment_size = 0; - - if (!IsValidElf(elf_mapped_base)) - return false; - - int cls = ElfClass(elf_mapped_base); - if (elfclass) { - *elfclass = cls; - } - - const char* elf_base = - static_cast<const char*>(elf_mapped_base); - - if (cls == ELFCLASS32) { - FindElfClassSegment<ElfClass32>(elf_base, segment_type, - segment_start, segment_size); - return *segment_start != NULL; - } else if (cls == ELFCLASS64) { - FindElfClassSegment<ElfClass64>(elf_base, segment_type, - segment_start, segment_size); - return *segment_start != NULL; - } - - return false; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h deleted file mode 100644 index f34ba8314..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2012, 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. -// -// elfutils.h: Utilities for dealing with ELF files. -// - -#ifndef COMMON_LINUX_ELFUTILS_H_ -#define COMMON_LINUX_ELFUTILS_H_ - -#include <elf.h> -#include <link.h> -#include <stdint.h> - -namespace google_breakpad { - -// Traits classes so consumers can write templatized code to deal -// with specific ELF bits. -struct ElfClass32 { - typedef Elf32_Addr Addr; - typedef Elf32_Ehdr Ehdr; - typedef Elf32_Nhdr Nhdr; - typedef Elf32_Phdr Phdr; - typedef Elf32_Shdr Shdr; - typedef Elf32_Half Half; - typedef Elf32_Off Off; - typedef Elf32_Sym Sym; - typedef Elf32_Word Word; - - static const int kClass = ELFCLASS32; - static const uint16_t kMachine = EM_386; - static const size_t kAddrSize = sizeof(Elf32_Addr); - static constexpr const char* kMachineName = "x86"; -}; - -struct ElfClass64 { - typedef Elf64_Addr Addr; - typedef Elf64_Ehdr Ehdr; - typedef Elf64_Nhdr Nhdr; - typedef Elf64_Phdr Phdr; - typedef Elf64_Shdr Shdr; - typedef Elf64_Half Half; - typedef Elf64_Off Off; - typedef Elf64_Sym Sym; - typedef Elf64_Word Word; - - static const int kClass = ELFCLASS64; - static const uint16_t kMachine = EM_X86_64; - static const size_t kAddrSize = sizeof(Elf64_Addr); - static constexpr const char* kMachineName = "x86_64"; -}; - -bool IsValidElf(const void* elf_header); -int ElfClass(const void* elf_base); - -// Attempt to find a section named |section_name| of type |section_type| -// in the ELF binary data at |elf_mapped_base|. On success, returns true -// and sets |*section_start| to point to the start of the section data, -// and |*section_size| to the size of the section's data. If |elfclass| -// is not NULL, set |*elfclass| to the ELF file class. -bool FindElfSection(const void *elf_mapped_base, - const char *section_name, - uint32_t section_type, - const void **section_start, - size_t *section_size, - int *elfclass); - -// Internal helper method, exposed for convenience for callers -// that already have more info. -template<typename ElfClass> -const typename ElfClass::Shdr* -FindElfSectionByName(const char* name, - typename ElfClass::Word section_type, - const typename ElfClass::Shdr* sections, - const char* section_names, - const char* names_end, - int nsection); - -// Attempt to find the first segment of type |segment_type| in the ELF -// binary data at |elf_mapped_base|. On success, returns true and sets -// |*segment_start| to point to the start of the segment data, and -// and |*segment_size| to the size of the segment's data. If |elfclass| -// is not NULL, set |*elfclass| to the ELF file class. -bool FindElfSegment(const void *elf_mapped_base, - uint32_t segment_type, - const void **segment_start, - size_t *segment_size, - int *elfclass); - -// Convert an offset from an Elf header into a pointer to the mapped -// address in the current process. Takes an extra template parameter -// to specify the return type to avoid having to dynamic_cast the -// result. -template<typename ElfClass, typename T> -const T* -GetOffset(const typename ElfClass::Ehdr* elf_header, - typename ElfClass::Off offset); - -} // namespace google_breakpad - -#endif // COMMON_LINUX_ELFUTILS_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc deleted file mode 100644 index 311e03020..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2006, 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. -// -// file_id.cc: Return a unique identifier for a file -// -// See file_id.h for documentation -// - -#include "common/linux/file_id.h" - -#include <arpa/inet.h> -#include <assert.h> -#include <string.h> - -#include <algorithm> -#include <string> - -#include "common/linux/elf_gnu_compat.h" -#include "common/linux/elfutils.h" -#include "common/linux/linux_libc_support.h" -#include "common/linux/memory_mapped_file.h" -#include "common/using_std_string.h" -#include "third_party/lss/linux_syscall_support.h" - -namespace google_breakpad { - -// Used in a few places for backwards-compatibility. -const size_t kMDGUIDSize = sizeof(MDGUID); - -FileID::FileID(const char* path) : path_(path) {} - -// ELF note name and desc are 32-bits word padded. -#define NOTE_PADDING(a) ((a + 3) & ~3) - -// These functions are also used inside the crashed process, so be safe -// and use the syscall/libc wrappers instead of direct syscalls or libc. - -template<typename ElfClass> -static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, - wasteful_vector<uint8_t>& identifier) { - typedef typename ElfClass::Nhdr Nhdr; - - const void* section_end = reinterpret_cast<const char*>(section) + length; - const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section); - while (reinterpret_cast<const void *>(note_header) < section_end) { - if (note_header->n_type == NT_GNU_BUILD_ID) - break; - note_header = reinterpret_cast<const Nhdr*>( - reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) + - NOTE_PADDING(note_header->n_namesz) + - NOTE_PADDING(note_header->n_descsz)); - } - if (reinterpret_cast<const void *>(note_header) >= section_end || - note_header->n_descsz == 0) { - return false; - } - - const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) + - sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz); - identifier.insert(identifier.end(), - build_id, - build_id + note_header->n_descsz); - - return true; -} - -// Attempt to locate a .note.gnu.build-id section in an ELF binary -// and copy it into |identifier|. -static bool FindElfBuildIDNote(const void* elf_mapped_base, - wasteful_vector<uint8_t>& identifier) { - void* note_section; - size_t note_size; - int elfclass; - if ((!FindElfSegment(elf_mapped_base, PT_NOTE, - (const void**)¬e_section, ¬e_size, &elfclass) || - note_size == 0) && - (!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE, - (const void**)¬e_section, ¬e_size, &elfclass) || - note_size == 0)) { - return false; - } - - if (elfclass == ELFCLASS32) { - return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size, - identifier); - } else if (elfclass == ELFCLASS64) { - return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size, - identifier); - } - - return false; -} - -// Attempt to locate the .text section of an ELF binary and generate -// a simple hash by XORing the first page worth of bytes into |identifier|. -static bool HashElfTextSection(const void* elf_mapped_base, - wasteful_vector<uint8_t>& identifier) { - identifier.resize(kMDGUIDSize); - - void* text_section; - size_t text_size; - if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, - (const void**)&text_section, &text_size, NULL) || - text_size == 0) { - return false; - } - - // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this - // function backwards-compatible. - my_memset(&identifier[0], 0, kMDGUIDSize); - const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section); - const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096)); - while (ptr < ptr_end) { - for (unsigned i = 0; i < kMDGUIDSize; i++) - identifier[i] ^= ptr[i]; - ptr += kMDGUIDSize; - } - return true; -} - -// static -bool FileID::ElfFileIdentifierFromMappedFile(const void* base, - wasteful_vector<uint8_t>& identifier) { - // Look for a build id note first. - if (FindElfBuildIDNote(base, identifier)) - return true; - - // Fall back on hashing the first page of the text section. - return HashElfTextSection(base, identifier); -} - -bool FileID::ElfFileIdentifier(wasteful_vector<uint8_t>& identifier) { - MemoryMappedFile mapped_file(path_.c_str(), 0); - if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)? - return false; - - return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier); -} - -// These three functions are not ever called in an unsafe context, so it's OK -// to allocate memory and use libc. -static string bytes_to_hex_string(const uint8_t* bytes, size_t count) { - string result; - for (unsigned int idx = 0; idx < count; ++idx) { - char buf[3]; - snprintf(buf, sizeof(buf), "%02X", bytes[idx]); - result.append(buf); - } - return result; -} - -// static -string FileID::ConvertIdentifierToUUIDString( - const wasteful_vector<uint8_t>& identifier) { - uint8_t identifier_swapped[kMDGUIDSize] = { 0 }; - - // Endian-ness swap to match dump processor expectation. - memcpy(identifier_swapped, &identifier[0], - std::min(kMDGUIDSize, identifier.size())); - uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped); - *data1 = htonl(*data1); - uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4); - *data2 = htons(*data2); - uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6); - *data3 = htons(*data3); - - return bytes_to_hex_string(identifier_swapped, kMDGUIDSize); -} - -// static -string FileID::ConvertIdentifierToString( - const wasteful_vector<uint8_t>& identifier) { - return bytes_to_hex_string(&identifier[0], identifier.size()); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h deleted file mode 100644 index a1d2fd6ed..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2006, 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. -// -// file_id.h: Return a unique identifier for a file -// - -#ifndef COMMON_LINUX_FILE_ID_H__ -#define COMMON_LINUX_FILE_ID_H__ - -#include <limits.h> -#include <string> - -#include "common/linux/guid_creator.h" -#include "common/memory.h" - -namespace google_breakpad { - -// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes, -// so this is enough to fit that, which most binaries will use. -// This is just a sensible default for auto_wasteful_vector so most -// callers can get away with stack allocation. -static const size_t kDefaultBuildIdSize = 20; - -class FileID { - public: - explicit FileID(const char* path); - ~FileID() {} - - // Load the identifier for the elf file path specified in the constructor into - // |identifier|. - // - // The current implementation will look for a .note.gnu.build-id - // section and use that as the file id, otherwise it falls back to - // XORing the first 4096 bytes of the .text section to generate an identifier. - bool ElfFileIdentifier(wasteful_vector<uint8_t>& identifier); - - // Load the identifier for the elf file mapped into memory at |base| into - // |identifier|. Return false if the identifier could not be created for this - // file. - static bool ElfFileIdentifierFromMappedFile( - const void* base, - wasteful_vector<uint8_t>& identifier); - - // Convert the |identifier| data to a string. The string will - // be formatted as a UUID in all uppercase without dashes. - // (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE). - static std::string ConvertIdentifierToUUIDString( - const wasteful_vector<uint8_t>& identifier); - - // Convert the entire |identifier| data to a hex string. - static std::string ConvertIdentifierToString( - const wasteful_vector<uint8_t>& identifier); - - private: - // Storage for the path specified - std::string path_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_FILE_ID_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc deleted file mode 100644 index 3a8193034..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright (c) 2010, 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. - -// Unit tests for FileID - -#include <elf.h> -#include <stdlib.h> - -#include <string> -#include <vector> - -#include "common/linux/elf_gnu_compat.h" -#include "common/linux/elfutils.h" -#include "common/linux/file_id.h" -#include "common/linux/safe_readlink.h" -#include "common/linux/synth_elf.h" -#include "common/test_assembler.h" -#include "common/tests/auto_tempdir.h" -#include "common/using_std_string.h" -#include "breakpad_googletest_includes.h" - -using namespace google_breakpad; -using google_breakpad::synth_elf::ELF; -using google_breakpad::synth_elf::Notes; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Section; -using std::vector; -using ::testing::Types; - -namespace { - -// Simply calling Section::Append(size, byte) produces a uninteresting pattern -// that tends to get hashed to 0000...0000. This populates the section with -// data to produce better hashes. -void PopulateSection(Section* section, int size, int prime_number) { - for (int i = 0; i < size; i++) - section->Append(1, (i % prime_number) % 256); -} - -typedef wasteful_vector<uint8_t> id_vector; - -} // namespace - -#ifndef __ANDROID__ -// This test is disabled on Android: It will always fail, since there is no -// 'strip' binary installed on test devices. -TEST(FileIDStripTest, StripSelf) { - // Calculate the File ID of this binary using - // FileID::ElfFileIdentifier, then make a copy of this binary, - // strip it, and ensure that the result is the same. - char exe_name[PATH_MAX]; - ASSERT_TRUE(SafeReadLink("/proc/self/exe", exe_name)); - - // copy our binary to a temp file, and strip it - AutoTempDir temp_dir; - string templ = temp_dir.path() + "/file-id-unittest"; - char cmdline[4096]; - sprintf(cmdline, "cp \"%s\" \"%s\"", exe_name, templ.c_str()); - ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline; - sprintf(cmdline, "chmod u+w \"%s\"", templ.c_str()); - ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline; - sprintf(cmdline, "strip \"%s\"", templ.c_str()); - ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline; - - PageAllocator allocator; - id_vector identifier1(&allocator, kDefaultBuildIdSize); - id_vector identifier2(&allocator, kDefaultBuildIdSize); - - FileID fileid1(exe_name); - EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1)); - FileID fileid2(templ.c_str()); - EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2)); - - string identifier_string1 = - FileID::ConvertIdentifierToUUIDString(identifier1); - string identifier_string2 = - FileID::ConvertIdentifierToUUIDString(identifier2); - EXPECT_EQ(identifier_string1, identifier_string2); -} -#endif // !__ANDROID__ - -template<typename ElfClass> -class FileIDTest : public testing::Test { -public: - void GetElfContents(ELF& elf) { - string contents; - ASSERT_TRUE(elf.GetContents(&contents)); - ASSERT_LT(0U, contents.size()); - - elfdata_v.clear(); - elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end()); - elfdata = &elfdata_v[0]; - } - - id_vector make_vector() { - return id_vector(&allocator, kDefaultBuildIdSize); - } - - template<size_t N> - string get_file_id(const uint8_t (&data)[N]) { - id_vector expected_identifier(make_vector()); - expected_identifier.insert(expected_identifier.end(), - &data[0], - data + N); - return FileID::ConvertIdentifierToUUIDString(expected_identifier); - } - - vector<uint8_t> elfdata_v; - uint8_t* elfdata; - PageAllocator allocator; -}; - -typedef Types<ElfClass32, ElfClass64> ElfClasses; - -TYPED_TEST_CASE(FileIDTest, ElfClasses); - -TYPED_TEST(FileIDTest, ElfClass) { - const char expected_identifier_string[] = - "80808080808000000000008080808080"; - const size_t kTextSectionSize = 128; - - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - for (size_t i = 0; i < kTextSectionSize; ++i) { - text.D8(i * 3); - } - elf.AddSection(".text", text, SHT_PROGBITS); - elf.Finish(); - this->GetElfContents(elf); - - id_vector identifier(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier)); - - string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); - EXPECT_EQ(expected_identifier_string, identifier_string); -} - -TYPED_TEST(FileIDTest, BuildID) { - const uint8_t kExpectedIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13}; - const string expected_identifier_string = - this->get_file_id(kExpectedIdentifierBytes); - - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - Notes notes(kLittleEndian); - notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, - sizeof(kExpectedIdentifierBytes)); - elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE); - elf.Finish(); - this->GetElfContents(elf); - - id_vector identifier(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier)); - EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size()); - - string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); - EXPECT_EQ(expected_identifier_string, identifier_string); -} - -// Test that a build id note with fewer bytes than usual is handled. -TYPED_TEST(FileIDTest, BuildIDShort) { - const uint8_t kExpectedIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03}; - const string expected_identifier_string = - this->get_file_id(kExpectedIdentifierBytes); - - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - Notes notes(kLittleEndian); - notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, - sizeof(kExpectedIdentifierBytes)); - elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE); - elf.Finish(); - this->GetElfContents(elf); - - id_vector identifier(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier)); - EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size()); - - string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); - EXPECT_EQ(expected_identifier_string, identifier_string); -} - -// Test that a build id note with more bytes than usual is handled. -TYPED_TEST(FileIDTest, BuildIDLong) { - const uint8_t kExpectedIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}; - const string expected_identifier_string = - this->get_file_id(kExpectedIdentifierBytes); - - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - Notes notes(kLittleEndian); - notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, - sizeof(kExpectedIdentifierBytes)); - elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE); - elf.Finish(); - this->GetElfContents(elf); - - id_vector identifier(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier)); - EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size()); - - string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); - EXPECT_EQ(expected_identifier_string, identifier_string); -} - -TYPED_TEST(FileIDTest, BuildIDPH) { - const uint8_t kExpectedIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13}; - const string expected_identifier_string = - this->get_file_id(kExpectedIdentifierBytes); - - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - text.Append(4096, 0); - elf.AddSection(".text", text, SHT_PROGBITS); - Notes notes(kLittleEndian); - notes.AddNote(0, "Linux", - reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4); - notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, - sizeof(kExpectedIdentifierBytes)); - int note_idx = elf.AddSection(".note", notes, SHT_NOTE); - elf.AddSegment(note_idx, note_idx, PT_NOTE); - elf.Finish(); - this->GetElfContents(elf); - - id_vector identifier(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier)); - EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size()); - - string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); - EXPECT_EQ(expected_identifier_string, identifier_string); -} - -// Test to make sure two files with different text sections produce -// different hashes when not using a build id. -TYPED_TEST(FileIDTest, UniqueHashes) { - { - ELF elf1(EM_386, TypeParam::kClass, kLittleEndian); - Section foo_1(kLittleEndian); - PopulateSection(&foo_1, 32, 5); - elf1.AddSection(".foo", foo_1, SHT_PROGBITS); - Section text_1(kLittleEndian); - PopulateSection(&text_1, 4096, 17); - elf1.AddSection(".text", text_1, SHT_PROGBITS); - elf1.Finish(); - this->GetElfContents(elf1); - } - - id_vector identifier_1(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier_1)); - string identifier_string_1 = - FileID::ConvertIdentifierToUUIDString(identifier_1); - - { - ELF elf2(EM_386, TypeParam::kClass, kLittleEndian); - Section text_2(kLittleEndian); - Section foo_2(kLittleEndian); - PopulateSection(&foo_2, 32, 5); - elf2.AddSection(".foo", foo_2, SHT_PROGBITS); - PopulateSection(&text_2, 4096, 31); - elf2.AddSection(".text", text_2, SHT_PROGBITS); - elf2.Finish(); - this->GetElfContents(elf2); - } - - id_vector identifier_2(this->make_vector()); - EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, - identifier_2)); - string identifier_string_2 = - FileID::ConvertIdentifierToUUIDString(identifier_2); - - EXPECT_NE(identifier_string_1, identifier_string_2); -} - -TYPED_TEST(FileIDTest, ConvertIdentifierToString) { - const uint8_t kIdentifierBytes[] = - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}; - const char* kExpected = - "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; - - id_vector identifier(this->make_vector()); - identifier.insert(identifier.end(), - kIdentifierBytes, - kIdentifierBytes + sizeof(kIdentifierBytes)); - ASSERT_EQ(kExpected, - FileID::ConvertIdentifierToString(identifier)); -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc deleted file mode 100644 index 6d86fb369..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright (c) 2009, 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/google_crashdump_uploader.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <iostream> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword) { - LibcurlWrapper* http_layer = new LibcurlWrapper(); - Init(product, - version, - guid, - ptime, - ctime, - email, - comments, - minidump_pathname, - crash_server, - proxy_host, - proxy_userpassword, - http_layer); -} - -GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword, - LibcurlWrapper* http_layer) { - Init(product, - version, - guid, - ptime, - ctime, - email, - comments, - minidump_pathname, - crash_server, - proxy_host, - proxy_userpassword, - http_layer); -} - -void GoogleCrashdumpUploader::Init(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword, - LibcurlWrapper* http_layer) { - product_ = product; - version_ = version; - guid_ = guid; - ptime_ = ptime; - ctime_ = ctime; - email_ = email; - comments_ = comments; - http_layer_.reset(http_layer); - - crash_server_ = crash_server; - proxy_host_ = proxy_host; - proxy_userpassword_ = proxy_userpassword; - minidump_pathname_ = minidump_pathname; - std::cout << "Uploader initializing"; - std::cout << "\tProduct: " << product_; - std::cout << "\tVersion: " << version_; - std::cout << "\tGUID: " << guid_; - if (!ptime_.empty()) { - std::cout << "\tProcess uptime: " << ptime_; - } - if (!ctime_.empty()) { - std::cout << "\tCumulative Process uptime: " << ctime_; - } - if (!email_.empty()) { - std::cout << "\tEmail: " << email_; - } - if (!comments_.empty()) { - std::cout << "\tComments: " << comments_; - } -} - -bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() { - string error_text; - if (product_.empty()) { - error_text.append("\nProduct name must be specified."); - } - - if (version_.empty()) { - error_text.append("\nProduct version must be specified."); - } - - if (guid_.empty()) { - error_text.append("\nClient ID must be specified."); - } - - if (minidump_pathname_.empty()) { - error_text.append("\nMinidump pathname must be specified."); - } - - if (!error_text.empty()) { - std::cout << error_text; - return false; - } - return true; - -} - -bool GoogleCrashdumpUploader::Upload(int* http_status_code, - string* http_response_header, - string* http_response_body) { - bool ok = http_layer_->Init(); - if (!ok) { - std::cout << "http layer init failed"; - return ok; - } - - if (!CheckRequiredParametersArePresent()) { - return false; - } - - struct stat st; - int err = stat(minidump_pathname_.c_str(), &st); - if (err) { - std::cout << minidump_pathname_ << " could not be found"; - return false; - } - - parameters_["prod"] = product_; - parameters_["ver"] = version_; - parameters_["guid"] = guid_; - parameters_["ptime"] = ptime_; - parameters_["ctime"] = ctime_; - parameters_["email"] = email_; - parameters_["comments_"] = comments_; - if (!http_layer_->AddFile(minidump_pathname_, - "upload_file_minidump")) { - return false; - } - std::cout << "Sending request to " << crash_server_; - return http_layer_->SendRequest(crash_server_, - parameters_, - http_status_code, - http_response_header, - http_response_body); -} -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h deleted file mode 100644 index a2d0575b5..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) 2009, 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_GOOGLE_CRASHDUMP_UPLOADER_H_ -#define COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_ - -#include <string> -#include <map> - -#include "common/linux/libcurl_wrapper.h" -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -class GoogleCrashdumpUploader { - public: - GoogleCrashdumpUploader(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword); - - GoogleCrashdumpUploader(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword, - LibcurlWrapper* http_layer); - - void Init(const string& product, - const string& version, - const string& guid, - const string& ptime, - const string& ctime, - const string& email, - const string& comments, - const string& minidump_pathname, - const string& crash_server, - const string& proxy_host, - const string& proxy_userpassword, - LibcurlWrapper* http_layer); - bool Upload(int* http_status_code, - string* http_response_header, - string* http_response_body); - - private: - bool CheckRequiredParametersArePresent(); - - scoped_ptr<LibcurlWrapper> http_layer_; - string product_; - string version_; - string guid_; - string ptime_; - string ctime_; - string email_; - string comments_; - string minidump_pathname_; - - string crash_server_; - string proxy_host_; - string proxy_userpassword_; - - std::map<string, string> parameters_; -}; -} - -#endif // COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc deleted file mode 100644 index e94c5d62a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2009, 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. - -// Unit test for crash dump uploader. - -#include <string> - -#include "common/linux/google_crashdump_uploader.h" -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -using ::testing::Return; -using ::testing::_; - -class MockLibcurlWrapper : public LibcurlWrapper { - public: - MOCK_METHOD0(Init, bool()); - MOCK_METHOD2(SetProxy, bool(const string& proxy_host, - const string& proxy_userpwd)); - MOCK_METHOD2(AddFile, bool(const string& upload_file_path, - const string& basename)); - MOCK_METHOD5(SendRequest, - bool(const string& url, - const std::map<string, string>& parameters, - int* http_status_code, - string* http_header_data, - string* http_response_data)); -}; - -class GoogleCrashdumpUploaderTest : public ::testing::Test { -}; - -TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) { - MockLibcurlWrapper m; - EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(false)); - GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", - "1.0", - "AAA-BBB", - "", - "", - "test@test.com", - "none", - "/tmp/foo.dmp", - "http://foo.com", - "", - "", - &m); - ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL)); -} - -TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { - // Create a temp file - char tempfn[80] = "/tmp/googletest-upload-XXXXXX"; - int fd = mkstemp(tempfn); - ASSERT_NE(fd, -1); - close(fd); - - MockLibcurlWrapper m; - EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); - EXPECT_CALL(m, AddFile(tempfn, _)).WillOnce(Return(true)); - EXPECT_CALL(m, - SendRequest("http://foo.com",_,_,_,_)).Times(1).WillOnce(Return(true)); - GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", - "1.0", - "AAA-BBB", - "", - "", - "test@test.com", - "none", - tempfn, - "http://foo.com", - "", - "", - &m); - ASSERT_TRUE(uploader->Upload(NULL, NULL, NULL)); -} - - -TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) { - MockLibcurlWrapper m; - EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); - EXPECT_CALL(m, SendRequest(_,_,_,_,_)).Times(0); - GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", - "1.0", - "AAA-BBB", - "", - "", - "test@test.com", - "none", - "/tmp/foo.dmp", - "http://foo.com", - "", - "", - &m); - ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL)); -} - -TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { - // Test with empty product name. - GoogleCrashdumpUploader uploader("", - "1.0", - "AAA-BBB", - "", - "", - "test@test.com", - "none", - "/tmp/foo.dmp", - "http://foo.com", - "", - ""); - ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); - - // Test with empty product version. - GoogleCrashdumpUploader uploader1("product", - "", - "AAA-BBB", - "", - "", - "", - "", - "/tmp/foo.dmp", - "", - "", - ""); - - ASSERT_FALSE(uploader1.Upload(NULL, NULL, NULL)); - - // Test with empty client GUID. - GoogleCrashdumpUploader uploader2("product", - "1.0", - "", - "", - "", - "", - "", - "/tmp/foo.dmp", - "", - "", - ""); - ASSERT_FALSE(uploader2.Upload(NULL, NULL, NULL)); -} -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc deleted file mode 100644 index bfb308ee2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2006, 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/guid_creator.h" - -#include <assert.h> -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> - -// -// GUIDGenerator -// -// This class is used to generate random GUID. -// Currently use random number to generate a GUID since Linux has -// no native GUID generator. This should be OK since we don't expect -// crash to happen very offen. -// -class GUIDGenerator { - public: - static uint32_t BytesToUInt32(const uint8_t bytes[]) { - return ((uint32_t) bytes[0] - | ((uint32_t) bytes[1] << 8) - | ((uint32_t) bytes[2] << 16) - | ((uint32_t) bytes[3] << 24)); - } - - static void UInt32ToBytes(uint8_t bytes[], uint32_t n) { - bytes[0] = n & 0xff; - bytes[1] = (n >> 8) & 0xff; - bytes[2] = (n >> 16) & 0xff; - bytes[3] = (n >> 24) & 0xff; - } - - static bool CreateGUID(GUID *guid) { - InitOnce(); - guid->data1 = random(); - guid->data2 = (uint16_t)(random()); - guid->data3 = (uint16_t)(random()); - UInt32ToBytes(&guid->data4[0], random()); - UInt32ToBytes(&guid->data4[4], random()); - return true; - } - - private: - static void InitOnce() { - pthread_once(&once_control, &InitOnceImpl); - } - - static void InitOnceImpl() { - srandom(time(NULL)); - } - - static pthread_once_t once_control; -}; - -pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT; - -bool CreateGUID(GUID *guid) { - return GUIDGenerator::CreateGUID(guid); -} - -// Parse guid to string. -bool GUIDToString(const GUID *guid, char *buf, int buf_len) { - // Should allow more space the the max length of GUID. - assert(buf_len > kGUIDStringLength); - int num = snprintf(buf, buf_len, kGUIDFormatString, - guid->data1, guid->data2, guid->data3, - GUIDGenerator::BytesToUInt32(&(guid->data4[0])), - GUIDGenerator::BytesToUInt32(&(guid->data4[4]))); - if (num != kGUIDStringLength) - return false; - - buf[num] = '\0'; - return true; -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h deleted file mode 100644 index c86d856c4..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2006, 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_GUID_CREATOR_H__ -#define COMMON_LINUX_GUID_CREATOR_H__ - -#include "google_breakpad/common/minidump_format.h" - -typedef MDGUID GUID; - -// Format string for parsing GUID. -#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x" -// Length of GUID string. Don't count the ending '\0'. -#define kGUIDStringLength 36 - -// Create a guid. -bool CreateGUID(GUID *guid); - -// Get the string from guid. -bool GUIDToString(const GUID *guid, char *buf, int buf_len); - -#endif diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc deleted file mode 100644 index 702526af7..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) 2006, 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/http_upload.h" - -#include <assert.h> -#include <dlfcn.h> -#include "third_party/curl/curl.h" - -namespace { - -// Callback to get the response data from server. -static size_t WriteCallback(void *ptr, size_t size, - size_t nmemb, void *userp) { - if (!userp) - return 0; - - string *response = reinterpret_cast<string *>(userp); - size_t real_size = size * nmemb; - response->append(reinterpret_cast<char *>(ptr), real_size); - return real_size; -} - -} // namespace - -namespace google_breakpad { - -static const char kUserAgent[] = "Breakpad/1.0 (Linux)"; - -// static -bool HTTPUpload::SendRequest(const string &url, - const map<string, string> ¶meters, - const map<string, string> &files, - const string &proxy, - const string &proxy_user_pwd, - const string &ca_certificate_file, - string *response_body, - long *response_code, - string *error_description) { - if (response_code != NULL) - *response_code = 0; - - if (!CheckParameters(parameters)) - return false; - - // We may have been linked statically; if curl_easy_init is in the - // current binary, no need to search for a dynamic version. - void* curl_lib = dlopen(NULL, RTLD_NOW); - if (!CheckCurlLib(curl_lib)) { - fprintf(stderr, - "Failed to open curl lib from binary, use libcurl.so instead\n"); - dlerror(); // Clear dlerror before attempting to open libraries. - dlclose(curl_lib); - curl_lib = NULL; - } - if (!curl_lib) { - curl_lib = dlopen("libcurl.so", RTLD_NOW); - } - if (!curl_lib) { - if (error_description != NULL) - *error_description = dlerror(); - curl_lib = dlopen("libcurl.so.4", RTLD_NOW); - } - if (!curl_lib) { - // Debian gives libcurl a different name when it is built against GnuTLS - // instead of OpenSSL. - curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_NOW); - } - if (!curl_lib) { - curl_lib = dlopen("libcurl.so.3", RTLD_NOW); - } - if (!curl_lib) { - return false; - } - - CURL* (*curl_easy_init)(void); - *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init"); - CURL *curl = (*curl_easy_init)(); - if (error_description != NULL) - *error_description = "No Error"; - - if (!curl) { - dlclose(curl_lib); - return false; - } - - CURLcode err_code = CURLE_OK; - CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...); - *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt"); - (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str()); - (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent); - // Support multithread by disabling timeout handling, would get SIGSEGV with - // Curl_resolv_timeout in stack trace otherwise. - // See https://curl.haxx.se/libcurl/c/threadsafe.html - (*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1); - // Set proxy information if necessary. - if (!proxy.empty()) - (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str()); - if (!proxy_user_pwd.empty()) - (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str()); - - if (!ca_certificate_file.empty()) - (*curl_easy_setopt)(curl, CURLOPT_CAINFO, ca_certificate_file.c_str()); - - struct curl_httppost *formpost = NULL; - struct curl_httppost *lastptr = NULL; - // Add form data. - CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...); - *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd"); - map<string, string>::const_iterator iter = parameters.begin(); - for (; iter != parameters.end(); ++iter) - (*curl_formadd)(&formpost, &lastptr, - CURLFORM_COPYNAME, iter->first.c_str(), - CURLFORM_COPYCONTENTS, iter->second.c_str(), - CURLFORM_END); - - // Add form files. - for (iter = files.begin(); iter != files.end(); ++iter) { - (*curl_formadd)(&formpost, &lastptr, - CURLFORM_COPYNAME, iter->first.c_str(), - CURLFORM_FILE, iter->second.c_str(), - CURLFORM_END); - } - - (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost); - - // Disable 100-continue header. - struct curl_slist *headerlist = NULL; - char buf[] = "Expect:"; - struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *); - *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append"); - headerlist = (*curl_slist_append)(headerlist, buf); - (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist); - - if (response_body != NULL) { - (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback); - (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA, - reinterpret_cast<void *>(response_body)); - } - - // Fail if 400+ is returned from the web server. - (*curl_easy_setopt)(curl, CURLOPT_FAILONERROR, 1); - - CURLcode (*curl_easy_perform)(CURL *); - *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform"); - err_code = (*curl_easy_perform)(curl); - if (response_code != NULL) { - CURLcode (*curl_easy_getinfo)(CURL *, CURLINFO, ...); - *(void**) (&curl_easy_getinfo) = dlsym(curl_lib, "curl_easy_getinfo"); - (*curl_easy_getinfo)(curl, CURLINFO_RESPONSE_CODE, response_code); - } - const char* (*curl_easy_strerror)(CURLcode); - *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror"); -#ifndef NDEBUG - if (err_code != CURLE_OK) - fprintf(stderr, "Failed to send http request to %s, error: %s\n", - url.c_str(), - (*curl_easy_strerror)(err_code)); -#endif - if (error_description != NULL) - *error_description = (*curl_easy_strerror)(err_code); - - void (*curl_easy_cleanup)(CURL *); - *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup"); - (*curl_easy_cleanup)(curl); - if (formpost != NULL) { - void (*curl_formfree)(struct curl_httppost *); - *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree"); - (*curl_formfree)(formpost); - } - if (headerlist != NULL) { - void (*curl_slist_free_all)(struct curl_slist *); - *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all"); - (*curl_slist_free_all)(headerlist); - } - dlclose(curl_lib); - return err_code == CURLE_OK; -} - -// static -bool HTTPUpload::CheckCurlLib(void* curl_lib) { - return curl_lib && - dlsym(curl_lib, "curl_easy_init") && - dlsym(curl_lib, "curl_easy_setopt"); -} - -// static -bool HTTPUpload::CheckParameters(const map<string, string> ¶meters) { - for (map<string, string>::const_iterator pos = parameters.begin(); - pos != parameters.end(); ++pos) { - const string &str = pos->first; - if (str.size() == 0) - return false; // disallow empty parameter names - for (unsigned int i = 0; i < str.size(); ++i) { - int c = str[i]; - if (c < 32 || c == '"' || c > 127) { - return false; - } - } - } - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h deleted file mode 100644 index bc1d5d570..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2006, 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. - -// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST -// request using libcurl. It currently supports requests that contain -// a set of string parameters (key/value pairs), and a file to upload. - -#ifndef COMMON_LINUX_HTTP_UPLOAD_H__ -#define COMMON_LINUX_HTTP_UPLOAD_H__ - -#include <map> -#include <string> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -using std::map; - -class HTTPUpload { - public: - // Sends the given sets of parameters and files as a multipart POST - // request to the given URL. - // Each key in |files| is the name of the file part of the request - // (i.e. it corresponds to the name= attribute on an <input type="file">. - // Parameter names must contain only printable ASCII characters, - // and may not contain a quote (") character. - // Only HTTP(S) URLs are currently supported. Returns true on success. - // If the request is successful and response_body is non-NULL, - // the response body will be returned in response_body. - // If response_code is non-NULL, it will be set to the HTTP response code - // received (or 0 if the request failed before getting an HTTP response). - // If the send fails, a description of the error will be - // returned in error_description. - static bool SendRequest(const string &url, - const map<string, string> ¶meters, - const map<string, string> &files, - const string &proxy, - const string &proxy_user_pwd, - const string &ca_certificate_file, - string *response_body, - long *response_code, - string *error_description); - - private: - // Checks that the given list of parameters has only printable - // ASCII characters in the parameter name, and does not contain - // any quote (") characters. Returns true if so. - static bool CheckParameters(const map<string, string> ¶meters); - - // Checks the curl_lib parameter points to a valid curl lib. - static bool CheckCurlLib(void* curl_lib); - - // No instances of this class should be created. - // Disallow all constructors, destructors, and operator=. - HTTPUpload(); - explicit HTTPUpload(const HTTPUpload &); - void operator=(const HTTPUpload &); - ~HTTPUpload(); -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_HTTP_UPLOAD_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h b/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h deleted file mode 100644 index efd274c20..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2012 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_IGNORE_RET_H_ -#define COMMON_LINUX_IGNORE_RET_H_ - -// Some compilers are prone to warn about unused return values. In cases where -// either a) the call cannot fail, or b) there is nothing that can be done when -// the call fails, IGNORE_RET() can be used to mark the return code as ignored. -// This avoids spurious compiler warnings. - -#define IGNORE_RET(x) do { if (x) {} } while (0) - -#endif // COMMON_LINUX_IGNORE_RET_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc deleted file mode 100644 index fd4e34cd8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2009, 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 <dlfcn.h> - -#include <iostream> -#include <string> - -#include "common/linux/libcurl_wrapper.h" -#include "common/using_std_string.h" - -namespace google_breakpad { -LibcurlWrapper::LibcurlWrapper() - : init_ok_(false), - formpost_(NULL), - lastptr_(NULL), - headerlist_(NULL) { - curl_lib_ = dlopen("libcurl.so", RTLD_NOW); - if (!curl_lib_) { - curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW); - } - if (!curl_lib_) { - curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW); - } - if (!curl_lib_) { - std::cout << "Could not find libcurl via dlopen"; - return; - } - std::cout << "LibcurlWrapper init succeeded"; - init_ok_ = true; - return; -} - -LibcurlWrapper::~LibcurlWrapper() {} - -bool LibcurlWrapper::SetProxy(const string& proxy_host, - const string& proxy_userpwd) { - if (!init_ok_) { - return false; - } - // Set proxy information if necessary. - if (!proxy_host.empty()) { - (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str()); - } else { - std::cout << "SetProxy called with empty proxy host."; - return false; - } - if (!proxy_userpwd.empty()) { - (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str()); - } else { - std::cout << "SetProxy called with empty proxy username/password."; - return false; - } - std::cout << "Set proxy host to " << proxy_host; - return true; -} - -bool LibcurlWrapper::AddFile(const string& upload_file_path, - const string& basename) { - if (!init_ok_) { - return false; - } - std::cout << "Adding " << upload_file_path << " to form upload."; - // Add form file. - (*formadd_)(&formpost_, &lastptr_, - CURLFORM_COPYNAME, basename.c_str(), - CURLFORM_FILE, upload_file_path.c_str(), - CURLFORM_END); - - return true; -} - -// Callback to get the response data from server. -static size_t WriteCallback(void *ptr, size_t size, - size_t nmemb, void *userp) { - if (!userp) - return 0; - - string *response = reinterpret_cast<string *>(userp); - size_t real_size = size * nmemb; - response->append(reinterpret_cast<char *>(ptr), real_size); - return real_size; -} - -bool LibcurlWrapper::SendRequest(const string& url, - const std::map<string, string>& parameters, - int* http_status_code, - string* http_header_data, - string* http_response_data) { - (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str()); - std::map<string, string>::const_iterator iter = parameters.begin(); - for (; iter != parameters.end(); ++iter) - (*formadd_)(&formpost_, &lastptr_, - CURLFORM_COPYNAME, iter->first.c_str(), - CURLFORM_COPYCONTENTS, iter->second.c_str(), - CURLFORM_END); - - (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_); - if (http_response_data != NULL) { - http_response_data->clear(); - (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback); - (*easy_setopt_)(curl_, CURLOPT_WRITEDATA, - reinterpret_cast<void *>(http_response_data)); - } - if (http_header_data != NULL) { - http_header_data->clear(); - (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback); - (*easy_setopt_)(curl_, CURLOPT_HEADERDATA, - reinterpret_cast<void *>(http_header_data)); - } - - CURLcode err_code = CURLE_OK; - err_code = (*easy_perform_)(curl_); - easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)> - (dlsym(curl_lib_, "curl_easy_strerror")); - - if (http_status_code != NULL) { - (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code); - } - -#ifndef NDEBUG - if (err_code != CURLE_OK) - fprintf(stderr, "Failed to send http request to %s, error: %s\n", - url.c_str(), - (*easy_strerror_)(err_code)); -#endif - if (headerlist_ != NULL) { - (*slist_free_all_)(headerlist_); - } - - (*easy_cleanup_)(curl_); - if (formpost_ != NULL) { - (*formfree_)(formpost_); - } - - return err_code == CURLE_OK; -} - -bool LibcurlWrapper::Init() { - if (!init_ok_) { - std::cout << "Init_OK was not true in LibcurlWrapper::Init(), check earlier log messages"; - return false; - } - - if (!SetFunctionPointers()) { - std::cout << "Could not find function pointers"; - init_ok_ = false; - return false; - } - - curl_ = (*easy_init_)(); - - last_curl_error_ = "No Error"; - - if (!curl_) { - dlclose(curl_lib_); - std::cout << "Curl initialization failed"; - return false; - } - - // Disable 100-continue header. - char buf[] = "Expect:"; - - headerlist_ = (*slist_append_)(headerlist_, buf); - (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_); - return true; -} - -#define SET_AND_CHECK_FUNCTION_POINTER(var, function_name, type) \ - var = reinterpret_cast<type>(dlsym(curl_lib_, function_name)); \ - if (!var) { \ - std::cout << "Could not find libcurl function " << function_name; \ - init_ok_ = false; \ - return false; \ - } - -bool LibcurlWrapper::SetFunctionPointers() { - - SET_AND_CHECK_FUNCTION_POINTER(easy_init_, - "curl_easy_init", - CURL*(*)()); - - SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_, - "curl_easy_setopt", - CURLcode(*)(CURL*, CURLoption, ...)); - - SET_AND_CHECK_FUNCTION_POINTER(formadd_, "curl_formadd", - CURLFORMcode(*)(curl_httppost**, curl_httppost**, ...)); - - SET_AND_CHECK_FUNCTION_POINTER(slist_append_, "curl_slist_append", - curl_slist*(*)(curl_slist*, const char*)); - - SET_AND_CHECK_FUNCTION_POINTER(easy_perform_, - "curl_easy_perform", - CURLcode(*)(CURL*)); - - SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_, - "curl_easy_cleanup", - void(*)(CURL*)); - - SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_, - "curl_easy_getinfo", - CURLcode(*)(CURL *, CURLINFO info, ...)); - - SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_, - "curl_slist_free_all", - void(*)(curl_slist*)); - - SET_AND_CHECK_FUNCTION_POINTER(formfree_, - "curl_formfree", - void(*)(curl_httppost*)); - return true; -} - -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h deleted file mode 100644 index 25905ad8f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2009, 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. - -// A wrapper for libcurl to do HTTP Uploads, to support easy mocking -// and unit testing of the HTTPUpload class. - -#ifndef COMMON_LINUX_LIBCURL_WRAPPER_H_ -#define COMMON_LINUX_LIBCURL_WRAPPER_H_ - -#include <string> -#include <map> - -#include "common/using_std_string.h" -#include "third_party/curl/curl.h" - -namespace google_breakpad { -class LibcurlWrapper { - public: - LibcurlWrapper(); - virtual ~LibcurlWrapper(); - virtual bool Init(); - virtual bool SetProxy(const string& proxy_host, - const string& proxy_userpwd); - virtual bool AddFile(const string& upload_file_path, - const string& basename); - virtual bool SendRequest(const string& url, - const std::map<string, string>& parameters, - int* http_status_code, - string* http_header_data, - string* http_response_data); - private: - // This function initializes class state corresponding to function - // pointers into the CURL library. - bool SetFunctionPointers(); - - bool init_ok_; // Whether init succeeded - void* curl_lib_; // Pointer to result of dlopen() on - // curl library - string last_curl_error_; // The text of the last error when - // dealing - // with CURL. - - CURL *curl_; // Pointer for handle for CURL calls. - - CURL* (*easy_init_)(void); - - // Stateful pointers for calling into curl_formadd() - struct curl_httppost *formpost_; - struct curl_httppost *lastptr_; - struct curl_slist *headerlist_; - - // Function pointers into CURL library - CURLcode (*easy_setopt_)(CURL *, CURLoption, ...); - CURLFORMcode (*formadd_)(struct curl_httppost **, - struct curl_httppost **, ...); - struct curl_slist* (*slist_append_)(struct curl_slist *, const char *); - void (*slist_free_all_)(struct curl_slist *); - CURLcode (*easy_perform_)(CURL *); - const char* (*easy_strerror_)(CURLcode); - void (*easy_cleanup_)(CURL *); - CURLcode (*easy_getinfo_)(CURL *, CURLINFO info, ...); - void (*formfree_)(struct curl_httppost *); - -}; -} - -#endif // COMMON_LINUX_LIBCURL_WRAPPER_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc deleted file mode 100644 index 08b0325e6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) 2012, 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. - -// This source file provides replacements for libc functions that we need. If -// we call the libc functions directly we risk crashing in the dynamic linker -// as it tries to resolve uncached PLT entries. - -#include "common/linux/linux_libc_support.h" - -#include <stddef.h> - -extern "C" { - -size_t my_strlen(const char* s) { - size_t len = 0; - while (*s++) len++; - return len; -} - -int my_strcmp(const char* a, const char* b) { - for (;;) { - if (*a < *b) - return -1; - else if (*a > *b) - return 1; - else if (*a == 0) - return 0; - a++; - b++; - } -} - -int my_strncmp(const char* a, const char* b, size_t len) { - for (size_t i = 0; i < len; ++i) { - if (*a < *b) - return -1; - else if (*a > *b) - return 1; - else if (*a == 0) - return 0; - a++; - b++; - } - - return 0; -} - -// Parse a non-negative integer. -// result: (output) the resulting non-negative integer -// s: a NUL terminated string -// Return true iff successful. -bool my_strtoui(int* result, const char* s) { - if (*s == 0) - return false; - int r = 0; - for (;; s++) { - if (*s == 0) - break; - const int old_r = r; - r *= 10; - if (*s < '0' || *s > '9') - return false; - r += *s - '0'; - if (r < old_r) - return false; - } - - *result = r; - return true; -} - -// Return the length of the given unsigned integer when expressed in base 10. -unsigned my_uint_len(uintmax_t i) { - if (!i) - return 1; - - int len = 0; - while (i) { - len++; - i /= 10; - } - - return len; -} - -// Convert an unsigned integer to a string -// output: (output) the resulting string is written here. This buffer must be -// large enough to hold the resulting string. Call |my_uint_len| to get the -// required length. -// i: the unsigned integer to serialise. -// i_len: the length of the integer in base 10 (see |my_uint_len|). -void my_uitos(char* output, uintmax_t i, unsigned i_len) { - for (unsigned index = i_len; index; --index, i /= 10) - output[index - 1] = '0' + (i % 10); -} - -const char* my_strchr(const char* haystack, char needle) { - while (*haystack && *haystack != needle) - haystack++; - if (*haystack == needle) - return haystack; - return (const char*) 0; -} - -const char* my_strrchr(const char* haystack, char needle) { - const char* ret = NULL; - while (*haystack) { - if (*haystack == needle) - ret = haystack; - haystack++; - } - return ret; -} - -void* my_memchr(const void* src, int needle, size_t src_len) { - const unsigned char* p = (const unsigned char*)src; - const unsigned char* p_end = p + src_len; - for (; p < p_end; ++p) { - if (*p == needle) - return (void*)p; - } - return NULL; -} - -// Read a hex value -// result: (output) the resulting value -// s: a string -// Returns a pointer to the first invalid charactor. -const char* my_read_hex_ptr(uintptr_t* result, const char* s) { - uintptr_t r = 0; - - for (;; ++s) { - if (*s >= '0' && *s <= '9') { - r <<= 4; - r += *s - '0'; - } else if (*s >= 'a' && *s <= 'f') { - r <<= 4; - r += (*s - 'a') + 10; - } else if (*s >= 'A' && *s <= 'F') { - r <<= 4; - r += (*s - 'A') + 10; - } else { - break; - } - } - - *result = r; - return s; -} - -const char* my_read_decimal_ptr(uintptr_t* result, const char* s) { - uintptr_t r = 0; - - for (;; ++s) { - if (*s >= '0' && *s <= '9') { - r *= 10; - r += *s - '0'; - } else { - break; - } - } - *result = r; - return s; -} - -void my_memset(void* ip, char c, size_t len) { - char* p = (char *) ip; - while (len--) - *p++ = c; -} - -size_t my_strlcpy(char* s1, const char* s2, size_t len) { - size_t pos1 = 0; - size_t pos2 = 0; - - while (s2[pos2] != '\0') { - if (pos1 + 1 < len) { - s1[pos1] = s2[pos2]; - pos1++; - } - pos2++; - } - if (len > 0) - s1[pos1] = '\0'; - - return pos2; -} - -size_t my_strlcat(char* s1, const char* s2, size_t len) { - size_t pos1 = 0; - - while (pos1 < len && s1[pos1] != '\0') - pos1++; - - if (pos1 == len) - return pos1; - - return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1); -} - -int my_isspace(int ch) { - // Matches the C locale. - const char spaces[] = " \t\f\n\r\t\v"; - for (size_t i = 0; i < sizeof(spaces); i++) { - if (ch == spaces[i]) - return 1; - } - return 0; -} - -} // extern "C" diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h deleted file mode 100644 index ec5a8d6b6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2009, 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. - -// This header provides replacements for libc functions that we need. We if -// call the libc functions directly we risk crashing in the dynamic linker as -// it tries to resolve uncached PLT entries. - -#ifndef CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ -#define CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ - -#include <stdint.h> -#include <limits.h> -#include <sys/types.h> - -extern "C" { - -extern size_t my_strlen(const char* s); - -extern int my_strcmp(const char* a, const char* b); - -extern int my_strncmp(const char* a, const char* b, size_t len); - -// Parse a non-negative integer. -// result: (output) the resulting non-negative integer -// s: a NUL terminated string -// Return true iff successful. -extern bool my_strtoui(int* result, const char* s); - -// Return the length of the given unsigned integer when expressed in base 10. -extern unsigned my_uint_len(uintmax_t i); - -// Convert an unsigned integer to a string -// output: (output) the resulting string is written here. This buffer must be -// large enough to hold the resulting string. Call |my_uint_len| to get the -// required length. -// i: the unsigned integer to serialise. -// i_len: the length of the integer in base 10 (see |my_uint_len|). -extern void my_uitos(char* output, uintmax_t i, unsigned i_len); - -extern const char* my_strchr(const char* haystack, char needle); - -extern const char* my_strrchr(const char* haystack, char needle); - -// Read a hex value -// result: (output) the resulting value -// s: a string -// Returns a pointer to the first invalid charactor. -extern const char* my_read_hex_ptr(uintptr_t* result, const char* s); - -extern const char* my_read_decimal_ptr(uintptr_t* result, const char* s); - -extern void my_memset(void* ip, char c, size_t len); - -extern void* my_memchr(const void* src, int c, size_t len); - -// The following are considered safe to use in a compromised environment. -// Besides, this gives the compiler an opportunity to optimize their calls. -#define my_memcpy memcpy -#define my_memmove memmove -#define my_memcmp memcmp - -extern size_t my_strlcpy(char* s1, const char* s2, size_t len); - -extern size_t my_strlcat(char* s1, const char* s2, size_t len); - -extern int my_isspace(int ch); - -} // extern "C" - -#endif // CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc deleted file mode 100644 index adadfed44..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2009, 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 "breakpad_googletest_includes.h" -#include "common/linux/linux_libc_support.h" - -namespace { -typedef testing::Test LinuxLibcSupportTest; -} - -TEST(LinuxLibcSupportTest, strlen) { - static const char* test_data[] = { "", "a", "aa", "aaa", "aabc", NULL }; - for (unsigned i = 0; ; ++i) { - if (!test_data[i]) - break; - ASSERT_EQ(strlen(test_data[i]), my_strlen(test_data[i])); - } -} - -TEST(LinuxLibcSupportTest, strcmp) { - static const char* test_data[] = { - "", "", - "a", "", - "", "a", - "a", "b", - "a", "a", - "ab", "aa", - "abc", "ab", - "abc", "abc", - NULL, - }; - - for (unsigned i = 0; ; ++i) { - if (!test_data[i*2]) - break; - int libc_result = strcmp(test_data[i*2], test_data[i*2 + 1]); - if (libc_result > 1) - libc_result = 1; - else if (libc_result < -1) - libc_result = -1; - ASSERT_EQ(my_strcmp(test_data[i*2], test_data[i*2 + 1]), libc_result); - } -} - -TEST(LinuxLibcSupportTest, strtoui) { - int result; - - ASSERT_FALSE(my_strtoui(&result, "")); - ASSERT_FALSE(my_strtoui(&result, "-1")); - ASSERT_FALSE(my_strtoui(&result, "-")); - ASSERT_FALSE(my_strtoui(&result, "a")); - ASSERT_FALSE(my_strtoui(&result, "23472893472938472987987398472398")); - - ASSERT_TRUE(my_strtoui(&result, "0")); - ASSERT_EQ(result, 0); - ASSERT_TRUE(my_strtoui(&result, "1")); - ASSERT_EQ(result, 1); - ASSERT_TRUE(my_strtoui(&result, "12")); - ASSERT_EQ(result, 12); - ASSERT_TRUE(my_strtoui(&result, "123")); - ASSERT_EQ(result, 123); - ASSERT_TRUE(my_strtoui(&result, "0123")); - ASSERT_EQ(result, 123); -} - -TEST(LinuxLibcSupportTest, uint_len) { - ASSERT_EQ(my_uint_len(0), 1U); - ASSERT_EQ(my_uint_len(2), 1U); - ASSERT_EQ(my_uint_len(5), 1U); - ASSERT_EQ(my_uint_len(9), 1U); - ASSERT_EQ(my_uint_len(10), 2U); - ASSERT_EQ(my_uint_len(99), 2U); - ASSERT_EQ(my_uint_len(100), 3U); - ASSERT_EQ(my_uint_len(101), 3U); - ASSERT_EQ(my_uint_len(1000), 4U); - // 0xFFFFFFFFFFFFFFFF - ASSERT_EQ(my_uint_len(18446744073709551615LLU), 20U); -} - -TEST(LinuxLibcSupportTest, uitos) { - char buf[32]; - - my_uitos(buf, 0, 1); - ASSERT_EQ(0, memcmp(buf, "0", 1)); - - my_uitos(buf, 1, 1); - ASSERT_EQ(0, memcmp(buf, "1", 1)); - - my_uitos(buf, 10, 2); - ASSERT_EQ(0, memcmp(buf, "10", 2)); - - my_uitos(buf, 63, 2); - ASSERT_EQ(0, memcmp(buf, "63", 2)); - - my_uitos(buf, 101, 3); - ASSERT_EQ(0, memcmp(buf, "101", 2)); - - // 0xFFFFFFFFFFFFFFFF - my_uitos(buf, 18446744073709551615LLU, 20); - ASSERT_EQ(0, memcmp(buf, "18446744073709551615", 20)); -} - -TEST(LinuxLibcSupportTest, strchr) { - ASSERT_EQ(NULL, my_strchr("abc", 'd')); - ASSERT_EQ(NULL, my_strchr("", 'd')); - ASSERT_EQ(NULL, my_strchr("efghi", 'd')); - - ASSERT_TRUE(my_strchr("a", 'a')); - ASSERT_TRUE(my_strchr("abc", 'a')); - ASSERT_TRUE(my_strchr("bcda", 'a')); - ASSERT_TRUE(my_strchr("sdfasdf", 'a')); - - static const char abc3[] = "abcabcabc"; - ASSERT_EQ(abc3, my_strchr(abc3, 'a')); -} - -TEST(LinuxLibcSupportTest, strrchr) { - ASSERT_EQ(NULL, my_strrchr("abc", 'd')); - ASSERT_EQ(NULL, my_strrchr("", 'd')); - ASSERT_EQ(NULL, my_strrchr("efghi", 'd')); - - ASSERT_TRUE(my_strrchr("a", 'a')); - ASSERT_TRUE(my_strrchr("abc", 'a')); - ASSERT_TRUE(my_strrchr("bcda", 'a')); - ASSERT_TRUE(my_strrchr("sdfasdf", 'a')); - - static const char abc3[] = "abcabcabc"; - ASSERT_EQ(abc3 + 6, my_strrchr(abc3, 'a')); -} - -TEST(LinuxLibcSupportTest, memchr) { - ASSERT_EQ(NULL, my_memchr("abc", 'd', 3)); - ASSERT_EQ(NULL, my_memchr("abcd", 'd', 3)); - ASSERT_EQ(NULL, my_memchr("a", 'a', 0)); - - static const char abc3[] = "abcabcabc"; - ASSERT_EQ(abc3, my_memchr(abc3, 'a', 3)); - ASSERT_EQ(abc3, my_memchr(abc3, 'a', 9)); - ASSERT_EQ(abc3+1, my_memchr(abc3, 'b', 9)); - ASSERT_EQ(abc3+2, my_memchr(abc3, 'c', 9)); -} - -TEST(LinuxLibcSupportTest, read_hex_ptr) { - uintptr_t result; - const char* last; - - last = my_read_hex_ptr(&result, ""); - ASSERT_EQ(result, 0U); - ASSERT_EQ(*last, 0); - - last = my_read_hex_ptr(&result, "0"); - ASSERT_EQ(result, 0U); - ASSERT_EQ(*last, 0); - - last = my_read_hex_ptr(&result, "0123"); - ASSERT_EQ(result, 0x123U); - ASSERT_EQ(*last, 0); - - last = my_read_hex_ptr(&result, "0123a"); - ASSERT_EQ(result, 0x123aU); - ASSERT_EQ(*last, 0); - - last = my_read_hex_ptr(&result, "0123a-"); - ASSERT_EQ(result, 0x123aU); - ASSERT_EQ(*last, '-'); -} - -TEST(LinuxLibcSupportTest, read_decimal_ptr) { - uintptr_t result; - const char* last; - - last = my_read_decimal_ptr(&result, "0"); - ASSERT_EQ(result, 0U); - ASSERT_EQ(*last, 0); - - last = my_read_decimal_ptr(&result, "0123"); - ASSERT_EQ(result, 123U); - ASSERT_EQ(*last, 0); - - last = my_read_decimal_ptr(&result, "1234"); - ASSERT_EQ(result, 1234U); - ASSERT_EQ(*last, 0); - - last = my_read_decimal_ptr(&result, "01234-"); - ASSERT_EQ(result, 1234U); - ASSERT_EQ(*last, '-'); -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc deleted file mode 100644 index 4e938269f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc +++ /dev/null @@ -1,107 +0,0 @@ -// 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> -#if defined(__ANDROID__) -#include <sys/stat.h> -#endif -#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, size_t offset) { - Map(path, offset); -} - -MemoryMappedFile::~MemoryMappedFile() { - Unmap(); -} - -#include <unistd.h> - -bool MemoryMappedFile::Map(const char* path, size_t offset) { - Unmap(); - - int fd = sys_open(path, O_RDONLY, 0); - if (fd == -1) { - return false; - } - -#if defined(__x86_64__) || defined(__aarch64__) || \ - (defined(__mips__) && _MIPS_SIM == _ABI64) - - 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; - } - - // Strangely file size can be negative, but we check above that it is not. - size_t file_len = static_cast<size_t>(st.st_size); - // If the file does not extend beyond the offset, 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 (offset >= file_len) { - sys_close(fd); - return true; - } - - void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); - sys_close(fd); - if (data == MAP_FAILED) { - return false; - } - - content_.Set(data, file_len - offset); - return true; -} - -void MemoryMappedFile::Unmap() { - if (content_.data()) { - sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length()); - content_.Set(NULL, 0); - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h deleted file mode 100644 index fa660cc91..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h +++ /dev/null @@ -1,87 +0,0 @@ -// 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 <stddef.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. - MemoryMappedFile(const char* path, size_t offset); - - ~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, size_t offset); - - // 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/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc deleted file mode 100644 index fad59f40c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc +++ /dev/null @@ -1,208 +0,0 @@ -// 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/memory_mapped_file.h" -#include "common/tests/auto_tempdir.h" -#include "common/tests/file_utils.h" -#include "common/using_std_string.h" - -using google_breakpad::AutoTempDir; -using google_breakpad::MemoryMappedFile; -using google_breakpad::WriteFile; - -namespace { - -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(0U, 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", 0); - ExpectNoMappedData(mapped_file); - } - { - MemoryMappedFile mapped_file; - EXPECT_FALSE(mapped_file.Map("nonexistent-file", 0)); - ExpectNoMappedData(mapped_file); - } -} - -TEST_F(MemoryMappedFileTest, MapEmptyFile) { - AutoTempDir temp_dir; - string test_file = temp_dir.path() + "/empty_file"; - ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0)); - - { - MemoryMappedFile mapped_file(test_file.c_str(), 0); - ExpectNoMappedData(mapped_file); - } - { - MemoryMappedFile mapped_file; - EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0)); - 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.c_str(), data, data_size)); - - { - MemoryMappedFile mapped_file(test_file.c_str(), 0); - 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(), 0)); - 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.c_str(), data1, data1_size)); - ASSERT_TRUE(WriteFile(test_file2.c_str(), data2, data2_size)); - - { - MemoryMappedFile mapped_file(test_file1.c_str(), 0); - 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(), 0); - 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(), 0)); - 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(), 0); - 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)); - } -} - -TEST_F(MemoryMappedFileTest, MapWithOffset) { - // Put more data in the test file this time. Offsets can only be - // done on page boundaries, so we need a two page file to test this. - const int page_size = 4096; - char data1[2 * page_size]; - size_t data1_size = sizeof(data1); - for (size_t i = 0; i < data1_size; ++i) { - data1[i] = i & 0x7f; - } - - AutoTempDir temp_dir; - string test_file1 = temp_dir.path() + "/test_file1"; - ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size)); - { - MemoryMappedFile mapped_file(test_file1.c_str(), page_size); - EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); - EXPECT_EQ(data1_size - page_size, mapped_file.size()); - EXPECT_EQ( - 0, - memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size)); - } - { - MemoryMappedFile mapped_file; - mapped_file.Map(test_file1.c_str(), page_size); - EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); - EXPECT_EQ(data1_size - page_size, mapped_file.size()); - EXPECT_EQ( - 0, - memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size)); - } -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build deleted file mode 100644 index 7450f6ba3..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build +++ /dev/null @@ -1,56 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -UNIFIED_SOURCES += [ - 'elfutils.cc', - 'guid_creator.cc', - 'linux_libc_support.cc', - 'memory_mapped_file.cc', - 'safe_readlink.cc', -] - -# file_id.cc cannot be built in unified mode because it uses a custom DISABLE_STL_WRAPPING -SOURCES += [ - 'file_id.cc', -] - -if CONFIG['OS_TARGET'] != 'Android': - UNIFIED_SOURCES += [ - 'http_upload.cc', - ] - -HostLibrary('host_breakpad_linux_common_s') -HOST_SOURCES += [ - 'crc32.cc', - 'dump_symbols.cc', - 'elf_symbols_to_module.cc', - 'elfutils.cc', - 'file_id.cc', - 'guid_creator.cc', - 'linux_libc_support.cc', - 'memory_mapped_file.cc', -] - -HOST_CXXFLAGS += [ - '-O2', - '-g', -] - -if CONFIG['OS_TARGET'] == 'Android': - LOCAL_INCLUDES += [ - '/toolkit/crashreporter/google-breakpad/src/common/android/include', - ] - -Library('breakpad_linux_common_s') - -FINAL_LIBRARY = 'xul' - -HOST_DEFINES['NO_STABS_SUPPORT'] = True - -include('/toolkit/crashreporter/crashreporter.mozbuild') - -if CONFIG['GNU_CXX']: - CXXFLAGS += ['-Wno-shadow'] diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc deleted file mode 100644 index 870c28af3..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc +++ /dev/null @@ -1,53 +0,0 @@ -// 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. - -// safe_readlink.cc: Implement google_breakpad::SafeReadLink. -// See safe_readlink.h for details. - -#include <stddef.h> - -#include "third_party/lss/linux_syscall_support.h" - -namespace google_breakpad { - -bool SafeReadLink(const char* path, char* buffer, size_t buffer_size) { - // sys_readlink() does not add a NULL byte to |buffer|. In order to return - // a NULL-terminated string in |buffer|, |buffer_size| should be at least - // one byte longer than the expected path length. Also, sys_readlink() - // returns the actual path length on success, which does not count the - // NULL byte, so |result_size| should be less than |buffer_size|. - ssize_t result_size = sys_readlink(path, buffer, buffer_size); - if (result_size >= 0 && static_cast<size_t>(result_size) < buffer_size) { - buffer[result_size] = '\0'; - return true; - } - return false; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h deleted file mode 100644 index 4ae131b58..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -// safe_readlink.h: Define the google_breakpad::SafeReadLink function, -// which wraps sys_readlink and gurantees the result is NULL-terminated. - -#ifndef COMMON_LINUX_SAFE_READLINK_H_ -#define COMMON_LINUX_SAFE_READLINK_H_ - -#include <stddef.h> - -namespace google_breakpad { - -// This function wraps sys_readlink() and performs the same functionalty, -// but guarantees |buffer| is NULL-terminated if sys_readlink() returns -// no error. It takes the same arguments as sys_readlink(), but unlike -// sys_readlink(), it returns true on success. -// -// |buffer_size| specifies the size of |buffer| in bytes. As this function -// always NULL-terminates |buffer| on success, |buffer_size| should be -// at least one byte longer than the expected path length (e.g. PATH_MAX, -// which is typically defined as the maximum length of a path name -// including the NULL byte). -// -// The implementation of this function calls sys_readlink() instead of -// readlink(), it can thus be used in the context where calling to libc -// functions is discouraged. -bool SafeReadLink(const char* path, char* buffer, size_t buffer_size); - -// Same as the three-argument version of SafeReadLink() but deduces the -// size of |buffer| if it is a char array of known size. -template <size_t N> -bool SafeReadLink(const char* path, char (&buffer)[N]) { - return SafeReadLink(path, buffer, sizeof(buffer)); -} - -} // namespace google_breakpad - -#endif // COMMON_LINUX_SAFE_READLINK_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc deleted file mode 100644 index d346b2a80..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc +++ /dev/null @@ -1,89 +0,0 @@ -// 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. - -// safe_readlink_unittest.cc: Unit tests for google_breakpad::SafeReadLink. - -#include "breakpad_googletest_includes.h" -#include "common/linux/safe_readlink.h" - -using google_breakpad::SafeReadLink; - -TEST(SafeReadLinkTest, ZeroBufferSize) { - char buffer[1]; - EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, 0)); -} - -TEST(SafeReadLinkTest, BufferSizeTooSmall) { - char buffer[1]; - EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, 1)); -} - -TEST(SafeReadLinkTest, BoundaryBufferSize) { - char buffer[PATH_MAX]; - EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer, sizeof(buffer))); - size_t path_length = strlen(buffer); - EXPECT_LT(0U, path_length); - EXPECT_GT(sizeof(buffer), path_length); - - // Buffer size equals to the expected path length plus 1 for the NULL byte. - char buffer2[PATH_MAX]; - EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer2, path_length + 1)); - EXPECT_EQ(path_length, strlen(buffer2)); - EXPECT_EQ(0, strncmp(buffer, buffer2, PATH_MAX)); - - // Buffer size equals to the expected path length. - EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, path_length)); -} - -TEST(SafeReadLinkTest, NonexistentPath) { - char buffer[PATH_MAX]; - EXPECT_FALSE(SafeReadLink("nonexistent_path", buffer, sizeof(buffer))); -} - -TEST(SafeReadLinkTest, NonSymbolicLinkPath) { - char actual_path[PATH_MAX]; - EXPECT_TRUE(SafeReadLink("/proc/self/exe", actual_path, sizeof(actual_path))); - - char buffer[PATH_MAX]; - EXPECT_FALSE(SafeReadLink(actual_path, buffer, sizeof(buffer))); -} - -TEST(SafeReadLinkTest, DeduceBufferSizeFromCharArray) { - char buffer[PATH_MAX]; - char* buffer_pointer = buffer; - EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer_pointer, sizeof(buffer))); - size_t path_length = strlen(buffer); - - // Use the template version of SafeReadLink to deduce the buffer size - // from the char array. - char buffer2[PATH_MAX]; - EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer2)); - EXPECT_EQ(path_length, strlen(buffer2)); - EXPECT_EQ(0, strncmp(buffer, buffer2, PATH_MAX)); -} diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc deleted file mode 100644 index bbd3181e1..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc +++ /dev/null @@ -1,155 +0,0 @@ -// 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. - -// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper -// function for linux symbol upload tool. - -#include "common/linux/http_upload.h" -#include "common/linux/symbol_upload.h" - -#include <assert.h> -#include <stdio.h> - -#include <functional> -#include <vector> - -namespace google_breakpad { -namespace sym_upload { - -void TokenizeByChar(const string &source_string, int c, - std::vector<string> *results) { - assert(results); - string::size_type cur_pos = 0, next_pos = 0; - while ((next_pos = source_string.find(c, cur_pos)) != string::npos) { - if (next_pos != cur_pos) - results->push_back(source_string.substr(cur_pos, next_pos - cur_pos)); - cur_pos = next_pos + 1; - } - if (cur_pos < source_string.size() && next_pos != cur_pos) - results->push_back(source_string.substr(cur_pos)); -} - -//============================================================================= -// Parse out the module line which have 5 parts. -// MODULE <os> <cpu> <uuid> <module-name> -bool ModuleDataForSymbolFile(const string &file, - std::vector<string> *module_parts) { - assert(module_parts); - const size_t kModulePartNumber = 5; - FILE* fp = fopen(file.c_str(), "r"); - if (fp) { - char buffer[1024]; - if (fgets(buffer, sizeof(buffer), fp)) { - string line(buffer); - string::size_type line_break_pos = line.find_first_of('\n'); - if (line_break_pos == string::npos) { - assert(0 && "The file is invalid!"); - fclose(fp); - return false; - } - line.resize(line_break_pos); - const char kDelimiter = ' '; - TokenizeByChar(line, kDelimiter, module_parts); - if (module_parts->size() != kModulePartNumber) - module_parts->clear(); - } - fclose(fp); - } - - return module_parts->size() == kModulePartNumber; -} - -//============================================================================= -string CompactIdentifier(const string &uuid) { - std::vector<string> components; - TokenizeByChar(uuid, '-', &components); - string result; - for (size_t i = 0; i < components.size(); ++i) - result += components[i]; - return result; -} - -//============================================================================= -void Start(Options *options) { - std::map<string, string> parameters; - options->success = false; - std::vector<string> module_parts; - if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) { - fprintf(stderr, "Failed to parse symbol file!\n"); - return; - } - - string compacted_id = CompactIdentifier(module_parts[3]); - - // Add parameters - if (!options->version.empty()) - parameters["version"] = options->version; - - // MODULE <os> <cpu> <uuid> <module-name> - // 0 1 2 3 4 - parameters["os"] = module_parts[1]; - parameters["cpu"] = module_parts[2]; - parameters["debug_file"] = module_parts[4]; - parameters["code_file"] = module_parts[4]; - parameters["debug_identifier"] = compacted_id; - - std::map<string, string> files; - files["symbol_file"] = options->symbolsPath; - - string response, error; - long response_code; - bool success = HTTPUpload::SendRequest(options->uploadURLStr, - parameters, - files, - options->proxy, - options->proxy_user_pwd, - "", - &response, - &response_code, - &error); - - if (!success) { - printf("Failed to send symbol file: %s\n", error.c_str()); - printf("Response code: %ld\n", response_code); - printf("Response:\n"); - printf("%s\n", response.c_str()); - } else if (response_code == 0) { - printf("Failed to send symbol file: No response code\n"); - } else if (response_code != 200) { - printf("Failed to send symbol file: Response code %ld\n", response_code); - printf("Response:\n"); - printf("%s\n", response.c_str()); - } else { - printf("Successfully sent the symbol file.\n"); - } - options->success = success; -} - -} // namespace sym_upload -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h deleted file mode 100644 index 0a469692a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h +++ /dev/null @@ -1,59 +0,0 @@ -// -*- mode: c++ -*- - -// 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. - -// symbol_upload.h: helper functions for linux symbol upload tool. - -#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_ -#define COMMON_LINUX_SYMBOL_UPLOAD_H_ - -#include <string> - -#include "common/using_std_string.h" - -namespace google_breakpad { -namespace sym_upload { - -typedef struct { - string symbolsPath; - string uploadURLStr; - string proxy; - string proxy_user_pwd; - string version; - bool success; -} Options; - -// Starts upload to symbol server with options. -void Start(Options* options); - -} // namespace sym_upload -} // namespace google_breakpad - -#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc deleted file mode 100644 index 98e81dab7..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc +++ /dev/null @@ -1,263 +0,0 @@ -#include "common/linux/synth_elf.h" - -#include <assert.h> -#include <elf.h> -#include <stdio.h> -#include <string.h> - -#include "common/linux/elf_gnu_compat.h" -#include "common/using_std_string.h" - -namespace google_breakpad { -namespace synth_elf { - -ELF::ELF(uint16_t machine, - uint8_t file_class, - Endianness endianness) - : Section(endianness), - addr_size_(file_class == ELFCLASS64 ? 8 : 4), - program_count_(0), - program_header_table_(endianness), - section_count_(0), - section_header_table_(endianness), - section_header_strings_(endianness) { - // Could add support for more machine types here if needed. - assert(machine == EM_386 || - machine == EM_X86_64 || - machine == EM_ARM); - assert(file_class == ELFCLASS32 || file_class == ELFCLASS64); - - start() = 0; - // Add ELF header - // e_ident - // EI_MAG0...EI_MAG3 - D8(ELFMAG0); - D8(ELFMAG1); - D8(ELFMAG2); - D8(ELFMAG3); - // EI_CLASS - D8(file_class); - // EI_DATA - D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB); - // EI_VERSION - D8(EV_CURRENT); - // EI_OSABI - D8(ELFOSABI_SYSV); - // EI_ABIVERSION - D8(0); - // EI_PAD - Append(7, 0); - assert(Size() == EI_NIDENT); - - // e_type - D16(ET_EXEC); //TODO: allow passing ET_DYN? - // e_machine - D16(machine); - // e_version - D32(EV_CURRENT); - // e_entry - Append(endianness, addr_size_, 0); - // e_phoff - Append(endianness, addr_size_, program_header_label_); - // e_shoff - Append(endianness, addr_size_, section_header_label_); - // e_flags - D32(0); - // e_ehsize - D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); - // e_phentsize - D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr)); - // e_phnum - D16(program_count_label_); - // e_shentsize - D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr)); - // e_shnum - D16(section_count_label_); - // e_shstrndx - D16(section_header_string_index_); - - // Add an empty section for SHN_UNDEF. - Section shn_undef; - AddSection("", shn_undef, SHT_NULL); -} - -int ELF::AddSection(const string& name, const Section& section, - uint32_t type, uint32_t flags, uint64_t addr, - uint32_t link, uint64_t entsize, uint64_t offset) { - Label offset_label; - Label string_label(section_header_strings_.Add(name)); - size_t size = section.Size(); - - int index = section_count_; - ++section_count_; - - section_header_table_ - // sh_name - .D32(string_label) - // sh_type - .D32(type) - // sh_flags - .Append(endianness(), addr_size_, flags) - // sh_addr - .Append(endianness(), addr_size_, addr) - // sh_offset - .Append(endianness(), addr_size_, offset_label) - // sh_size - .Append(endianness(), addr_size_, size) - // sh_link - .D32(link) - // sh_info - .D32(0) - // sh_addralign - .Append(endianness(), addr_size_, 0) - // sh_entsize - .Append(endianness(), addr_size_, entsize); - - sections_.push_back(ElfSection(section, type, addr, offset, offset_label, - size)); - return index; -} - -void ELF::AppendSection(ElfSection §ion) { - // NULL and NOBITS sections have no content, so they - // don't need to be written to the file. - if (section.type_ == SHT_NULL) { - section.offset_label_ = 0; - } else if (section.type_ == SHT_NOBITS) { - section.offset_label_ = section.offset_; - } else { - Mark(§ion.offset_label_); - Append(section); - Align(4); - } -} - -void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) { - assert(start > 0); - assert(size_t(start) < sections_.size()); - assert(end > 0); - assert(size_t(end) < sections_.size()); - ++program_count_; - - // p_type - program_header_table_.D32(type); - - if (addr_size_ == 8) { - // p_flags - program_header_table_.D32(flags); - } - - size_t filesz = 0; - size_t memsz = 0; - bool prev_was_nobits = false; - for (int i = start; i <= end; ++i) { - size_t size = sections_[i].size_; - if (sections_[i].type_ != SHT_NOBITS) { - assert(!prev_was_nobits); - // non SHT_NOBITS sections are 4-byte aligned (see AddSection) - size = (size + 3) & ~3; - filesz += size; - } else { - prev_was_nobits = true; - } - memsz += size; - } - - program_header_table_ - // p_offset - .Append(endianness(), addr_size_, sections_[start].offset_label_) - // p_vaddr - .Append(endianness(), addr_size_, sections_[start].addr_) - // p_paddr - .Append(endianness(), addr_size_, sections_[start].addr_) - // p_filesz - .Append(endianness(), addr_size_, filesz) - // p_memsz - .Append(endianness(), addr_size_, memsz); - - if (addr_size_ == 4) { - // p_flags - program_header_table_.D32(flags); - } - - // p_align - program_header_table_.Append(endianness(), addr_size_, 0); -} - -void ELF::Finish() { - // Add the section header string table at the end. - section_header_string_index_ = section_count_; - //printf(".shstrtab size: %ld\n", section_header_strings_.Size()); - AddSection(".shstrtab", section_header_strings_, SHT_STRTAB); - //printf("section_count_: %ld, sections_.size(): %ld\n", - // section_count_, sections_.size()); - if (program_count_) { - Mark(&program_header_label_); - Append(program_header_table_); - } else { - program_header_label_ = 0; - } - - for (vector<ElfSection>::iterator it = sections_.begin(); - it < sections_.end(); ++it) { - AppendSection(*it); - } - section_count_label_ = section_count_; - program_count_label_ = program_count_; - - // Section header table starts here. - Mark(§ion_header_label_); - Append(section_header_table_); -} - -SymbolTable::SymbolTable(Endianness endianness, - size_t addr_size, - StringTable& table) : Section(endianness), - table_(table) { -#ifndef NDEBUG - addr_size_ = addr_size; -#endif - assert(addr_size_ == 4 || addr_size_ == 8); -} - -void SymbolTable::AddSymbol(const string& name, uint32_t value, - uint32_t size, unsigned info, uint16_t shndx) { - assert(addr_size_ == 4); - D32(table_.Add(name)); - D32(value); - D32(size); - D8(info); - D8(0); // other - D16(shndx); -} - -void SymbolTable::AddSymbol(const string& name, uint64_t value, - uint64_t size, unsigned info, uint16_t shndx) { - assert(addr_size_ == 8); - D32(table_.Add(name)); - D8(info); - D8(0); // other - D16(shndx); - D64(value); - D64(size); -} - -void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes, - size_t desc_size) { - // Elf32_Nhdr and Elf64_Nhdr are exactly the same. - Elf32_Nhdr note_header; - memset(¬e_header, 0, sizeof(note_header)); - note_header.n_namesz = name.length() + 1; - note_header.n_descsz = desc_size; - note_header.n_type = type; - - Append(reinterpret_cast<const uint8_t*>(¬e_header), - sizeof(note_header)); - AppendCString(name); - Align(4); - Append(desc_bytes, desc_size); - Align(4); -} - -} // namespace synth_elf -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h deleted file mode 100644 index 1d2a20ca2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h +++ /dev/null @@ -1,197 +0,0 @@ -// -*- mode: C++ -*- - -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -// synth_elf.h: Interface to synth_elf::ELF: fake ELF generator. - -#ifndef COMMON_LINUX_SYNTH_ELF_H_ -#define COMMON_LINUX_SYNTH_ELF_H_ - -#include "common/test_assembler.h" - -#include <list> -#include <vector> -#include <map> -#include <string> -#include <utility> - -#include "common/using_std_string.h" - -namespace google_breakpad { -namespace synth_elf { - -using std::list; -using std::vector; -using std::map; -using std::pair; -using test_assembler::Endianness; -using test_assembler::kLittleEndian; -using test_assembler::kUnsetEndian; -using test_assembler::Label; -using test_assembler::Section; - -// String tables are common in ELF headers, so subclass Section -// to make them easy to generate. -class StringTable : public Section { -public: - StringTable(Endianness endianness = kUnsetEndian) - : Section(endianness) { - start() = 0; - empty_string = Add(""); - } - - // Add the string s to the string table, and return - // a label containing the offset into the string table - // at which it was added. - Label Add(const string& s) { - if (strings_.find(s) != strings_.end()) - return strings_[s]; - - Label string_label(Here()); - AppendCString(s); - strings_[s] = string_label; - return string_label; - } - - // All StringTables contain an empty string as their first - // entry. - Label empty_string; - - // Avoid inserting duplicate strings. - map<string,Label> strings_; -}; - -// A Section representing an entire ELF file. -class ELF : public Section { - public: - ELF(uint16_t machine, // EM_386, etc - uint8_t file_class, // ELFCLASS{32,64} - Endianness endianness = kLittleEndian); - - // Add the Section section to the section header table and append it - // to the file. Returns the index of the section in the section - // header table. - int AddSection(const string& name, const Section& section, - uint32_t type, uint32_t flags = 0, uint64_t addr = 0, - uint32_t link = 0, uint64_t entsize = 0, uint64_t offset = 0); - - // Add a segment containing from section index start to section index end. - // The indexes must have been gotten from AddSection. - void AddSegment(int start, int end, uint32_t type, uint32_t flags = 0); - - // Write out all data. GetContents may be used after this. - void Finish(); - - private: - // Size of an address, in bytes. - const size_t addr_size_; - - // Offset to the program header table. - Label program_header_label_; - // Number of entries in the program header table. - int program_count_; - Label program_count_label_; - // The program header table itself. - Section program_header_table_; - - // Offset to the section header table. - Label section_header_label_; - // Number of entries in the section header table. - int section_count_; - Label section_count_label_; - // The section header table itself. - Section section_header_table_; - - // Index of the section header string table in the section - // header table. - Label section_header_string_index_; - // Section containing the names of section header table entries. - StringTable section_header_strings_; - - // Record of an added section - struct ElfSection : public Section { - ElfSection(const Section& section, uint32_t type, uint32_t addr, - uint32_t offset, Label offset_label, uint32_t size) - : Section(section), type_(type), addr_(addr), offset_(offset) - , offset_label_(offset_label), size_(size) { - } - - uint32_t type_; - uint32_t addr_; - uint32_t offset_; - Label offset_label_; - uint32_t size_; - }; - - vector<ElfSection> sections_; - - void AppendSection(ElfSection §ion); -}; - -// A class to build .symtab or .dynsym sections. -class SymbolTable : public Section { - public: - // table is the StringTable that contains symbol names. The caller - // must ensure that it remains alive for the life of the - // SymbolTable. - SymbolTable(Endianness endianness, size_t addr_size, StringTable& table); - - // Add an Elf32_Sym. - void AddSymbol(const string& name, uint32_t value, - uint32_t size, unsigned info, uint16_t shndx); - // Add an Elf64_Sym. - void AddSymbol(const string& name, uint64_t value, - uint64_t size, unsigned info, uint16_t shndx); - - private: -#ifndef NDEBUG - size_t addr_size_; -#endif - StringTable& table_; -}; - -// A class for note sections -class Notes : public Section { -public: - Notes(Endianness endianness) - : Section(endianness) { - } - - // Add a note. - void AddNote(int type, const string &name, const uint8_t* desc_bytes, - size_t desc_size); -}; - -} // namespace synth_elf -} // namespace google_breakpad - -#endif // COMMON_LINUX_SYNTH_ELF_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc deleted file mode 100644 index 3715b6e60..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc +++ /dev/null @@ -1,413 +0,0 @@ -// 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. - -// Original author: Ted Mielczarek <ted.mielczarek@gmail.com> - -// synth_elf_unittest.cc: -// Unittests for google_breakpad::synth_elf::ELF - -#include <elf.h> - -#include "breakpad_googletest_includes.h" -#include "common/linux/elfutils.h" -#include "common/linux/synth_elf.h" -#include "common/using_std_string.h" - -using google_breakpad::ElfClass32; -using google_breakpad::ElfClass64; -using google_breakpad::synth_elf::ELF; -using google_breakpad::synth_elf::Notes; -using google_breakpad::synth_elf::Section; -using google_breakpad::synth_elf::StringTable; -using google_breakpad::synth_elf::SymbolTable; -using google_breakpad::test_assembler::Endianness; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using ::testing::Test; -using ::testing::Types; - -class StringTableTest : public Test { -public: - StringTableTest() : table(kLittleEndian) {} - - StringTable table; -}; - -TEST_F(StringTableTest, Empty) { - EXPECT_EQ(1U, table.Size()); - string contents; - ASSERT_TRUE(table.GetContents(&contents)); - const char* kExpectedContents = "\0"; - EXPECT_EQ(0, memcmp(kExpectedContents, - contents.c_str(), - contents.size())); - ASSERT_TRUE(table.empty_string.IsKnownConstant()); - EXPECT_EQ(0U, table.empty_string.Value()); -} - -TEST_F(StringTableTest, Basic) { - const string s1("table fills with strings"); - const string s2("offsets preserved as labels"); - const string s3("verified with tests"); - const char* kExpectedContents = - "\0table fills with strings\0" - "offsets preserved as labels\0" - "verified with tests\0"; - Label l1(table.Add(s1)); - Label l2(table.Add(s2)); - Label l3(table.Add(s3)); - string contents; - ASSERT_TRUE(table.GetContents(&contents)); - EXPECT_EQ(0, memcmp(kExpectedContents, - contents.c_str(), - contents.size())); - // empty_string is at zero, other strings start at 1. - ASSERT_TRUE(l1.IsKnownConstant()); - EXPECT_EQ(1U, l1.Value()); - // Each string has an extra byte for a trailing null. - EXPECT_EQ(1 + s1.length() + 1, l2.Value()); - EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value()); -} - -TEST_F(StringTableTest, Duplicates) { - const string s1("string 1"); - const string s2("string 2"); - const string s3(""); - const char* kExpectedContents = "\0string 1\0string 2\0"; - Label l1(table.Add(s1)); - Label l2(table.Add(s2)); - // Adding strings twice should return the same Label. - Label l3(table.Add(s3)); - Label l4(table.Add(s2)); - string contents; - ASSERT_TRUE(table.GetContents(&contents)); - EXPECT_EQ(0, memcmp(kExpectedContents, - contents.c_str(), - contents.size())); - EXPECT_EQ(0U, table.empty_string.Value()); - EXPECT_EQ(table.empty_string.Value(), l3.Value()); - EXPECT_EQ(l2.Value(), l4.Value()); -} - -class SymbolTableTest : public Test {}; - -TEST_F(SymbolTableTest, Simple32) { - StringTable table(kLittleEndian); - SymbolTable syms(kLittleEndian, 4, table); - - const string kFuncName1 = "superfunc"; - const uint32_t kFuncAddr1 = 0x10001000; - const uint32_t kFuncSize1 = 0x10; - const string kFuncName2 = "awesomefunc"; - const uint32_t kFuncAddr2 = 0x20002000; - const uint32_t kFuncSize2 = 0x2f; - const string kFuncName3 = "megafunc"; - const uint32_t kFuncAddr3 = 0x30003000; - const uint32_t kFuncSize3 = 0x3c; - - syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1, - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), - SHN_UNDEF + 1); - syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2, - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), - SHN_UNDEF + 2); - syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3, - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), - SHN_UNDEF + 3); - - const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc"; - const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable); - EXPECT_EQ(kExpectedStringTableSize, table.Size()); - string table_contents; - table.GetContents(&table_contents); - EXPECT_EQ(0, memcmp(kExpectedStringTable, - table_contents.c_str(), - table_contents.size())); - - const uint8_t kExpectedSymbolContents[] = { - // Symbol 1 - 0x01, 0x00, 0x00, 0x00, // name - 0x00, 0x10, 0x00, 0x10, // value - 0x10, 0x00, 0x00, 0x00, // size - ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info - 0x00, // other - 0x01, 0x00, // shndx - // Symbol 2 - 0x0B, 0x00, 0x00, 0x00, // name - 0x00, 0x20, 0x00, 0x20, // value - 0x2f, 0x00, 0x00, 0x00, // size - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info - 0x00, // other - 0x02, 0x00, // shndx - // Symbol 3 - 0x17, 0x00, 0x00, 0x00, // name - 0x00, 0x30, 0x00, 0x30, // value - 0x3c, 0x00, 0x00, 0x00, // size - ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info - 0x00, // other - 0x03, 0x00, // shndx - }; - const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents); - EXPECT_EQ(kExpectedSymbolSize, syms.Size()); - - string symbol_contents; - syms.GetContents(&symbol_contents); - EXPECT_EQ(0, memcmp(kExpectedSymbolContents, - symbol_contents.c_str(), - symbol_contents.size())); -} - -template<typename ElfClass> -class BasicElf : public Test {}; - -// Doesn't seem worthwhile writing the tests to be endian-independent -// when they're unlikely to ever be run on big-endian systems. -#if defined(__i386__) || defined(__x86_64__) - -typedef Types<ElfClass32, ElfClass64> ElfClasses; - -TYPED_TEST_CASE(BasicElf, ElfClasses); - -TYPED_TEST(BasicElf, EmptyLE) { - typedef typename TypeParam::Ehdr Ehdr; - typedef typename TypeParam::Phdr Phdr; - typedef typename TypeParam::Shdr Shdr; - const size_t kStringTableSize = sizeof("\0.shstrtab"); - const size_t kStringTableAlign = 4 - kStringTableSize % 4; - const size_t kExpectedSize = sizeof(Ehdr) + - // Two sections, SHT_NULL + the section header string table. - 2 * sizeof(Shdr) + - kStringTableSize + kStringTableAlign; - - // It doesn't really matter that the machine type is right for the class. - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - elf.Finish(); - EXPECT_EQ(kExpectedSize, elf.Size()); - - string contents; - ASSERT_TRUE(elf.GetContents(&contents)); - ASSERT_EQ(kExpectedSize, contents.size()); - const Ehdr* header = - reinterpret_cast<const Ehdr*>(contents.data()); - const uint8_t kIdent[] = { - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent))); - EXPECT_EQ(ET_EXEC, header->e_type); - EXPECT_EQ(EM_386, header->e_machine); - EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version); - EXPECT_EQ(0U, header->e_entry); - EXPECT_EQ(0U, header->e_phoff); - EXPECT_EQ(sizeof(Ehdr) + kStringTableSize + kStringTableAlign, - header->e_shoff); - EXPECT_EQ(0U, header->e_flags); - EXPECT_EQ(sizeof(Ehdr), header->e_ehsize); - EXPECT_EQ(sizeof(Phdr), header->e_phentsize); - EXPECT_EQ(0, header->e_phnum); - EXPECT_EQ(sizeof(Shdr), header->e_shentsize); - EXPECT_EQ(2, header->e_shnum); - EXPECT_EQ(1, header->e_shstrndx); - - const Shdr* shdr = - reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff); - EXPECT_EQ(0U, shdr[0].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type); - EXPECT_EQ(0U, shdr[0].sh_flags); - EXPECT_EQ(0U, shdr[0].sh_addr); - EXPECT_EQ(0U, shdr[0].sh_offset); - EXPECT_EQ(0U, shdr[0].sh_size); - EXPECT_EQ(0U, shdr[0].sh_link); - EXPECT_EQ(0U, shdr[0].sh_info); - EXPECT_EQ(0U, shdr[0].sh_addralign); - EXPECT_EQ(0U, shdr[0].sh_entsize); - - EXPECT_EQ(1U, shdr[1].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[1].sh_type); - EXPECT_EQ(0U, shdr[1].sh_flags); - EXPECT_EQ(0U, shdr[1].sh_addr); - EXPECT_EQ(sizeof(Ehdr), shdr[1].sh_offset); - EXPECT_EQ(kStringTableSize, shdr[1].sh_size); - EXPECT_EQ(0U, shdr[1].sh_link); - EXPECT_EQ(0U, shdr[1].sh_info); - EXPECT_EQ(0U, shdr[1].sh_addralign); - EXPECT_EQ(0U, shdr[1].sh_entsize); -} - -TYPED_TEST(BasicElf, BasicLE) { - typedef typename TypeParam::Ehdr Ehdr; - typedef typename TypeParam::Phdr Phdr; - typedef typename TypeParam::Shdr Shdr; - const size_t kStringTableSize = sizeof("\0.text\0.bss\0.shstrtab"); - const size_t kStringTableAlign = 4 - kStringTableSize % 4; - const size_t kExpectedSize = sizeof(Ehdr) + - // Four sections, SHT_NULL + the section header string table + - // 4096 bytes of the size-aligned .text section + one program header. - sizeof(Phdr) + 4 * sizeof(Shdr) + 4096 + - kStringTableSize + kStringTableAlign; - - // It doesn't really matter that the machine type is right for the class. - ELF elf(EM_386, TypeParam::kClass, kLittleEndian); - Section text(kLittleEndian); - text.Append(4094, 0); - int text_idx = elf.AddSection(".text", text, SHT_PROGBITS); - Section bss(kLittleEndian); - bss.Append(16, 0); - int bss_idx = elf.AddSection(".bss", bss, SHT_NOBITS); - elf.AddSegment(text_idx, bss_idx, PT_LOAD); - elf.Finish(); - EXPECT_EQ(kExpectedSize, elf.Size()); - - string contents; - ASSERT_TRUE(elf.GetContents(&contents)); - ASSERT_EQ(kExpectedSize, contents.size()); - const Ehdr* header = - reinterpret_cast<const Ehdr*>(contents.data()); - const uint8_t kIdent[] = { - ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, - TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV, - 0, 0, 0, 0, 0, 0, 0, 0 - }; - EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent))); - EXPECT_EQ(ET_EXEC, header->e_type); - EXPECT_EQ(EM_386, header->e_machine); - EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version); - EXPECT_EQ(0U, header->e_entry); - EXPECT_EQ(sizeof(Ehdr), header->e_phoff); - EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096 + kStringTableSize + - kStringTableAlign, header->e_shoff); - EXPECT_EQ(0U, header->e_flags); - EXPECT_EQ(sizeof(Ehdr), header->e_ehsize); - EXPECT_EQ(sizeof(Phdr), header->e_phentsize); - EXPECT_EQ(1, header->e_phnum); - EXPECT_EQ(sizeof(Shdr), header->e_shentsize); - EXPECT_EQ(4, header->e_shnum); - EXPECT_EQ(3, header->e_shstrndx); - - const Shdr* shdr = - reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff); - EXPECT_EQ(0U, shdr[0].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type); - EXPECT_EQ(0U, shdr[0].sh_flags); - EXPECT_EQ(0U, shdr[0].sh_addr); - EXPECT_EQ(0U, shdr[0].sh_offset); - EXPECT_EQ(0U, shdr[0].sh_size); - EXPECT_EQ(0U, shdr[0].sh_link); - EXPECT_EQ(0U, shdr[0].sh_info); - EXPECT_EQ(0U, shdr[0].sh_addralign); - EXPECT_EQ(0U, shdr[0].sh_entsize); - - EXPECT_EQ(1U, shdr[1].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_PROGBITS), shdr[1].sh_type); - EXPECT_EQ(0U, shdr[1].sh_flags); - EXPECT_EQ(0U, shdr[1].sh_addr); - EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), shdr[1].sh_offset); - EXPECT_EQ(4094U, shdr[1].sh_size); - EXPECT_EQ(0U, shdr[1].sh_link); - EXPECT_EQ(0U, shdr[1].sh_info); - EXPECT_EQ(0U, shdr[1].sh_addralign); - EXPECT_EQ(0U, shdr[1].sh_entsize); - - EXPECT_EQ(sizeof("\0.text"), shdr[2].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_NOBITS), shdr[2].sh_type); - EXPECT_EQ(0U, shdr[2].sh_flags); - EXPECT_EQ(0U, shdr[2].sh_addr); - EXPECT_EQ(0U, shdr[2].sh_offset); - EXPECT_EQ(16U, shdr[2].sh_size); - EXPECT_EQ(0U, shdr[2].sh_link); - EXPECT_EQ(0U, shdr[2].sh_info); - EXPECT_EQ(0U, shdr[2].sh_addralign); - EXPECT_EQ(0U, shdr[2].sh_entsize); - - EXPECT_EQ(sizeof("\0.text\0.bss"), shdr[3].sh_name); - EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[3].sh_type); - EXPECT_EQ(0U, shdr[3].sh_flags); - EXPECT_EQ(0U, shdr[3].sh_addr); - EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096, shdr[3].sh_offset); - EXPECT_EQ(kStringTableSize, shdr[3].sh_size); - EXPECT_EQ(0U, shdr[3].sh_link); - EXPECT_EQ(0U, shdr[3].sh_info); - EXPECT_EQ(0U, shdr[3].sh_addralign); - EXPECT_EQ(0U, shdr[3].sh_entsize); - - const Phdr* phdr = - reinterpret_cast<const Phdr*>(contents.data() + header->e_phoff); - EXPECT_EQ(static_cast<unsigned int>(PT_LOAD), phdr->p_type); - EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), phdr->p_offset); - EXPECT_EQ(0U, phdr->p_vaddr); - EXPECT_EQ(0U, phdr->p_paddr); - EXPECT_EQ(4096U, phdr->p_filesz); - EXPECT_EQ(4096U + 16U, phdr->p_memsz); - EXPECT_EQ(0U, phdr->p_flags); - EXPECT_EQ(0U, phdr->p_align); -} - -class ElfNotesTest : public Test {}; - -TEST_F(ElfNotesTest, Empty) { - Notes notes(kLittleEndian); - string contents; - ASSERT_TRUE(notes.GetContents(&contents)); - EXPECT_EQ(0U, contents.size()); -} - -TEST_F(ElfNotesTest, Notes) { - Notes notes(kLittleEndian); - notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t *>("\x42\x02\0\0"), - 4); - notes.AddNote(2, "a", reinterpret_cast<const uint8_t *>("foobar"), - sizeof("foobar") - 1); - - const uint8_t kExpectedNotesContents[] = { - // Note 1 - 0x06, 0x00, 0x00, 0x00, // name size, including terminating zero - 0x04, 0x00, 0x00, 0x00, // desc size - 0x01, 0x00, 0x00, 0x00, // type - 'L', 'i', 'n', 'u', 'x', 0x00, 0x00, 0x00, // padded "Linux" - 0x42, 0x02, 0x00, 0x00, // desc - // Note 2 - 0x02, 0x00, 0x00, 0x00, // name size - 0x06, 0x00, 0x00, 0x00, // desc size - 0x02, 0x00, 0x00, 0x00, // type - 'a', 0x00, 0x00, 0x00, // padded "a" - 'f', 'o', 'o', 'b', 'a', 'r', 0x00, 0x00, // padded "foobar" - }; - const size_t kExpectedNotesSize = sizeof(kExpectedNotesContents); - EXPECT_EQ(kExpectedNotesSize, notes.Size()); - - string notes_contents; - ASSERT_TRUE(notes.GetContents(¬es_contents)); - EXPECT_EQ(0, memcmp(kExpectedNotesContents, - notes_contents.data(), - notes_contents.size())); -} - -#endif // defined(__i386__) || defined(__x86_64__) diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h deleted file mode 100644 index 92fe017b9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2013, 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. - -// Utility class for creating a temporary file for unit tests -// that is deleted in the destructor. - -#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE -#define GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE - -#include <unistd.h> -#include <sys/types.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/linux/eintr_wrapper.h" -#include "common/tests/auto_tempdir.h" - -namespace google_breakpad { - -class AutoTestFile { - public: - // Create a new empty test file. - // test_prefix: (input) test-specific prefix, can't be NULL. - explicit AutoTestFile(const char* test_prefix) { - Init(test_prefix); - } - - // Create a new test file, and fill it with initial data from a C string. - // The terminating zero is not written. - // test_prefix: (input) test-specific prefix, can't be NULL. - // text: (input) initial content. - AutoTestFile(const char* test_prefix, const char* text) { - Init(test_prefix); - if (fd_ >= 0) - WriteText(text, static_cast<size_t>(strlen(text))); - } - - AutoTestFile(const char* test_prefix, const char* text, size_t text_len) { - Init(test_prefix); - if (fd_ >= 0) - WriteText(text, text_len); - } - - // Destroy test file on scope exit. - ~AutoTestFile() { - if (fd_ >= 0) { - close(fd_); - fd_ = -1; - } - } - - // Returns true iff the test file could be created properly. - // Useful in tests inside EXPECT_TRUE(file.IsOk()); - bool IsOk() { - return fd_ >= 0; - } - - // Returns the Posix file descriptor for the test file, or -1 - // If IsOk() returns false. Note: on Windows, this always returns -1. - int GetFd() { - return fd_; - } - - private: - void Init(const char* test_prefix) { - fd_ = -1; - char path_templ[PATH_MAX]; - int ret = snprintf(path_templ, sizeof(path_templ), - TEMPDIR "/%s-unittest.XXXXXX", - test_prefix); - if (ret >= static_cast<int>(sizeof(path_templ))) - return; - - fd_ = mkstemp(path_templ); - if (fd_ < 0) - return; - - unlink(path_templ); - } - - void WriteText(const char* text, size_t text_len) { - ssize_t r = HANDLE_EINTR(write(fd_, text, text_len)); - if (r != static_cast<ssize_t>(text_len)) { - close(fd_); - fd_ = -1; - return; - } - - lseek(fd_, 0, SEEK_SET); - } - - int fd_; -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc deleted file mode 100644 index c9491f6f2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc +++ /dev/null @@ -1,322 +0,0 @@ -// 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. - -// crash_generator.cc: Implement google_breakpad::CrashGenerator. -// See crash_generator.h for details. - -#include "common/linux/tests/crash_generator.h" - -#include <pthread.h> -#include <signal.h> -#include <stdio.h> -#include <sys/mman.h> -#include <sys/resource.h> -#include <sys/syscall.h> -#include <sys/wait.h> -#include <unistd.h> - -#include <string> - -#if defined(__ANDROID__) -#include "common/android/testing/pthread_fixes.h" -#endif -#include "common/linux/eintr_wrapper.h" -#include "common/tests/auto_tempdir.h" -#include "common/tests/file_utils.h" -#include "common/using_std_string.h" - -namespace { - -struct ThreadData { - pthread_t thread; - pthread_barrier_t* barrier; - pid_t* thread_id_ptr; -}; - -const char* const kProcFilesToCopy[] = { - "auxv", "cmdline", "environ", "maps", "status" -}; -const size_t kNumProcFilesToCopy = - sizeof(kProcFilesToCopy) / sizeof(kProcFilesToCopy[0]); - -int gettid() { - // Glibc does not provide a wrapper for this. - return syscall(__NR_gettid); -} - -int tkill(pid_t tid, int sig) { - // Glibc does not provide a wrapper for this. - return syscall(__NR_tkill, tid, sig); -} - -// Core file size limit set to 1 MB, which is big enough for test purposes. -const rlim_t kCoreSizeLimit = 1024 * 1024; - -void *thread_function(void *data) { - ThreadData* thread_data = reinterpret_cast<ThreadData*>(data); - volatile pid_t thread_id = gettid(); - *(thread_data->thread_id_ptr) = thread_id; - int result = pthread_barrier_wait(thread_data->barrier); - if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) { - perror("Failed to wait for sync barrier"); - exit(1); - } - while (true) { - pthread_yield(); - } -} - -} // namespace - -namespace google_breakpad { - -CrashGenerator::CrashGenerator() - : shared_memory_(NULL), - shared_memory_size_(0) { -} - -CrashGenerator::~CrashGenerator() { - UnmapSharedMemory(); -} - -bool CrashGenerator::HasDefaultCorePattern() const { - char buffer[8]; - ssize_t buffer_size = sizeof(buffer); - return ReadFile("/proc/sys/kernel/core_pattern", buffer, &buffer_size) && - buffer_size == 5 && memcmp(buffer, "core", 4) == 0; -} - -string CrashGenerator::GetCoreFilePath() const { - return temp_dir_.path() + "/core"; -} - -string CrashGenerator::GetDirectoryOfProcFilesCopy() const { - return temp_dir_.path() + "/proc"; -} - -pid_t CrashGenerator::GetThreadId(unsigned index) const { - return reinterpret_cast<pid_t*>(shared_memory_)[index]; -} - -pid_t* CrashGenerator::GetThreadIdPointer(unsigned index) { - return reinterpret_cast<pid_t*>(shared_memory_) + index; -} - -bool CrashGenerator::MapSharedMemory(size_t memory_size) { - if (!UnmapSharedMemory()) - return false; - - void* mapped_memory = mmap(0, memory_size, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (mapped_memory == MAP_FAILED) { - perror("CrashGenerator: Failed to map shared memory"); - return false; - } - - memset(mapped_memory, 0, memory_size); - shared_memory_ = mapped_memory; - shared_memory_size_ = memory_size; - return true; -} - -bool CrashGenerator::UnmapSharedMemory() { - if (!shared_memory_) - return true; - - if (munmap(shared_memory_, shared_memory_size_) == 0) { - shared_memory_ = NULL; - shared_memory_size_ = 0; - return true; - } - - perror("CrashGenerator: Failed to unmap shared memory"); - return false; -} - -bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const { - struct rlimit limits = { limit, limit }; - if (setrlimit(RLIMIT_CORE, &limits) == -1) { - perror("CrashGenerator: Failed to set core file size limit"); - return false; - } - return true; -} - -bool CrashGenerator::CreateChildCrash( - unsigned num_threads, unsigned crash_thread, int crash_signal, - pid_t* child_pid) { - if (num_threads == 0 || crash_thread >= num_threads) { - fprintf(stderr, "CrashGenerator: Invalid thread counts; num_threads=%u" - " crash_thread=%u\n", num_threads, crash_thread); - return false; - } - - if (!MapSharedMemory(num_threads * sizeof(pid_t))) { - perror("CrashGenerator: Unable to map shared memory"); - return false; - } - - pid_t pid = fork(); - if (pid == 0) { - if (chdir(temp_dir_.path().c_str()) == -1) { - perror("CrashGenerator: Failed to change directory"); - exit(1); - } - if (SetCoreFileSizeLimit(kCoreSizeLimit)) { - CreateThreadsInChildProcess(num_threads); - string proc_dir = GetDirectoryOfProcFilesCopy(); - if (mkdir(proc_dir.c_str(), 0755) == -1) { - perror("CrashGenerator: Failed to create proc directory"); - exit(1); - } - if (!CopyProcFiles(getpid(), proc_dir.c_str())) { - fprintf(stderr, "CrashGenerator: Failed to copy proc files\n"); - exit(1); - } - // On Android the signal sometimes doesn't seem to get sent even though - // tkill returns '0'. Retry a couple of times if the signal doesn't get - // through on the first go: - // https://code.google.com/p/google-breakpad/issues/detail?id=579 -#if defined(__ANDROID__) - const int kRetries = 60; - const unsigned int kSleepTimeInSeconds = 1; -#else - const int kRetries = 1; - const unsigned int kSleepTimeInSeconds = 600; -#endif - for (int i = 0; i < kRetries; i++) { - if (tkill(*GetThreadIdPointer(crash_thread), crash_signal) == -1) { - perror("CrashGenerator: Failed to kill thread by signal"); - } else { - // At this point, we've queued the signal for delivery, but there's no - // guarantee when it'll be delivered. We don't want the main thread to - // race and exit before the thread we signaled is processed. So sleep - // long enough that we won't flake even under fairly high load. - // TODO: See if we can't be a bit more deterministic. There doesn't - // seem to be an API to check on signal delivery status, so we can't - // really poll and wait for the kernel to declare the signal has been - // delivered. If it has, and things worked, we'd be killed, so the - // sleep length doesn't really matter. - sleep(kSleepTimeInSeconds); - } - } - } else { - perror("CrashGenerator: Failed to set core limit"); - } - exit(1); - } else if (pid == -1) { - perror("CrashGenerator: Failed to create child process"); - return false; - } - - int status; - if (HANDLE_EINTR(waitpid(pid, &status, 0)) == -1) { - perror("CrashGenerator: Failed to wait for child process"); - return false; - } - if (!WIFSIGNALED(status) || WTERMSIG(status) != crash_signal) { - fprintf(stderr, "CrashGenerator: Child process not killed by the expected signal\n" - " exit status=0x%x pid=%u signaled=%s sig=%d expected=%d\n", - status, pid, WIFSIGNALED(status) ? "true" : "false", - WTERMSIG(status), crash_signal); - return false; - } - - if (child_pid) - *child_pid = pid; - return true; -} - -bool CrashGenerator::CopyProcFiles(pid_t pid, const char* path) const { - char from_path[PATH_MAX], to_path[PATH_MAX]; - for (size_t i = 0; i < kNumProcFilesToCopy; ++i) { - int num_chars = snprintf(from_path, PATH_MAX, "/proc/%d/%s", - pid, kProcFilesToCopy[i]); - if (num_chars < 0 || num_chars >= PATH_MAX) - return false; - - num_chars = snprintf(to_path, PATH_MAX, "%s/%s", - path, kProcFilesToCopy[i]); - if (num_chars < 0 || num_chars >= PATH_MAX) - return false; - - if (!CopyFile(from_path, to_path)) - return false; - } - return true; -} - -void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) { - *GetThreadIdPointer(0) = getpid(); - - if (num_threads <= 1) - return; - - // This method does not clean up any pthread resource, as the process - // is expected to be killed anyway. - ThreadData* thread_data = new ThreadData[num_threads]; - - // Create detached threads so that we do not worry about pthread_join() - // later being called or not. - pthread_attr_t thread_attributes; - if (pthread_attr_init(&thread_attributes) != 0 || - pthread_attr_setdetachstate(&thread_attributes, - PTHREAD_CREATE_DETACHED) != 0) { - fprintf(stderr, "CrashGenerator: Failed to initialize thread attribute\n"); - exit(1); - } - - pthread_barrier_t thread_barrier; - if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) { - fprintf(stderr, "CrashGenerator: Failed to initialize thread barrier\n"); - exit(1); - } - - for (unsigned i = 1; i < num_threads; ++i) { - thread_data[i].barrier = &thread_barrier; - thread_data[i].thread_id_ptr = GetThreadIdPointer(i); - if (pthread_create(&thread_data[i].thread, &thread_attributes, - thread_function, &thread_data[i]) != 0) { - fprintf(stderr, "CrashGenerator: Failed to create thread %d\n", i); - exit(1); - } - } - - int result = pthread_barrier_wait(&thread_barrier); - if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) { - fprintf(stderr, "CrashGenerator: Failed to wait for thread barrier\n"); - exit(1); - } - - pthread_barrier_destroy(&thread_barrier); - pthread_attr_destroy(&thread_attributes); - delete[] thread_data; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h deleted file mode 100644 index 7e2fcbf98..000000000 --- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h +++ /dev/null @@ -1,117 +0,0 @@ -// 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. - -// crash_generator.h: Define the google_breakpad::CrashGenerator class, -// which is used to generate a crash (and a core dump file) for testing. - -#ifndef COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ -#define COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ - -#include <sys/resource.h> - -#include <string> - -#include "common/tests/auto_tempdir.h" -#include "common/using_std_string.h" - -namespace google_breakpad { - -// A utility class for generating a crash (and a core dump file) for -// testing. It creates a child process with the specified number of -// threads, which is then termainated by the specified signal. A core -// dump file is expected to be created upon the termination of the child -// process, which can then be used for testing code that processes core -// dump files. -class CrashGenerator { - public: - CrashGenerator(); - - ~CrashGenerator(); - - // Returns true if a core dump file named 'core' will be generated in - // the current directory for a test that produces a crash by checking - // if /proc/sys/kernel/core_pattern has the default value 'core'. - bool HasDefaultCorePattern() const; - - // Returns the expected path of the core dump file. - string GetCoreFilePath() const; - - // Returns the directory of a copy of proc files of the child process. - string GetDirectoryOfProcFilesCopy() const; - - // Creates a crash (and a core dump file) by creating a child process with - // |num_threads| threads, and the terminating the child process by sending - // a signal with number |crash_signal| to the |crash_thread|-th thread. - // Returns true on success. - bool CreateChildCrash(unsigned num_threads, unsigned crash_thread, - int crash_signal, pid_t* child_pid); - - // Returns the thread ID of the |index|-th thread in the child process. - // This method does not validate |index|. - pid_t GetThreadId(unsigned index) const; - - private: - // Copies the following proc files of the process with |pid| to the directory - // at |path|: auxv, cmdline, environ, maps, status - // The directory must have been created. Returns true on success. - bool CopyProcFiles(pid_t pid, const char* path) const; - - // Creates |num_threads| threads in the child process. - void CreateThreadsInChildProcess(unsigned num_threads); - - // Sets the maximum size of core dump file (both the soft and hard limit) - // to |limit| bytes. Returns true on success. - bool SetCoreFileSizeLimit(rlim_t limit) const; - - // Creates a shared memory of |memory_size| bytes for communicating thread - // IDs between the parent and child process. Returns true on success. - bool MapSharedMemory(size_t memory_size); - - // Releases any shared memory created by MapSharedMemory(). Returns true on - // success. - bool UnmapSharedMemory(); - - // Returns the pointer to the thread ID of the |index|-th thread in the child - // process. This method does not validate |index|. - pid_t* GetThreadIdPointer(unsigned index); - - // Temporary directory in which a core file is generated. - AutoTempDir temp_dir_; - - // Shared memory for communicating thread IDs between the parent and - // child process. - void* shared_memory_; - - // Number of bytes mapped for |shared_memory_|. - size_t shared_memory_size_; -}; - -} // namespace google_breakpad - -#endif // COMMON_LINUX_TESTS_CRASH_GENERATOR_H_ |