diff options
Diffstat (limited to 'src/common/linux')
52 files changed, 913 insertions, 473 deletions
diff --git a/src/common/linux/breakpad_getcontext.S b/src/common/linux/breakpad_getcontext.S index fea0109d..286047bf 100644 --- a/src/common/linux/breakpad_getcontext.S +++ b/src/common/linux/breakpad_getcontext.S @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -32,7 +31,7 @@ #include "common/linux/ucontext_constants.h" -/* int getcontext (ucontext_t *ucp) */ +/* int getcontext (ucontext_t* ucp) */ #if defined(__arm__) @@ -90,6 +89,47 @@ breakpad_getcontext: #elif defined(__aarch64__) +#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT + // ENABLE_PAUTH must be defined to 1 since this value will be used in + // bitwise-shift later! + #define ENABLE_PAUTH 1 + + #if ((__ARM_FEATURE_PAC_DEFAULT&((1<<0)|(1<<1)))==0) + #error Pointer authentication defines no valid key! + #endif +#else + #define ENABLE_PAUTH 0 +#endif + +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT==1) + // ENABLE_BTI must be defined to 1 since this value will be used in + // bitwise-shift later! + #define ENABLE_BTI 1 +#else + #define ENABLE_BTI 0 +#endif + + +// Although Pointer Authentication and Branch Target Instructions are technically +// seperate features they work together, i.e. the paciasp and pacibsp instructions +// serve as BTI landing pads. +// Therefore PA-instructions are enabled when PA _or_ BTI is enabled! +#if ENABLE_PAUTH || ENABLE_BTI + // See section "Pointer Authentication" of + // https://developer.arm.com/documentation/101028/0012/5--Feature-test-macros + // for details how to interpret __ARM_FEATURE_PAC_DEFAULT + #if (__ARM_FEATURE_PAC_DEFAULT & (1<<0)) + #define PAUTH_SIGN_SP paciasp + #define PAUTH_AUTH_SP autiasp + #else + #define PAUTH_SIGN_SP pacibsp + #define PAUTH_AUTH_SP autibsp + #endif +#else + #define PAUTH_SIGN_SP + #define PAUTH_AUTH_SP +#endif + #define _NSIG 64 #define __NR_rt_sigprocmask 135 @@ -101,6 +141,8 @@ breakpad_getcontext: .cfi_startproc breakpad_getcontext: + PAUTH_SIGN_SP + /* The saved context will return to the getcontext() call point with a return value of 0 */ str xzr, [x0, MCONTEXT_GREGS_OFFSET + 0 * REGISTER_SIZE] @@ -170,6 +212,9 @@ breakpad_getcontext: /* Return x0 for success */ mov x0, 0 + + PAUTH_AUTH_SP + ret .cfi_endproc @@ -336,7 +381,7 @@ symbol: .frame sp, framesize, rpc; .size function,.-function #endif -/* int getcontext (ucontext_t *ucp) */ +/* int getcontext (ucontext_t* ucp) */ NESTED (breakpad_getcontext, FRAME_SIZE, ra) .mask 0x10000000, 0 @@ -481,6 +526,120 @@ breakpad_getcontext: .cfi_endproc .size breakpad_getcontext, . - breakpad_getcontext +#elif defined(__riscv) + +# define SIG_BLOCK 0 +# define _NSIG8 8 +# define __NR_rt_sigprocmask 135 + + .text + .globl breakpad_getcontext + .type breakpad_getcontext, @function + .align 0 + .cfi_startproc +breakpad_getcontext: + REG_S ra, MCONTEXT_GREGS_PC(a0) + REG_S ra, MCONTEXT_GREGS_RA(a0) + REG_S sp, MCONTEXT_GREGS_SP(a0) + REG_S gp, MCONTEXT_GREGS_SP(a0) + REG_S tp, MCONTEXT_GREGS_TP(a0) + REG_S t0, MCONTEXT_GREGS_T0(a0) + REG_S t1, MCONTEXT_GREGS_T1(a0) + REG_S t2, MCONTEXT_GREGS_T2(a0) + REG_S s0, MCONTEXT_GREGS_S0(a0) + REG_S s1, MCONTEXT_GREGS_S1(a0) + REG_S a0, MCONTEXT_GREGS_A0(a0) + REG_S a1, MCONTEXT_GREGS_A1(a0) + REG_S a2, MCONTEXT_GREGS_A2(a0) + REG_S a3, MCONTEXT_GREGS_A3(a0) + REG_S a4, MCONTEXT_GREGS_A4(a0) + REG_S a5, MCONTEXT_GREGS_A5(a0) + REG_S a6, MCONTEXT_GREGS_A6(a0) + REG_S a7, MCONTEXT_GREGS_A7(a0) + REG_S s2, MCONTEXT_GREGS_S2(a0) + REG_S s3, MCONTEXT_GREGS_S3(a0) + REG_S s4, MCONTEXT_GREGS_S4(a0) + REG_S s5, MCONTEXT_GREGS_S5(a0) + REG_S s6, MCONTEXT_GREGS_S6(a0) + REG_S s7, MCONTEXT_GREGS_S7(a0) + REG_S s8, MCONTEXT_GREGS_S8(a0) + REG_S s9, MCONTEXT_GREGS_S9(a0) + REG_S s10, MCONTEXT_GREGS_S10(a0) + REG_S s11, MCONTEXT_GREGS_S11(a0) + REG_S t3, MCONTEXT_GREGS_T3(a0) + REG_S t4, MCONTEXT_GREGS_T4(a0) + REG_S t5, MCONTEXT_GREGS_T5(a0) + REG_S t6 , MCONTEXT_GREGS_T6(a0) +# ifndef __riscv_float_abi_soft + frsr a1 + + FREG_S ft0, MCONTEXT_FPREGS_FT0(a0) + FREG_S ft1, MCONTEXT_FPREGS_FT1(a0) + FREG_S ft2, MCONTEXT_FPREGS_FT2(a0) + FREG_S ft3, MCONTEXT_FPREGS_FT3(a0) + FREG_S ft4, MCONTEXT_FPREGS_FT4(a0) + FREG_S ft5, MCONTEXT_FPREGS_FT5(a0) + FREG_S ft6, MCONTEXT_FPREGS_FT6(a0) + FREG_S ft7, MCONTEXT_FPREGS_FT7(a0) + FREG_S fs0, MCONTEXT_FPREGS_FS0(a0) + FREG_S fs1, MCONTEXT_FPREGS_FS1(a0) + FREG_S fa0, MCONTEXT_FPREGS_FA0(a0) + FREG_S fa1, MCONTEXT_FPREGS_FA1(a0) + FREG_S fa2, MCONTEXT_FPREGS_FA2(a0) + FREG_S fa3, MCONTEXT_FPREGS_FA3(a0) + FREG_S fa4, MCONTEXT_FPREGS_FA4(a0) + FREG_S fa5, MCONTEXT_FPREGS_FA5(a0) + FREG_S fa6, MCONTEXT_FPREGS_FA6(a0) + FREG_S fa7, MCONTEXT_FPREGS_FA7(a0) + FREG_S fs2, MCONTEXT_FPREGS_FS2(a0) + FREG_S fs3, MCONTEXT_FPREGS_FS3(a0) + FREG_S fs4, MCONTEXT_FPREGS_FS4(a0) + FREG_S fs5, MCONTEXT_FPREGS_FS5(a0) + FREG_S fs6, MCONTEXT_FPREGS_FS6(a0) + FREG_S fs7, MCONTEXT_FPREGS_FS7(a0) + FREG_S fs8, MCONTEXT_FPREGS_FS8(a0) + FREG_S fs9, MCONTEXT_FPREGS_FS9(a0) + FREG_S fs10, MCONTEXT_FPREGS_FS10(a0) + FREG_S fs11, MCONTEXT_FPREGS_FS11(a0) + FREG_S ft8, MCONTEXT_FPREGS_FT8(a0) + FREG_S ft9, MCONTEXT_FPREGS_FT9(a0) + FREG_S ft10, MCONTEXT_FPREGS_FT10(a0) + FREG_S ft11, MCONTEXT_FPREGS_FT11(a0) + + sw a1, MCONTEXT_FPC_CSR(a0) +# endif // __riscv_float_abi_soft + mv a1, zero + add a2, a0, UCONTEXT_SIGMASK_OFFSET + li a3, _NSIG8 + mv a0, zero + li a7, __NR_rt_sigprocmask + ecall + mv a0, zero + ret + + .cfi_endproc + .size breakpad_getcontext, . - breakpad_getcontext + #else -#error "This file has not been ported for your CPU!" +# error "This file has not been ported for your CPU!" +#endif + +#if defined(__aarch64__) +// ENABLE_PAUTH and ENABLE_BTI would be enabled at the definition +// of AArch64 specific breakpad_getcontext function +#if ENABLE_PAUTH || ENABLE_BTI +// for further information on the .note.gnu.property section see +// https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#program-property +.pushsection .note.gnu.property, "a"; + .balign 8 + .long 4 + .long 0x10 + .long 0x5 + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4 + .long ((ENABLE_PAUTH)<<1) | ((ENABLE_BTI)<<0) /* PAuth and BTI */ + .long 0 +.popsection +#endif #endif diff --git a/src/common/linux/breakpad_getcontext.h b/src/common/linux/breakpad_getcontext.h index 1418cde6..c553219f 100644 --- a/src/common/linux/breakpad_getcontext.h +++ b/src/common/linux/breakpad_getcontext.h @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/breakpad_getcontext_unittest.cc b/src/common/linux/breakpad_getcontext_unittest.cc index a57bfedf..573ddd88 100644 --- a/src/common/linux/breakpad_getcontext_unittest.cc +++ b/src/common/linux/breakpad_getcontext_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -114,6 +113,25 @@ TEST(AndroidUContext, GRegsOffset) { ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR), offsetof(ucontext_t,uc_mcontext.fpc_csr)); +#elif defined(__riscv) + ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET), + offsetof(ucontext_t,uc_mcontext.__gregs[0])); + +#define CHECK_REG(x) \ + ASSERT_EQ(static_cast<size_t>(MCONTEXT_##x##_OFFSET), \ + offsetof(ucontext_t,uc_mcontext.__gregs[REG_##x])) + CHECK_REG(PC) + CHECK_REG(RA) + CHECK_REG(SP) + CHECK_REG(S0) + CHECK_REG(S1) + CHECK_REG(S2) + + ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPREGS_OFFSET), + offsetof(ucontext_t,uc_mcontext.__fpregs)); + + ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR), + offsetof(ucontext_t,uc_mcontext.__fpregs.__fcsr)); #elif defined(__x86_64__) COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET), diff --git a/src/common/linux/crc32.cc b/src/common/linux/crc32.cc index 8df636ce..c02f06c4 100644 --- a/src/common/linux/crc32.cc +++ b/src/common/linux/crc32.cc @@ -1,5 +1,4 @@ -// Copyright 2014 Google Inc. -// All rights reserved. +// Copyright 2014 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/crc32.h b/src/common/linux/crc32.h index e3d9db92..7df46999 100644 --- a/src/common/linux/crc32.h +++ b/src/common/linux/crc32.h @@ -1,5 +1,4 @@ -// Copyright 2014 Google Inc. -// All rights reserved. +// Copyright 2014 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index b7e77ab7..b436f765 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -47,8 +46,8 @@ #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> +#include <zlib.h> -#include <iostream> #include <set> #include <string> #include <utility> @@ -87,11 +86,11 @@ using google_breakpad::DwarfRangeListHandler; using google_breakpad::ElfClass; using google_breakpad::ElfClass32; using google_breakpad::ElfClass64; -using google_breakpad::FileID; +using google_breakpad::elf::FileID; using google_breakpad::FindElfSectionByName; using google_breakpad::GetOffset; using google_breakpad::IsValidElf; -using google_breakpad::kDefaultBuildIdSize; +using google_breakpad::elf::kDefaultBuildIdSize; using google_breakpad::Module; using google_breakpad::PageAllocator; #ifndef NO_STABS_SUPPORT @@ -144,7 +143,7 @@ class MmapWrapper { munmap(base_, size_); } } - void set(void *mapped_address, size_t mapped_size) { + void set(void* mapped_address, size_t mapped_size) { is_set_ = true; base_ = mapped_address; size_ = mapped_size; @@ -228,62 +227,121 @@ bool LoadStabs(const typename ElfClass::Ehdr* elf_header, #endif // NO_STABS_SUPPORT // A range handler that accepts rangelist data parsed by -// dwarf2reader::RangeListReader and populates a range vector (typically +// google_breakpad::RangeListReader and populates a range vector (typically // owned by a function) with the results. class DumperRangesHandler : public DwarfCUToModule::RangesHandler { public: - DumperRangesHandler(const uint8_t *buffer, uint64_t size, - dwarf2reader::ByteReader* reader) - : buffer_(buffer), size_(size), reader_(reader) { } - - bool ReadRanges(uint64_t offset, Module::Address base_address, - vector<Module::Range>* ranges) { - DwarfRangeListHandler handler(base_address, ranges); - dwarf2reader::RangeListReader rangelist_reader(buffer_, size_, reader_, - &handler); - - return rangelist_reader.ReadRangeList(offset); + DumperRangesHandler(google_breakpad::ByteReader* reader) : + reader_(reader) { } + + bool ReadRanges( + enum google_breakpad::DwarfForm form, uint64_t data, + google_breakpad::RangeListReader::CURangesInfo* cu_info, + vector<Module::Range>* ranges) { + DwarfRangeListHandler handler(ranges); + google_breakpad::RangeListReader range_list_reader(reader_, cu_info, + &handler); + return range_list_reader.ReadRanges(form, data); } private: - const uint8_t *buffer_; - uint64_t size_; - dwarf2reader::ByteReader* reader_; + google_breakpad::ByteReader* reader_; }; // A line-to-module loader that accepts line number info parsed by -// dwarf2reader::LineInfo and populates a Module and a line vector +// google_breakpad::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) + explicit DumperLineToModule(google_breakpad::ByteReader* byte_reader) : byte_reader_(byte_reader) { } void StartCompilationUnit(const string& compilation_dir) { compilation_dir_ = compilation_dir; } - void ReadProgram(const uint8_t *program, uint64_t length, - Module* module, std::vector<Module::Line>* lines) { - DwarfLineToModule handler(module, compilation_dir_, lines); - dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); + void ReadProgram(const uint8_t* program, + uint64_t length, + const uint8_t* string_section, + uint64_t string_section_length, + const uint8_t* line_string_section, + uint64_t line_string_section_length, + Module* module, + std::vector<Module::Line>* lines, + std::map<uint32_t, Module::File*>* files) { + DwarfLineToModule handler(module, compilation_dir_, lines, files); + google_breakpad::LineInfo parser(program, length, byte_reader_, + string_section, string_section_length, + line_string_section, + line_string_section_length, + &handler); parser.Start(); } private: string compilation_dir_; - dwarf2reader::ByteReader *byte_reader_; + google_breakpad::ByteReader* byte_reader_; }; template<typename ElfClass> +bool IsCompressedHeader(const typename ElfClass::Shdr* section) { + return (section->sh_flags & SHF_COMPRESSED) != 0; +} + +template<typename ElfClass> +uint32_t GetCompressionHeader( + typename ElfClass::Chdr& compression_header, + const uint8_t* content, uint64_t size) { + const typename ElfClass::Chdr* header = + reinterpret_cast<const typename ElfClass::Chdr *>(content); + + if (size < sizeof (*header)) { + return 0; + } + + compression_header = *header; + return sizeof (*header); +} + +std::pair<uint8_t *, uint64_t> UncompressSectionContents( + const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) { + z_stream stream; + memset(&stream, 0, sizeof stream); + + stream.avail_in = compressed_size; + stream.avail_out = uncompressed_size; + stream.next_in = const_cast<uint8_t *>(compressed_buffer); + + google_breakpad::scoped_array<uint8_t> uncompressed_buffer( + new uint8_t[uncompressed_size]); + + int status = inflateInit(&stream); + while (stream.avail_in != 0 && status == Z_OK) { + stream.next_out = + uncompressed_buffer.get() + uncompressed_size - stream.avail_out; + + if ((status = inflate(&stream, Z_FINISH)) != Z_STREAM_END) { + break; + } + + status = inflateReset(&stream); + } + + return inflateEnd(&stream) != Z_OK || status != Z_OK || stream.avail_out != 0 + ? std::make_pair(nullptr, 0) + : std::make_pair(uncompressed_buffer.release(), uncompressed_size); +} + +template<typename ElfClass> bool LoadDwarf(const string& dwarf_filename, const typename ElfClass::Ehdr* elf_header, const bool big_endian, bool handle_inter_cu_refs, + bool handle_inline, Module* module) { typedef typename ElfClass::Shdr Shdr; - const dwarf2reader::Endianness endianness = big_endian ? - dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; - dwarf2reader::ByteReader byte_reader(endianness); + const google_breakpad::Endianness endianness = big_endian ? + google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE; + google_breakpad::ByteReader byte_reader(endianness); // Construct a context for this file. DwarfCUToModule::FileContext file_context(dwarf_filename, @@ -300,29 +358,44 @@ bool LoadDwarf(const string& dwarf_filename, string name = GetOffset<ElfClass, char>(elf_header, section_names->sh_offset) + section->sh_name; - const uint8_t *contents = GetOffset<ElfClass, uint8_t>(elf_header, + const uint8_t* contents = GetOffset<ElfClass, uint8_t>(elf_header, section->sh_offset); - file_context.AddSectionToSectionMap(name, contents, section->sh_size); - } + uint64_t size = section->sh_size; + + if (!IsCompressedHeader<ElfClass>(section)) { + file_context.AddSectionToSectionMap(name, contents, size); + continue; + } + + typename ElfClass::Chdr chdr; - // Optional .debug_ranges reader - scoped_ptr<DumperRangesHandler> ranges_handler; - dwarf2reader::SectionMap::const_iterator ranges_entry = - file_context.section_map().find(".debug_ranges"); - if (ranges_entry != file_context.section_map().end()) { - const std::pair<const uint8_t *, uint64_t>& ranges_section = - ranges_entry->second; - ranges_handler.reset( - new DumperRangesHandler(ranges_section.first, ranges_section.second, - &byte_reader)); + uint32_t compression_header_size = + GetCompressionHeader<ElfClass>(chdr, contents, size); + + if (compression_header_size == 0 || chdr.ch_size == 0) { + continue; + } + + contents += compression_header_size; + size -= compression_header_size; + + std::pair<uint8_t *, uint64_t> uncompressed = + UncompressSectionContents(contents, size, chdr.ch_size); + + if (uncompressed.first != nullptr && uncompressed.second != 0) { + file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second); + } } + // .debug_ranges and .debug_rnglists reader + DumperRangesHandler ranges_handler(&byte_reader); + // Parse all the compilation units in the .debug_info section. DumperLineToModule line_to_module(&byte_reader); - dwarf2reader::SectionMap::const_iterator debug_info_entry = + google_breakpad::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_t>& debug_info_section = + const std::pair<const uint8_t*, uint64_t>& debug_info_section = debug_info_entry->second; // This should never have been called if the file doesn't have a // .debug_info section. @@ -333,11 +406,11 @@ bool LoadDwarf(const string& dwarf_filename, // data that was found. DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset); DwarfCUToModule root_handler(&file_context, &line_to_module, - ranges_handler.get(), &reporter); + &ranges_handler, &reporter, handle_inline); // Make a Dwarf2Handler that drives the DIEHandler. - dwarf2reader::DIEDispatcher die_dispatcher(&root_handler); + google_breakpad::DIEDispatcher die_dispatcher(&root_handler); // Make a DWARF parser for the compilation unit at OFFSET. - dwarf2reader::CompilationUnit reader(dwarf_filename, + google_breakpad::CompilationUnit reader(dwarf_filename, file_context.section_map(), offset, &byte_reader, @@ -397,18 +470,18 @@ bool LoadDwarfCFI(const string& dwarf_filename, return false; } - const dwarf2reader::Endianness endianness = big_endian ? - dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; + const google_breakpad::Endianness endianness = big_endian ? + google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE; // Find the call frame information and its size. - const uint8_t *cfi = + 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); + google_breakpad::ByteReader byte_reader(endianness); byte_reader.SetAddressSize(ElfClass::kAddrSize); @@ -420,11 +493,44 @@ bool LoadDwarfCFI(const string& dwarf_filename, if (text_section) byte_reader.SetTextBase(text_section->sh_addr); - dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename, + google_breakpad::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename, section_name); - dwarf2reader::CallFrameInfo parser(cfi, cfi_size, - &byte_reader, &handler, &dwarf_reporter, - eh_frame); + if (!IsCompressedHeader<ElfClass>(section)) { + google_breakpad::CallFrameInfo parser(cfi, cfi_size, + &byte_reader, &handler, + &dwarf_reporter, eh_frame); + parser.Start(); + return true; + } + + typename ElfClass::Chdr chdr; + uint32_t compression_header_size = + GetCompressionHeader<ElfClass>(chdr, cfi, cfi_size); + + if (compression_header_size == 0 || chdr.ch_size == 0) { + fprintf(stderr, "%s: decompression failed at header\n", + dwarf_filename.c_str()); + return false; + } + if (compression_header_size > cfi_size) { + fprintf(stderr, "%s: decompression error, compression_header too large\n", + dwarf_filename.c_str()); + return false; + } + + cfi += compression_header_size; + cfi_size -= compression_header_size; + + std::pair<uint8_t *, uint64_t> uncompressed = + UncompressSectionContents(cfi, cfi_size, chdr.ch_size); + + if (uncompressed.first == nullptr || uncompressed.second == 0) { + fprintf(stderr, "%s: decompression failed\n", dwarf_filename.c_str()); + return false; + } + google_breakpad::CallFrameInfo parser(uncompressed.first, uncompressed.second, + &byte_reader, &handler, &dwarf_reporter, + eh_frame); parser.Start(); return true; } @@ -489,13 +595,13 @@ bool IsSameFile(const char* left_abspath, const string& right_path) { // Read the .gnu_debuglink and get the debug file name. If anything goes // wrong, return an empty string. -string ReadDebugLink(const uint8_t *debuglink, +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; + 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. @@ -517,7 +623,7 @@ string ReadDebugLink(const uint8_t *debuglink, for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) { const string& debug_dir = *it; debuglink_path = debug_dir + "/" + - reinterpret_cast<const char *>(debuglink); + 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, @@ -533,9 +639,9 @@ string ReadDebugLink(const uint8_t *debuglink, 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); + const google_breakpad::Endianness endianness = big_endian ? + google_breakpad::ENDIANNESS_BIG : google_breakpad::ENDIANNESS_LITTLE; + google_breakpad::ByteReader byte_reader(endianness); uint32_t expected_crc = byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]); @@ -591,7 +697,7 @@ class LoadSymbolsInfo { // 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) { + void LoadedSection(const string& section) { if (loaded_sections_.count(section) == 0) { loaded_sections_.insert(section); } else { @@ -602,7 +708,7 @@ class LoadSymbolsInfo { // 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) { + void set_loading_addr(Addr addr, const string& filename) { if (!has_loading_addr_) { loading_addr_ = addr; loaded_file_ = filename; @@ -679,11 +785,12 @@ bool LoadSymbols(const string& obj_file, 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 char* names_end = names + section_names->sh_size; bool found_debug_info_section = false; bool found_usable_info = false; - if (options.symbol_data != ONLY_CFI) { + if ((options.symbol_data & SYMBOLS_AND_FILES) || + (options.symbol_data & INLINES)) { #ifndef NO_STABS_SUPPORT // Look for STABS debugging information, and load it if present. const Shdr* stab_section = @@ -705,32 +812,6 @@ bool LoadSymbols(const string& obj_file, } #endif // NO_STABS_SUPPORT - // Look for DWARF debugging information, and load it if present. - const Shdr* dwarf_section = - FindElfSectionByName<ElfClass>(".debug_info", SHT_PROGBITS, - sections, names, names_end, - elf_header->e_shnum); - - // .debug_info section type is SHT_PROGBITS for mips on pnacl toolchains, - // but MIPS_DWARF for regular gnu toolchains, so both need to be checked - if (elf_header->e_machine == EM_MIPS && !dwarf_section) { - dwarf_section = - FindElfSectionByName<ElfClass>(".debug_info", SHT_MIPS_DWARF, - 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, @@ -788,9 +869,38 @@ bool LoadSymbols(const string& obj_file, found_usable_info = found_usable_info || result; } } + + // Only Load .debug_info after loading symbol table to avoid duplicate + // PUBLIC records. + // Look for DWARF debugging information, and load it if present. + const Shdr* dwarf_section = + FindElfSectionByName<ElfClass>(".debug_info", SHT_PROGBITS, + sections, names, names_end, + elf_header->e_shnum); + + // .debug_info section type is SHT_PROGBITS for mips on pnacl toolchains, + // but MIPS_DWARF for regular gnu toolchains, so both need to be checked + if (elf_header->e_machine == EM_MIPS && !dwarf_section) { + dwarf_section = + FindElfSectionByName<ElfClass>(".debug_info", SHT_MIPS_DWARF, + 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, + options.symbol_data & INLINES, module)) { + fprintf(stderr, "%s: \".debug_info\" section found, but failed to load " + "DWARF debugging information\n", obj_file.c_str()); + } + } } - if (options.symbol_data != NO_CFI) { + if (options.symbol_data & 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 = @@ -859,7 +969,7 @@ bool LoadSymbols(const string& obj_file, names_end, elf_header->e_shnum); if (gnu_debuglink_section) { if (!info->debug_dirs().empty()) { - const uint8_t *debuglink_contents = + const uint8_t* debuglink_contents = GetOffset<ElfClass, uint8_t>(elf_header, gnu_debuglink_section->sh_offset); string debuglink_file = @@ -947,7 +1057,8 @@ template<typename ElfClass> bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, const string& obj_filename, const string& obj_os, - scoped_ptr<Module>& module) { + scoped_ptr<Module>& module, + bool enable_multiple_field) { PageAllocator allocator; wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize); if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) { @@ -956,7 +1067,7 @@ bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, return false; } - const char *architecture = ElfArchitecture<ElfClass>(elf_header); + 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); @@ -976,7 +1087,8 @@ bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, // This is just the raw Build ID in hex. string code_id = FileID::ConvertIdentifierToString(identifier); - module.reset(new Module(name, obj_os, architecture, id, code_id)); + module.reset(new Module(name, obj_os, architecture, id, code_id, + enable_multiple_field)); return true; } @@ -993,8 +1105,8 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, *out_module = NULL; scoped_ptr<Module> module; - if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, obj_os, - module)) { + if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, obj_os, module, + options.enable_multiple_field)) { return false; } @@ -1066,12 +1178,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file, return false; } -bool WriteSymbolFile(const string &load_path, - const string &obj_file, - const string &obj_os, +bool WriteSymbolFile(const string& load_path, + const string& obj_file, + const string& obj_os, const std::vector<string>& debug_dirs, const DumpOptions& options, - std::ostream &sym_stream) { + std::ostream& sym_stream) { Module* module; if (!ReadSymbolData(load_path, obj_file, obj_os, debug_dirs, options, &module)) @@ -1088,7 +1200,7 @@ bool WriteSymbolFile(const string &load_path, bool WriteSymbolFileHeader(const string& load_path, const string& obj_file, const string& obj_os, - std::ostream &sym_stream) { + std::ostream& sym_stream) { MmapWrapper map_wrapper; void* elf_header = NULL; if (!LoadELF(load_path, &map_wrapper, &elf_header)) { @@ -1106,14 +1218,14 @@ bool WriteSymbolFileHeader(const string& load_path, if (elfclass == ELFCLASS32) { if (!InitModuleForElfClass<ElfClass32>( reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, obj_os, - module)) { + module, /*enable_multiple_field=*/false)) { 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, obj_os, - module)) { + module, /*enable_multiple_field=*/false)) { fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); return false; } diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h index eaddd8b2..f1802ecc 100644 --- a/src/common/linux/dump_symbols.h +++ b/src/common/linux/dump_symbols.h @@ -1,7 +1,6 @@ // -*- mode: c++ -*- -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -13,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -47,13 +46,16 @@ namespace google_breakpad { class Module; struct DumpOptions { - DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs) + DumpOptions(SymbolData symbol_data, + bool handle_inter_cu_refs, + bool enable_multiple_field) : symbol_data(symbol_data), - handle_inter_cu_refs(handle_inter_cu_refs) { - } + handle_inter_cu_refs(handle_inter_cu_refs), + enable_multiple_field(enable_multiple_field) {} SymbolData symbol_data; bool handle_inter_cu_refs; + bool enable_multiple_field; }; // Find all the debugging information in OBJ_FILE, an ELF executable @@ -62,12 +64,12 @@ struct DumpOptions { // 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 &load_path, - const string &obj_file, - const string &obj_os, +bool WriteSymbolFile(const string& load_path, + const string& obj_file, + const string& obj_os, const std::vector<string>& debug_dirs, const DumpOptions& options, - std::ostream &sym_stream); + 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 @@ -76,7 +78,7 @@ bool WriteSymbolFile(const string &load_path, bool WriteSymbolFileHeader(const string& load_path, const string& obj_file, const string& obj_os, - std::ostream &sym_stream); + 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 diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc index 54c21096..97d5827e 100644 --- a/src/common/linux/dump_symbols_unittest.cc +++ b/src/common/linux/dump_symbols_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -92,7 +91,7 @@ TYPED_TEST(DumpSymbols, Invalid) { Elf32_Ehdr header; memset(&header, 0, sizeof(header)); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); + DumpOptions options(ALL_SYMBOL_DATA, true, false); EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header), "foo", "Linux", @@ -129,7 +128,7 @@ TYPED_TEST(DumpSymbols, SimplePublic) { this->GetElfContents(elf); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); + DumpOptions options(ALL_SYMBOL_DATA, true, false); EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, "foo", "Linux", @@ -186,7 +185,7 @@ TYPED_TEST(DumpSymbols, SimpleBuildID) { this->GetElfContents(elf); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true); + DumpOptions options(ALL_SYMBOL_DATA, true, false); EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, "foo", "Linux", diff --git a/src/common/linux/eintr_wrapper.h b/src/common/linux/eintr_wrapper.h index 3f1d1848..a8428a9d 100644 --- a/src/common/linux/eintr_wrapper.h +++ b/src/common/linux/eintr_wrapper.h @@ -1,5 +1,4 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. +// Copyright 2010 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/elf_core_dump.cc b/src/common/linux/elf_core_dump.cc index 0e7db7b1..f5ee3033 100644 --- a/src/common/linux/elf_core_dump.cc +++ b/src/common/linux/elf_core_dump.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -34,6 +33,7 @@ #include <stddef.h> #include <string.h> +#include <unistd.h> namespace google_breakpad { @@ -95,16 +95,29 @@ size_t ElfCoreDump::Note::AlignedSize(size_t size) { // Implementation of ElfCoreDump. -ElfCoreDump::ElfCoreDump() {} +ElfCoreDump::ElfCoreDump() : proc_mem_fd_(-1) {} ElfCoreDump::ElfCoreDump(const MemoryRange& content) - : content_(content) { + : content_(content), proc_mem_fd_(-1) {} + +ElfCoreDump::~ElfCoreDump() { + if (proc_mem_fd_ != -1) { + close(proc_mem_fd_); + proc_mem_fd_ = -1; + } } void ElfCoreDump::SetContent(const MemoryRange& content) { content_ = content; } +void ElfCoreDump::SetProcMem(int fd) { + if (proc_mem_fd_ != -1) { + close(proc_mem_fd_); + } + proc_mem_fd_ = fd; +} + bool ElfCoreDump::IsValid() const { const Ehdr* header = GetHeader(); return (header && @@ -163,6 +176,16 @@ bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) { } } } + + /* fallback: if available, read from /proc/<pid>/mem */ + if (proc_mem_fd_ != -1) { + off_t offset = virtual_address; + ssize_t r = pread(proc_mem_fd_, buffer, length, offset); + if (r < ssize_t(length)) { + return false; + } + return true; + } return false; } diff --git a/src/common/linux/elf_core_dump.h b/src/common/linux/elf_core_dump.h index 6e153745..4f27179f 100644 --- a/src/common/linux/elf_core_dump.h +++ b/src/common/linux/elf_core_dump.h @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -106,6 +105,8 @@ class ElfCoreDump { // Constructor that takes the core dump content from |content|. explicit ElfCoreDump(const MemoryRange& content); + ~ElfCoreDump(); + // Sets the core dump content to |content|. void SetContent(const MemoryRange& content); @@ -139,9 +140,15 @@ class ElfCoreDump { // an empty note if no note is found. Note GetFirstNote() const; + // Sets the mem fd. + void SetProcMem(const int fd); + private: // Core dump content. MemoryRange content_; + + // Descriptor for /proc/<pid>/mem. + int proc_mem_fd_; }; } // namespace google_breakpad diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc index 2399c12f..6789dd84 100644 --- a/src/common/linux/elf_core_dump_unittest.cc +++ b/src/common/linux/elf_core_dump_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -130,9 +129,13 @@ TEST(ElfCoreDumpTest, TestElfHeader) { TEST(ElfCoreDumpTest, ValidCoreFile) { CrashGenerator crash_generator; if (!crash_generator.HasDefaultCorePattern()) { - fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped " - "due to non-default core pattern"); - return; + GTEST_SKIP() << "ElfCoreDumpTest.ValidCoreFile test is skipped " + "due to non-default core pattern"; + } + + if (!crash_generator.HasResourceLimitsAmenableToCrashCollection()) { + GTEST_SKIP() << "ElfCoreDumpTest.ValidCoreFile test is skipped " + "due to inadequate system resource limits"; } const unsigned kNumOfThreads = 3; diff --git a/src/common/linux/elf_gnu_compat.h b/src/common/linux/elf_gnu_compat.h index 0a3dfedb..5d56c1e9 100644 --- a/src/common/linux/elf_gnu_compat.h +++ b/src/common/linux/elf_gnu_compat.h @@ -1,7 +1,6 @@ // -*- mode: C++ -*- -// Copyright (c) 2013, Google Inc. -// All rights reserved. +// Copyright 2013 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -13,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/elf_symbols_to_module.cc b/src/common/linux/elf_symbols_to_module.cc index 562875e1..3c33be99 100644 --- a/src/common/linux/elf_symbols_to_module.cc +++ b/src/common/linux/elf_symbols_to_module.cc @@ -1,6 +1,6 @@ // -*- mode: c++ -*- -// Copyright (c) 2011 Google Inc. All Rights Reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -12,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -36,6 +36,9 @@ #include <elf.h> #include <string.h> +#include <memory> +#include <utility> + #include "common/byte_cursor.h" #include "common/module.h" @@ -69,7 +72,7 @@ public: // otherwise. Assume each symbol has a 'value' field whose size is // VALUE_SIZE. // - ELFSymbolIterator(const ByteBuffer *buffer, bool big_endian, + 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 @@ -81,13 +84,13 @@ public: // 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; } + 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_; } + const Symbol& operator*() const { return symbol_; } + const Symbol* operator->() const { return &symbol_; } private: // Read the symbol at cursor_, and set symbol_ appropriately. @@ -126,21 +129,21 @@ private: Symbol symbol_; }; -const char *SymbolString(ptrdiff_t offset, ByteBuffer& strings) { +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); + return reinterpret_cast<const char*>(strings.start + offset); } -bool ELFSymbolsToModule(const uint8_t *symtab_section, +bool ELFSymbolsToModule(const uint8_t* symtab_section, size_t symtab_size, - const uint8_t *string_section, + const uint8_t* string_section, size_t string_size, const bool big_endian, size_t value_size, - Module *module) { + Module* module) { ByteBuffer symbols(symtab_section, symtab_size); // Ensure that the string section is null-terminated. if (string_section[string_size - 1] != '\0') { @@ -156,7 +159,7 @@ bool ELFSymbolsToModule(const uint8_t *symtab_section, while(!iterator->at_end) { if (ELF32_ST_TYPE(iterator->info) == STT_FUNC && iterator->shndx != SHN_UNDEF) { - Module::Extern *ext = new Module::Extern(iterator->value); + auto ext = std::make_unique<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; @@ -168,7 +171,7 @@ bool ELFSymbolsToModule(const uint8_t *symtab_section, free(demangled); } #endif - module->AddExtern(ext); + module->AddExtern(std::move(ext)); } ++iterator; } diff --git a/src/common/linux/elf_symbols_to_module.h b/src/common/linux/elf_symbols_to_module.h index 2e7c0971..ab27ef6b 100644 --- a/src/common/linux/elf_symbols_to_module.h +++ b/src/common/linux/elf_symbols_to_module.h @@ -1,6 +1,6 @@ // -*- mode: c++ -*- -// Copyright (c) 2011 Google Inc. All Rights Reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -12,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -44,13 +44,13 @@ namespace google_breakpad { class Module; -bool ELFSymbolsToModule(const uint8_t *symtab_section, +bool ELFSymbolsToModule(const uint8_t* symtab_section, size_t symtab_size, - const uint8_t *string_section, + const uint8_t* string_section, size_t string_size, const bool big_endian, size_t value_size, - Module *module); + Module* module); } // namespace google_breakpad diff --git a/src/common/linux/elf_symbols_to_module_unittest.cc b/src/common/linux/elf_symbols_to_module_unittest.cc index 8984449a..17eb670f 100644 --- a/src/common/linux/elf_symbols_to_module_unittest.cc +++ b/src/common/linux/elf_symbols_to_module_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -86,7 +85,7 @@ public: // 4 or 8 (bytes) size_t value_size; - vector<Module::Extern *> externs; + vector<Module::Extern*> externs; }; class ELFSymbolsToModuleTest32 : public ELFSymbolsToModuleTestFixture, @@ -248,9 +247,9 @@ TEST_P(ELFSymbolsToModuleTest32, SkipStuff) { } // Run all the 32-bit tests with both endianness -INSTANTIATE_TEST_CASE_P(Endian, - ELFSymbolsToModuleTest32, - ::testing::Values(kLittleEndian, kBigEndian)); +INSTANTIATE_TEST_SUITE_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, @@ -365,6 +364,6 @@ TEST_P(ELFSymbolsToModuleTest64, SkipStuff) { } // Run all the 64-bit tests with both endianness -INSTANTIATE_TEST_CASE_P(Endian, - ELFSymbolsToModuleTest64, - ::testing::Values(kLittleEndian, kBigEndian)); +INSTANTIATE_TEST_SUITE_P(Endian, + ELFSymbolsToModuleTest64, + ::testing::Values(kLittleEndian, kBigEndian)); diff --git a/src/common/linux/elfutils-inl.h b/src/common/linux/elfutils-inl.h index e56b37a9..5fcc9c44 100644 --- a/src/common/linux/elfutils-inl.h +++ b/src/common/linux/elfutils-inl.h @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/elfutils.cc b/src/common/linux/elfutils.cc index 9532d5ad..a68cc0af 100644 --- a/src/common/linux/elfutils.cc +++ b/src/common/linux/elfutils.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -40,11 +39,11 @@ namespace google_breakpad { namespace { template<typename ElfClass> -void FindElfClassSection(const char *elf_base, - const char *section_name, +void FindElfClassSection(const char* elf_base, + const char* section_name, typename ElfClass::Word section_type, - const void **section_start, - size_t *section_size) { + const void** section_start, + size_t* section_size) { typedef typename ElfClass::Ehdr Ehdr; typedef typename ElfClass::Shdr Shdr; @@ -57,12 +56,18 @@ void FindElfClassSection(const char *elf_base, const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base); assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); + if (elf_header->e_shoff == 0) { + *section_start = NULL; + *section_size = 0; + return; + } + 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 char* names_end = names + section_names->sh_size; const Shdr* section = FindElfSectionByName<ElfClass>(section_name, section_type, @@ -76,9 +81,9 @@ void FindElfClassSection(const char *elf_base, } template<typename ElfClass> -void FindElfClassSegment(const char *elf_base, +void FindElfClassSegment(const char* elf_base, typename ElfClass::Word segment_type, - wasteful_vector<ElfSegment> *segments) { + wasteful_vector<ElfSegment>* segments) { typedef typename ElfClass::Ehdr Ehdr; typedef typename ElfClass::Phdr Phdr; @@ -117,11 +122,11 @@ int ElfClass(const void* elf_base) { return elf_header->e_ident[EI_CLASS]; } -bool FindElfSection(const void *elf_mapped_base, - const char *section_name, +bool FindElfSection(const void* elf_mapped_base, + const char* section_name, uint32_t section_type, - const void **section_start, - size_t *section_size) { + const void** section_start, + size_t* section_size) { assert(elf_mapped_base); assert(section_start); assert(section_size); diff --git a/src/common/linux/elfutils.h b/src/common/linux/elfutils.h index aefb6cf5..130a8ac1 100644 --- a/src/common/linux/elfutils.h +++ b/src/common/linux/elfutils.h @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -41,6 +40,39 @@ namespace google_breakpad { +typedef struct Elf32_Chdr { + typedef Elf32_Word Type; + typedef Elf32_Word Size; + typedef Elf32_Addr Addr; + + static_assert(sizeof (Type) == 4); + static_assert(sizeof (Size) == 4); + static_assert(sizeof (Addr) == 4); + + Type ch_type; // Compression type + Size ch_size; // Uncompressed data size in bytes + Addr ch_addralign; // Uncompressed data alignment +} Elf32_Chdr; + +static_assert(sizeof (Elf32_Chdr) == 12); + +typedef struct Elf64_Chdr { + typedef Elf64_Word Type; + typedef Elf64_Xword Size; + typedef Elf64_Addr Addr; + + static_assert(sizeof (Type) == 4); + static_assert(sizeof (Size) == 8); + static_assert(sizeof (Addr) == 8); + + Type ch_type; // Compression type + Type ch_reserved; // Padding + Size ch_size; // Uncompressed data size in bytes + Addr ch_addralign; // Uncompressed data alignment +} Elf64_Chdr; + +static_assert(sizeof (Elf64_Chdr) == 24); + // Traits classes so consumers can write templatized code to deal // with specific ELF bits. struct ElfClass32 { @@ -50,6 +82,7 @@ struct ElfClass32 { typedef Elf32_Nhdr Nhdr; typedef Elf32_Phdr Phdr; typedef Elf32_Shdr Shdr; + typedef Elf32_Chdr Chdr; typedef Elf32_Half Half; typedef Elf32_Off Off; typedef Elf32_Sym Sym; @@ -68,6 +101,7 @@ struct ElfClass64 { typedef Elf64_Nhdr Nhdr; typedef Elf64_Phdr Phdr; typedef Elf64_Shdr Shdr; + typedef Elf64_Chdr Chdr; typedef Elf64_Half Half; typedef Elf64_Off Off; typedef Elf64_Sym Sym; @@ -86,11 +120,11 @@ int ElfClass(const void* elf_base); // 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. -bool FindElfSection(const void *elf_mapped_base, - const char *section_name, +bool FindElfSection(const void* elf_mapped_base, + const char* section_name, uint32_t section_type, - const void **section_start, - size_t *section_size); + const void** section_start, + size_t* section_size); // Internal helper method, exposed for convenience for callers // that already have more info. diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index 67921c45..0bd2a759 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -49,6 +48,7 @@ #include "third_party/lss/linux_syscall_support.h" namespace google_breakpad { +namespace elf { // Used in a few places for backwards-compatibility. const size_t kMDGUIDSize = sizeof(MDGUID); @@ -61,7 +61,7 @@ FileID::FileID(const char* path) : path_(path) {} // These functions are also used inside the crashed process, so be safe // and use the syscall/libc wrappers instead of direct syscalls or libc. -static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, +static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length, wasteful_vector<uint8_t>& identifier) { static_assert(sizeof(ElfClass32::Nhdr) == sizeof(ElfClass64::Nhdr), "Elf32_Nhdr and Elf64_Nhdr should be the same"); @@ -69,7 +69,7 @@ static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, 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) { + 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*>( @@ -77,7 +77,7 @@ static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length, NOTE_PADDING(note_header->n_namesz) + NOTE_PADDING(note_header->n_descsz)); } - if (reinterpret_cast<const void *>(note_header) >= section_end || + if (reinterpret_cast<const void*>(note_header) >= section_end || note_header->n_descsz == 0) { return false; } @@ -198,4 +198,5 @@ string FileID::ConvertIdentifierToString( return bytes_to_hex_string(&identifier[0], identifier.size()); } +} // elf } // namespace google_breakpad diff --git a/src/common/linux/file_id.h b/src/common/linux/file_id.h index 4aff021d..8e58d56e 100644 --- a/src/common/linux/file_id.h +++ b/src/common/linux/file_id.h @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -41,6 +40,7 @@ #include "common/using_std_string.h" namespace google_breakpad { +namespace elf { // GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes, // so this is enough to fit that, which most binaries will use. @@ -83,6 +83,7 @@ class FileID { string path_; }; +} // namespace elf } // namespace google_breakpad #endif // COMMON_LINUX_FILE_ID_H__ diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc index f4f9ac45..74bf9e1b 100644 --- a/src/common/linux/file_id_unittest.cc +++ b/src/common/linux/file_id_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. +// Copyright 2010 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -30,7 +29,10 @@ // Unit tests for FileID #include <elf.h> +#include <spawn.h> #include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> #include <string> #include <vector> @@ -42,10 +44,13 @@ #include "common/linux/synth_elf.h" #include "common/test_assembler.h" #include "common/tests/auto_tempdir.h" +#include "common/tests/file_utils.h" #include "common/using_std_string.h" #include "breakpad_googletest_includes.h" using namespace google_breakpad; +using google_breakpad::elf::FileID; +using google_breakpad::elf::kDefaultBuildIdSize; using google_breakpad::synth_elf::ELF; using google_breakpad::synth_elf::Notes; using google_breakpad::test_assembler::kLittleEndian; @@ -80,13 +85,18 @@ TEST(FileIDStripTest, StripSelf) { // 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; + ASSERT_TRUE(CopyFile(exe_name, templ)); + pid_t pid; + char* argv[] = { + const_cast<char*>("strip"), + const_cast<char*>(templ.c_str()), + nullptr, + }; + ASSERT_EQ(0, posix_spawnp(&pid, argv[0], nullptr, nullptr, argv, nullptr)); + int status; + ASSERT_EQ(pid, waitpid(pid, &status, 0)); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(0, WEXITSTATUS(status)); PageAllocator allocator; id_vector identifier1(&allocator, kDefaultBuildIdSize); @@ -261,7 +271,7 @@ TYPED_TEST(FileIDTest, BuildIDPH) { elf.AddSection(".text", text, SHT_PROGBITS); Notes notes(kLittleEndian); notes.AddNote(0, "Linux", - reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4); + 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); @@ -292,7 +302,7 @@ TYPED_TEST(FileIDTest, BuildIDMultiplePH) { elf.AddSection(".text", text, SHT_PROGBITS); Notes notes1(kLittleEndian); notes1.AddNote(0, "Linux", - reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4); + reinterpret_cast<const uint8_t*>("\0x42\0x02\0\0"), 4); Notes notes2(kLittleEndian); notes2.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, sizeof(kExpectedIdentifierBytes)); diff --git a/src/common/linux/google_crashdump_uploader.cc b/src/common/linux/google_crashdump_uploader.cc index a0d940b6..6242e6d2 100644 --- a/src/common/linux/google_crashdump_uploader.cc +++ b/src/common/linux/google_crashdump_uploader.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -35,6 +34,7 @@ #include <unistd.h> #include <iostream> +#include <utility> #include "common/using_std_string.h" @@ -51,7 +51,7 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product, const string& crash_server, const string& proxy_host, const string& proxy_userpassword) { - LibcurlWrapper* http_layer = new LibcurlWrapper(); + std::unique_ptr<LibcurlWrapper> http_layer{new LibcurlWrapper()}; Init(product, version, guid, @@ -63,21 +63,22 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product, crash_server, proxy_host, proxy_userpassword, - http_layer); + std::move(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) { +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, + std::unique_ptr<LibcurlWrapper> http_layer) { Init(product, version, guid, @@ -89,7 +90,7 @@ GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product, crash_server, proxy_host, proxy_userpassword, - http_layer); + std::move(http_layer)); } void GoogleCrashdumpUploader::Init(const string& product, @@ -103,7 +104,7 @@ void GoogleCrashdumpUploader::Init(const string& product, const string& crash_server, const string& proxy_host, const string& proxy_userpassword, - LibcurlWrapper* http_layer) { + std::unique_ptr<LibcurlWrapper> http_layer) { product_ = product; version_ = version; guid_ = guid; @@ -111,7 +112,7 @@ void GoogleCrashdumpUploader::Init(const string& product, ctime_ = ctime; email_ = email; comments_ = comments; - http_layer_.reset(http_layer); + http_layer_ = std::move(http_layer); crash_server_ = crash_server; proxy_host_ = proxy_host; diff --git a/src/common/linux/google_crashdump_uploader.h b/src/common/linux/google_crashdump_uploader.h index a2d0575b..74b5e1be 100644 --- a/src/common/linux/google_crashdump_uploader.h +++ b/src/common/linux/google_crashdump_uploader.h @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -31,11 +30,11 @@ #ifndef COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_ #define COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_ -#include <string> #include <map> +#include <memory> +#include <string> #include "common/linux/libcurl_wrapper.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" namespace google_breakpad { @@ -65,7 +64,7 @@ class GoogleCrashdumpUploader { const string& crash_server, const string& proxy_host, const string& proxy_userpassword, - LibcurlWrapper* http_layer); + std::unique_ptr<LibcurlWrapper> http_layer); void Init(const string& product, const string& version, @@ -78,7 +77,7 @@ class GoogleCrashdumpUploader { const string& crash_server, const string& proxy_host, const string& proxy_userpassword, - LibcurlWrapper* http_layer); + std::unique_ptr<LibcurlWrapper> http_layer); bool Upload(int* http_status_code, string* http_response_header, string* http_response_body); @@ -86,7 +85,7 @@ class GoogleCrashdumpUploader { private: bool CheckRequiredParametersArePresent(); - scoped_ptr<LibcurlWrapper> http_layer_; + std::unique_ptr<LibcurlWrapper> http_layer_; string product_; string version_; string guid_; diff --git a/src/common/linux/google_crashdump_uploader_test.cc b/src/common/linux/google_crashdump_uploader_test.cc index 3d6612e8..39aab65d 100644 --- a/src/common/linux/google_crashdump_uploader_test.cc +++ b/src/common/linux/google_crashdump_uploader_test.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -59,21 +58,12 @@ 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)); + std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()}; + EXPECT_CALL(*m, Init()).Times(1).WillOnce(Return(false)); + GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "", + "test@test.com", "none", "/tmp/foo.dmp", + "http://foo.com", "", "", std::move(m)); + ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); } TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { @@ -83,44 +73,27 @@ TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { 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)); + std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()}; + 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("foobar", "1.0", "AAA-BBB", "", "", + "test@test.com", "none", tempfn, + "http://foo.com", "", "", std::move(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)); + std::unique_ptr<MockLibcurlWrapper> m{new MockLibcurlWrapper()}; + EXPECT_CALL(*m, Init()).Times(1).WillOnce(Return(true)); + EXPECT_CALL(*m, SendRequest(_,_,_,_,_)).Times(0); + GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "", + "test@test.com", "none", "/tmp/foo.dmp", + "http://foo.com", "", "", std::move(m)); + ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); } TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { diff --git a/src/common/linux/guid_creator.cc b/src/common/linux/guid_creator.cc index 03e3d781..31a326c7 100644 --- a/src/common/linux/guid_creator.cc +++ b/src/common/linux/guid_creator.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -105,7 +104,7 @@ class GUIDGenerator { private: #ifdef HAVE_ARC4RANDOM static void CreateGuidFromArc4Random(GUID *guid) { - char *buf = reinterpret_cast<char *>(guid); + char *buf = reinterpret_cast<char*>(guid); for (size_t i = 0; i < sizeof(GUID); i += sizeof(uint32_t)) { uint32_t random_data = arc4random(); @@ -129,7 +128,7 @@ class GUIDGenerator { #if defined(HAVE_SYS_RANDOM_H) && defined(HAVE_GETRANDOM) static bool CreateGUIDFromGetrandom(GUID *guid) { - char *buf = reinterpret_cast<char *>(guid); + char *buf = reinterpret_cast<char*>(guid); int read_bytes = getrandom(buf, sizeof(GUID), GRND_NONBLOCK); return (read_bytes == static_cast<int>(sizeof(GUID))); @@ -139,7 +138,7 @@ class GUIDGenerator { // Populate the GUID using random bytes read from /dev/urandom, returns false // if the GUID wasn't fully populated with random data. static bool CreateGUIDFromDevUrandom(GUID *guid) { - char *buf = reinterpret_cast<char *>(guid); + char *buf = reinterpret_cast<char*>(guid); int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); if (fd == -1) { @@ -154,7 +153,7 @@ class GUIDGenerator { // Populate the GUID using a stream of random bytes obtained from rand(). static void CreateGUIDFromRand(GUID *guid) { - char *buf = reinterpret_cast<char *>(guid); + char *buf = reinterpret_cast<char*>(guid); InitOnce(); diff --git a/src/common/linux/guid_creator.h b/src/common/linux/guid_creator.h index c86d856c..c02f5552 100644 --- a/src/common/linux/guid_creator.h +++ b/src/common/linux/guid_creator.h @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc index 702526af..1b576ea6 100644 --- a/src/common/linux/http_upload.cc +++ b/src/common/linux/http_upload.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -36,14 +35,14 @@ namespace { // Callback to get the response data from server. -static size_t WriteCallback(void *ptr, size_t size, - size_t nmemb, void *userp) { +static size_t WriteCallback(void* ptr, size_t size, + size_t nmemb, void* userp) { if (!userp) return 0; - string *response = reinterpret_cast<string *>(userp); + string* response = reinterpret_cast<string*>(userp); size_t real_size = size * nmemb; - response->append(reinterpret_cast<char *>(ptr), real_size); + response->append(reinterpret_cast<char*>(ptr), real_size); return real_size; } @@ -54,15 +53,15 @@ 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) { +bool HTTPUpload::SendRequest(const string& url, + const map<string, string>& parameters, + 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; @@ -101,7 +100,7 @@ bool HTTPUpload::SendRequest(const string &url, CURL* (*curl_easy_init)(void); *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init"); - CURL *curl = (*curl_easy_init)(); + CURL* curl = (*curl_easy_init)(); if (error_description != NULL) *error_description = "No Error"; @@ -111,7 +110,7 @@ bool HTTPUpload::SendRequest(const string &url, } CURLcode err_code = CURLE_OK; - CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...); + 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); @@ -128,10 +127,10 @@ bool HTTPUpload::SendRequest(const string &url, 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; + struct curl_httppost* formpost = NULL; + struct curl_httppost* lastptr = NULL; // Add form data. - CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...); + 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) @@ -151,9 +150,9 @@ bool HTTPUpload::SendRequest(const string &url, (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost); // Disable 100-continue header. - struct curl_slist *headerlist = NULL; + struct curl_slist* headerlist = NULL; char buf[] = "Expect:"; - struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *); + 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); @@ -161,17 +160,17 @@ bool HTTPUpload::SendRequest(const string &url, if (response_body != NULL) { (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback); (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA, - reinterpret_cast<void *>(response_body)); + 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 *); + 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, ...); + 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); } @@ -186,16 +185,16 @@ bool HTTPUpload::SendRequest(const string &url, if (error_description != NULL) *error_description = (*curl_easy_strerror)(err_code); - void (*curl_easy_cleanup)(CURL *); + 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)(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)(struct curl_slist*); *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all"); (*curl_slist_free_all)(headerlist); } @@ -211,10 +210,10 @@ bool HTTPUpload::CheckCurlLib(void* curl_lib) { } // static -bool HTTPUpload::CheckParameters(const map<string, string> ¶meters) { +bool HTTPUpload::CheckParameters(const map<string, string>& parameters) { for (map<string, string>::const_iterator pos = parameters.begin(); pos != parameters.end(); ++pos) { - const string &str = pos->first; + const string& str = pos->first; if (str.size() == 0) return false; // disallow empty parameter names for (unsigned int i = 0; i < str.size(); ++i) { diff --git a/src/common/linux/http_upload.h b/src/common/linux/http_upload.h index bc1d5d57..b7e557a0 100644 --- a/src/common/linux/http_upload.h +++ b/src/common/linux/http_upload.h @@ -1,5 +1,4 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. +// Copyright 2006 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -58,21 +57,21 @@ class HTTPUpload { // 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); + static bool SendRequest(const string& url, + const map<string, string>& parameters, + 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); + static bool CheckParameters(const map<string, string>& parameters); // Checks the curl_lib parameter points to a valid curl lib. static bool CheckCurlLib(void* curl_lib); @@ -80,8 +79,8 @@ class HTTPUpload { // No instances of this class should be created. // Disallow all constructors, destructors, and operator=. HTTPUpload(); - explicit HTTPUpload(const HTTPUpload &); - void operator=(const HTTPUpload &); + explicit HTTPUpload(const HTTPUpload&); + void operator=(const HTTPUpload&); ~HTTPUpload(); }; diff --git a/src/common/linux/ignore_ret.h b/src/common/linux/ignore_ret.h index efd274c2..1f879e8f 100644 --- a/src/common/linux/ignore_ret.h +++ b/src/common/linux/ignore_ret.h @@ -1,5 +1,4 @@ -// Copyright (c) 2012 Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc index e96c2038..a53087d9 100644 --- a/src/common/linux/libcurl_wrapper.cc +++ b/src/common/linux/libcurl_wrapper.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -48,6 +47,7 @@ LibcurlWrapper::LibcurlWrapper() LibcurlWrapper::~LibcurlWrapper() { if (init_ok_) { (*easy_cleanup_)(curl_); + (*global_cleanup_)(); dlclose(curl_lib_); } } @@ -88,14 +88,14 @@ bool LibcurlWrapper::AddFile(const string& upload_file_path, } // Callback to get the response data from server. -static size_t WriteCallback(void *ptr, size_t size, - size_t nmemb, void *userp) { +static size_t WriteCallback(void* ptr, size_t size, + size_t nmemb, void* userp) { if (!userp) return 0; - string *response = reinterpret_cast<string *>(userp); + string* response = reinterpret_cast<string*>(userp); size_t real_size = size * nmemb; - response->append(reinterpret_cast<char *>(ptr), real_size); + response->append(reinterpret_cast<char*>(ptr), real_size); return real_size; } @@ -250,7 +250,7 @@ bool LibcurlWrapper::SetFunctionPointers() { SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_, "curl_easy_getinfo", - CURLcode(*)(CURL *, CURLINFO info, ...)); + CURLcode(*)(CURL*, CURLINFO info, ...)); SET_AND_CHECK_FUNCTION_POINTER(easy_reset_, "curl_easy_reset", @@ -263,6 +263,10 @@ bool LibcurlWrapper::SetFunctionPointers() { SET_AND_CHECK_FUNCTION_POINTER(formfree_, "curl_formfree", void(*)(curl_httppost*)); + + SET_AND_CHECK_FUNCTION_POINTER(global_cleanup_, + "curl_global_cleanup", + void(*)(void)); return true; } diff --git a/src/common/linux/libcurl_wrapper.h b/src/common/linux/libcurl_wrapper.h index 77aa6cbb..f8f961c1 100644 --- a/src/common/linux/libcurl_wrapper.h +++ b/src/common/linux/libcurl_wrapper.h @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -40,6 +39,9 @@ #include "third_party/curl/curl.h" namespace google_breakpad { + +// This class is only safe to be used on single-threaded code because of its +// usage of libcurl's curl_global_cleanup(). class LibcurlWrapper { public: LibcurlWrapper(); @@ -91,27 +93,28 @@ class LibcurlWrapper { // dealing // with CURL. - CURL *curl_; // Pointer for handle for CURL calls. + 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_; + 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 *); + 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 (*easy_cleanup_)(CURL*); + CURLcode (*easy_getinfo_)(CURL*, CURLINFO info, ...); void (*easy_reset_)(CURL*); - void (*formfree_)(struct curl_httppost *); + void (*formfree_)(struct curl_httppost*); + void (*global_cleanup_)(void); }; } diff --git a/src/common/linux/linux_libc_support.cc b/src/common/linux/linux_libc_support.cc index 08b0325e..10cbeaef 100644 --- a/src/common/linux/linux_libc_support.cc +++ b/src/common/linux/linux_libc_support.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -190,7 +189,7 @@ const char* my_read_decimal_ptr(uintptr_t* result, const char* s) { } void my_memset(void* ip, char c, size_t len) { - char* p = (char *) ip; + char* p = (char*) ip; while (len--) *p++ = c; } diff --git a/src/common/linux/linux_libc_support.h b/src/common/linux/linux_libc_support.h index ec5a8d6b..05e2aa24 100644 --- a/src/common/linux/linux_libc_support.h +++ b/src/common/linux/linux_libc_support.h @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/linux_libc_support_unittest.cc b/src/common/linux/linux_libc_support_unittest.cc index adadfed4..449f995f 100644 --- a/src/common/linux/linux_libc_support_unittest.cc +++ b/src/common/linux/linux_libc_support_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2009, Google Inc. -// All rights reserved. +// Copyright 2009 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc index 4e938269..7e444607 100644 --- a/src/common/linux/memory_mapped_file.cc +++ b/src/common/linux/memory_mapped_file.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -65,7 +64,8 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { } #if defined(__x86_64__) || defined(__aarch64__) || \ - (defined(__mips__) && _MIPS_SIM == _ABI64) + (defined(__mips__) && _MIPS_SIM == _ABI64) || \ + (defined(__riscv) && __riscv_xlen == 64) struct kernel_stat st; if (sys_fstat(fd, &st) == -1 || st.st_size < 0) { @@ -87,13 +87,14 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { return true; } - void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset); + size_t content_len = file_len - offset; + void* data = sys_mmap(NULL, content_len, PROT_READ, MAP_PRIVATE, fd, offset); sys_close(fd); if (data == MAP_FAILED) { return false; } - content_.Set(data, file_len - offset); + content_.Set(data, content_len); return true; } diff --git a/src/common/linux/memory_mapped_file.h b/src/common/linux/memory_mapped_file.h index fa660cc9..d4a85051 100644 --- a/src/common/linux/memory_mapped_file.h +++ b/src/common/linux/memory_mapped_file.h @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc index fad59f40..5ed677df 100644 --- a/src/common/linux/memory_mapped_file_unittest.cc +++ b/src/common/linux/memory_mapped_file_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/safe_readlink.cc b/src/common/linux/safe_readlink.cc index 870c28af..97ea62c0 100644 --- a/src/common/linux/safe_readlink.cc +++ b/src/common/linux/safe_readlink.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/safe_readlink.h b/src/common/linux/safe_readlink.h index 4ae131b5..f3aa9332 100644 --- a/src/common/linux/safe_readlink.h +++ b/src/common/linux/safe_readlink.h @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/safe_readlink_unittest.cc b/src/common/linux/safe_readlink_unittest.cc index d346b2a8..6f5f9d75 100644 --- a/src/common/linux/safe_readlink_unittest.cc +++ b/src/common/linux/safe_readlink_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/symbol_collector_client.cc b/src/common/linux/symbol_collector_client.cc index 92b25ddb..1c1dc97a 100644 --- a/src/common/linux/symbol_collector_client.cc +++ b/src/common/linux/symbol_collector_client.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2019 Google Inc. -// All rights reserved. +// Copyright 2019 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/symbol_collector_client.h b/src/common/linux/symbol_collector_client.h index 0e23242a..6190376f 100644 --- a/src/common/linux/symbol_collector_client.h +++ b/src/common/linux/symbol_collector_client.h @@ -1,5 +1,4 @@ -// Copyright (c) 2019, Google Inc. -// All rights reserved. +// Copyright 2019 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/symbol_upload.cc b/src/common/linux/symbol_upload.cc index 87741a0a..c080533a 100644 --- a/src/common/linux/symbol_upload.cc +++ b/src/common/linux/symbol_upload.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -46,8 +45,8 @@ namespace google_breakpad { namespace sym_upload { -void TokenizeByChar(const string &source_string, int c, - std::vector<string> *results) { +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) { @@ -62,8 +61,8 @@ void TokenizeByChar(const string &source_string, int c, //============================================================================= // 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) { +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"); @@ -90,7 +89,7 @@ bool ModuleDataForSymbolFile(const string &file, } //============================================================================= -string CompactIdentifier(const string &uuid) { +string CompactIdentifier(const string& uuid) { std::vector<string> components; TokenizeByChar(uuid, '-', &components); string result; diff --git a/src/common/linux/symbol_upload.h b/src/common/linux/symbol_upload.h index 9033152b..a9d30e7b 100644 --- a/src/common/linux/symbol_upload.h +++ b/src/common/linux/symbol_upload.h @@ -1,7 +1,6 @@ // -*- mode: c++ -*- -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -13,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/synth_elf.cc b/src/common/linux/synth_elf.cc index 98e81dab..2ba25e61 100644 --- a/src/common/linux/synth_elf.cc +++ b/src/common/linux/synth_elf.cc @@ -118,7 +118,7 @@ int ELF::AddSection(const string& name, const Section& section, return index; } -void ELF::AppendSection(ElfSection §ion) { +void ELF::AppendSection(ElfSection& section) { // NULL and NOBITS sections have no content, so they // don't need to be written to the file. if (section.type_ == SHT_NULL) { @@ -242,7 +242,7 @@ void SymbolTable::AddSymbol(const string& name, uint64_t value, D64(size); } -void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes, +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; diff --git a/src/common/linux/synth_elf.h b/src/common/linux/synth_elf.h index 1d2a20ca..bf22081b 100644 --- a/src/common/linux/synth_elf.h +++ b/src/common/linux/synth_elf.h @@ -1,7 +1,6 @@ // -*- mode: C++ -*- -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -13,7 +12,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -154,7 +153,7 @@ class ELF : public Section { vector<ElfSection> sections_; - void AppendSection(ElfSection §ion); + void AppendSection(ElfSection& section); }; // A class to build .symtab or .dynsym sections. @@ -187,7 +186,7 @@ public: } // Add a note. - void AddNote(int type, const string &name, const uint8_t* desc_bytes, + void AddNote(int type, const string& name, const uint8_t* desc_bytes, size_t desc_size); }; diff --git a/src/common/linux/synth_elf_unittest.cc b/src/common/linux/synth_elf_unittest.cc index cd74c286..44ef6ef3 100644 --- a/src/common/linux/synth_elf_unittest.cc +++ b/src/common/linux/synth_elf_unittest.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011 Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -381,9 +380,9 @@ TEST_F(ElfNotesTest, Empty) { TEST_F(ElfNotesTest, Notes) { Notes notes(kLittleEndian); - notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t *>("\x42\x02\0\0"), + notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t*>("\x42\x02\0\0"), 4); - notes.AddNote(2, "a", reinterpret_cast<const uint8_t *>("foobar"), + notes.AddNote(2, "a", reinterpret_cast<const uint8_t*>("foobar"), sizeof("foobar") - 1); const uint8_t kExpectedNotesContents[] = { diff --git a/src/common/linux/tests/auto_testfile.h b/src/common/linux/tests/auto_testfile.h index 92fe017b..e2d2ff23 100644 --- a/src/common/linux/tests/auto_testfile.h +++ b/src/common/linux/tests/auto_testfile.h @@ -1,5 +1,4 @@ -// Copyright (c) 2013, Google Inc. -// All rights reserved. +// Copyright 2013 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // diff --git a/src/common/linux/tests/crash_generator.cc b/src/common/linux/tests/crash_generator.cc index 6896a688..0db0c4a2 100644 --- a/src/common/linux/tests/crash_generator.cc +++ b/src/common/linux/tests/crash_generator.cc @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -79,7 +78,7 @@ int tkill(pid_t tid, int 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) { +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; @@ -169,6 +168,15 @@ bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const { return true; } +bool CrashGenerator::HasResourceLimitsAmenableToCrashCollection() const { + struct rlimit limits; + if (getrlimit(RLIMIT_CORE, &limits) == -1) { + perror("CrashGenerator: Failed to get core file size limit"); + return false; + } + return limits.rlim_max >= kCoreSizeLimit; +} + bool CrashGenerator::CreateChildCrash( unsigned num_threads, unsigned crash_thread, int crash_signal, pid_t* child_pid) { diff --git a/src/common/linux/tests/crash_generator.h b/src/common/linux/tests/crash_generator.h index 7e2fcbf9..71c05d27 100644 --- a/src/common/linux/tests/crash_generator.h +++ b/src/common/linux/tests/crash_generator.h @@ -1,5 +1,4 @@ -// Copyright (c) 2011, Google Inc. -// All rights reserved. +// Copyright 2011 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -65,6 +64,10 @@ class CrashGenerator { // Returns the directory of a copy of proc files of the child process. string GetDirectoryOfProcFilesCopy() const; + // Returns whether current resource limits would prevent `CreateChildCrash` + // from operating. + bool HasResourceLimitsAmenableToCrashCollection() 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. diff --git a/src/common/linux/ucontext_constants.h b/src/common/linux/ucontext_constants.h index c390508a..3dcdecb0 100644 --- a/src/common/linux/ucontext_constants.h +++ b/src/common/linux/ucontext_constants.h @@ -1,5 +1,4 @@ -// Copyright (c) 2012, Google Inc. -// All rights reserved. +// Copyright 2012 Google LLC // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -11,7 +10,7 @@ // 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 +// * Neither the name of Google LLC nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // @@ -146,8 +145,107 @@ #endif #define FPREGS_OFFSET_MXCSR 24 +#elif defined(__riscv) + +#if __riscv_xlen == 32 +#define UCONTEXT_SIGMASK_OFFSET 20 +#define MCONTEXT_GREGS_OFFSET 148 +#define MCONTEXT_GREGS_SIZE 4 +#define REG_S sw +#elif __riscv_xlen == 64 +#define UCONTEXT_SIGMASK_OFFSET 40 +#define MCONTEXT_GREGS_OFFSET 168 +#define MCONTEXT_GREGS_SIZE 8 +#define REG_S sd #else -#error "This header has not been ported for your CPU" +#error "Unexpected __riscv_xlen" +#endif + +#define MCONTEXT_GREGS_PC MCONTEXT_GREGS_OFFSET + 0*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_RA MCONTEXT_GREGS_OFFSET + 1*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_SP MCONTEXT_GREGS_OFFSET + 2*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_GP MCONTEXT_GREGS_OFFSET + 3*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_TP MCONTEXT_GREGS_OFFSET + 4*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T0 MCONTEXT_GREGS_OFFSET + 5*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T1 MCONTEXT_GREGS_OFFSET + 6*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T2 MCONTEXT_GREGS_OFFSET + 7*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S0 MCONTEXT_GREGS_OFFSET + 8*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S1 MCONTEXT_GREGS_OFFSET + 9*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A0 MCONTEXT_GREGS_OFFSET + 10*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A1 MCONTEXT_GREGS_OFFSET + 11*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A2 MCONTEXT_GREGS_OFFSET + 12*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A3 MCONTEXT_GREGS_OFFSET + 13*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A4 MCONTEXT_GREGS_OFFSET + 14*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A5 MCONTEXT_GREGS_OFFSET + 15*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A6 MCONTEXT_GREGS_OFFSET + 16*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_A7 MCONTEXT_GREGS_OFFSET + 17*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S2 MCONTEXT_GREGS_OFFSET + 18*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S3 MCONTEXT_GREGS_OFFSET + 19*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S4 MCONTEXT_GREGS_OFFSET + 20*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S5 MCONTEXT_GREGS_OFFSET + 21*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S6 MCONTEXT_GREGS_OFFSET + 22*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S7 MCONTEXT_GREGS_OFFSET + 23*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S8 MCONTEXT_GREGS_OFFSET + 24*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S9 MCONTEXT_GREGS_OFFSET + 25*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S10 MCONTEXT_GREGS_OFFSET + 26*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_S11 MCONTEXT_GREGS_OFFSET + 27*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T3 MCONTEXT_GREGS_OFFSET + 28*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T4 MCONTEXT_GREGS_OFFSET + 29*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T5 MCONTEXT_GREGS_OFFSET + 30*MCONTEXT_GREGS_SIZE +#define MCONTEXT_GREGS_T6 MCONTEXT_GREGS_OFFSET + 31*MCONTEXT_GREGS_SIZE + +#define MCONTEXT_FPREGS_OFFSET MCONTEXT_GREGS_OFFSET + 32*MCONTEXT_GREGS_SIZE + +#if __riscv_flen == 32 +#define MCONTEXT_FPREGS_SIZE 4 +#define FREG_S fsw +#elif __riscv_flen == 64 +#define MCONTEXT_FPREGS_SIZE 8 +#define FREG_S fsd +#elif __riscv_flen == 128 +#define MCONTEXT_FPREGS_SIZE 16 +#define FREG_S fsq +#else +#error "Unexpected __riscv_flen" +#endif + +#define MCONTEXT_FPREGS_FT0 MCONTEXT_FPREGS_OFFSET + 0*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT1 MCONTEXT_FPREGS_OFFSET + 1*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT2 MCONTEXT_FPREGS_OFFSET + 2*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT3 MCONTEXT_FPREGS_OFFSET + 3*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT4 MCONTEXT_FPREGS_OFFSET + 4*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT5 MCONTEXT_FPREGS_OFFSET + 5*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT6 MCONTEXT_FPREGS_OFFSET + 6*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT7 MCONTEXT_FPREGS_OFFSET + 7*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS0 MCONTEXT_FPREGS_OFFSET + 8*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS1 MCONTEXT_FPREGS_OFFSET + 9*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA0 MCONTEXT_FPREGS_OFFSET + 10*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA1 MCONTEXT_FPREGS_OFFSET + 11*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA2 MCONTEXT_FPREGS_OFFSET + 12*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA3 MCONTEXT_FPREGS_OFFSET + 13*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA4 MCONTEXT_FPREGS_OFFSET + 14*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA5 MCONTEXT_FPREGS_OFFSET + 15*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA6 MCONTEXT_FPREGS_OFFSET + 16*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FA7 MCONTEXT_FPREGS_OFFSET + 17*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS2 MCONTEXT_FPREGS_OFFSET + 18*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS3 MCONTEXT_FPREGS_OFFSET + 19*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS4 MCONTEXT_FPREGS_OFFSET + 20*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS5 MCONTEXT_FPREGS_OFFSET + 21*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS6 MCONTEXT_FPREGS_OFFSET + 22*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS7 MCONTEXT_FPREGS_OFFSET + 23*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS8 MCONTEXT_FPREGS_OFFSET + 24*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS9 MCONTEXT_FPREGS_OFFSET + 25*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS10 MCONTEXT_FPREGS_OFFSET + 26*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FS11 MCONTEXT_FPREGS_OFFSET + 27*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT8 MCONTEXT_FPREGS_OFFSET + 28*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT9 MCONTEXT_FPREGS_OFFSET + 29*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT10 MCONTEXT_FPREGS_OFFSET + 30*MCONTEXT_FPREGS_SIZE +#define MCONTEXT_FPREGS_FT11 MCONTEXT_FPREGS_OFFSET + 31*MCONTEXT_FPREGS_SIZE + +#define MCONTEXT_FPC_CSR MCONTEXT_FPREGS_OFFSET + 32*MCONTEXT_FPREGS_SIZE + +#else +# error "This header has not been ported for your CPU" #endif #endif // GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H |