Move dead submodules in-tree

Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
swurl 2025-05-31 02:33:02 -04:00
parent c0cceff365
commit 6c655321e6
No known key found for this signature in database
GPG key ID: A5A7629F109C8FD1
4081 changed files with 1185566 additions and 45 deletions

View file

@ -0,0 +1,77 @@
// Copyright 2012 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.
// core2md.cc: A utility to convert an ELF core file to a minidump file.
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include <stdio.h>
#include "client/linux/minidump_writer/minidump_writer.h"
#include "client/linux/minidump_writer/linux_core_dumper.h"
#include "common/path_helper.h"
using google_breakpad::AppMemoryList;
using google_breakpad::MappingList;
using google_breakpad::LinuxCoreDumper;
static int ShowUsage(const char* argv0) {
fprintf(stderr, "Usage: %s <core file> <procfs dir> <output>\n",
google_breakpad::BaseName(argv0).c_str());
return 1;
}
bool WriteMinidumpFromCore(const char* filename,
const char* core_path,
const char* procfs_override) {
MappingList mappings;
AppMemoryList memory_list;
LinuxCoreDumper dumper(0, core_path, procfs_override);
return google_breakpad::WriteMinidump(filename, mappings, memory_list,
&dumper);
}
int main(int argc, char *argv[]) {
if (argc != 4) {
return ShowUsage(argv[0]);
}
const char* core_file = argv[1];
const char* procfs_dir = argv[2];
const char* minidump_file = argv[3];
if (!WriteMinidumpFromCore(minidump_file,
core_file,
procfs_dir)) {
perror("core2md: Unable to generate minidump");
return 1;
}
return 0;
}

View file

@ -0,0 +1,151 @@
// Copyright 2020 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.
// core_handler.cc: A tool to handle coredumps on Linux
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
#include <sstream>
#include "client/linux/minidump_writer/linux_core_dumper.h"
#include "client/linux/minidump_writer/minidump_writer.h"
#include "common/path_helper.h"
#include "common/scoped_ptr.h"
namespace {
using google_breakpad::AppMemoryList;
using google_breakpad::LinuxCoreDumper;
using google_breakpad::MappingList;
using google_breakpad::scoped_array;
// Size of the core dump to read in order to access all the threads
// descriptions.
//
// The first section is the note0 section which contains the thread states. On
// x86-64 a typical thread description take about 1432B. Reading 1 MB allows
// several hundreds of threads.
const int core_read_size = 1024 * 1024;
void ShowUsage(const char* argv0) {
fprintf(stderr, "Usage: %s <process id> <minidump file>\n\n",
google_breakpad::BaseName(argv0).c_str());
fprintf(stderr,
"A tool which serves as a core dump handler and produces "
"minidump files.\n");
fprintf(stderr, "Please refer to the online documentation:\n");
fprintf(stderr,
"https://chromium.googlesource.com/breakpad/breakpad/+/HEAD"
"/docs/linux_core_handler.md\n");
}
bool WriteMinidumpFromCore(const char* filename,
const char* core_path,
const char* procfs_override) {
MappingList mappings;
AppMemoryList memory_list;
LinuxCoreDumper dumper(0, core_path, procfs_override);
return google_breakpad::WriteMinidump(filename, mappings, memory_list,
&dumper);
}
bool HandleCrash(pid_t pid, const char* procfs_dir, const char* md_filename) {
int r = 0;
scoped_array<char> buf(new char[core_read_size]);
while (r != core_read_size) {
int ret = read(STDIN_FILENO, &buf[r], core_read_size - r);
if (ret == 0) {
break;
} else if (ret == -1) {
return false;
}
r += ret;
}
int fd = memfd_create("core_file", MFD_CLOEXEC);
if (fd == -1) {
return false;
}
int w = write(fd, &buf[0], r);
if (w != r) {
close(fd);
return false;
}
std::stringstream core_file_ss;
core_file_ss << "/proc/self/fd/" << fd;
std::string core_file(core_file_ss.str());
if (!WriteMinidumpFromCore(md_filename, core_file.c_str(), procfs_dir)) {
close(fd);
return false;
}
close(fd);
return true;
}
} // namespace
int main(int argc, char* argv[]) {
int ret = EXIT_FAILURE;
if (argc != 3) {
ShowUsage(argv[0]);
return ret;
}
const char* pid_str = argv[1];
const char* md_filename = argv[2];
pid_t pid = atoi(pid_str);
std::stringstream proc_dir_ss;
proc_dir_ss << "/proc/" << pid_str;
std::string proc_dir(proc_dir_ss.str());
openlog("core_handler", 0, 0);
if (HandleCrash(pid, proc_dir.c_str(), md_filename)) {
syslog(LOG_NOTICE, "Minidump generated at %s\n", md_filename);
ret = EXIT_SUCCESS;
} else {
syslog(LOG_ERR, "Cannot generate minidump %s\n", md_filename);
}
closelog();
return ret;
}

