aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux/file_id_unittest.cc
diff options
context:
space:
mode:
authorTed Mielczarek <ted@mielczarek.org>2016-04-05 09:34:20 -0400
committerTed Mielczarek <ted@mielczarek.org>2016-04-05 09:34:20 -0400
commit6c8f80aa8b3ba8120c4158c069bb298c044dedf9 (patch)
tree2164203da75d894883e042368c34370f6c3af4c8 /src/common/linux/file_id_unittest.cc
parentsample_app: enable C++11 for Android builds (diff)
downloadbreakpad-6c8f80aa8b3ba8120c4158c069bb298c044dedf9.tar.xz
Switch the Linux minidump writer to use MDCVInfoELF for CV data.
This preserves full build ids in minidumps, which are useful for tracking down the right version of system libraries from Linux distributions. The default build id produced by GNU binutils' ld is a 160-bit SHA-1 hash of some parts of the binary, which is exactly 20 bytes: https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292 The bulk of the changes here are to change the signatures of the FileID methods to use a wasteful_vector instead of raw pointers, since build ids can be of arbitrary length. The previous change that added support for this in the processor code preserved the return value of `Minidump::debug_identifier()` as the current `GUID+age` treatment for backwards-compatibility, and exposed the full build id from `Minidump::code_identifier()`, which was previously stubbed out for Linux dumps. This change keeps the debug ID in the `dump_syms` output the same to match. R=mark@chromium.org, thestig@chromium.org BUG= Review URL: https://codereview.chromium.org/1688743002 .
Diffstat (limited to 'src/common/linux/file_id_unittest.cc')
-rw-r--r--src/common/linux/file_id_unittest.cc176
1 files changed, 117 insertions, 59 deletions
diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc
index 760eae82..ec11bb25 100644
--- a/src/common/linux/file_id_unittest.cc
+++ b/src/common/linux/file_id_unittest.cc
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string>
+#include <vector>
#include "common/linux/elf_gnu_compat.h"
#include "common/linux/elfutils.h"
@@ -45,13 +46,11 @@
#include "breakpad_googletest_includes.h"
using namespace google_breakpad;
-using google_breakpad::ElfClass32;
-using google_breakpad::ElfClass64;
-using google_breakpad::SafeReadLink;
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 std::vector;
using ::testing::Types;
namespace {
@@ -64,6 +63,8 @@ void PopulateSection(Section* section, int size, int prime_number) {
section->Append(1, (i % prime_number) % 256);
}
+typedef wasteful_vector<uint8_t> id_vector;
+
} // namespace
#ifndef __ANDROID__
@@ -87,19 +88,20 @@ TEST(FileIDStripTest, StripSelf) {
sprintf(cmdline, "strip \"%s\"", templ.c_str());
ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
- uint8_t identifier1[sizeof(MDGUID)];
- uint8_t identifier2[sizeof(MDGUID)];
+ PageAllocator allocator;
+ id_vector identifier1(&allocator, kDefaultBuildIdSize);
+ id_vector identifier2(&allocator, kDefaultBuildIdSize);
+
FileID fileid1(exe_name);
EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1));
FileID fileid2(templ.c_str());
EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2));
- char identifier_string1[37];
- char identifier_string2[37];
- FileID::ConvertIdentifierToString(identifier1, identifier_string1,
- 37);
- FileID::ConvertIdentifierToString(identifier2, identifier_string2,
- 37);
- EXPECT_STREQ(identifier_string1, identifier_string2);
+
+ string identifier_string1 =
+ FileID::ConvertIdentifierToUUIDString(identifier1);
+ string identifier_string2 =
+ FileID::ConvertIdentifierToUUIDString(identifier2);
+ EXPECT_EQ(identifier_string1, identifier_string2);
}
#endif // !__ANDROID__
@@ -116,8 +118,22 @@ public:
elfdata = &elfdata_v[0];
}
+ id_vector make_vector() {
+ return id_vector(&allocator, kDefaultBuildIdSize);
+ }
+
+ template<size_t N>
+ string get_file_id(const uint8_t (&data)[N]) {
+ id_vector expected_identifier(make_vector());
+ expected_identifier.insert(expected_identifier.end(),
+ &data[0],
+ data + N);
+ return FileID::ConvertIdentifierToUUIDString(expected_identifier);
+ }
+
vector<uint8_t> elfdata_v;
uint8_t* elfdata;
+ PageAllocator allocator;
};
typedef Types<ElfClass32, ElfClass64> ElfClasses;
@@ -125,10 +141,8 @@ typedef Types<ElfClass32, ElfClass64> ElfClasses;
TYPED_TEST_CASE(FileIDTest, ElfClasses);
TYPED_TEST(FileIDTest, ElfClass) {
- uint8_t identifier[sizeof(MDGUID)];
const char expected_identifier_string[] =
- "80808080-8080-0000-0000-008080808080";
- char identifier_string[sizeof(expected_identifier_string)];
+ "80808080808000000000008080808080";
const size_t kTextSectionSize = 128;
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
@@ -140,58 +154,106 @@ TYPED_TEST(FileIDTest, ElfClass) {
elf.Finish();
this->GetElfContents(elf);
+ id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
- FileID::ConvertIdentifierToString(identifier, identifier_string,
- sizeof(identifier_string));
- EXPECT_STREQ(expected_identifier_string, identifier_string);
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ EXPECT_EQ(expected_identifier_string, identifier_string);
}
TYPED_TEST(FileIDTest, BuildID) {
- const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
+ const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
- char expected_identifier_string[] =
- "00000000-0000-0000-0000-000000000000";
- FileID::ConvertIdentifierToString(kExpectedIdentifier,
- expected_identifier_string,
- sizeof(expected_identifier_string));
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13};
+ const string expected_identifier_string =
+ this->get_file_id(kExpectedIdentifierBytes);
+
+ ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
+ Section text(kLittleEndian);
+ text.Append(4096, 0);
+ elf.AddSection(".text", text, SHT_PROGBITS);
+ Notes notes(kLittleEndian);
+ notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
+ sizeof(kExpectedIdentifierBytes));
+ elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
+ elf.Finish();
+ this->GetElfContents(elf);
- uint8_t identifier[sizeof(MDGUID)];
- char identifier_string[sizeof(expected_identifier_string)];
+ id_vector identifier(this->make_vector());
+ EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
+ identifier));
+ EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
+
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ EXPECT_EQ(expected_identifier_string, identifier_string);
+}
+
+// Test that a build id note with fewer bytes than usual is handled.
+TYPED_TEST(FileIDTest, BuildIDShort) {
+ const uint8_t kExpectedIdentifierBytes[] =
+ {0x00, 0x01, 0x02, 0x03};
+ const string expected_identifier_string =
+ this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
text.Append(4096, 0);
elf.AddSection(".text", text, SHT_PROGBITS);
Notes notes(kLittleEndian);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
- sizeof(kExpectedIdentifier));
+ notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
+ sizeof(kExpectedIdentifierBytes));
elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
elf.Finish();
this->GetElfContents(elf);
+ id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
+ EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
- FileID::ConvertIdentifierToString(identifier, identifier_string,
- sizeof(identifier_string));
- EXPECT_STREQ(expected_identifier_string, identifier_string);
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ EXPECT_EQ(expected_identifier_string, identifier_string);
}
-TYPED_TEST(FileIDTest, BuildIDPH) {
- const uint8_t kExpectedIdentifier[sizeof(MDGUID)] =
+// Test that a build id note with more bytes than usual is handled.
+TYPED_TEST(FileIDTest, BuildIDLong) {
+ const uint8_t kExpectedIdentifierBytes[] =
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
- char expected_identifier_string[] =
- "00000000-0000-0000-0000-000000000000";
- FileID::ConvertIdentifierToString(kExpectedIdentifier,
- expected_identifier_string,
- sizeof(expected_identifier_string));
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
+ const string expected_identifier_string =
+ this->get_file_id(kExpectedIdentifierBytes);
- uint8_t identifier[sizeof(MDGUID)];
- char identifier_string[sizeof(expected_identifier_string)];
+ ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
+ Section text(kLittleEndian);
+ text.Append(4096, 0);
+ elf.AddSection(".text", text, SHT_PROGBITS);
+ Notes notes(kLittleEndian);
+ notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
+ sizeof(kExpectedIdentifierBytes));
+ elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
+ elf.Finish();
+ this->GetElfContents(elf);
+
+ id_vector identifier(this->make_vector());
+ EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
+ identifier));
+ EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
+
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ EXPECT_EQ(expected_identifier_string, identifier_string);
+}
+
+TYPED_TEST(FileIDTest, BuildIDPH) {
+ const uint8_t kExpectedIdentifierBytes[] =
+ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13};
+ const string expected_identifier_string =
+ this->get_file_id(kExpectedIdentifierBytes);
ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
Section text(kLittleEndian);
@@ -200,31 +262,25 @@ TYPED_TEST(FileIDTest, BuildIDPH) {
Notes notes(kLittleEndian);
notes.AddNote(0, "Linux",
reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifier,
- sizeof(kExpectedIdentifier));
+ notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
+ sizeof(kExpectedIdentifierBytes));
int note_idx = elf.AddSection(".note", notes, SHT_NOTE);
elf.AddSegment(note_idx, note_idx, PT_NOTE);
elf.Finish();
this->GetElfContents(elf);
+ id_vector identifier(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier));
+ EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
- FileID::ConvertIdentifierToString(identifier, identifier_string,
- sizeof(identifier_string));
- EXPECT_STREQ(expected_identifier_string, identifier_string);
+ string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
+ EXPECT_EQ(expected_identifier_string, identifier_string);
}
// Test to make sure two files with different text sections produce
// different hashes when not using a build id.
TYPED_TEST(FileIDTest, UniqueHashes) {
- char identifier_string_1[] =
- "00000000-0000-0000-0000-000000000000";
- char identifier_string_2[] =
- "00000000-0000-0000-0000-000000000000";
- uint8_t identifier_1[sizeof(MDGUID)];
- uint8_t identifier_2[sizeof(MDGUID)];
-
{
ELF elf1(EM_386, TypeParam::kClass, kLittleEndian);
Section foo_1(kLittleEndian);
@@ -237,10 +293,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
this->GetElfContents(elf1);
}
+ id_vector identifier_1(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier_1));
- FileID::ConvertIdentifierToString(identifier_1, identifier_string_1,
- sizeof(identifier_string_1));
+ string identifier_string_1 =
+ FileID::ConvertIdentifierToUUIDString(identifier_1);
{
ELF elf2(EM_386, TypeParam::kClass, kLittleEndian);
@@ -254,10 +311,11 @@ TYPED_TEST(FileIDTest, UniqueHashes) {
this->GetElfContents(elf2);
}
+ id_vector identifier_2(this->make_vector());
EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
identifier_2));
- FileID::ConvertIdentifierToString(identifier_2, identifier_string_2,
- sizeof(identifier_string_2));
+ string identifier_string_2 =
+ FileID::ConvertIdentifierToUUIDString(identifier_2);
- EXPECT_STRNE(identifier_string_1, identifier_string_2);
+ EXPECT_NE(identifier_string_1, identifier_string_2);
}