Skip to content

Commit

Permalink
Adds a custom Module ID flag to dump_syms
Browse files Browse the repository at this point in the history
TEST=make check
BUG=b:328511413

Change-Id: I09d4c5e92213501b647311b804e65f272772bbaf
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/5523975
Reviewed-by: Ivan Penkov <ivanpe@chromium.org>
Reviewed-by: Ivan Penkov <ivanpe@google.com>
  • Loading branch information
Sean Carpenter authored and Ivan Penkov committed May 10, 2024
1 parent 6fe410d commit 54986d3
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 14 deletions.
34 changes: 22 additions & 12 deletions src/common/linux/dump_symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,7 @@ template<typename ElfClass>
bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
const string& obj_os,
const string& module_id,
scoped_ptr<Module>& module,
bool enable_multiple_field) {
PageAllocator allocator;
Expand All @@ -1171,10 +1172,14 @@ bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
? name_buf
: google_breakpad::BaseName(obj_filename);

// Add an extra "0" at the end. PDB files on Windows have an 'age'
// number appended to the end of the file identifier; this isn't
// really used or necessary on other platforms, but be consistent.
string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0";
// Use the provided module_id
string id = module_id.empty()
// Add an extra "0" at the end. PDB files on Windows have an 'age'
// number appended to the end of the file identifier; this isn't
// really used or necessary on other platforms, but be consistent.
? FileID::ConvertIdentifierToUUIDString(identifier) + "0"
: module_id;

// This is just the raw Build ID in hex.
string code_id = FileID::ConvertIdentifierToString(identifier);

Expand All @@ -1188,6 +1193,7 @@ template<typename ElfClass>
bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
const string& obj_filename,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** out_module) {
Expand All @@ -1196,8 +1202,8 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
*out_module = NULL;

scoped_ptr<Module> module;
if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, obj_os, module,
options.enable_multiple_field)) {
if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, obj_os, module_id,
module, options.enable_multiple_field)) {
return false;
}

Expand Down Expand Up @@ -1246,6 +1252,7 @@ namespace google_breakpad {
bool ReadSymbolDataInternal(const uint8_t* obj_file,
const string& obj_filename,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** module) {
Expand All @@ -1258,12 +1265,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
if (elfclass == ELFCLASS32) {
return ReadSymbolDataElfClass<ElfClass32>(
reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, obj_os,
debug_dirs, options, module);
module_id, debug_dirs, options, module);
}
if (elfclass == ELFCLASS64) {
return ReadSymbolDataElfClass<ElfClass64>(
reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, obj_os,
debug_dirs, options, module);
module_id, debug_dirs, options, module);
}

return false;
Expand All @@ -1272,11 +1279,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file,
bool WriteSymbolFile(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
std::ostream& sym_stream) {
Module* module;
if (!ReadSymbolData(load_path, obj_file, obj_os, debug_dirs, options,
if (!ReadSymbolData(load_path, obj_file, obj_os, module_id, debug_dirs, options,
&module))
return false;

Expand All @@ -1291,6 +1299,7 @@ bool WriteSymbolFile(const string& load_path,
bool WriteSymbolFileHeader(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
std::ostream& sym_stream) {
MmapWrapper map_wrapper;
void* elf_header = NULL;
Expand All @@ -1309,14 +1318,14 @@ bool WriteSymbolFileHeader(const string& load_path,
if (elfclass == ELFCLASS32) {
if (!InitModuleForElfClass<ElfClass32>(
reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, obj_os,
module, /*enable_multiple_field=*/false)) {
module_id, module, /*enable_multiple_field=*/false)) {
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
return false;
}
} else if (elfclass == ELFCLASS64) {
if (!InitModuleForElfClass<ElfClass64>(
reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, obj_os,
module, /*enable_multiple_field=*/false)) {
module_id, module, /*enable_multiple_field=*/false)) {
fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
return false;
}
Expand All @@ -1331,6 +1340,7 @@ bool WriteSymbolFileHeader(const string& load_path,
bool ReadSymbolData(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** module) {
Expand All @@ -1340,7 +1350,7 @@ bool ReadSymbolData(const string& load_path,
return false;

return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
obj_file, obj_os, debug_dirs, options, module);
obj_file, obj_os, module_id, debug_dirs, options, module);
}

} // namespace google_breakpad
3 changes: 3 additions & 0 deletions src/common/linux/dump_symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ struct DumpOptions {
bool WriteSymbolFile(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
std::ostream& sym_stream);
Expand All @@ -81,6 +82,7 @@ bool WriteSymbolFile(const string& load_path,
bool WriteSymbolFileHeader(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
std::ostream& sym_stream);

// As above, but simply return the debugging information in MODULE
Expand All @@ -89,6 +91,7 @@ bool WriteSymbolFileHeader(const string& load_path,
bool ReadSymbolData(const string& load_path,
const string& obj_file,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dirs,
const DumpOptions& options,
Module** module);
Expand Down
52 changes: 52 additions & 0 deletions src/common/linux/dump_symbols_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ namespace google_breakpad {
bool ReadSymbolDataInternal(const uint8_t* obj_file,
const string& obj_filename,
const string& obj_os,
const string& module_id,
const std::vector<string>& debug_dir,
const DumpOptions& options,
Module** module);
Expand Down Expand Up @@ -99,6 +100,7 @@ TYPED_TEST(DumpSymbols, Invalid) {
EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
"foo",
"Linux",
"",
vector<string>(),
options,
&module));
Expand Down Expand Up @@ -136,6 +138,7 @@ TYPED_TEST(DumpSymbols, SimplePublic) {
EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
"foo",
"Linux",
"",
vector<string>(),
options,
&module));
Expand All @@ -151,6 +154,54 @@ TYPED_TEST(DumpSymbols, SimplePublic) {
delete module;
}

TYPED_TEST(DumpSymbols, ModuleIdOverride) {
ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
// Zero out text section for simplicity.
Section text(kLittleEndian);
text.Append(4096, 0);
elf.AddSection(".text", text, SHT_PROGBITS);

// Add a public symbol.
StringTable table(kLittleEndian);
SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table);
syms.AddSymbol("superfunc",
(typename TypeParam::Addr)0x1000,
(typename TypeParam::Addr)0x10,
// ELF32_ST_INFO works for 32-or 64-bit.
ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
SHN_UNDEF + 1);
int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
elf.AddSection(".dynsym", syms,
SHT_DYNSYM, // type
SHF_ALLOC, // flags
0, // addr
index, // link
sizeof(typename TypeParam::Sym)); // entsize

elf.Finish();
this->GetElfContents(elf);

Module* module;
DumpOptions options(ALL_SYMBOL_DATA, true, false, false);
EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
"foo",
"Linux",
"some_module_id",
vector<string>(),
options,
&module));

stringstream s;
module->Write(s, ALL_SYMBOL_DATA);
const string expected =
string("MODULE Linux ") + TypeParam::kMachineName
+ " some_module_id foo\n"
"INFO CODE_ID 00000000000000000000000000000000\n"
"PUBLIC 1000 0 superfunc\n";
EXPECT_EQ(expected, s.str());
delete module;
}

TYPED_TEST(DumpSymbols, SimpleBuildID) {
ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
// Zero out text section for simplicity.
Expand Down Expand Up @@ -193,6 +244,7 @@ TYPED_TEST(DumpSymbols, SimpleBuildID) {
EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
"foo",
"Linux",
"",
vector<string>(),
options,
&module));
Expand Down
13 changes: 11 additions & 2 deletions src/tools/linux/dump_syms/dump_syms.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ int usage(const char* self) {
fprintf(stderr, " -r Do not handle inter-compilation "
"unit references\n");
fprintf(stderr, " -v Print all warnings to stderr\n");
fprintf(stderr, " -b <id> Use specified id for the module id\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");
Expand All @@ -79,6 +80,7 @@ int main(int argc, char** argv) {
bool log_to_stderr = false;
bool enable_multiple_field = false;
std::string obj_name;
std::string module_id;
const char* obj_os = "Linux";
int arg_index = 1;
while (arg_index < argc && strlen(argv[arg_index]) > 0 &&
Expand All @@ -95,6 +97,13 @@ int main(int argc, char** argv) {
handle_inter_cu_refs = false;
} else if (strcmp("-v", argv[arg_index]) == 0) {
log_to_stderr = true;
} else if (strcmp("-b", argv[arg_index]) == 0) {
if (arg_index + 1 >= argc) {
fprintf(stderr, "Missing argument to -b\n");
return usage(argv[0]);
}
module_id = argv[arg_index + 1];
++arg_index;
} else if (strcmp("-n", argv[arg_index]) == 0) {
if (arg_index + 1 >= argc) {
fprintf(stderr, "Missing argument to -n\n");
Expand Down Expand Up @@ -140,7 +149,7 @@ int main(int argc, char** argv) {
obj_name = binary;

if (header_only) {
if (!WriteSymbolFileHeader(binary, obj_name, obj_os, std::cout)) {
if (!WriteSymbolFileHeader(binary, obj_name, obj_os, module_id, std::cout)) {
fprintf(saved_stderr, "Failed to process file.\n");
return 1;
}
Expand All @@ -149,7 +158,7 @@ int main(int argc, char** argv) {
(cfi ? CFI : NO_DATA) | SYMBOLS_AND_FILES;
google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs,
enable_multiple_field, preserve_load_address);
if (!WriteSymbolFile(binary, obj_name, obj_os, debug_dirs, options,
if (!WriteSymbolFile(binary, obj_name, obj_os, module_id, debug_dirs, options,
std::cout)) {
fprintf(saved_stderr, "Failed to write symbol file.\n");
return 1;
Expand Down

0 comments on commit 54986d3

Please sign in to comment.