View file

@ -0,0 +1,155 @@
// Copyright 2011 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 <paths.h>
#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include "common/linux/dump_symbols.h"
#include "common/path_helper.h"
using google_breakpad::WriteSymbolFile;
using google_breakpad::WriteSymbolFileHeader;
int usage(const char* self) {
fprintf(stderr,
"Usage: %s [OPTION] <binary-with-debugging-info> "
"[directories-for-debug-file]\n\n",
google_breakpad::BaseName(self).c_str());
fprintf(stderr, "Options:\n");
fprintf(stderr, " -i: Output module header information only.\n");
fprintf(stderr, " -c Do not generate CFI section\n");
fprintf(stderr, " -d Generate INLINE/INLINE_ORIGIN records\n");
fprintf(stderr, " -r Do not handle inter-compilation "
"unit references\n");
fprintf(stderr, " -v Print all warnings to stderr\n");
fprintf(stderr, " -n <name> Use specified name for name of the object\n");
fprintf(stderr, " -o <os> Use specified name for the "
"operating system\n");
fprintf(stderr, " -m Enable writing the optional 'm' field on FUNC "
"and PUBLIC, denoting multiple symbols for "
"the address.\n");
return 1;
}
int main(int argc, char** argv) {
if (argc < 2)
return usage(argv[0]);
bool header_only = false;
bool cfi = true;
bool handle_inlines = false;
bool handle_inter_cu_refs = true;
bool log_to_stderr = false;
bool enable_multiple_field = false;
std::string obj_name;
const char* obj_os = "Linux";
int arg_index = 1;
while (arg_index < argc && strlen(argv[arg_index]) > 0 &&
argv[arg_index][0] == '-') {
if (strcmp("-i", argv[arg_index]) == 0) {
header_only = true;
} else if (strcmp("-c", argv[arg_index]) == 0) {
cfi = false;
} else if (strcmp("-d", argv[arg_index]) == 0) {
handle_inlines = true;
} else if (strcmp("-r", argv[arg_index]) == 0) {
handle_inter_cu_refs = false;
} else if (strcmp("-v", argv[arg_index]) == 0) {
log_to_stderr = true;
} else if (strcmp("-n", argv[arg_index]) == 0) {
if (arg_index + 1 >= argc) {
fprintf(stderr, "Missing argument to -n\n");
return usage(argv[0]);
}
obj_name = argv[arg_index + 1];
++arg_index;
} else if (strcmp("-o", argv[arg_index]) == 0) {
if (arg_index + 1 >= argc) {
fprintf(stderr, "Missing argument to -o\n");
return usage(argv[0]);
}
obj_os = argv[arg_index + 1];
++arg_index;
} else if (strcmp("-m", argv[arg_index]) == 0) {
enable_multiple_field = true;
} else {
printf("2.4 %s\n", argv[arg_index]);
return usage(argv[0]);
}
++arg_index;
}
if (arg_index == argc)
return usage(argv[0]);
// Save stderr so it can be used below.
FILE* saved_stderr = fdopen(dup(fileno(stderr)), "w");
if (!log_to_stderr) {
if (freopen(_PATH_DEVNULL, "w", stderr)) {
// If it fails, not a lot we can (or should) do.
// Add this brace section to silence gcc warnings.
}
}
const char* binary;
std::vector<string> debug_dirs;
binary = argv[arg_index];
for (int debug_dir_index = arg_index + 1;
debug_dir_index < argc;
++debug_dir_index) {
debug_dirs.push_back(argv[debug_dir_index]);
}
if (obj_name.empty())
obj_name = binary;
if (header_only) {
if (!WriteSymbolFileHeader(binary, obj_name, obj_os, std::cout)) {
fprintf(saved_stderr, "Failed to process file.\n");
return 1;
}
} else {
SymbolData symbol_data = (handle_inlines ? INLINES : NO_DATA) |
(cfi ? CFI : NO_DATA) | SYMBOLS_AND_FILES;
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs,
enable_multiple_field);
if (!WriteSymbolFile(binary, obj_name, obj_os, debug_dirs, options,
std::cout)) {
fprintf(saved_stderr, "Failed to write symbol file.\n");
return 1;
}
}
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,88 @@
// Copyright 2011 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.
// minidump_memory_range.h: Define the google_breakpad::MinidumpMemoryRange
// class, which adds methods for handling minidump specific data structures
// on top of google_breakpad::MemoryRange. See common/memory_range.h for
// more details on MemoryRange.
#ifndef TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
#define TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_
#include <string>
#include "common/memory_range.h"
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
// A derived class of MemoryRange with added methods for handling minidump
// specific data structures. To avoid virtual functions, it is not designed
// to be used polymorphically.
class MinidumpMemoryRange : public MemoryRange {
public:
MinidumpMemoryRange() {}
MinidumpMemoryRange(const void* data, size_t length)
: MemoryRange(data, length) {}
// Returns a subrange of |length| bytes at |offset| bytes of this memory
// range, or an empty range if the subrange is out of bounds.
// This methods overrides the base implemementation in order to return
// an instance of MinidumpMemoryRange instead of MemoryRange.
MinidumpMemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
if (Covers(sub_offset, sub_length))
return MinidumpMemoryRange(data() + sub_offset, sub_length);
return MinidumpMemoryRange();
}
// Returns a subrange that covers the offset and length specified by
// |location|, or an empty range if the subrange is out of bounds.
MinidumpMemoryRange Subrange(const MDLocationDescriptor& location) const {
return MinidumpMemoryRange::Subrange(location.rva, location.data_size);
}
// Gets a STL string from a MDString at |sub_offset| bytes of this memory
// range. This method only works correctly for ASCII characters and does
// not convert between UTF-16 and UTF-8.
const std::string GetAsciiMDString(size_t sub_offset) const {
std::string str;
const MDString* md_str = GetData<MDString>(sub_offset);
if (md_str) {
const uint16_t* buffer = &md_str->buffer[0];
for (uint32_t i = 0; i < md_str->length && buffer[i]; ++i) {
str.push_back(buffer[i]);
}
}
return str;
}
};
} // namespace google_breakpad
#endif // TOOLS_LINUX_MD2CORE_MINIDUMP_MEMORY_RANGE_H_

