Support ELF64 in set_haiku_revision.

This commit is contained in:
Alex Smith
2012-08-11 09:17:15 +01:00
parent 8098ef47db
commit d384cac443
3 changed files with 223 additions and 129 deletions
+1 -6
View File
@@ -115,12 +115,7 @@ if $(TARGET_ARCH) = x86_64 {
} }
# kernel # kernel
if $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system : <revisioned>kernel_$(TARGET_ARCH) ;
# TODO x86_64: ELF64 support not added to set_haiku_revision.
AddFilesToFloppyBootArchive system : kernel_$(TARGET_ARCH) ;
} else {
AddFilesToFloppyBootArchive system : <revisioned>kernel_$(TARGET_ARCH) ;
}
# scripts and data files # scripts and data files
+2 -2
View File
@@ -45,7 +45,7 @@ SYSTEM_PREFERENCES = Appearance Backgrounds <preference>Deskbar FileTypes
SYSTEM_DEMOS = ; SYSTEM_DEMOS = ;
SYSTEM_LIBS = libbe.so libbnetapi.so libdebug.so libjpeg.so libnetwork.so SYSTEM_LIBS = libbe.so libbnetapi.so libdebug.so libjpeg.so libnetwork.so
libpng.so libroot.so libroot-addon-icu.so libpng.so <revisioned>libroot.so libroot-addon-icu.so
libtextencoding.so libtiff.so libtracker.so libtranslation.so libtextencoding.so libtiff.so libtracker.so libtranslation.so
libz.so libz.so
$(HAIKU_SHARED_LIBSTDC++) $(HAIKU_SHARED_LIBSUPC++) $(HAIKU_SHARED_LIBSTDC++) $(HAIKU_SHARED_LIBSUPC++)
@@ -118,7 +118,7 @@ AddDriversToHaikuImage input : ps2_hid usb_hid ;
AddDriversToHaikuImage net : $(SYSTEM_ADD_ONS_DRIVERS_NET) ; AddDriversToHaikuImage net : $(SYSTEM_ADD_ONS_DRIVERS_NET) ;
# kernel # kernel
AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; AddFilesToHaikuImage system : <revisioned>kernel_$(TARGET_ARCH) ;
# libs # libs
AddLibrariesToHaikuHybridImage system lib AddLibrariesToHaikuHybridImage system lib
+220 -121
View File
@@ -39,6 +39,13 @@ typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off; typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword; typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word; typedef uint32_t Elf32_Word;
typedef uint64_t Elf64_Addr;
typedef uint64_t Elf64_Off;
typedef uint16_t Elf64_Half;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
// e_ident indices // e_ident indices
#define EI_MAG0 0 #define EI_MAG0 0
@@ -69,6 +76,23 @@ typedef struct {
Elf32_Half e_shstrndx; Elf32_Half e_shstrndx;
} Elf32_Ehdr; } Elf32_Ehdr;
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
// e_ident EI_CLASS and EI_DATA values // e_ident EI_CLASS and EI_DATA values
#define ELFCLASSNONE 0 #define ELFCLASSNONE 0
#define ELFCLASS32 1 #define ELFCLASS32 1
@@ -89,6 +113,17 @@ typedef struct {
Elf32_Word p_align; Elf32_Word p_align;
} Elf32_Phdr; } Elf32_Phdr;
typedef struct {
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
// p_type // p_type
#define PT_NULL 0 #define PT_NULL 0
#define PT_LOAD 1 #define PT_LOAD 1
@@ -114,6 +149,19 @@ typedef struct {
Elf32_Word sh_entsize; Elf32_Word sh_entsize;
} Elf32_Shdr; } Elf32_Shdr;
typedef struct {
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
// sh_type values // sh_type values
#define SHT_NULL 0 #define SHT_NULL 0
#define SHT_PROGBITS 1 #define SHT_PROGBITS 1
@@ -135,7 +183,6 @@ typedef struct {
// special section indexes // special section indexes
#define SHN_UNDEF 0 #define SHN_UNDEF 0
static const uint32_t kMaxELFHeaderSize = sizeof(Elf32_Ehdr) + 32;
static const char kELFFileMagic[4] = { 0x7f, 'E', 'L', 'F' }; static const char kELFFileMagic[4] = { 0x7f, 'E', 'L', 'F' };
@@ -168,8 +215,7 @@ print_usage(bool error)
} }
// print_usage_and_exit // print_usage_and_exit
static static void
void
print_usage_and_exit(bool error) print_usage_and_exit(bool error)
{ {
print_usage(error); print_usage(error);
@@ -262,8 +308,8 @@ private:
struct SectionInfo { struct SectionInfo {
uint32_t type; uint32_t type;
uint32_t offset; off_t offset;
uint32_t size; size_t size;
const char* name; const char* name;
}; };
@@ -307,82 +353,17 @@ public:
if (fFileSize < 0) if (fFileSize < 0)
throw Exception("Failed to get the file size."); throw Exception("Failed to get the file size.");
// read ELF header // Read identification information
Elf32_Ehdr fileHeader; unsigned char ident[EI_NIDENT];
Read(0, &fileHeader, sizeof(Elf32_Ehdr), "Failed to read ELF header."); Read(0, ident, sizeof(ident), "Failed to read ELF identification.");
if (memcmp(ident, kELFFileMagic, sizeof(kELFFileMagic)) != 0)
throw Exception("Not a valid ELF file.");
fELFClass = ident[EI_CLASS];
// check data encoding (endianess) if (fELFClass == ELFCLASS64)
switch (fileHeader.e_ident[EI_DATA]) { _ParseELFHeader<Elf64_Ehdr, Elf64_Shdr>();
case ELFDATA2LSB: else
fHostEndianess = (htonl(1) != 1); _ParseELFHeader<Elf32_Ehdr, Elf32_Shdr>();
break;
case ELFDATA2MSB:
fHostEndianess = (htonl(1) == 1);
break;
default:
case ELFDATANONE:
throw Exception(EIO, "Unsupported ELF data encoding.");
break;
}
// get the header values
fELFHeaderSize = GetUInt16(fileHeader.e_ehsize);
fSectionHeaderTableOffset = GetUInt32(fileHeader.e_shoff);
fSectionHeaderSize = GetUInt16(fileHeader.e_shentsize);
fSectionHeaderCount = GetUInt16(fileHeader.e_shnum);
bool hasSectionHeaderTable = (fSectionHeaderTableOffset != 0);
// check the sanity of the header values
// ELF header size
if (fELFHeaderSize < sizeof(Elf32_Ehdr) || fELFHeaderSize > kMaxELFHeaderSize) {
throw Exception(EIO,
"Invalid ELF header: invalid ELF header size: %lu.",
fELFHeaderSize);
}
// section header table offset and entry count/size
uint32_t sectionHeaderTableSize = 0;
if (hasSectionHeaderTable) {
if (fSectionHeaderTableOffset < fELFHeaderSize
|| fSectionHeaderTableOffset > fFileSize) {
throw Exception(EIO, "Invalid ELF header: invalid section "
"header table offset: %lu.",
fSectionHeaderTableOffset);
}
sectionHeaderTableSize = fSectionHeaderSize * fSectionHeaderCount;
if (fSectionHeaderSize < sizeof(Elf32_Shdr)
|| fSectionHeaderTableOffset + sectionHeaderTableSize
> fFileSize) {
throw Exception(EIO, "Invalid ELF header: section header "
"table exceeds file: %lu.",
fSectionHeaderTableOffset
+ sectionHeaderTableSize);
}
// load section header string section
uint16_t sectionHeaderStringSectionIndex
= GetUInt16(fileHeader.e_shstrndx);
if (sectionHeaderStringSectionIndex != SHN_UNDEF) {
if (sectionHeaderStringSectionIndex >= fSectionHeaderCount) {
throw Exception(EIO, "Invalid ELF header: invalid section "
"header string section index: %lu.",
sectionHeaderStringSectionIndex);
}
// get the section info
SectionInfo info;
if (_ReadSectionHeader(sectionHeaderStringSectionIndex,
info)) {
fSectionHeaderStrings = new char[info.size + 1];
Read(info.offset, fSectionHeaderStrings, info.size,
"Failed to read section header string section.");
fSectionHeaderStringsLength = info.size;
// null-terminate to be on the safe side
fSectionHeaderStrings[info.size] = '\0';
}
}
}
} }
bool FindSectionByName(const char* name, SectionInfo& foundInfo) bool FindSectionByName(const char* name, SectionInfo& foundInfo)
@@ -392,9 +373,16 @@ public:
return false; return false;
// iterate through the section headers // iterate through the section headers
for (int32_t i = 0; i < (int32_t)fSectionHeaderCount; i++) { for (size_t i = 0; i < fSectionHeaderCount; i++) {
SectionInfo info; SectionInfo info;
if (_ReadSectionHeader(i, info)) {
bool result;
if (fELFClass == ELFCLASS64)
result = _ReadSectionHeader<Elf64_Shdr>(i, info);
else
result = _ReadSectionHeader<Elf32_Shdr>(i, info);
if (result) {
//printf("section %3d: offset: %7d, size: %7d, name: %s\n", i, info.offset, info.size, info.name); //printf("section %3d: offset: %7d, size: %7d, name: %s\n", i, info.offset, info.size, info.name);
if (strcmp(info.name, name) == 0) { if (strcmp(info.name, name) == 0) {
foundInfo = info; foundInfo = info;
@@ -457,44 +445,105 @@ public:
return lseek(fFD, currentPos, SEEK_SET); return lseek(fFD, currentPos, SEEK_SET);
} }
// GetInt16 template<typename Type>
int16_t GetInt16(int16_t value) Type GetValue(Type& value);
{
return (fHostEndianess ? value : _SwapUInt16(value));
}
// GetUInt16
uint16_t GetUInt16(uint16_t value)
{
return (fHostEndianess ? value : _SwapUInt16(value));
}
// GetInt32
int32_t GetInt32(int32_t value)
{
return (fHostEndianess ? value : _SwapUInt32(value));
}
// GetUInt32
uint32_t GetUInt32(uint32_t value)
{
return (fHostEndianess ? value : _SwapUInt32(value));
}
private: private:
template<typename EhdrType, typename ShdrType>
void _ParseELFHeader()
{
// read ELF header
EhdrType fileHeader;
Read(0, &fileHeader, sizeof(EhdrType), "Failed to read ELF header.");
// check data encoding (endianess)
switch (fileHeader.e_ident[EI_DATA]) {
case ELFDATA2LSB:
fHostEndianess = (htonl(1) != 1);
break;
case ELFDATA2MSB:
fHostEndianess = (htonl(1) == 1);
break;
default:
case ELFDATANONE:
throw Exception(EIO, "Unsupported ELF data encoding.");
break;
}
// get the header values
fELFHeaderSize = GetValue(fileHeader.e_ehsize);
fSectionHeaderTableOffset = GetValue(fileHeader.e_shoff);
fSectionHeaderSize = GetValue(fileHeader.e_shentsize);
fSectionHeaderCount = GetValue(fileHeader.e_shnum);
bool hasSectionHeaderTable = (fSectionHeaderTableOffset != 0);
// check the sanity of the header values
// ELF header size
if (fELFHeaderSize < sizeof(EhdrType)) {
throw Exception(EIO,
"Invalid ELF header: invalid ELF header size: %lu.",
fELFHeaderSize);
}
// section header table offset and entry count/size
if (hasSectionHeaderTable) {
if (fSectionHeaderTableOffset < (off_t)fELFHeaderSize
|| fSectionHeaderTableOffset > fFileSize) {
throw Exception(EIO, "Invalid ELF header: invalid section "
"header table offset: %llu.",
fSectionHeaderTableOffset);
}
size_t sectionHeaderTableSize
= fSectionHeaderSize * fSectionHeaderCount;
if (fSectionHeaderSize < (off_t)sizeof(ShdrType)
|| fSectionHeaderTableOffset + (off_t)sectionHeaderTableSize
> fFileSize) {
throw Exception(EIO, "Invalid ELF header: section header "
"table exceeds file: %llu.",
fSectionHeaderTableOffset
+ sectionHeaderTableSize);
}
// load section header string section
uint16_t sectionHeaderStringSectionIndex
= GetValue(fileHeader.e_shstrndx);
if (sectionHeaderStringSectionIndex != SHN_UNDEF) {
if (sectionHeaderStringSectionIndex >= fSectionHeaderCount) {
throw Exception(EIO, "Invalid ELF header: invalid section "
"header string section index: %u.",
sectionHeaderStringSectionIndex);
}
// get the section info
SectionInfo info;
if (_ReadSectionHeader<ShdrType>(sectionHeaderStringSectionIndex,
info)) {
fSectionHeaderStrings = new char[info.size + 1];
Read(info.offset, fSectionHeaderStrings, info.size,
"Failed to read section header string section.");
fSectionHeaderStringsLength = info.size;
// null-terminate to be on the safe side
fSectionHeaderStrings[info.size] = '\0';
}
}
}
}
template<typename ShdrType>
bool _ReadSectionHeader(int index, SectionInfo& info) bool _ReadSectionHeader(int index, SectionInfo& info)
{ {
uint32_t shOffset = fSectionHeaderTableOffset off_t shOffset = fSectionHeaderTableOffset
+ index * fSectionHeaderSize; + index * fSectionHeaderSize;
Elf32_Shdr sectionHeader; ShdrType sectionHeader;
Read(shOffset, &sectionHeader, sizeof(Elf32_Shdr), Read(shOffset, &sectionHeader, sizeof(ShdrType),
"Failed to read ELF section header."); "Failed to read ELF section header.");
// get the header values // get the header values
uint32_t type = GetUInt32(sectionHeader.sh_type); uint32_t type = GetValue(sectionHeader.sh_type);
uint32_t offset = GetUInt32(sectionHeader.sh_offset); off_t offset = GetValue(sectionHeader.sh_offset);
uint32_t size = GetUInt32(sectionHeader.sh_size); size_t size = GetValue(sectionHeader.sh_size);
uint32_t nameIndex = GetUInt32(sectionHeader.sh_name); uint32_t nameIndex = GetValue(sectionHeader.sh_name);
// check the values // check the values
// SHT_NULL marks the header unused, // SHT_NULL marks the header unused,
@@ -503,14 +552,14 @@ private:
// SHT_NOBITS sections take no space in the file // SHT_NOBITS sections take no space in the file
if (type != SHT_NOBITS) { if (type != SHT_NOBITS) {
if (offset < fELFHeaderSize || offset > fFileSize) { if (offset < (off_t)fELFHeaderSize || offset > fFileSize) {
throw Exception(EIO, "Invalid ELF section header: " throw Exception(EIO, "Invalid ELF section header: "
"invalid section offset: %lu.", offset); "invalid section offset: %llu.", offset);
} }
uint32_t sectionEnd = offset + size; off_t sectionEnd = offset + size;
if (sectionEnd > fFileSize) { if (sectionEnd > fFileSize) {
throw Exception(EIO, "Invalid ELF section header: " throw Exception(EIO, "Invalid ELF section header: "
"section exceeds file: %lu.", sectionEnd); "section exceeds file: %llu.", sectionEnd);
} }
} }
@@ -546,19 +595,69 @@ private:
| _SwapUInt16(uint16_t(value >> 16)); | _SwapUInt16(uint16_t(value >> 16));
} }
// _SwapUInt64
static inline uint64_t _SwapUInt64(uint64_t value)
{
return ((uint64_t)_SwapUInt32(value & 0xffffffff) << 32)
| _SwapUInt32(uint32_t(value >> 32));
}
private: private:
int fFD; int fFD;
uint8_t fELFClass;
bool fHostEndianess; bool fHostEndianess;
off_t fFileSize; off_t fFileSize;
uint32_t fELFHeaderSize; size_t fELFHeaderSize;
uint32_t fSectionHeaderTableOffset; off_t fSectionHeaderTableOffset;
uint32_t fSectionHeaderSize; size_t fSectionHeaderSize;
uint32_t fSectionHeaderCount; size_t fSectionHeaderCount;
char* fSectionHeaderStrings; char* fSectionHeaderStrings;
int fSectionHeaderStringsLength; uint32_t fSectionHeaderStringsLength;
}; };
template<>
int16_t ELFObject::GetValue(int16_t& value)
{
return (fHostEndianess ? value : _SwapUInt16(value));
}
template<>
uint16_t ELFObject::GetValue(uint16_t& value)
{
return (fHostEndianess ? value : _SwapUInt16(value));
}
template<>
int32_t ELFObject::GetValue(int32_t& value)
{
return (fHostEndianess ? value : _SwapUInt32(value));
}
template<>
uint32_t ELFObject::GetValue(uint32_t& value)
{
return (fHostEndianess ? value : _SwapUInt32(value));
}
template<>
int64_t ELFObject::GetValue(int64_t& value)
{
return (fHostEndianess ? value : _SwapUInt64(value));
}
template<>
uint64_t ELFObject::GetValue(uint64_t& value)
{
return (fHostEndianess ? value : _SwapUInt64(value));
}
// main // main
int int
main(int argc, const char* const* argv) main(int argc, const char* const* argv)