added 1 changeset to branch 'refs/remotes/xyzzy-github/x86_64' old head: 8098ef47db1f499e149cd5757798687267813cc2 new head: d384cac4439511a49ec1b0b0c673bbcb324e6fdb ---------------------------------------------------------------------------- d384cac: Support ELF64 in set_haiku_revision. [ Alex Smith <alex@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: d384cac4439511a49ec1b0b0c673bbcb324e6fdb Author: Alex Smith <alex@xxxxxxxxxxxxxxxx> Date: Sat Aug 11 08:17:15 2012 UTC ---------------------------------------------------------------------------- 3 files changed, 220 insertions(+), 126 deletions(-) build/jam/FloppyBootImage | 7 +- build/jam/Haiku64Image | 4 +- src/tools/set_haiku_revision.cpp | 335 ++++++++++++++++++++++------------ ---------------------------------------------------------------------------- diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index 1538fa7..fa713da 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -115,12 +115,7 @@ if $(TARGET_ARCH) = x86_64 { } # kernel -if $(TARGET_ARCH) = x86_64 { - # TODO x86_64: ELF64 support not added to set_haiku_revision. - AddFilesToFloppyBootArchive system : kernel_$(TARGET_ARCH) ; -} else { - AddFilesToFloppyBootArchive system : <revisioned>kernel_$(TARGET_ARCH) ; -} +AddFilesToFloppyBootArchive system : <revisioned>kernel_$(TARGET_ARCH) ; # scripts and data files diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 2e0d698..1c6e288 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -45,7 +45,7 @@ SYSTEM_PREFERENCES = Appearance Backgrounds <preference>Deskbar FileTypes SYSTEM_DEMOS = ; 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 libz.so $(HAIKU_SHARED_LIBSTDC++) $(HAIKU_SHARED_LIBSUPC++) @@ -118,7 +118,7 @@ AddDriversToHaikuImage input : ps2_hid usb_hid ; AddDriversToHaikuImage net : $(SYSTEM_ADD_ONS_DRIVERS_NET) ; # kernel -AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; +AddFilesToHaikuImage system : <revisioned>kernel_$(TARGET_ARCH) ; # libs AddLibrariesToHaikuHybridImage system lib diff --git a/src/tools/set_haiku_revision.cpp b/src/tools/set_haiku_revision.cpp index 5022398..acaa697 100644 --- a/src/tools/set_haiku_revision.cpp +++ b/src/tools/set_haiku_revision.cpp @@ -39,6 +39,13 @@ typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Off; typedef int32_t Elf32_Sword; 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 #define EI_MAG0 0 @@ -69,6 +76,23 @@ typedef struct { Elf32_Half e_shstrndx; } 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 #define ELFCLASSNONE 0 #define ELFCLASS32 1 @@ -89,6 +113,17 @@ typedef struct { Elf32_Word p_align; } 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 #define PT_NULL 0 #define PT_LOAD 1 @@ -114,6 +149,19 @@ typedef struct { Elf32_Word sh_entsize; } 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 #define SHT_NULL 0 #define SHT_PROGBITS 1 @@ -135,7 +183,6 @@ typedef struct { // special section indexes #define SHN_UNDEF 0 -static const uint32_t kMaxELFHeaderSize = sizeof(Elf32_Ehdr) + 32; static const char kELFFileMagic[4] = { 0x7f, 'E', 'L', 'F' }; @@ -168,8 +215,7 @@ print_usage(bool error) } // print_usage_and_exit -static -void +static void print_usage_and_exit(bool error) { print_usage(error); @@ -262,8 +308,8 @@ private: struct SectionInfo { uint32_t type; - uint32_t offset; - uint32_t size; + off_t offset; + size_t size; const char* name; }; @@ -307,82 +353,17 @@ public: if (fFileSize < 0) throw Exception("Failed to get the file size."); - // read ELF header - Elf32_Ehdr fileHeader; - Read(0, &fileHeader, sizeof(Elf32_Ehdr), "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 = 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'; - } - } - } + // Read identification information + unsigned char ident[EI_NIDENT]; + 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]; + + if (fELFClass == ELFCLASS64) + _ParseELFHeader<Elf64_Ehdr, Elf64_Shdr>(); + else + _ParseELFHeader<Elf32_Ehdr, Elf32_Shdr>(); } bool FindSectionByName(const char* name, SectionInfo& foundInfo) @@ -392,9 +373,16 @@ public: return false; // 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; - 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); if (strcmp(info.name, name) == 0) { foundInfo = info; @@ -457,44 +445,105 @@ public: return lseek(fFD, currentPos, SEEK_SET); } - // GetInt16 - int16_t GetInt16(int16_t value) - { - return (fHostEndianess ? value : _SwapUInt16(value)); - } + template<typename Type> + Type GetValue(Type& value); - // GetUInt16 - uint16_t GetUInt16(uint16_t value) +private: + template<typename EhdrType, typename ShdrType> + void _ParseELFHeader() { - return (fHostEndianess ? value : _SwapUInt16(value)); - } + // read ELF header + EhdrType fileHeader; + Read(0, &fileHeader, sizeof(EhdrType), "Failed to read ELF header."); - // GetInt32 - int32_t GetInt32(int32_t value) - { - return (fHostEndianess ? value : _SwapUInt32(value)); - } + // 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; + } - // GetUInt32 - uint32_t GetUInt32(uint32_t value) - { - return (fHostEndianess ? value : _SwapUInt32(value)); + // 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'; + } + } + } } -private: + template<typename ShdrType> bool _ReadSectionHeader(int index, SectionInfo& info) { - uint32_t shOffset = fSectionHeaderTableOffset + off_t shOffset = fSectionHeaderTableOffset + index * fSectionHeaderSize; - Elf32_Shdr sectionHeader; - Read(shOffset, §ionHeader, sizeof(Elf32_Shdr), + ShdrType sectionHeader; + Read(shOffset, §ionHeader, sizeof(ShdrType), "Failed to read ELF section header."); // get the header values - uint32_t type = GetUInt32(sectionHeader.sh_type); - uint32_t offset = GetUInt32(sectionHeader.sh_offset); - uint32_t size = GetUInt32(sectionHeader.sh_size); - uint32_t nameIndex = GetUInt32(sectionHeader.sh_name); + uint32_t type = GetValue(sectionHeader.sh_type); + off_t offset = GetValue(sectionHeader.sh_offset); + size_t size = GetValue(sectionHeader.sh_size); + uint32_t nameIndex = GetValue(sectionHeader.sh_name); // check the values // SHT_NULL marks the header unused, @@ -503,14 +552,14 @@ private: // SHT_NOBITS sections take no space in the file if (type != SHT_NOBITS) { - if (offset < fELFHeaderSize || offset > fFileSize) { + if (offset < (off_t)fELFHeaderSize || offset > fFileSize) { 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) { 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)); } + // _SwapUInt64 + static inline uint64_t _SwapUInt64(uint64_t value) + { + return ((uint64_t)_SwapUInt32(value & 0xffffffff) << 32) + | _SwapUInt32(uint32_t(value >> 32)); + } + private: int fFD; + uint8_t fELFClass; bool fHostEndianess; off_t fFileSize; - uint32_t fELFHeaderSize; - uint32_t fSectionHeaderTableOffset; - uint32_t fSectionHeaderSize; - uint32_t fSectionHeaderCount; + size_t fELFHeaderSize; + off_t fSectionHeaderTableOffset; + size_t fSectionHeaderSize; + size_t fSectionHeaderCount; 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 int main(int argc, const char* const* argv)