View file

@ -0,0 +1,261 @@
// Copyright 2011 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.
// minidump_memory_range_unittest.cc:
// Unit tests for google_breakpad::MinidumpMemoryRange.
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include "breakpad_googletest_includes.h"
#include "tools/linux/md2core/minidump_memory_range.h"
using google_breakpad::MinidumpMemoryRange;
using testing::Message;
namespace {
const uint32_t kBuffer[10] = { 0 };
const size_t kBufferSize = sizeof(kBuffer);
const uint8_t* kBufferPointer = reinterpret_cast<const uint8_t*>(kBuffer);
// Test vectors for verifying Covers, GetData, and Subrange.
const struct {
bool valid;
size_t offset;
size_t length;
} kSubranges[] = {
{ true, 0, 0 },
{ true, 0, 2 },
{ true, 0, kBufferSize },
{ true, 2, 0 },
{ true, 2, 4 },
{ true, 2, kBufferSize - 2 },
{ true, kBufferSize - 1, 1 },
{ false, kBufferSize, 0 },
{ false, kBufferSize, static_cast<size_t>(-1) },
{ false, kBufferSize + 1, 0 },
{ false, static_cast<size_t>(-1), 2 },
{ false, 1, kBufferSize },
{ false, kBufferSize - 1, 2 },
{ false, 0, static_cast<size_t>(-1) },
{ false, 1, static_cast<size_t>(-1) },
};
const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]);
// Test vectors for verifying GetArrayElement.
const struct {
size_t offset;
size_t size;
size_t index;
const void* const pointer;
} kElements[] = {
// Valid array elemenets
{ 0, 1, 0, kBufferPointer },
{ 0, 1, 1, kBufferPointer + 1 },
{ 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 },
{ 0, 2, 1, kBufferPointer + 2 },
{ 0, 4, 2, kBufferPointer + 8 },
{ 0, 4, 9, kBufferPointer + 36 },
{ kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 },
// Invalid array elemenets
{ 0, 1, kBufferSize, NULL },
{ 0, 4, 10, NULL },
{ kBufferSize - 1, 1, 1, NULL },
{ kBufferSize - 1, 2, 0, NULL },
{ kBufferSize, 1, 0, NULL },
};
const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]);
} // namespace
TEST(MinidumpMemoryRangeTest, DefaultConstructor) {
MinidumpMemoryRange range;
EXPECT_EQ(NULL, range.data());
EXPECT_EQ(0U, range.length());
}
TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
EXPECT_EQ(kBufferPointer, range.data());
EXPECT_EQ(kBufferSize, range.length());
}
TEST(MinidumpMemoryRangeTest, Reset) {
MinidumpMemoryRange range;
range.Reset();
EXPECT_EQ(NULL, range.data());
EXPECT_EQ(0U, range.length());
range.Set(kBuffer, kBufferSize);
EXPECT_EQ(kBufferPointer, range.data());
EXPECT_EQ(kBufferSize, range.length());
range.Reset();
EXPECT_EQ(NULL, range.data());
EXPECT_EQ(0U, range.length());
}
TEST(MinidumpMemoryRangeTest, Set) {
MinidumpMemoryRange range;
range.Set(kBuffer, kBufferSize);
EXPECT_EQ(kBufferPointer, range.data());
EXPECT_EQ(kBufferSize, range.length());
range.Set(NULL, 0);
EXPECT_EQ(NULL, range.data());
EXPECT_EQ(0U, range.length());
}
TEST(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) {
MinidumpMemoryRange range;
MinidumpMemoryRange subrange = range.Subrange(0, 10);
EXPECT_EQ(NULL, subrange.data());
EXPECT_EQ(0U, subrange.length());
}
TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
for (size_t i = 0; i < kNumSubranges; ++i) {
bool valid = kSubranges[i].valid;
size_t sub_offset = kSubranges[i].offset;
size_t sub_length = kSubranges[i].length;
SCOPED_TRACE(Message() << "offset=" << sub_offset
<< ", length=" << sub_length);
MinidumpMemoryRange subrange = range.Subrange(sub_offset, sub_length);
if (valid) {
EXPECT_TRUE(range.Covers(sub_offset, sub_length));
EXPECT_EQ(kBufferPointer + sub_offset,
range.GetData(sub_offset, sub_length));
EXPECT_EQ(kBufferPointer + sub_offset, subrange.data());
EXPECT_EQ(sub_length, subrange.length());
} else {
EXPECT_FALSE(range.Covers(sub_offset, sub_length));
EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length));
EXPECT_EQ(NULL, subrange.data());
EXPECT_EQ(0U, subrange.length());
}
}
}
TEST(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
for (size_t i = 0; i < kNumSubranges; ++i) {
bool valid = kSubranges[i].valid;
size_t sub_offset = kSubranges[i].offset;
size_t sub_length = kSubranges[i].length;
SCOPED_TRACE(Message() << "offset=" << sub_offset
<< ", length=" << sub_length);
MDLocationDescriptor location;
location.rva = sub_offset;
location.data_size = sub_length;
MinidumpMemoryRange subrange = range.Subrange(location);
if (valid) {
EXPECT_TRUE(range.Covers(sub_offset, sub_length));
EXPECT_EQ(kBufferPointer + sub_offset,
range.GetData(sub_offset, sub_length));
EXPECT_EQ(kBufferPointer + sub_offset, subrange.data());
EXPECT_EQ(sub_length, subrange.length());
} else {
EXPECT_FALSE(range.Covers(sub_offset, sub_length));
EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length));
EXPECT_EQ(NULL, subrange.data());
EXPECT_EQ(0U, subrange.length());
}
}
}
TEST(MinidumpMemoryRangeTest, GetDataWithTemplateType) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
const char* char_pointer = range.GetData<char>(0);
EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
const int* int_pointer = range.GetData<int>(0);
EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
}
TEST(MinidumpMemoryRangeTest, GetArrayElement) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
for (size_t i = 0; i < kNumElements; ++i) {
size_t element_offset = kElements[i].offset;
size_t element_size = kElements[i].size;
unsigned element_index = kElements[i].index;
const void* const element_pointer = kElements[i].pointer;
SCOPED_TRACE(Message() << "offset=" << element_offset
<< ", size=" << element_size
<< ", index=" << element_index);
EXPECT_EQ(element_pointer, range.GetArrayElement(
element_offset, element_size, element_index));
}
}
TEST(MinidumpMemoryRangeTest, GetArrayElmentWithTemplateType) {
MinidumpMemoryRange range(kBuffer, kBufferSize);
const char* char_pointer = range.GetArrayElement<char>(0, 0);
EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
const int* int_pointer = range.GetArrayElement<int>(0, 0);
EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
}
TEST(MinidumpMemoryRangeTest, GetAsciiMDString) {
uint8_t buffer[100] = { 0 };
MDString* md_str = reinterpret_cast<MDString*>(buffer);
md_str->length = 4;
md_str->buffer[0] = 'T';
md_str->buffer[1] = 'e';
md_str->buffer[2] = 's';
md_str->buffer[3] = 't';
md_str->buffer[4] = '\0';
size_t str2_offset =
sizeof(MDString) + (md_str->length + 1) * sizeof(uint16_t);
md_str = reinterpret_cast<MDString*>(buffer + str2_offset);
md_str->length = 9; // Test length larger than actual string
md_str->buffer[0] = 'S';
md_str->buffer[1] = 't';
md_str->buffer[2] = 'r';
md_str->buffer[3] = 'i';
md_str->buffer[4] = 'n';
md_str->buffer[5] = 'g';
md_str->buffer[6] = '\0';
md_str->buffer[7] = '1';
md_str->buffer[8] = '2';
MinidumpMemoryRange range(buffer, sizeof(buffer));
EXPECT_EQ("Test", range.GetAsciiMDString(0));
EXPECT_EQ("String", range.GetAsciiMDString(str2_offset));
// Test out-of-bounds cases.
EXPECT_EQ("", range.GetAsciiMDString(
sizeof(buffer) - sizeof(MDString) + 1));
EXPECT_EQ("", range.GetAsciiMDString(sizeof(buffer)));
}

