mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-19 08:07:36 +00:00
Provide a ReadSymbolData function to get symbol data in a Module instead of just serializing it
R=thestig at https://breakpad.appspot.com/510002/ git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1099 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
e086f8a9c8
commit
7e72c6677a
|
@ -62,6 +62,7 @@
|
||||||
#include "common/linux/elf_symbols_to_module.h"
|
#include "common/linux/elf_symbols_to_module.h"
|
||||||
#include "common/linux/file_id.h"
|
#include "common/linux/file_id.h"
|
||||||
#include "common/module.h"
|
#include "common/module.h"
|
||||||
|
#include "common/scoped_ptr.h"
|
||||||
#include "common/stabs_reader.h"
|
#include "common/stabs_reader.h"
|
||||||
#include "common/stabs_to_module.h"
|
#include "common/stabs_to_module.h"
|
||||||
#include "common/using_std_string.h"
|
#include "common/using_std_string.h"
|
||||||
|
@ -80,6 +81,7 @@ using google_breakpad::GetOffset;
|
||||||
using google_breakpad::IsValidElf;
|
using google_breakpad::IsValidElf;
|
||||||
using google_breakpad::Module;
|
using google_breakpad::Module;
|
||||||
using google_breakpad::StabsToModule;
|
using google_breakpad::StabsToModule;
|
||||||
|
using google_breakpad::scoped_ptr;
|
||||||
|
|
||||||
//
|
//
|
||||||
// FDWrapper
|
// FDWrapper
|
||||||
|
@ -708,14 +710,16 @@ string BaseFileName(const string &filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ElfClass>
|
template<typename ElfClass>
|
||||||
bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header,
|
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||||
const string& obj_filename,
|
const string& obj_filename,
|
||||||
const string& debug_dir,
|
const string& debug_dir,
|
||||||
bool cfi,
|
bool cfi,
|
||||||
std::ostream& sym_stream) {
|
Module** out_module) {
|
||||||
typedef typename ElfClass::Ehdr Ehdr;
|
typedef typename ElfClass::Ehdr Ehdr;
|
||||||
typedef typename ElfClass::Shdr Shdr;
|
typedef typename ElfClass::Shdr Shdr;
|
||||||
|
|
||||||
|
*out_module = NULL;
|
||||||
|
|
||||||
unsigned char identifier[16];
|
unsigned char identifier[16];
|
||||||
if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header,
|
if (!google_breakpad::FileID::ElfFileIdentifierFromMappedFile(elf_header,
|
||||||
identifier)) {
|
identifier)) {
|
||||||
|
@ -741,9 +745,9 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||||
string id = FormatIdentifier(identifier);
|
string id = FormatIdentifier(identifier);
|
||||||
|
|
||||||
LoadSymbolsInfo<ElfClass> info(debug_dir);
|
LoadSymbolsInfo<ElfClass> info(debug_dir);
|
||||||
Module module(name, os, architecture, id);
|
scoped_ptr<Module> module(new Module(name, os, architecture, id));
|
||||||
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
|
if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
|
||||||
!debug_dir.empty(), &info, &module)) {
|
!debug_dir.empty(), &info, module.get())) {
|
||||||
const string debuglink_file = info.debuglink_file();
|
const string debuglink_file = info.debuglink_file();
|
||||||
if (debuglink_file.empty())
|
if (debuglink_file.empty())
|
||||||
return false;
|
return false;
|
||||||
|
@ -781,13 +785,12 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian,
|
if (!LoadSymbols<ElfClass>(debuglink_file, debug_big_endian,
|
||||||
debug_elf_header, false, &info, &module)) {
|
debug_elf_header, false, &info, module.get())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!module.Write(sym_stream, cfi))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
|
*out_module = module.release();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -796,11 +799,11 @@ bool WriteSymbolFileElfClass(const typename ElfClass::Ehdr* elf_header,
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
// Not explicitly exported, but not static so it can be used in unit tests.
|
// Not explicitly exported, but not static so it can be used in unit tests.
|
||||||
bool WriteSymbolFileInternal(const uint8_t* obj_file,
|
bool ReadSymbolDataInternal(const uint8_t* obj_file,
|
||||||
const string& obj_filename,
|
const string& obj_filename,
|
||||||
const string& debug_dir,
|
const string& debug_dir,
|
||||||
bool cfi,
|
bool cfi,
|
||||||
std::ostream& sym_stream) {
|
Module** module) {
|
||||||
|
|
||||||
if (!IsValidElf(obj_file)) {
|
if (!IsValidElf(obj_file)) {
|
||||||
fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str());
|
fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str());
|
||||||
|
@ -809,14 +812,14 @@ bool WriteSymbolFileInternal(const uint8_t* obj_file,
|
||||||
|
|
||||||
int elfclass = ElfClass(obj_file);
|
int elfclass = ElfClass(obj_file);
|
||||||
if (elfclass == ELFCLASS32) {
|
if (elfclass == ELFCLASS32) {
|
||||||
return WriteSymbolFileElfClass<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_dir,
|
||||||
cfi, sym_stream);
|
cfi, module);
|
||||||
}
|
}
|
||||||
if (elfclass == ELFCLASS64) {
|
if (elfclass == ELFCLASS64) {
|
||||||
return WriteSymbolFileElfClass<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_dir,
|
||||||
cfi, sym_stream);
|
cfi, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -826,13 +829,26 @@ bool WriteSymbolFile(const string &obj_file,
|
||||||
const string &debug_dir,
|
const string &debug_dir,
|
||||||
bool cfi,
|
bool cfi,
|
||||||
std::ostream &sym_stream) {
|
std::ostream &sym_stream) {
|
||||||
|
Module* module;
|
||||||
|
if (!ReadSymbolData(obj_file, debug_dir, cfi, &module))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool result = module->Write(sym_stream, cfi);
|
||||||
|
delete module;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadSymbolData(const string& obj_file,
|
||||||
|
const string& debug_dir,
|
||||||
|
bool cfi,
|
||||||
|
Module** module) {
|
||||||
MmapWrapper map_wrapper;
|
MmapWrapper map_wrapper;
|
||||||
void* elf_header = NULL;
|
void* elf_header = NULL;
|
||||||
if (!LoadELF(obj_file, &map_wrapper, &elf_header))
|
if (!LoadELF(obj_file, &map_wrapper, &elf_header))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(elf_header),
|
return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
|
||||||
obj_file, debug_dir, cfi, sym_stream);
|
obj_file, debug_dir, cfi, module);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
class Module;
|
||||||
|
|
||||||
// Find all the debugging information in OBJ_FILE, an ELF executable
|
// Find all the debugging information in OBJ_FILE, an ELF executable
|
||||||
// or shared library, and write it to SYM_STREAM in the Breakpad symbol
|
// or shared library, and write it to SYM_STREAM in the Breakpad symbol
|
||||||
// file format.
|
// file format.
|
||||||
|
@ -53,6 +55,14 @@ bool WriteSymbolFile(const string &obj_file,
|
||||||
bool cfi,
|
bool cfi,
|
||||||
std::ostream &sym_stream);
|
std::ostream &sym_stream);
|
||||||
|
|
||||||
|
// As above, but simply return the debugging information in MODULE
|
||||||
|
// instead of writing it to a stream. The caller owns the resulting
|
||||||
|
// Module object and must delete it when finished.
|
||||||
|
bool ReadSymbolData(const string& obj_file,
|
||||||
|
const string& debug_dir,
|
||||||
|
bool cfi,
|
||||||
|
Module** module);
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
||||||
#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
|
#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
|
||||||
|
|
|
@ -37,19 +37,19 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "breakpad_googletest_includes.h"
|
#include "breakpad_googletest_includes.h"
|
||||||
#include "common/linux/synth_elf.h"
|
#include "common/linux/synth_elf.h"
|
||||||
|
#include "common/module.h"
|
||||||
#include "common/using_std_string.h"
|
#include "common/using_std_string.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
bool WriteSymbolFileInternal(const uint8_t* obj_file,
|
bool ReadSymbolDataInternal(const uint8_t* obj_file,
|
||||||
const string &obj_filename,
|
const string &obj_filename,
|
||||||
const string &debug_dir,
|
const string &debug_dir,
|
||||||
bool cfi,
|
bool cfi,
|
||||||
std::ostream &sym_stream);
|
Module** module);
|
||||||
}
|
}
|
||||||
|
|
||||||
using google_breakpad::synth_elf::ELF;
|
using google_breakpad::synth_elf::ELF;
|
||||||
|
@ -57,7 +57,8 @@ using google_breakpad::synth_elf::StringTable;
|
||||||
using google_breakpad::synth_elf::SymbolTable;
|
using google_breakpad::synth_elf::SymbolTable;
|
||||||
using google_breakpad::test_assembler::kLittleEndian;
|
using google_breakpad::test_assembler::kLittleEndian;
|
||||||
using google_breakpad::test_assembler::Section;
|
using google_breakpad::test_assembler::Section;
|
||||||
using google_breakpad::WriteSymbolFileInternal;
|
using google_breakpad::Module;
|
||||||
|
using google_breakpad::ReadSymbolDataInternal;
|
||||||
using std::stringstream;
|
using std::stringstream;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using ::testing::Test;
|
using ::testing::Test;
|
||||||
|
@ -81,12 +82,12 @@ class DumpSymbols : public Test {
|
||||||
TEST_F(DumpSymbols, Invalid) {
|
TEST_F(DumpSymbols, Invalid) {
|
||||||
Elf32_Ehdr header;
|
Elf32_Ehdr header;
|
||||||
memset(&header, 0, sizeof(header));
|
memset(&header, 0, sizeof(header));
|
||||||
stringstream s;
|
Module* module;
|
||||||
EXPECT_FALSE(WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(&header),
|
EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
|
||||||
"foo",
|
"foo",
|
||||||
"",
|
"",
|
||||||
true,
|
true,
|
||||||
s));
|
&module));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DumpSymbols, SimplePublic32) {
|
TEST_F(DumpSymbols, SimplePublic32) {
|
||||||
|
@ -113,15 +114,19 @@ TEST_F(DumpSymbols, SimplePublic32) {
|
||||||
elf.Finish();
|
elf.Finish();
|
||||||
GetElfContents(elf);
|
GetElfContents(elf);
|
||||||
|
|
||||||
|
Module* module;
|
||||||
|
EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
|
||||||
|
"foo",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
&module));
|
||||||
|
|
||||||
stringstream s;
|
stringstream s;
|
||||||
ASSERT_TRUE(WriteSymbolFileInternal(elfdata,
|
module->Write(s, true);
|
||||||
"foo",
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
s));
|
|
||||||
EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n"
|
EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n"
|
||||||
"PUBLIC 1000 0 superfunc\n",
|
"PUBLIC 1000 0 superfunc\n",
|
||||||
s.str());
|
s.str());
|
||||||
|
delete module;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DumpSymbols, SimplePublic64) {
|
TEST_F(DumpSymbols, SimplePublic64) {
|
||||||
|
@ -148,12 +153,15 @@ TEST_F(DumpSymbols, SimplePublic64) {
|
||||||
elf.Finish();
|
elf.Finish();
|
||||||
GetElfContents(elf);
|
GetElfContents(elf);
|
||||||
|
|
||||||
|
Module* module;
|
||||||
|
EXPECT_TRUE(ReadSymbolDataInternal(elfdata,
|
||||||
|
"foo",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
&module));
|
||||||
|
|
||||||
stringstream s;
|
stringstream s;
|
||||||
ASSERT_TRUE(WriteSymbolFileInternal(elfdata,
|
module->Write(s, true);
|
||||||
"foo",
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
s));
|
|
||||||
EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n"
|
EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n"
|
||||||
"PUBLIC 1000 0 superfunc\n",
|
"PUBLIC 1000 0 superfunc\n",
|
||||||
s.str());
|
s.str());
|
||||||
|
|
Loading…
Reference in a new issue