aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/linux/dump_symbols.cc56
-rw-r--r--src/common/linux/dump_symbols.h7
-rw-r--r--src/common/linux/dump_symbols_unittest.cc16
-rw-r--r--src/tools/linux/dump_syms/dump_syms.cc25
4 files changed, 60 insertions, 44 deletions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index bcb39ca7..4a85ab8f 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -387,7 +387,7 @@ template<typename ElfClass>
string ReadDebugLink(const char* debuglink,
size_t debuglink_size,
const string& obj_file,
- const string& debug_dir) {
+ const std::vector<string>& debug_dirs) {
size_t debuglink_len = strlen(debuglink) + 5; // '\0' + CRC32.
debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round to nearest 4 bytes.
@@ -398,13 +398,26 @@ string ReadDebugLink(const char* debuglink,
return "";
}
- string debuglink_path = debug_dir + "/" + debuglink;
- int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
- if (debuglink_fd < 0) {
+ bool found = false;
+ int debuglink_fd = -1;
+ string debuglink_path;
+ std::vector<string>::const_iterator it;
+ for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
+ const string& debug_dir = *it;
+ debuglink_path = debug_dir + "/" + debuglink;
+ debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
+ if (debuglink_fd >= 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
fprintf(stderr, "Failed to open debug ELF file '%s' for '%s': %s\n",
debuglink_path.c_str(), obj_file.c_str(), strerror(errno));
return "";
}
+
FDWrapper debuglink_fd_wrapper(debuglink_fd);
// TODO(thestig) check the CRC-32 at the end of the .gnu_debuglink
// section.
@@ -424,8 +437,8 @@ class LoadSymbolsInfo {
public:
typedef typename ElfClass::Addr Addr;
- explicit LoadSymbolsInfo(const string &dbg_dir) :
- debug_dir_(dbg_dir),
+ explicit LoadSymbolsInfo(const std::vector<string>& dbg_dirs) :
+ debug_dirs_(dbg_dirs),
has_loading_addr_(false) {}
// Keeps track of which sections have been loaded so sections don't
@@ -458,8 +471,8 @@ class LoadSymbolsInfo {
}
// Setters and getters
- const string &debug_dir() const {
- return debug_dir_;
+ const std::vector<string>& debug_dirs() const {
+ return debug_dirs_;
}
string debuglink_file() const {
@@ -470,7 +483,8 @@ class LoadSymbolsInfo {
}
private:
- const string &debug_dir_; // Directory with the debug ELF file.
+ const std::vector<string>& debug_dirs_; // Directories in which to
+ // search for the debug ELF file.
string debuglink_file_; // Full path to the debug ELF file.
@@ -601,14 +615,14 @@ bool LoadSymbols(const string& obj_file,
sections, names,
names_end, elf_header->e_shnum);
if (gnu_debuglink_section) {
- if (!info->debug_dir().empty()) {
+ if (!info->debug_dirs().empty()) {
const char* debuglink_contents =
GetOffset<ElfClass, char>(elf_header,
gnu_debuglink_section->sh_offset);
string debuglink_file
= ReadDebugLink<ElfClass>(debuglink_contents,
gnu_debuglink_section->sh_size,
- obj_file, info->debug_dir());
+ obj_file, info->debug_dirs());
info->set_debuglink_file(debuglink_file);
} else {
fprintf(stderr, ".gnu_debuglink section found in '%s', "
@@ -712,7 +726,7 @@ string BaseFileName(const string &filename) {
template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
- const string& debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
Module** out_module) {
typedef typename ElfClass::Ehdr Ehdr;
@@ -744,10 +758,10 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
string os = "Linux";
string id = FormatIdentifier(identifier);
- LoadSymbolsInfo<ElfClass> info(debug_dir);
+ LoadSymbolsInfo<ElfClass> info(debug_dirs);
scoped_ptr<Module> module(new Module(name, os, architecture, id));
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
- !debug_dir.empty(), &info, module.get())) {
+ !debug_dirs.empty(), &info, module.get())) {
const string debuglink_file = info.debuglink_file();
if (debuglink_file.empty())
return false;
@@ -801,7 +815,7 @@ namespace google_breakpad {
// Not explicitly exported, but not static so it can be used in unit tests.
bool ReadSymbolDataInternal(const uint8_t* obj_file,
const string& obj_filename,
- const string& debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
Module** module) {
@@ -813,12 +827,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
int elfclass = ElfClass(obj_file);
if (elfclass == ELFCLASS32) {
return ReadSymbolDataElfClass<ElfClass32>(
- reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dir,
+ reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dirs,
cfi, module);
}
if (elfclass == ELFCLASS64) {
return ReadSymbolDataElfClass<ElfClass64>(
- reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dir,
+ reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dirs,
cfi, module);
}
@@ -826,11 +840,11 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
}
bool WriteSymbolFile(const string &obj_file,
- const string &debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
std::ostream &sym_stream) {
Module* module;
- if (!ReadSymbolData(obj_file, debug_dir, cfi, &module))
+ if (!ReadSymbolData(obj_file, debug_dirs, cfi, &module))
return false;
bool result = module->Write(sym_stream, cfi);
@@ -839,7 +853,7 @@ bool WriteSymbolFile(const string &obj_file,
}
bool ReadSymbolData(const string& obj_file,
- const string& debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
Module** module) {
MmapWrapper map_wrapper;
@@ -848,7 +862,7 @@ bool ReadSymbolData(const string& obj_file,
return false;
return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
- obj_file, debug_dir, cfi, module);
+ obj_file, debug_dirs, cfi, module);
}
} // namespace google_breakpad
diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h
index 9084733e..8765ffdb 100644
--- a/src/common/linux/dump_symbols.h
+++ b/src/common/linux/dump_symbols.h
@@ -37,6 +37,7 @@
#include <iostream>
#include <string>
+#include <vector>
#include "common/using_std_string.h"
@@ -48,10 +49,10 @@ class Module;
// or shared library, and write it to SYM_STREAM in the Breakpad symbol
// file format.
// If OBJ_FILE has been stripped but contains a .gnu_debuglink section,
-// then look for the debug file in DEBUG_DIR.
+// then look for the debug file in DEBUG_DIRS.
// If CFI is set to false, then omit the CFI section.
bool WriteSymbolFile(const string &obj_file,
- const string &debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
std::ostream &sym_stream);
@@ -59,7 +60,7 @@ bool WriteSymbolFile(const string &obj_file,
// instead of writing it to a stream. The caller owns the resulting
// Module object and must delete it when finished.
bool ReadSymbolData(const string& obj_file,
- const string& debug_dir,
+ const std::vector<string>& debug_dirs,
bool cfi,
Module** module);
diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc
index 3d9b4a9e..d48512f7 100644
--- a/src/common/linux/dump_symbols_unittest.cc
+++ b/src/common/linux/dump_symbols_unittest.cc
@@ -46,8 +46,8 @@
namespace google_breakpad {
bool ReadSymbolDataInternal(const uint8_t* obj_file,
- const string &obj_filename,
- const string &debug_dir,
+ const string& obj_filename,
+ const std::vector<string>& debug_dir,
bool cfi,
Module** module);
}
@@ -84,10 +84,10 @@ TEST_F(DumpSymbols, Invalid) {
memset(&header, 0, sizeof(header));
Module* module;
EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
- "foo",
- "",
- true,
- &module));
+ "foo",
+ vector<string>(),
+ true,
+ &module));
}
TEST_F(DumpSymbols, SimplePublic32) {
@@ -117,7 +117,7 @@ TEST_F(DumpSymbols, SimplePublic32) {
Module* module;
EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
"foo",
- "",
+ vector<string>(),
true,
&module));
@@ -156,7 +156,7 @@ TEST_F(DumpSymbols, SimplePublic64) {
Module* module;
EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
"foo",
- "",
+ vector<string>(),
true,
&module));
diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc
index adac216c..aa504589 100644
--- a/src/tools/linux/dump_syms/dump_syms.cc
+++ b/src/tools/linux/dump_syms/dump_syms.cc
@@ -32,6 +32,7 @@
#include <cstring>
#include <iostream>
#include <string>
+#include <vector>
#include "common/linux/dump_symbols.h"
@@ -39,7 +40,7 @@ using google_breakpad::WriteSymbolFile;
int usage(const char* self) {
fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
- "[directory-for-debug-file]\n\n", self);
+ "[directories-for-debug-file]\n\n", self);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -c Do not generate CFI section\n");
return 1;
@@ -50,24 +51,24 @@ int main(int argc, char **argv) {
return usage(argv[0]);
bool cfi = true;
- if (strcmp("-c", argv[1]) == 0)
+ int binary_index = 1;
+ if (strcmp("-c", argv[1]) == 0) {
cfi = false;
+ ++binary_index;
+ }
if (!cfi && argc == 2)
return usage(argv[0]);
const char *binary;
- std::string debug_dir;
- if (cfi) {
- binary = argv[1];
- if (argc == 3)
- debug_dir = argv[2];
- } else {
- binary = argv[2];
- if (argc == 4)
- debug_dir = argv[3];
+ std::vector<string> debug_dirs;
+ binary = argv[binary_index];
+ for (int debug_dir_index = binary_index + 1;
+ debug_dir_index < argc;
+ ++debug_dir_index) {
+ debug_dirs.push_back(argv[debug_dir_index]);
}
- if (!WriteSymbolFile(binary, debug_dir, cfi, std::cout)) {
+ if (!WriteSymbolFile(binary, debug_dirs, cfi, std::cout)) {
fprintf(stderr, "Failed to write symbol file.\n");
return 1;
}