aboutsummaryrefslogtreecommitdiff
path: root/src/common/linux
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-08-27 18:52:09 +0000
committermark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-08-27 18:52:09 +0000
commit3a7466663c7b8ddc550a96666c2a14c82d91536f (patch)
treecc6c980dec48d4a80561d28f8353d077d054e6ba /src/common/linux
parentUse <inttypes.h> macros for formatting fixed-width types. (diff)
downloadbreakpad-3a7466663c7b8ddc550a96666c2a14c82d91536f.tar.xz
Linux FileID should work with ELFCLASS32 and ELFCLASS64 regardless of what's
native. BUG=399 TEST=none Review URL: http://breakpad.appspot.com/178001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@677 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/linux')
-rw-r--r--src/common/linux/file_id.cc81
-rw-r--r--src/common/linux/file_id_unittest.cc67
2 files changed, 123 insertions, 25 deletions
diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc
index d2461b9c..a4e3a6e3 100644
--- a/src/common/linux/file_id.cc
+++ b/src/common/linux/file_id.cc
@@ -56,37 +56,44 @@ FileID::FileID(const char* path) {
strncpy(path_, path, sizeof(path_));
}
-// These two functions are also used inside the crashed process, so be safe
+struct ElfClass32 {
+ typedef Elf32_Ehdr Ehdr;
+ typedef Elf32_Shdr Shdr;
+ static const int kClass = ELFCLASS32;
+};
+
+struct ElfClass64 {
+ typedef Elf64_Ehdr Ehdr;
+ typedef Elf64_Shdr Shdr;
+ static const int kClass = ELFCLASS64;
+};
+
+// These three functions are also used inside the crashed process, so be safe
// and use the syscall/libc wrappers instead of direct syscalls or libc.
- static bool FindElfTextSection(const void *elf_mapped_base,
- const void **text_start,
- int *text_size) {
- assert(elf_mapped_base);
+template<typename ElfClass>
+static void FindElfClassTextSection(const char *elf_base,
+ const void **text_start,
+ int *text_size) {
+ typedef typename ElfClass::Ehdr Ehdr;
+ typedef typename ElfClass::Shdr Shdr;
+
+ assert(elf_base);
assert(text_start);
assert(text_size);
- const char* elf_base =
- static_cast<const char*>(elf_mapped_base);
- const ElfW(Ehdr)* elf_header =
- reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
- if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0)
- return false;
-#if __ELF_NATIVE_CLASS == 32
-#define ELFCLASS ELFCLASS32
-#else
-#define ELFCLASS ELFCLASS64
-#endif
- //TODO: support dumping 32-bit binaries from a 64-bit dump_syms?
- if (elf_header->e_ident[EI_CLASS] != ELFCLASS)
- return false;
- *text_start = NULL;
- *text_size = 0;
- const ElfW(Shdr)* sections =
- reinterpret_cast<const ElfW(Shdr)*>(elf_base + elf_header->e_shoff);
+ assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
+
const char* text_section_name = ".text";
int name_len = my_strlen(text_section_name);
- const ElfW(Shdr)* string_section = sections + elf_header->e_shstrndx;
- const ElfW(Shdr)* text_section = NULL;
+
+ const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
+ assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
+
+ const Shdr* sections =
+ reinterpret_cast<const Shdr*>(elf_base + elf_header->e_shoff);
+ const Shdr* string_section = sections + elf_header->e_shstrndx;
+
+ const Shdr* text_section = NULL;
for (int i = 0; i < elf_header->e_shnum; ++i) {
if (sections[i].sh_type == SHT_PROGBITS) {
const char* section_name = (char*)(elf_base +
@@ -102,6 +109,30 @@ FileID::FileID(const char* path) {
*text_start = elf_base + text_section->sh_offset;
*text_size = text_section->sh_size;
}
+}
+
+static bool FindElfTextSection(const void *elf_mapped_base,
+ const void **text_start,
+ int *text_size) {
+ assert(elf_mapped_base);
+ assert(text_start);
+ assert(text_size);
+
+ const char* elf_base =
+ static_cast<const char*>(elf_mapped_base);
+ const ElfW(Ehdr)* elf_header =
+ reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
+ if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0)
+ return false;
+
+ if (elf_header->e_ident[EI_CLASS] == ELFCLASS32) {
+ FindElfClassTextSection<ElfClass32>(elf_base, text_start, text_size);
+ } else if (elf_header->e_ident[EI_CLASS] == ELFCLASS64) {
+ FindElfClassTextSection<ElfClass64>(elf_base, text_start, text_size);
+ } else {
+ return false;
+ }
+
return true;
}
diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc
index e15d39fb..e28a2f09 100644
--- a/src/common/linux/file_id_unittest.cc
+++ b/src/common/linux/file_id_unittest.cc
@@ -29,6 +29,7 @@
// Unit tests for FileID
+#include <elf.h>
#include <stdlib.h>
#include "common/linux/file_id.h"
@@ -74,3 +75,69 @@ TEST(FileIDTest, FileIDStrip) {
EXPECT_STREQ(identifier_string1, identifier_string2);
unlink(templ);
}
+
+struct ElfClass32 {
+ typedef Elf32_Ehdr Ehdr;
+ typedef Elf32_Shdr Shdr;
+ static const int kClass = ELFCLASS32;
+};
+
+struct ElfClass64 {
+ typedef Elf64_Ehdr Ehdr;
+ typedef Elf64_Shdr Shdr;
+ static const int kClass = ELFCLASS64;
+};
+
+template<typename ElfClass>
+struct ElfishElf {
+ typedef typename ElfClass::Ehdr Ehdr;
+ typedef typename ElfClass::Shdr Shdr;
+
+ Ehdr elf_header;
+ Shdr text_header;
+ Shdr string_header;
+ char text_section[128];
+ char string_section[8];
+
+ static void Populate(ElfishElf* elf) {
+ memset(elf, 0, sizeof(ElfishElf));
+ memcpy(elf, ELFMAG, SELFMAG);
+ elf->elf_header.e_ident[EI_CLASS] = ElfClass::kClass;
+ elf->elf_header.e_shoff = offsetof(ElfishElf, text_header);
+ elf->elf_header.e_shnum = 2;
+ elf->elf_header.e_shstrndx = 1;
+ elf->text_header.sh_name = 0;
+ elf->text_header.sh_type = SHT_PROGBITS;
+ elf->text_header.sh_offset = offsetof(ElfishElf, text_section);
+ elf->text_header.sh_size = sizeof(text_section);
+ for (size_t i = 0; i < sizeof(text_section); ++i) {
+ elf->text_section[i] = i * 3;
+ }
+ elf->string_header.sh_offset = offsetof(ElfishElf, string_section);
+ strcpy(elf->string_section, ".text");
+ }
+};
+
+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)];
+
+ ElfishElf<ElfClass32> elf32;
+ ElfishElf<ElfClass32>::Populate(&elf32);
+ EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(&elf32, identifier));
+ FileID::ConvertIdentifierToString(identifier, identifier_string,
+ sizeof(identifier_string));
+ EXPECT_STREQ(expected_identifier_string, identifier_string);
+
+ memset(identifier, 0, sizeof(identifier));
+ memset(identifier_string, 0, sizeof(identifier_string));
+
+ ElfishElf<ElfClass64> elf64;
+ ElfishElf<ElfClass64>::Populate(&elf64);
+ EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(&elf64, identifier));
+ FileID::ConvertIdentifierToString(identifier, identifier_string,
+ sizeof(identifier_string));
+ EXPECT_STREQ(expected_identifier_string, identifier_string);
+}