View file

@ -0,0 +1,62 @@
// Copyright 2020 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.
// pid2md.cc: An utility to generate a minidump from a running process
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "client/linux/minidump_writer/minidump_writer.h"
#include "common/path_helper.h"
int main(int argc, char* argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s <process id> <minidump file>\n\n",
google_breakpad::BaseName(argv[0]).c_str());
fprintf(stderr,
"A tool to generate a minidump from a running process. The process "
"resumes its\nactivity once the operation is completed. Permission "
"to trace the process is\nrequired.\n");
return EXIT_FAILURE;
}
pid_t process_id = atoi(argv[1]);
const char* minidump_file = argv[2];
if (!google_breakpad::WriteMinidump(minidump_file, process_id, process_id)) {
fprintf(stderr, "Unable to generate minidump.\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,159 @@
// Copyright 2006 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.
// minidump_upload.cc: Upload a minidump to a HTTP server.
// The upload is sent as a multipart/form-data POST request with
// the following parameters:
// prod: the product name
// ver: the product version
// symbol_file: the breakpad format symbol file
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include "common/linux/http_upload.h"
#include "common/path_helper.h"
#include "common/using_std_string.h"
using google_breakpad::HTTPUpload;
struct Options {
string minidumpPath;
string uploadURLStr;
string product;
string version;
string proxy;
string proxy_user_pwd;
bool success;
};
//=============================================================================
static void Start(Options *options) {
std::map<string, string> parameters;
// Add parameters
parameters["prod"] = options->product;
parameters["ver"] = options->version;
std::map<string, string> files;
files["upload_file_minidump"] = options->minidumpPath;
// Send it
string response, error;
bool success = HTTPUpload::SendRequest(options->uploadURLStr,
parameters,
files,
options->proxy,
options->proxy_user_pwd,
"",
&response,
NULL,
&error);
if (success) {
printf("Successfully sent the minidump file.\n");
} else {
printf("Failed to send minidump: %s\n", error.c_str());
}
printf("Response:\n");
printf("%s\n", response.c_str());
options->success = success;
}
//=============================================================================
static void
Usage(int argc, const char *argv[]) {
fprintf(stderr, "Submit minidump information.\n");
fprintf(stderr,
"Usage: %s [options...] -p <product> -v <version> <minidump> "
"<upload-URL>\n",
google_breakpad::BaseName(argv[0]).c_str());
fprintf(stderr, "Options:\n");
fprintf(stderr, "<minidump> should be a minidump.\n");
fprintf(stderr, "<upload-URL> is the destination for the upload\n");
fprintf(stderr, "-p:\t <product> Product name\n");
fprintf(stderr, "-v:\t <version> Product version\n");
fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n");
fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n");
fprintf(stderr, "-h:\t Usage\n");
fprintf(stderr, "-?:\t Usage\n");
}
//=============================================================================
static void
SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind;
int ch;
while ((ch = getopt(argc, (char * const*)argv, "p:u:v:x:h?")) != -1) {
switch (ch) {
case 'p':
options->product = optarg;
break;
case 'u':
options->proxy_user_pwd = optarg;
break;
case 'v':
options->version = optarg;
break;
case 'x':
options->proxy = optarg;
break;
default:
fprintf(stderr, "Invalid option '%c'\n", ch);
Usage(argc, argv);
exit(1);
break;
}
}
if ((argc - optind) != 2) {
fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
Usage(argc, argv);
exit(1);
}
options->minidumpPath = argv[optind];
options->uploadURLStr = argv[optind + 1];
}
//=============================================================================
int main(int argc, const char* argv[]) {
Options options;
SetupOptions(argc, argv, &options);
Start(&options);
return options.success ? 0 : 1;
}

View file

@ -0,0 +1,217 @@
// Copyright 2006 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.
// symupload.cc: Upload a symbol file to a HTTP server. The upload is sent as
// a multipart/form-data POST request with the following parameters:
// code_file: the basename of the module, e.g. "app"
// debug_file: the basename of the debugging file, e.g. "app"
// debug_identifier: the debug file's identifier, usually consisting of
// the guid and age embedded in the pdb, e.g.
// "11111111BBBB3333DDDD555555555555F"
// version: the file version of the module, e.g. "1.2.3.4"
// os: the operating system that the module was built for
// cpu: the CPU that the module was built for
// symbol_file: the contents of the breakpad-format symbol file
#ifdef HAVE_CONFIG_H
#include <config.h> // Must come first
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <locale>
#include "common/linux/symbol_upload.h"
#include "common/path_helper.h"
using google_breakpad::sym_upload::UploadProtocol;
using google_breakpad::sym_upload::Options;
static void StrToUpper(std::string* str) {
if (str == nullptr) {
fprintf(stderr, "nullptr passed to StrToUpper.\n");
exit(1);
}
for (size_t i = 0; i < str->length(); i++) {
(*str)[i] = std::toupper((*str)[i], std::locale::classic());
}
}
//=============================================================================
static void
Usage(int argc, const char *argv[]) {
fprintf(stderr, "Submit symbol information.\n");
fprintf(stderr, "Usage: %s [options...] <symbol-file> <upload-URL>\n",
google_breakpad::BaseName(argv[0]).c_str());
fprintf(stderr, "Options:\n");
fprintf(stderr,
"<symbol-file> should be created by using the dump_syms "
"tool.\n");
fprintf(stderr, "<upload-URL> is the destination for the upload\n");
fprintf(stderr, "-p:\t <protocol> One of ['sym-upload-v1',"
" 'sym-upload-v2'], defaults to 'sym-upload-v1'.\n");
fprintf(stderr, "-v:\t Version information (e.g., 1.2.3.4)\n");
fprintf(stderr, "-x:\t <host[:port]> Use HTTP proxy on given port\n");
fprintf(stderr, "-u:\t <user[:password]> Set proxy user and password\n");
fprintf(stderr, "-h:\t Usage\n");
fprintf(stderr, "-?:\t Usage\n");
fprintf(stderr, "\n");
fprintf(stderr, "These options only work with 'sym-upload-v2' protocol:\n");
fprintf(stderr, "-k:\t <API-key> A secret used to authenticate with the"
" API.\n");
fprintf(stderr, "-f:\t Force symbol upload if already exists.\n");
fprintf(stderr, "-t:\t <symbol-type> Explicitly set symbol upload type ("
"default is 'breakpad').\n"
"\t One of ['breakpad', 'elf', 'pe', 'macho', 'debug_only', 'dwp', "
"'dsym', 'pdb'].\n"
"\t Note: When this flag is set to anything other than 'breakpad', then "
"the '-c' and '-i' flags must also be set.\n");
fprintf(stderr, "-c:\t <code-file> Explicitly set 'code_file' for symbol "
"upload (basename of executable).\n");
fprintf(stderr, "-i:\t <debug-id> Explicitly set 'debug_id' for symbol "
"upload (typically build ID of executable).\n");
fprintf(stderr, "\n");
fprintf(stderr, "Examples:\n");
fprintf(stderr, " With 'sym-upload-v1':\n");
fprintf(stderr, " %s path/to/symbol_file http://myuploadserver\n",
argv[0]);
fprintf(stderr, " With 'sym-upload-v2':\n");
fprintf(stderr, " [Defaulting to symbol type 'BREAKPAD']\n");
fprintf(stderr, " %s -p sym-upload-v2 -k mysecret123! "
"path/to/symbol_file http://myuploadserver\n", argv[0]);
fprintf(stderr, " [Explicitly set symbol type to 'elf']\n");
fprintf(stderr, " %s -p sym-upload-v2 -k mysecret123! -t elf "
"-c app -i 11111111BBBB3333DDDD555555555555F "
"path/to/symbol_file http://myuploadserver\n", argv[0]);
}
//=============================================================================
static void
SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind, optopt;
int ch;
constexpr char flag_pattern[] = "u:v:x:p:k:t:c:i:hf?";
while ((ch = getopt(argc, (char * const*)argv, flag_pattern)) != -1) {
switch (ch) {
case 'h':
case '?':
Usage(argc, argv);
// ch might be '?' because getopt found an error while parsing args (as
// opposed to finding "-?" as an arg), in which case optopt is set to
// the bad arg value, so return an error code if optopt is set,
// otherwise exit cleanly.
exit(optopt == 0 ? 0 : 1);
case 'u':
options->proxy_user_pwd = optarg;
break;
case 'v':
options->version = optarg;
break;
case 'x':
options->proxy = optarg;
break;
case 'p':
if (strcmp(optarg, "sym-upload-v2") == 0) {
options->upload_protocol = UploadProtocol::SYM_UPLOAD_V2;
} else if (strcmp(optarg, "sym-upload-v1") == 0) {
options->upload_protocol = UploadProtocol::SYM_UPLOAD_V1;
} else {
fprintf(stderr, "Invalid protocol '%s'\n", optarg);
Usage(argc, argv);
exit(1);
}
break;
case 'k':
options->api_key = optarg;
break;
case 't': {
// This is really an enum, so treat as upper-case for consistency with
// enum naming convention on server-side.
options->type = optarg;
StrToUpper(&(options->type));
break;
}
case 'c':
options->code_file = optarg;
break;
case 'i':
options->debug_id = optarg;
break;
case 'f':
options->force = true;
break;
default:
fprintf(stderr, "Invalid option '%c'\n", ch);
Usage(argc, argv);
exit(1);
}
}
if ((argc - optind) != 2) {
fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
Usage(argc, argv);
exit(1);
}
bool is_breakpad_upload = options->type.empty() ||
options->type == google_breakpad::sym_upload::kBreakpadSymbolType;
bool has_code_file = !options->code_file.empty();
bool has_debug_id = !options->debug_id.empty();
if (is_breakpad_upload && (has_code_file || has_debug_id)) {
fprintf(stderr, "\n");
fprintf(stderr, "%s: -c and -i should only be specified for non-breakpad "
"symbol upload types.\n", argv[0]);
fprintf(stderr, "\n");
Usage(argc, argv);
exit(1);
}
if (!is_breakpad_upload && (!has_code_file || !has_debug_id)) {
fprintf(stderr, "\n");
fprintf(stderr, "%s: -c and -i must be specified for non-breakpad "
"symbol upload types.\n", argv[0]);
fprintf(stderr, "\n");
Usage(argc, argv);
exit(1);
}
options->symbolsPath = argv[optind];
options->uploadURLStr = argv[optind + 1];
}
//=============================================================================
int main(int argc, const char* argv[]) {
Options options;
SetupOptions(argc, argv, &options);
google_breakpad::sym_upload::Start(&options);
return options.success ? 0 : 1;
}