Make DumpSymbols methods take a vector of debug_dirs
r=thestig at https://breakpad.appspot.com/512002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1102 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
834f7ee611
commit
c6f6d9ef30
4 changed files with 60 additions and 44 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue