aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/linux')
-rw-r--r--src/common/linux/breakpad_getcontext.h4
-rw-r--r--src/common/linux/breakpad_getcontext_unittest.cc4
-rw-r--r--src/common/linux/crc32.cc4
-rw-r--r--src/common/linux/dump_symbols.cc111
-rw-r--r--src/common/linux/dump_symbols_unittest.cc4
-rw-r--r--src/common/linux/elf_core_dump.cc4
-rw-r--r--src/common/linux/elf_core_dump_unittest.cc4
-rw-r--r--src/common/linux/elf_symbols_to_module.cc4
-rw-r--r--src/common/linux/elf_symbols_to_module_unittest.cc4
-rw-r--r--src/common/linux/elfutils.cc4
-rw-r--r--src/common/linux/file_id.cc4
-rw-r--r--src/common/linux/file_id_unittest.cc4
-rw-r--r--src/common/linux/google_crashdump_uploader.cc4
-rw-r--r--src/common/linux/google_crashdump_uploader_test.cc4
-rw-r--r--src/common/linux/guid_creator.cc2
-rw-r--r--src/common/linux/http_upload.cc4
-rw-r--r--src/common/linux/libcurl_wrapper.cc6
-rw-r--r--src/common/linux/linux_libc_support.cc4
-rw-r--r--src/common/linux/linux_libc_support_unittest.cc4
-rw-r--r--src/common/linux/memory_mapped_file.cc11
-rw-r--r--src/common/linux/memory_mapped_file.h7
-rw-r--r--src/common/linux/memory_mapped_file_unittest.cc4
-rw-r--r--src/common/linux/safe_readlink.cc4
-rw-r--r--src/common/linux/safe_readlink_unittest.cc4
-rw-r--r--src/common/linux/scoped_pipe.cc132
-rw-r--r--src/common/linux/scoped_pipe.h115
-rw-r--r--src/common/linux/scoped_pipe_unittest.cc75
-rw-r--r--src/common/linux/scoped_tmpfile.cc103
-rw-r--r--src/common/linux/scoped_tmpfile.h85
-rw-r--r--src/common/linux/scoped_tmpfile_unittest.cc50
-rw-r--r--src/common/linux/symbol_collector_client.cc4
-rw-r--r--src/common/linux/symbol_upload.cc4
-rw-r--r--src/common/linux/synth_elf.cc4
-rw-r--r--src/common/linux/synth_elf_unittest.cc4
-rw-r--r--src/common/linux/tests/auto_testfile.h123
-rw-r--r--src/common/linux/tests/crash_generator.cc4
36 files changed, 778 insertions, 138 deletions
diff --git a/src/common/linux/breakpad_getcontext.h b/src/common/linux/breakpad_getcontext.h
index c553219f..d64784d4 100644
--- a/src/common/linux/breakpad_getcontext.h
+++ b/src/common/linux/breakpad_getcontext.h
@@ -29,10 +29,6 @@
#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
#define GOOGLE_BREAKPAD_COMMON_LINUX_INCLUDE_UCONTEXT_H
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#ifndef HAVE_GETCONTEXT
#include <signal.h>
diff --git a/src/common/linux/breakpad_getcontext_unittest.cc b/src/common/linux/breakpad_getcontext_unittest.cc
index 573ddd88..5b340eb7 100644
--- a/src/common/linux/breakpad_getcontext_unittest.cc
+++ b/src/common/linux/breakpad_getcontext_unittest.cc
@@ -29,6 +29,10 @@
// asm/sigcontext.h can't be included with signal.h on glibc or
// musl, so only compare _libc_fpstate and _fpstate on Android.
#if defined(__ANDROID__) && defined(__x86_64__)
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <asm/sigcontext.h>
#endif
diff --git a/src/common/linux/crc32.cc b/src/common/linux/crc32.cc
index c02f06c4..cf386a24 100644
--- a/src/common/linux/crc32.cc
+++ b/src/common/linux/crc32.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/crc32.h"
namespace google_breakpad {
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index b436f765..b693fc9e 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -31,6 +31,10 @@
// dump_symbols.cc: implement google_breakpad::WriteSymbolFile:
// Find all the debugging info in a file and dump it as a Breakpad symbol file.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/dump_symbols.h"
#include <assert.h>
@@ -47,6 +51,9 @@
#include <sys/stat.h>
#include <unistd.h>
#include <zlib.h>
+#ifdef HAVE_LIBZSTD
+#include <zstd.h>
+#endif
#include <set>
#include <string>
@@ -104,6 +111,11 @@ using google_breakpad::wasteful_vector;
#define EM_AARCH64 183
#endif
+// Define ZStd compression if host machine does not include this define.
+#ifndef ELFCOMPRESS_ZSTD
+#define ELFCOMPRESS_ZSTD 2
+#endif
+
//
// FDWrapper
//
@@ -301,7 +313,7 @@ uint32_t GetCompressionHeader(
return sizeof (*header);
}
-std::pair<uint8_t *, uint64_t> UncompressSectionContents(
+std::pair<uint8_t *, uint64_t> UncompressZlibSectionContents(
const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) {
z_stream stream;
memset(&stream, 0, sizeof stream);
@@ -330,6 +342,90 @@ std::pair<uint8_t *, uint64_t> UncompressSectionContents(
: std::make_pair(uncompressed_buffer.release(), uncompressed_size);
}
+#ifdef HAVE_LIBZSTD
+std::pair<uint8_t *, uint64_t> UncompressZstdSectionContents(
+ const uint8_t* compressed_buffer, uint64_t compressed_size,uint64_t uncompressed_size) {
+
+ google_breakpad::scoped_array<uint8_t> uncompressed_buffer(new uint8_t[uncompressed_size]);
+ size_t out_size = ZSTD_decompress(uncompressed_buffer.get(), uncompressed_size,
+ compressed_buffer, compressed_size);
+ if (ZSTD_isError(out_size)) {
+ return std::make_pair(nullptr, 0);
+ }
+ assert(out_size == uncompressed_size);
+ return std::make_pair(uncompressed_buffer.release(), uncompressed_size);
+}
+#endif
+
+std::pair<uint8_t *, uint64_t> UncompressSectionContents(
+ uint64_t compression_type, const uint8_t* compressed_buffer,
+ uint64_t compressed_size, uint64_t uncompressed_size) {
+ if (compression_type == ELFCOMPRESS_ZLIB) {
+ return UncompressZlibSectionContents(compressed_buffer, compressed_size, uncompressed_size);
+ }
+
+#ifdef HAVE_LIBZSTD
+ if (compression_type == ELFCOMPRESS_ZSTD) {
+ return UncompressZstdSectionContents(compressed_buffer, compressed_size, uncompressed_size);
+ }
+#endif
+
+ return std::make_pair(nullptr, 0);
+}
+
+void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
+ Module* module,
+ google_breakpad::Endianness endianness,
+ bool handle_inter_cu_refs,
+ bool handle_inline) {
+ std::string split_file;
+ google_breakpad::SectionMap split_sections;
+ google_breakpad::ByteReader split_byte_reader(endianness);
+ uint64_t cu_offset = 0;
+ if (!reader->ProcessSplitDwarf(split_file, split_sections, split_byte_reader,
+ cu_offset))
+ return;
+ DwarfCUToModule::FileContext file_context(split_file, module,
+ handle_inter_cu_refs);
+ for (auto section : split_sections)
+ file_context.AddSectionToSectionMap(section.first, section.second.first,
+ section.second.second);
+ // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str,
+ // its debug info will refer to .debug_addr/.debug_line in the main binary.
+ if (file_context.section_map().find(".debug_addr") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
+ reader->GetAddrBufferLen());
+ if (file_context.section_map().find(".debug_line") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_line", reader->GetLineBuffer(),
+ reader->GetLineBufferLen());
+ if (file_context.section_map().find(".debug_line_str") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_line_str",
+ reader->GetLineStrBuffer(),
+ reader->GetLineStrBufferLen());
+
+ DumperRangesHandler ranges_handler(&split_byte_reader);
+ DumperLineToModule line_to_module(&split_byte_reader);
+ DwarfCUToModule::WarningReporter reporter(split_file, cu_offset);
+ DwarfCUToModule root_handler(
+ &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline,
+ reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(),
+ reader->GetSourceLineOffset());
+ google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
+ google_breakpad::CompilationUnit split_reader(
+ split_file, file_context.section_map(), cu_offset, &split_byte_reader,
+ &die_dispatcher);
+ split_reader.SetSplitDwarf(reader->GetAddrBase(), reader->GetDWOID());
+ split_reader.Start();
+ // Normally, it won't happen unless we have transitive reference.
+ if (split_reader.ShouldProcessSplitDwarf()) {
+ StartProcessSplitDwarf(&split_reader, module, endianness,
+ handle_inter_cu_refs, handle_inline);
+ }
+}
+
template<typename ElfClass>
bool LoadDwarf(const string& dwarf_filename,
const typename ElfClass::Ehdr* elf_header,
@@ -380,7 +476,7 @@ bool LoadDwarf(const string& dwarf_filename,
size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed =
- UncompressSectionContents(contents, size, chdr.ch_size);
+ UncompressSectionContents(chdr.ch_type, contents, size, chdr.ch_size);
if (uncompressed.first != nullptr && uncompressed.second != 0) {
file_context.AddManagedSectionToSectionMap(name, uncompressed.first, uncompressed.second);
@@ -417,6 +513,11 @@ bool LoadDwarf(const string& dwarf_filename,
&die_dispatcher);
// Process the entire compilation unit; get the offset of the next.
offset += reader.Start();
+ // Start to process split dwarf file.
+ if (reader.ShouldProcessSplitDwarf()) {
+ StartProcessSplitDwarf(&reader, module, endianness, handle_inter_cu_refs,
+ handle_inline);
+ }
}
return true;
}
@@ -445,6 +546,9 @@ bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
case EM_X86_64:
*register_names = DwarfCFIToModule::RegisterNames::X86_64();
return true;
+ case EM_RISCV:
+ *register_names = DwarfCFIToModule::RegisterNames::RISCV();
+ return true;
default:
return false;
}
@@ -522,7 +626,7 @@ bool LoadDwarfCFI(const string& dwarf_filename,
cfi_size -= compression_header_size;
std::pair<uint8_t *, uint64_t> uncompressed =
- UncompressSectionContents(cfi, cfi_size, chdr.ch_size);
+ UncompressSectionContents(chdr.ch_type, cfi, cfi_size, chdr.ch_size);
if (uncompressed.first == nullptr || uncompressed.second == 0) {
fprintf(stderr, "%s: decompression failed\n", dwarf_filename.c_str());
@@ -1018,6 +1122,7 @@ const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
case EM_SPARC: return "sparc";
case EM_SPARCV9: return "sparcv9";
case EM_X86_64: return "x86_64";
+ case EM_RISCV: return "riscv";
default: return NULL;
}
}
diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc
index 97d5827e..55dcdeed 100644
--- a/src/common/linux/dump_symbols_unittest.cc
+++ b/src/common/linux/dump_symbols_unittest.cc
@@ -31,6 +31,10 @@
// dump_symbols_unittest.cc:
// Unittests for google_breakpad::DumpSymbols
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <elf.h>
#include <link.h>
#include <stdio.h>
diff --git a/src/common/linux/elf_core_dump.cc b/src/common/linux/elf_core_dump.cc
index f5ee3033..67257fd2 100644
--- a/src/common/linux/elf_core_dump.cc
+++ b/src/common/linux/elf_core_dump.cc
@@ -29,6 +29,10 @@
// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump.
// See elf_core_dump.h for details.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/elf_core_dump.h"
#include <stddef.h>
diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc
index 6789dd84..25cab99f 100644
--- a/src/common/linux/elf_core_dump_unittest.cc
+++ b/src/common/linux/elf_core_dump_unittest.cc
@@ -28,6 +28,10 @@
// elf_core_dump_unittest.cc: Unit tests for google_breakpad::ElfCoreDump.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <sys/procfs.h>
#include <set>
diff --git a/src/common/linux/elf_symbols_to_module.cc b/src/common/linux/elf_symbols_to_module.cc
index 3c33be99..70d50f89 100644
--- a/src/common/linux/elf_symbols_to_module.cc
+++ b/src/common/linux/elf_symbols_to_module.cc
@@ -30,6 +30,10 @@
// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/elf_symbols_to_module.h"
#include <cxxabi.h>
diff --git a/src/common/linux/elf_symbols_to_module_unittest.cc b/src/common/linux/elf_symbols_to_module_unittest.cc
index 17eb670f..a74b29f0 100644
--- a/src/common/linux/elf_symbols_to_module_unittest.cc
+++ b/src/common/linux/elf_symbols_to_module_unittest.cc
@@ -31,6 +31,10 @@
// elf_symbols_to_module_unittest.cc:
// Unittests for google_breakpad::ELFSymbolsToModule
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <elf.h>
#include <string>
diff --git a/src/common/linux/elfutils.cc b/src/common/linux/elfutils.cc
index a68cc0af..95b5db82 100644
--- a/src/common/linux/elfutils.cc
+++ b/src/common/linux/elfutils.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/elfutils.h"
#include <assert.h>
diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc
index 0bd2a759..d8fcbd8d 100644
--- a/src/common/linux/file_id.cc
+++ b/src/common/linux/file_id.cc
@@ -31,6 +31,10 @@
// See file_id.h for documentation
//
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/file_id.h"
#include <arpa/inet.h>
diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc
index 74bf9e1b..0ef45353 100644
--- a/src/common/linux/file_id_unittest.cc
+++ b/src/common/linux/file_id_unittest.cc
@@ -28,6 +28,10 @@
// Unit tests for FileID
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <elf.h>
#include <spawn.h>
#include <stdlib.h>
diff --git a/src/common/linux/google_crashdump_uploader.cc b/src/common/linux/google_crashdump_uploader.cc
index 6242e6d2..8c5e0492 100644
--- a/src/common/linux/google_crashdump_uploader.cc
+++ b/src/common/linux/google_crashdump_uploader.cc
@@ -27,6 +27,10 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/google_crashdump_uploader.h"
#include <sys/types.h>
diff --git a/src/common/linux/google_crashdump_uploader_test.cc b/src/common/linux/google_crashdump_uploader_test.cc
index 39aab65d..e81f21d6 100644
--- a/src/common/linux/google_crashdump_uploader_test.cc
+++ b/src/common/linux/google_crashdump_uploader_test.cc
@@ -28,6 +28,10 @@
// Unit test for crash dump uploader.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <string>
#include "common/linux/google_crashdump_uploader.h"
diff --git a/src/common/linux/guid_creator.cc b/src/common/linux/guid_creator.cc
index 31a326c7..8635f9dc 100644
--- a/src/common/linux/guid_creator.cc
+++ b/src/common/linux/guid_creator.cc
@@ -27,7 +27,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef HAVE_CONFIG_H
-#include <config.h>
+#include <config.h> // Must come first
#endif
#include "common/linux/eintr_wrapper.h"
diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc
index 1b576ea6..0a5bdb50 100644
--- a/src/common/linux/http_upload.cc
+++ b/src/common/linux/http_upload.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/http_upload.h"
#include <assert.h>
diff --git a/src/common/linux/libcurl_wrapper.cc b/src/common/linux/libcurl_wrapper.cc
index a53087d9..2b639098 100644
--- a/src/common/linux/libcurl_wrapper.cc
+++ b/src/common/linux/libcurl_wrapper.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <dlfcn.h>
#include <iostream>
@@ -303,12 +307,10 @@ bool LibcurlWrapper::SendRequestInner(const string& url,
(*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
}
-#ifndef NDEBUG
if (err_code != CURLE_OK)
fprintf(stderr, "Failed to send http request to %s, error: %s\n",
url.c_str(),
(*easy_strerror_)(err_code));
-#endif
Reset();
diff --git a/src/common/linux/linux_libc_support.cc b/src/common/linux/linux_libc_support.cc
index 10cbeaef..abcbfde8 100644
--- a/src/common/linux/linux_libc_support.cc
+++ b/src/common/linux/linux_libc_support.cc
@@ -30,6 +30,10 @@
// we call the libc functions directly we risk crashing in the dynamic linker
// as it tries to resolve uncached PLT entries.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/linux_libc_support.h"
#include <stddef.h>
diff --git a/src/common/linux/linux_libc_support_unittest.cc b/src/common/linux/linux_libc_support_unittest.cc
index 449f995f..30dd1430 100644
--- a/src/common/linux/linux_libc_support_unittest.cc
+++ b/src/common/linux/linux_libc_support_unittest.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "breakpad_googletest_includes.h"
#include "common/linux/linux_libc_support.h"
diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc
index 7e444607..a7b96eb5 100644
--- a/src/common/linux/memory_mapped_file.cc
+++ b/src/common/linux/memory_mapped_file.cc
@@ -29,6 +29,10 @@
// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile.
// See memory_mapped_file.h for details.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/memory_mapped_file.h"
#include <fcntl.h>
@@ -57,8 +61,11 @@ MemoryMappedFile::~MemoryMappedFile() {
bool MemoryMappedFile::Map(const char* path, size_t offset) {
Unmap();
-
- int fd = sys_open(path, O_RDONLY, 0);
+ // Based on https://pubs.opengroup.org/onlinepubs/7908799/xsh/open.html
+ // If O_NONBLOCK is set: The open() function will return without blocking
+ // for the device to be ready or available. Setting this value will provent
+ // hanging if file is not avilable.
+ int fd = sys_open(path, O_RDONLY | O_NONBLOCK, 0);
if (fd == -1) {
return false;
}
diff --git a/src/common/linux/memory_mapped_file.h b/src/common/linux/memory_mapped_file.h
index d4a85051..462e116e 100644
--- a/src/common/linux/memory_mapped_file.h
+++ b/src/common/linux/memory_mapped_file.h
@@ -33,7 +33,7 @@
#define COMMON_LINUX_MEMORY_MAPPED_FILE_H_
#include <stddef.h>
-#include "common/basictypes.h"
+
#include "common/memory_range.h"
namespace google_breakpad {
@@ -49,6 +49,9 @@ class MemoryMappedFile {
// If Map() fails, the object behaves as if it is default constructed.
MemoryMappedFile(const char* path, size_t offset);
+ MemoryMappedFile(const MemoryMappedFile&) = delete;
+ void operator=(const MemoryMappedFile&) = delete;
+
~MemoryMappedFile();
// Maps a file at |path| into memory, which can then be accessed via
@@ -77,8 +80,6 @@ class MemoryMappedFile {
private:
// Mapped file content as a MemoryRange object.
MemoryRange content_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
};
} // namespace google_breakpad
diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc
index 5ed677df..b7a61a70 100644
--- a/src/common/linux/memory_mapped_file_unittest.cc
+++ b/src/common/linux/memory_mapped_file_unittest.cc
@@ -29,6 +29,10 @@
// memory_mapped_file_unittest.cc:
// Unit tests for google_breakpad::MemoryMappedFile.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
diff --git a/src/common/linux/safe_readlink.cc b/src/common/linux/safe_readlink.cc
index 97ea62c0..a42b01a5 100644
--- a/src/common/linux/safe_readlink.cc
+++ b/src/common/linux/safe_readlink.cc
@@ -29,6 +29,10 @@
// safe_readlink.cc: Implement google_breakpad::SafeReadLink.
// See safe_readlink.h for details.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stddef.h>
#include "third_party/lss/linux_syscall_support.h"
diff --git a/src/common/linux/safe_readlink_unittest.cc b/src/common/linux/safe_readlink_unittest.cc
index 6f5f9d75..8fa6d065 100644
--- a/src/common/linux/safe_readlink_unittest.cc
+++ b/src/common/linux/safe_readlink_unittest.cc
@@ -28,6 +28,10 @@
// safe_readlink_unittest.cc: Unit tests for google_breakpad::SafeReadLink.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "breakpad_googletest_includes.h"
#include "common/linux/safe_readlink.h"
diff --git a/src/common/linux/scoped_pipe.cc b/src/common/linux/scoped_pipe.cc
new file mode 100644
index 00000000..8de04ce9
--- /dev/null
+++ b/src/common/linux/scoped_pipe.cc
@@ -0,0 +1,132 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
+#include "common/linux/scoped_pipe.h"
+
+#include <unistd.h>
+
+#include "common/linux/eintr_wrapper.h"
+
+namespace google_breakpad {
+
+ScopedPipe::ScopedPipe() {
+ fds_[0] = -1;
+ fds_[1] = -1;
+}
+
+ScopedPipe::~ScopedPipe() {
+ CloseReadFd();
+ CloseWriteFd();
+}
+
+bool ScopedPipe::Init() {
+ return pipe(fds_) == 0;
+}
+
+void ScopedPipe::CloseReadFd() {
+ if (fds_[0] != -1) {
+ close(fds_[0]);
+ fds_[0] = -1;
+ }
+}
+
+void ScopedPipe::CloseWriteFd() {
+ if (fds_[1] != -1) {
+ close(fds_[1]);
+ fds_[1] = -1;
+ }
+}
+
+bool ScopedPipe::ReadLine(std::string& line) {
+ // Simple buffered file read. `read_buffer_` stores previously read bytes, and
+ // we either return a line from this buffer, or we append blocks of read bytes
+ // to the buffer until we have a complete line.
+ size_t eol_index = read_buffer_.find('\n');
+
+ // While we don't have a full line, and read pipe is valid.
+ while (eol_index == std::string::npos && GetReadFd() != -1) {
+ // Read a block of 128 bytes from the read pipe.
+ char read_buf[128];
+ ssize_t read_len = HANDLE_EINTR(
+ read(GetReadFd(), read_buf, sizeof(read_buf)));
+ if (read_len <= 0) {
+ // Pipe error, or pipe has been closed.
+ CloseReadFd();
+ break;
+ }
+
+ // Append the block, and check if we have a full line now.
+ read_buffer_.append(read_buf, read_len);
+ eol_index = read_buffer_.find('\n');
+ }
+
+ if (eol_index != std::string::npos) {
+ // We have a full line to output.
+ line = read_buffer_.substr(0, eol_index);
+ if (eol_index < read_buffer_.size()) {
+ read_buffer_ = read_buffer_.substr(eol_index + 1);
+ } else {
+ read_buffer_ = "";
+ }
+
+ return true;
+ }
+
+ if (read_buffer_.size()) {
+ // We don't have a full line to output, but we can only reach here if the
+ // pipe has closed and there are some bytes left at the end, so we should
+ // return those bytes.
+ line = std::move(read_buffer_);
+ read_buffer_ = "";
+
+ return true;
+ }
+
+ // We don't have any buffered data left, and the pipe has closed.
+ return false;
+}
+
+int ScopedPipe::Dup2WriteFd(int new_fd) const {
+ return dup2(fds_[1], new_fd);
+}
+
+bool ScopedPipe::WriteForTesting(const void* bytes, size_t bytes_len) {
+ ssize_t r = HANDLE_EINTR(write(GetWriteFd(), bytes, bytes_len));
+ if (r != static_cast<ssize_t>(bytes_len)) {
+ CloseWriteFd();
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace google_breakpad
diff --git a/src/common/linux/scoped_pipe.h b/src/common/linux/scoped_pipe.h
new file mode 100644
index 00000000..25394c2a
--- /dev/null
+++ b/src/common/linux/scoped_pipe.h
@@ -0,0 +1,115 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef COMMON_LINUX_SCOPED_PIPE_H_
+#define COMMON_LINUX_SCOPED_PIPE_H_
+
+#include <stdint.h>
+#include <string>
+
+namespace google_breakpad {
+
+// Small RAII wrapper for a pipe pair.
+//
+// Example (both ends of pipe in same process):
+// ScopedPipe tmp;
+// std::string line;
+// if (tmp.Init() && tmp.Write(bytes, bytes_len)) {
+// tmp.CloseWriteFd();
+// while (tmp.ReadLine(&line)) {
+// std::cerr << line << std::endl;
+// }
+// }
+//
+// Example (reading output from a child process):
+// ScopedPipe tmp;
+// if (fork()) {
+// // Parent process, read from the read end of the pipe.
+// std::string line;
+// while (tmp.ReadLine(line)) {
+// // Process output...
+// }
+// // Close read pipe once done processing the output that we wanted, this
+// // should ensure that the child process exits even if we didn't read all
+// // of the output.
+// tmp.CloseReadFd();
+// // Parent process should handle waiting for child to exit here...
+// } else {
+// // Child process, close the read fd and dup the write fd before exec'ing.
+// tmp.CloseReadFd();
+// tmp.Dup2WriteFd(STDOUT_FILENO);
+// tmp.Dup2WriteFd(STDERR_FILENO);
+// execl("some-command", "some-arguments");
+// }
+class ScopedPipe {
+ public:
+ ScopedPipe();
+ ~ScopedPipe();
+
+ // Creates the pipe pair - returns false on error.
+ bool Init();
+
+ // Close the read pipe. This only needs to be used when the read pipe needs to
+ // be closed earlier.
+ void CloseReadFd();
+
+ // Close the write pipe. This only needs to be used when the write pipe needs
+ // to be closed earlier.
+ void CloseWriteFd();
+
+ // Reads characters until newline or end of pipe. On read failure this will
+ // close the read pipe, but continue to return true and read buffered lines
+ // until the internal buffering is exhausted. This will block if there is no
+ // data available on the read pipe.
+ bool ReadLine(std::string& line);
+
+ // Writes bytes to the write end of the pipe, returns false and closes write
+ // pipe on failure.
+ bool WriteForTesting(const void* bytes, size_t bytes_len);
+
+ // Calls the dup2 system call to replace any existing open file descriptor
+ // with number new_fd with a copy of the current write end file descriptor
+ // for the pipe.
+ int Dup2WriteFd(int new_fd) const;
+
+ private:
+ int GetReadFd() const {
+ return fds_[0];
+ }
+
+ int GetWriteFd() const {
+ return fds_[1];
+ }
+
+ int fds_[2];
+ std::string read_buffer_;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SCOPED_PIPE_H_
diff --git a/src/common/linux/scoped_pipe_unittest.cc b/src/common/linux/scoped_pipe_unittest.cc
new file mode 100644
index 00000000..4daa5c25
--- /dev/null
+++ b/src/common/linux/scoped_pipe_unittest.cc
@@ -0,0 +1,75 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// scoped_pipe_unittest.cc: Unit tests for google_breakpad::ScopedPipe.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
+#include "common/linux/scoped_pipe.h"
+
+#include "breakpad_googletest_includes.h"
+
+namespace google_breakpad {
+
+TEST(ScopedPipeTest, WriteAndClose) {
+ const char kTestData[] = "One\nTwo\nThree";
+ ScopedPipe pipe;
+ std::string line;
+
+ ASSERT_TRUE(pipe.Init());
+ ASSERT_TRUE(pipe.WriteForTesting(kTestData, strlen(kTestData)));
+ pipe.CloseWriteFd();
+
+ ASSERT_TRUE(pipe.ReadLine(line));
+ ASSERT_EQ(line, "One");
+ ASSERT_TRUE(pipe.ReadLine(line));
+ ASSERT_EQ(line, "Two");
+ ASSERT_TRUE(pipe.ReadLine(line));
+ ASSERT_EQ(line, "Three");
+ ASSERT_FALSE(pipe.ReadLine(line));
+}
+
+TEST(ScopedPipeTest, MultipleWrites) {
+ const char kTestDataOne[] = "One\n";
+ const char kTestDataTwo[] = "Two\n";
+ ScopedPipe pipe;
+ std::string line;
+
+ ASSERT_TRUE(pipe.Init());
+ ASSERT_TRUE(pipe.WriteForTesting(kTestDataOne, strlen(kTestDataOne)));
+ ASSERT_TRUE(pipe.ReadLine(line));
+ ASSERT_EQ(line, "One");
+
+ ASSERT_TRUE(pipe.WriteForTesting(kTestDataTwo, strlen(kTestDataTwo)));
+ ASSERT_TRUE(pipe.ReadLine(line));
+ ASSERT_EQ(line, "Two");
+}
+
+} // namespace google_breakpad
diff --git a/src/common/linux/scoped_tmpfile.cc b/src/common/linux/scoped_tmpfile.cc
new file mode 100644
index 00000000..2395a64e
--- /dev/null
+++ b/src/common/linux/scoped_tmpfile.cc
@@ -0,0 +1,103 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility class for creating a temporary file that is deleted in the
+// destructor.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
+#include "common/linux/scoped_tmpfile.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "common/linux/eintr_wrapper.h"
+
+#if !defined(__ANDROID__)
+#define TEMPDIR "/tmp"
+#else
+#define TEMPDIR "/data/local/tmp"
+#endif
+
+namespace google_breakpad {
+
+ScopedTmpFile::ScopedTmpFile() = default;
+
+ScopedTmpFile::~ScopedTmpFile() {
+ if (fd_ >= 0) {
+ close(fd_);
+ fd_ = -1;
+ }
+}
+
+bool ScopedTmpFile::InitEmpty() {
+ // Prevent calling Init when fd_ is already valid, leaking the file.
+ if (fd_ != -1) {
+ return false;
+ }
+
+ // Respect the TMPDIR environment variable.
+ const char* tempdir = getenv("TMPDIR");
+ if (!tempdir) {
+ tempdir = TEMPDIR;
+ }
+
+ // Create a temporary file that is not linked in to the filesystem, and that
+ // is only accessible by the current user.
+ fd_ = open(tempdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
+
+ return fd_ >= 0;
+}
+
+bool ScopedTmpFile::InitString(const char* text) {
+ return InitData(text, strlen(text));
+}
+
+bool ScopedTmpFile::InitData(const void* data, size_t data_len) {
+ if (!InitEmpty()) {
+ return false;
+ }
+
+ return SetContents(data, data_len);
+}
+
+bool ScopedTmpFile::SetContents(const void* data, size_t data_len) {
+ ssize_t r = HANDLE_EINTR(write(fd_, data, data_len));
+ if (r != static_cast<ssize_t>(data_len)) {
+ return false;
+ }
+
+ return 0 == lseek(fd_, 0, SEEK_SET);
+}
+
+} // namespace google_breakpad
diff --git a/src/common/linux/scoped_tmpfile.h b/src/common/linux/scoped_tmpfile.h
new file mode 100644
index 00000000..dffec182
--- /dev/null
+++ b/src/common/linux/scoped_tmpfile.h
@@ -0,0 +1,85 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility class for creating a temporary file for that is deleted in the
+// destructor.
+
+#ifndef COMMON_LINUX_SCOPED_TMPFILE_H_
+#define COMMON_LINUX_SCOPED_TMPFILE_H_
+
+#include <string>
+
+namespace google_breakpad {
+
+// Small RAII wrapper for temporary files.
+//
+// Example:
+// ScopedTmpFile tmp;
+// if (tmp.Init("Some file contents")) {
+// ...
+// }
+class ScopedTmpFile {
+ public:
+ // Initialize the ScopedTmpFile object - this does not create the temporary
+ // file until Init is called.
+ ScopedTmpFile();
+
+ // Destroy temporary file on scope exit.
+ ~ScopedTmpFile();
+
+ // Creates the empty temporary file - returns true iff the temporary file was
+ // created successfully. Should always be checked before using the file.
+ bool InitEmpty();
+
+ // Creates the temporary file with the provided C string. The terminating null
+ // is not written. Returns true iff the temporary file was created
+ // successfully and the contents were written successfully.
+ bool InitString(const char* text);
+
+ // Creates the temporary file with the provided data. Returns true iff the
+ // temporary file was created successfully and the contents were written
+ // successfully.
+ bool InitData(const void* data, size_t data_len);
+
+ // Returns the Posix file descriptor for the test file, or -1 if Init()
+ // returned false. Note: on Windows, this always returns -1.
+ int GetFd() const {
+ return fd_;
+ }
+
+ private:
+ // Set the contents of the temporary file, and seek back to the start of the
+ // file. On failure, returns false.
+ bool SetContents(const void* data, size_t data_len);
+
+ int fd_ = -1;
+};
+
+} // namespace google_breakpad
+
+#endif // COMMON_LINUX_SCOPED_TMPFILE_H_
diff --git a/src/common/linux/scoped_tmpfile_unittest.cc b/src/common/linux/scoped_tmpfile_unittest.cc
new file mode 100644
index 00000000..f0bb2bbb
--- /dev/null
+++ b/src/common/linux/scoped_tmpfile_unittest.cc
@@ -0,0 +1,50 @@
+// Copyright 2022 Google LLC
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// scoped_tmpfile_unittest.cc: Unit tests for google_breakpad::ScopedTmpfile.
+
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
+#include "common/linux/scoped_tmpfile.h"
+
+#include <unistd.h>
+
+#include "breakpad_googletest_includes.h"
+
+using google_breakpad::ScopedTmpFile;
+
+TEST(ScopedTmpFileTest, CheckContentsMatch) {
+ ScopedTmpFile file;
+ ASSERT_TRUE(file.InitString("Test"));
+
+ char file_contents[5] = {0};
+ ASSERT_EQ(4, read(file.GetFd(), file_contents, sizeof(file_contents)));
+ EXPECT_STREQ(file_contents, "Test");
+}
diff --git a/src/common/linux/symbol_collector_client.cc b/src/common/linux/symbol_collector_client.cc
index 1c1dc97a..e9a1893c 100644
--- a/src/common/linux/symbol_collector_client.cc
+++ b/src/common/linux/symbol_collector_client.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/symbol_collector_client.h"
#include <stdio.h>
diff --git a/src/common/linux/symbol_upload.cc b/src/common/linux/symbol_upload.cc
index c080533a..8ab143c6 100644
--- a/src/common/linux/symbol_upload.cc
+++ b/src/common/linux/symbol_upload.cc
@@ -29,6 +29,10 @@
// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper
// function for linux symbol upload tool.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/symbol_upload.h"
#include <assert.h>
diff --git a/src/common/linux/synth_elf.cc b/src/common/linux/synth_elf.cc
index 2ba25e61..8e9170e7 100644
--- a/src/common/linux/synth_elf.cc
+++ b/src/common/linux/synth_elf.cc
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/synth_elf.h"
#include <assert.h>
diff --git a/src/common/linux/synth_elf_unittest.cc b/src/common/linux/synth_elf_unittest.cc
index 44ef6ef3..578f6a26 100644
--- a/src/common/linux/synth_elf_unittest.cc
+++ b/src/common/linux/synth_elf_unittest.cc
@@ -31,6 +31,10 @@
// synth_elf_unittest.cc:
// Unittests for google_breakpad::synth_elf::ELF
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <elf.h>
#include "breakpad_googletest_includes.h"
diff --git a/src/common/linux/tests/auto_testfile.h b/src/common/linux/tests/auto_testfile.h
deleted file mode 100644
index e2d2ff23..00000000
--- a/src/common/linux/tests/auto_testfile.h
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2013 Google LLC
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google LLC nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Utility class for creating a temporary file for unit tests
-// that is deleted in the destructor.
-
-#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
-#define GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/eintr_wrapper.h"
-#include "common/tests/auto_tempdir.h"
-
-namespace google_breakpad {
-
-class AutoTestFile {
- public:
- // Create a new empty test file.
- // test_prefix: (input) test-specific prefix, can't be NULL.
- explicit AutoTestFile(const char* test_prefix) {
- Init(test_prefix);
- }
-
- // Create a new test file, and fill it with initial data from a C string.
- // The terminating zero is not written.
- // test_prefix: (input) test-specific prefix, can't be NULL.
- // text: (input) initial content.
- AutoTestFile(const char* test_prefix, const char* text) {
- Init(test_prefix);
- if (fd_ >= 0)
- WriteText(text, static_cast<size_t>(strlen(text)));
- }
-
- AutoTestFile(const char* test_prefix, const char* text, size_t text_len) {
- Init(test_prefix);
- if (fd_ >= 0)
- WriteText(text, text_len);
- }
-
- // Destroy test file on scope exit.
- ~AutoTestFile() {
- if (fd_ >= 0) {
- close(fd_);
- fd_ = -1;
- }
- }
-
- // Returns true iff the test file could be created properly.
- // Useful in tests inside EXPECT_TRUE(file.IsOk());
- bool IsOk() {
- return fd_ >= 0;
- }
-
- // Returns the Posix file descriptor for the test file, or -1
- // If IsOk() returns false. Note: on Windows, this always returns -1.
- int GetFd() {
- return fd_;
- }
-
- private:
- void Init(const char* test_prefix) {
- fd_ = -1;
- char path_templ[PATH_MAX];
- int ret = snprintf(path_templ, sizeof(path_templ),
- TEMPDIR "/%s-unittest.XXXXXX",
- test_prefix);
- if (ret >= static_cast<int>(sizeof(path_templ)))
- return;
-
- fd_ = mkstemp(path_templ);
- if (fd_ < 0)
- return;
-
- unlink(path_templ);
- }
-
- void WriteText(const char* text, size_t text_len) {
- ssize_t r = HANDLE_EINTR(write(fd_, text, text_len));
- if (r != static_cast<ssize_t>(text_len)) {
- close(fd_);
- fd_ = -1;
- return;
- }
-
- lseek(fd_, 0, SEEK_SET);
- }
-
- int fd_;
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
diff --git a/src/common/linux/tests/crash_generator.cc b/src/common/linux/tests/crash_generator.cc
index 0db0c4a2..1cad9ae2 100644
--- a/src/common/linux/tests/crash_generator.cc
+++ b/src/common/linux/tests/crash_generator.cc
@@ -29,6 +29,10 @@
// crash_generator.cc: Implement google_breakpad::CrashGenerator.
// See crash_generator.h for details.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/linux/tests/crash_generator.h"
#include <pthread.h>