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
This commit is contained in:
mark@chromium.org 2010-08-27 18:52:09 +00:00
parent 8ca54e486c
commit 3a7466663c
2 changed files with 123 additions and 25 deletions

View File

@ -56,37 +56,44 @@ FileID::FileID(const char* path) {
strncpy(path_, path, sizeof(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. // and use the syscall/libc wrappers instead of direct syscalls or libc.
static bool FindElfTextSection(const void *elf_mapped_base, template<typename ElfClass>
const void **text_start, static void FindElfClassTextSection(const char *elf_base,
int *text_size) { const void **text_start,
assert(elf_mapped_base); int *text_size) {
typedef typename ElfClass::Ehdr Ehdr;
typedef typename ElfClass::Shdr Shdr;
assert(elf_base);
assert(text_start); assert(text_start);
assert(text_size); assert(text_size);
const char* elf_base = assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
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);
const char* text_section_name = ".text"; const char* text_section_name = ".text";
int name_len = my_strlen(text_section_name); 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) { for (int i = 0; i < elf_header->e_shnum; ++i) {
if (sections[i].sh_type == SHT_PROGBITS) { if (sections[i].sh_type == SHT_PROGBITS) {
const char* section_name = (char*)(elf_base + 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_start = elf_base + text_section->sh_offset;
*text_size = text_section->sh_size; *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; return true;
} }

View File

@ -29,6 +29,7 @@
// Unit tests for FileID // Unit tests for FileID
#include <elf.h>
#include <stdlib.h> #include <stdlib.h>
#include "common/linux/file_id.h" #include "common/linux/file_id.h"
@ -74,3 +75,69 @@ TEST(FileIDTest, FileIDStrip) {
EXPECT_STREQ(identifier_string1, identifier_string2); EXPECT_STREQ(identifier_string1, identifier_string2);
unlink(templ); 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);
}