diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc index 7c6550b1..e2e13747 100644 --- a/src/common/linux/file_id_unittest.cc +++ b/src/common/linux/file_id_unittest.cc @@ -47,8 +47,8 @@ using namespace google_breakpad; using google_breakpad::ElfClass32; using google_breakpad::ElfClass64; using google_breakpad::SafeReadLink; -using google_breakpad::synth_elf::BuildIDNote; using google_breakpad::synth_elf::ELF; +using google_breakpad::synth_elf::Notes; using google_breakpad::test_assembler::kLittleEndian; using google_breakpad::test_assembler::Section; using ::testing::Types; @@ -160,9 +160,10 @@ TYPED_TEST(FileIDTest, BuildID) { Section text(kLittleEndian); text.Append(4096, 0); elf.AddSection(".text", text, SHT_PROGBITS); - BuildIDNote::AppendSection(elf, - kExpectedIdentifier, - sizeof(kExpectedIdentifier)); + Notes notes(kLittleEndian); + notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier, + sizeof(kExpectedIdentifier)); + elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE); elf.Finish(); this->GetElfContents(elf); diff --git a/src/common/linux/synth_elf.cc b/src/common/linux/synth_elf.cc index 1a741e55..9cd03ef8 100644 --- a/src/common/linux/synth_elf.cc +++ b/src/common/linux/synth_elf.cc @@ -243,30 +243,21 @@ void SymbolTable::AddSymbol(const string& name, uint64_t value, D64(size); } -BuildIDNote::BuildIDNote(const uint8_t* id_bytes, - size_t id_size, - Endianness endianness) : Section(endianness) { - const char kNoteName[] = "GNU"; +void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes, + size_t desc_size) { // Elf32_Nhdr and Elf64_Nhdr are exactly the same. Elf32_Nhdr note_header; memset(¬e_header, 0, sizeof(note_header)); - note_header.n_namesz = sizeof(kNoteName); - note_header.n_descsz = id_size; - note_header.n_type = NT_GNU_BUILD_ID; + note_header.n_namesz = name.length() + 1; + note_header.n_descsz = desc_size; + note_header.n_type = type; Append(reinterpret_cast(¬e_header), sizeof(note_header)); - AppendCString(kNoteName); - Append(id_bytes, id_size); -} - -// static -void BuildIDNote::AppendSection(ELF& elf, - const uint8_t* id_bytes, - size_t id_size) { - const char kBuildIDSectionName[] = ".note.gnu.build-id"; - BuildIDNote note(id_bytes, id_size, elf.endianness()); - elf.AddSection(kBuildIDSectionName, note, SHT_NOTE); + AppendCString(name); + Align(4); + Append(desc_bytes, desc_size); + Align(4); } } // namespace synth_elf diff --git a/src/common/linux/synth_elf.h b/src/common/linux/synth_elf.h index 9a6c0316..330ceae8 100644 --- a/src/common/linux/synth_elf.h +++ b/src/common/linux/synth_elf.h @@ -177,13 +177,16 @@ class SymbolTable : public Section { StringTable& table_; }; -// A class to build GNU Build ID note sections -class BuildIDNote : public Section { +// A class for note sections +class Notes : public Section { public: - BuildIDNote(const uint8_t* id_bytes, size_t id_size, Endianness endianness); + Notes(Endianness endianness) + : Section(endianness) { + } - // Append a new Build ID note section to |elf|. - static void AppendSection(ELF& elf, const uint8_t* id_bytes, size_t id_size); + // Add a note. + void AddNote(int type, const string &name, const uint8_t* desc_bytes, + size_t desc_size); }; } // namespace synth_elf diff --git a/src/common/linux/synth_elf_unittest.cc b/src/common/linux/synth_elf_unittest.cc index 94ff5052..3715b6e6 100644 --- a/src/common/linux/synth_elf_unittest.cc +++ b/src/common/linux/synth_elf_unittest.cc @@ -42,6 +42,7 @@ using google_breakpad::ElfClass32; using google_breakpad::ElfClass64; using google_breakpad::synth_elf::ELF; +using google_breakpad::synth_elf::Notes; using google_breakpad::synth_elf::Section; using google_breakpad::synth_elf::StringTable; using google_breakpad::synth_elf::SymbolTable; @@ -369,4 +370,44 @@ TYPED_TEST(BasicElf, BasicLE) { EXPECT_EQ(0U, phdr->p_align); } +class ElfNotesTest : public Test {}; + +TEST_F(ElfNotesTest, Empty) { + Notes notes(kLittleEndian); + string contents; + ASSERT_TRUE(notes.GetContents(&contents)); + EXPECT_EQ(0U, contents.size()); +} + +TEST_F(ElfNotesTest, Notes) { + Notes notes(kLittleEndian); + notes.AddNote(1, "Linux", reinterpret_cast("\x42\x02\0\0"), + 4); + notes.AddNote(2, "a", reinterpret_cast("foobar"), + sizeof("foobar") - 1); + + const uint8_t kExpectedNotesContents[] = { + // Note 1 + 0x06, 0x00, 0x00, 0x00, // name size, including terminating zero + 0x04, 0x00, 0x00, 0x00, // desc size + 0x01, 0x00, 0x00, 0x00, // type + 'L', 'i', 'n', 'u', 'x', 0x00, 0x00, 0x00, // padded "Linux" + 0x42, 0x02, 0x00, 0x00, // desc + // Note 2 + 0x02, 0x00, 0x00, 0x00, // name size + 0x06, 0x00, 0x00, 0x00, // desc size + 0x02, 0x00, 0x00, 0x00, // type + 'a', 0x00, 0x00, 0x00, // padded "a" + 'f', 'o', 'o', 'b', 'a', 'r', 0x00, 0x00, // padded "foobar" + }; + const size_t kExpectedNotesSize = sizeof(kExpectedNotesContents); + EXPECT_EQ(kExpectedNotesSize, notes.Size()); + + string notes_contents; + ASSERT_TRUE(notes.GetContents(¬es_contents)); + EXPECT_EQ(0, memcmp(kExpectedNotesContents, + notes_contents.data(), + notes_contents.size())); +} + #endif // defined(__i386__) || defined(__x86_64__)