Debugger: Make ElfFile more flexible

* It was previously geared towards shared object files. Now it is
  fairly agostic and also accepts e.g. files without sections and
  different endianess.
* The handling of 32 vs. 64 bit files works a bit differently now.
  There're structs ElfClass32 and ElfClass64 now which provide the
  types for the respective bitness.
* Add a few more getters.
This commit is contained in:
Ingo Weinhold 2016-04-24 18:34:07 +02:00
parent 6dc2384f6e
commit 05c7cd7647
3 changed files with 299 additions and 181 deletions

View File

@ -1584,11 +1584,11 @@ DwarfFile::_ParseEntryAttributes(DataReader& dataReader,
case DW_FORM_strp:
{
if (fDebugStringSection != NULL) {
off_t offset = unit->IsDwarf64()
? (off_t)dataReader.Read<uint64>(0)
: (off_t)dataReader.Read<uint32>(0);
uint64 offset = unit->IsDwarf64()
? dataReader.Read<uint64>(0)
: dataReader.Read<uint32>(0);
if (offset >= fDebugStringSection->Size()) {
WARNING("Invalid DW_FORM_strp offset: %" B_PRIdOFF "\n",
WARNING("Invalid DW_FORM_strp offset: %" B_PRIu64 "\n",
offset);
return B_BAD_DATA;
}
@ -2097,7 +2097,7 @@ DwarfFile::_ParseCIEHeader(ElfSection* debugFrameSection,
CfaContext& context, off_t cieOffset, CIEAugmentation& cieAugmentation,
DataReader& dataReader, off_t& _cieRemaining)
{
if (cieOffset < 0 || cieOffset >= debugFrameSection->Size())
if (cieOffset < 0 || (uint64)cieOffset >= debugFrameSection->Size())
return B_BAD_DATA;
dataReader.SetTo((uint8*)debugFrameSection->Data() + cieOffset,

View File

@ -23,7 +23,7 @@
// #pragma mark - ElfSection
ElfSection::ElfSection(const char* name, int fd, off_t offset, off_t size,
ElfSection::ElfSection(const char* name, int fd, uint64 offset, uint64 size,
target_addr_t loadAddress, uint32 flags)
:
fName(name),
@ -57,7 +57,7 @@ ElfSection::Load()
return B_NO_MEMORY;
ssize_t bytesRead = pread(fFD, fData, fSize, fOffset);
if (bytesRead != fSize) {
if (bytesRead < 0 || (uint64)bytesRead != fSize) {
free(fData);
fData = NULL;
return bytesRead < 0 ? errno : B_ERROR;
@ -84,14 +84,15 @@ ElfSection::Unload()
// #pragma mark - ElfSegment
ElfSegment::ElfSegment(off_t fileOffset, off_t fileSize,
target_addr_t loadAddress, target_size_t loadSize, bool writable)
ElfSegment::ElfSegment(uint32 type, uint64 fileOffset, uint64 fileSize,
target_addr_t loadAddress, target_size_t loadSize, uint32 flags)
:
fFileOffset(fileOffset),
fFileSize(fileSize),
fLoadAddress(loadAddress),
fLoadSize(loadSize),
fWritable(writable)
fType(type),
fFlags(flags)
{
}
@ -107,19 +108,19 @@ ElfSegment::~ElfSegment()
ElfFile::ElfFile()
:
fFileSize(0),
fFD(-1)
fFD(-1),
fType(ET_NONE),
fMachine(EM_NONE),
f64Bit(false),
fSwappedByteOrder(false),
fSections(16, true),
fSegments(16, true)
{
}
ElfFile::~ElfFile()
{
while (ElfSegment* segment = fSegments.RemoveHead())
delete segment;
while (ElfSection* section = fSections.RemoveHead())
delete section;
if (fFD >= 0)
close(fFD);
}
@ -143,16 +144,40 @@ ElfFile::Init(const char* fileName)
}
fFileSize = st.st_size;
// Read the identification information to determine the class.
// Read the identification information to determine whether this is an
// ELF file at all and some relevant properties for reading it.
uint8 elfIdent[EI_NIDENT];
ssize_t bytesRead = pread(fFD, elfIdent, sizeof(elfIdent), 0);
if (bytesRead != (ssize_t)sizeof(elfIdent))
return bytesRead < 0 ? errno : B_ERROR;
if(elfIdent[EI_CLASS] == ELFCLASS64)
return _LoadFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(fileName);
else
return _LoadFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(fileName);
// magic
if (!memcmp(elfIdent, ELF_MAGIC, 4) == 0)
return B_ERROR;
// endianess
if (elfIdent[EI_DATA] == ELFDATA2LSB) {
fSwappedByteOrder = B_HOST_IS_BENDIAN != 0;
} else if (elfIdent[EI_DATA] == ELFDATA2MSB) {
fSwappedByteOrder = B_HOST_IS_LENDIAN != 0;
} else {
WARNING("%s: Invalid ELF data byte order: %d\n", fileName,
elfIdent[EI_DATA]);
return B_BAD_DATA;
}
// determine class and load
if(elfIdent[EI_CLASS] == ELFCLASS64) {
f64Bit = true;
return _LoadFile<ElfClass64>(fileName);
}
if(elfIdent[EI_CLASS] == ELFCLASS32) {
f64Bit = false;
return _LoadFile<ElfClass32>(fileName);
}
WARNING("%s: Invalid ELF class: %d\n", fileName, elfIdent[EI_CLASS]);
return B_BAD_DATA;
}
@ -178,8 +203,9 @@ ElfFile::PutSection(ElfSection* section)
ElfSection*
ElfFile::FindSection(const char* name) const
{
for (SectionList::ConstIterator it = fSections.GetIterator();
ElfSection* section = it.Next();) {
int32 count = fSections.CountItems();
for (int32 i = 0; i < count; i++) {
ElfSection* section = fSections.ItemAt(i);
if (strcmp(section->Name(), name) == 0)
return section;
}
@ -191,9 +217,10 @@ ElfFile::FindSection(const char* name) const
ElfSegment*
ElfFile::TextSegment() const
{
for (SegmentList::ConstIterator it = fSegments.GetIterator();
ElfSegment* segment = it.Next();) {
if (!segment->IsWritable())
int32 count = fSegments.CountItems();
for (int32 i = 0; i < count; i++) {
ElfSegment* segment = fSegments.ItemAt(i);
if (segment->Type() == PT_LOAD && !segment->IsWritable())
return segment;
}
@ -204,9 +231,10 @@ ElfFile::TextSegment() const
ElfSegment*
ElfFile::DataSegment() const
{
for (SegmentList::ConstIterator it = fSegments.GetIterator();
ElfSegment* segment = it.Next();) {
if (segment->IsWritable())
int32 count = fSegments.CountItems();
for (int32 i = 0; i < count; i++) {
ElfSegment* segment = fSegments.ItemAt(i);
if (segment->Type() == PT_LOAD && segment->IsWritable())
return segment;
}
@ -214,128 +242,150 @@ ElfFile::DataSegment() const
}
template<typename Ehdr, typename Phdr, typename Shdr>
template<typename ElfClass>
status_t
ElfFile::_LoadFile(const char* fileName)
{
Ehdr elfHeader;
typedef typename ElfClass::Ehdr Ehdr;
typedef typename ElfClass::Phdr Phdr;
typedef typename ElfClass::Shdr Shdr;
// read the elf header
ssize_t bytesRead = pread(fFD, &elfHeader, sizeof(Ehdr), 0);
if (bytesRead != (ssize_t)sizeof(Ehdr))
Ehdr elfHeader;
ssize_t bytesRead = pread(fFD, &elfHeader, sizeof(elfHeader), 0);
if (bytesRead != (ssize_t)sizeof(elfHeader))
return bytesRead < 0 ? errno : B_ERROR;
// check the ELF header
if (!_CheckRange(0, sizeof(Ehdr)) || !_CheckElfHeader(elfHeader)) {
WARNING("\"%s\": Not an ELF file\n", fileName);
if (!_CheckRange(0, sizeof(elfHeader))
|| !_CheckElfHeader<ElfClass>(elfHeader)) {
WARNING("\"%s\": Not a valid ELF file\n", fileName);
return B_BAD_DATA;
}
// check section header table values
off_t sectionHeadersOffset = elfHeader.e_shoff;
size_t sectionHeaderSize = elfHeader.e_shentsize;
int sectionCount = elfHeader.e_shnum;
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
WARNING("\"%s\": Invalid ELF header\n", fileName);
return B_BAD_DATA;
}
fType = Get(elfHeader.e_type);
fMachine = Get(elfHeader.e_machine);
// read the section header table
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
if (sectionHeaderTable == NULL)
return B_NO_MEMORY;
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
sectionHeadersOffset);
if (bytesRead != (ssize_t)sectionHeaderTableSize)
return bytesRead < 0 ? errno : B_ERROR;
// check and get the section header string section
Shdr* stringSectionHeader = (Shdr*)(sectionHeaderTable
+ elfHeader.e_shstrndx * sectionHeaderSize);
if (!_CheckRange(stringSectionHeader->sh_offset,
stringSectionHeader->sh_size)) {
WARNING("\"%s\": Invalid string section header\n", fileName);
return B_BAD_DATA;
}
size_t sectionStringSize = stringSectionHeader->sh_size;
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(".shstrtab",
fFD, stringSectionHeader->sh_offset, sectionStringSize,
stringSectionHeader->sh_addr, stringSectionHeader->sh_flags);
if (sectionStringSection == NULL)
return B_NO_MEMORY;
fSections.Add(sectionStringSection);
status_t error = sectionStringSection->Load();
if (error != B_OK)
return error;
const char* sectionStrings = (const char*)sectionStringSection->Data();
// read the other sections
for (int i = 0; i < sectionCount; i++) {
Shdr* sectionHeader = (Shdr*)(sectionHeaderTable + i
* sectionHeaderSize);
// skip invalid sections and the section header string section
const char* name = sectionStrings + sectionHeader->sh_name;
if (sectionHeader->sh_name >= sectionStringSize
|| !_CheckRange(sectionHeader->sh_offset, sectionHeader->sh_size)
|| i == elfHeader.e_shstrndx) {
continue;
if (Get(elfHeader.e_shnum) > 0) {
// check section header table values
uint64 sectionHeadersOffset = Get(elfHeader.e_shoff);
size_t sectionHeaderSize = Get(elfHeader.e_shentsize);
int sectionCount = Get(elfHeader.e_shnum);
size_t sectionHeaderTableSize = sectionHeaderSize * sectionCount;
if (!_CheckRange(sectionHeadersOffset, sectionHeaderTableSize)) {
WARNING("\"%s\": Invalid ELF header\n", fileName);
return B_BAD_DATA;
}
// create an ElfSection
ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
sectionHeader->sh_offset, sectionHeader->sh_size,
sectionHeader->sh_addr, sectionHeader->sh_flags);
if (section == NULL)
// read the section header table
uint8* sectionHeaderTable = (uint8*)malloc(sectionHeaderTableSize);
if (sectionHeaderTable == NULL)
return B_NO_MEMORY;
fSections.Add(section);
}
MemoryDeleter sectionHeaderTableDeleter(sectionHeaderTable);
// check program header table values
off_t programHeadersOffset = elfHeader.e_phoff;
size_t programHeaderSize = elfHeader.e_phentsize;
int segmentCount = elfHeader.e_phnum;
size_t programHeaderTableSize = programHeaderSize * segmentCount;
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
WARNING("\"%s\": Invalid ELF header\n", fileName);
return B_BAD_DATA;
}
bytesRead = pread(fFD, sectionHeaderTable, sectionHeaderTableSize,
sectionHeadersOffset);
if (bytesRead != (ssize_t)sectionHeaderTableSize)
return bytesRead < 0 ? errno : B_ERROR;
// read the program header table
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
if (programHeaderTable == NULL)
return B_NO_MEMORY;
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
// check and get the section header string section
Shdr* stringSectionHeader = (Shdr*)(sectionHeaderTable
+ Get(elfHeader.e_shstrndx) * sectionHeaderSize);
if (!_CheckRange(Get(stringSectionHeader->sh_offset),
Get(stringSectionHeader->sh_size))) {
WARNING("\"%s\": Invalid string section header\n", fileName);
return B_BAD_DATA;
}
size_t sectionStringSize = Get(stringSectionHeader->sh_size);
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
programHeadersOffset);
if (bytesRead != (ssize_t)programHeaderTableSize)
return bytesRead < 0 ? errno : B_ERROR;
// read the program headers and create ElfSegment objects
for (int i = 0; i < segmentCount; i++) {
Phdr* programHeader = (Phdr*)(programHeaderTable + i
* programHeaderSize);
// skip program headers we aren't interested in or that are invalid
if (programHeader->p_type != PT_LOAD || programHeader->p_filesz == 0
|| programHeader->p_memsz == 0
|| !_CheckRange(programHeader->p_offset, programHeader->p_filesz)) {
continue;
ElfSection* sectionStringSection = new(std::nothrow) ElfSection(
".shstrtab", fFD, Get(stringSectionHeader->sh_offset),
sectionStringSize, Get(stringSectionHeader->sh_addr),
Get(stringSectionHeader->sh_flags));
if (sectionStringSection == NULL)
return B_NO_MEMORY;
if (!fSections.AddItem(sectionStringSection)) {
delete sectionStringSection;
return B_NO_MEMORY;
}
// create an ElfSegment
ElfSegment* segment = new(std::nothrow) ElfSegment(
programHeader->p_offset, programHeader->p_filesz,
programHeader->p_vaddr, programHeader->p_memsz,
(programHeader->p_flags & PF_WRITE) != 0);
if (segment == NULL)
status_t error = sectionStringSection->Load();
if (error != B_OK)
return error;
const char* sectionStrings = (const char*)sectionStringSection->Data();
// read the other sections
for (int i = 0; i < sectionCount; i++) {
Shdr* sectionHeader = (Shdr*)(sectionHeaderTable + i
* sectionHeaderSize);
// skip invalid sections and the section header string section
const char* name = sectionStrings + Get(sectionHeader->sh_name);
if (Get(sectionHeader->sh_name) >= sectionStringSize
|| !_CheckRange(Get(sectionHeader->sh_offset),
Get(sectionHeader->sh_size))
|| i == Get(elfHeader.e_shstrndx)) {
continue;
}
// create an ElfSection
ElfSection* section = new(std::nothrow) ElfSection(name, fFD,
Get(sectionHeader->sh_offset), Get(sectionHeader->sh_size),
Get(sectionHeader->sh_addr), Get(sectionHeader->sh_flags));
if (section == NULL)
return B_NO_MEMORY;
if (!fSections.AddItem(section)) {
delete section;
return B_NO_MEMORY;
}
}
}
if (Get(elfHeader.e_phnum) > 0) {
// check program header table values
uint64 programHeadersOffset = Get(elfHeader.e_phoff);
size_t programHeaderSize = Get(elfHeader.e_phentsize);
int segmentCount = Get(elfHeader.e_phnum);
size_t programHeaderTableSize = programHeaderSize * segmentCount;
if (!_CheckRange(programHeadersOffset, programHeaderTableSize)) {
WARNING("\"%s\": Invalid ELF header\n", fileName);
return B_BAD_DATA;
}
// read the program header table
uint8* programHeaderTable = (uint8*)malloc(programHeaderTableSize);
if (programHeaderTable == NULL)
return B_NO_MEMORY;
fSegments.Add(segment);
MemoryDeleter programHeaderTableDeleter(programHeaderTable);
bytesRead = pread(fFD, programHeaderTable, programHeaderTableSize,
programHeadersOffset);
if (bytesRead != (ssize_t)programHeaderTableSize)
return bytesRead < 0 ? errno : B_ERROR;
// read the program headers and create ElfSegment objects
for (int i = 0; i < segmentCount; i++) {
Phdr* programHeader = (Phdr*)(programHeaderTable + i
* programHeaderSize);
// skip invalid program headers
if (Get(programHeader->p_filesz) > 0
&& !_CheckRange(Get(programHeader->p_offset),
Get(programHeader->p_filesz))) {
continue;
}
// create an ElfSegment
ElfSegment* segment = new(std::nothrow) ElfSegment(
Get(programHeader->p_type), Get(programHeader->p_offset),
Get(programHeader->p_filesz), Get(programHeader->p_vaddr),
Get(programHeader->p_memsz), Get(programHeader->p_flags));
if (segment == NULL)
return B_NO_MEMORY;
if (!fSegments.AddItem(segment)) {
delete segment;
return B_NO_MEMORY;
}
}
}
return B_OK;
@ -343,39 +393,31 @@ ElfFile::_LoadFile(const char* fileName)
bool
ElfFile::_CheckRange(off_t offset, off_t size) const
ElfFile::_CheckRange(uint64 offset, uint64 size) const
{
return offset < fFileSize && offset + size <= fFileSize;
}
template<typename ElfClass>
bool
ElfFile::_CheckElfHeader(Elf32_Ehdr& elfHeader)
ElfFile::_CheckElfHeader(typename ElfClass::Ehdr& elfHeader)
{
return memcmp(elfHeader.e_ident, ELF_MAGIC, 4) == 0
&& elfHeader.e_ident[4] == ELFCLASS32
&& elfHeader.e_shoff > 0
&& elfHeader.e_shnum > 0
&& elfHeader.e_shentsize >= sizeof(Elf32_Shdr)
&& elfHeader.e_shstrndx != SHN_UNDEF
&& elfHeader.e_shstrndx < elfHeader.e_shnum
&& elfHeader.e_phoff > 0
&& elfHeader.e_phnum > 0
&& elfHeader.e_phentsize >= sizeof(Elf32_Phdr);
}
if (Get(elfHeader.e_shnum) > 0) {
if (Get(elfHeader.e_shoff) == 0
|| Get(elfHeader.e_shentsize) < sizeof(typename ElfClass::Shdr)
|| Get(elfHeader.e_shstrndx) == SHN_UNDEF
|| Get(elfHeader.e_shstrndx) >= Get(elfHeader.e_shnum)) {
return false;
}
}
if (Get(elfHeader.e_phnum) > 0) {
if (Get(elfHeader.e_phoff) == 0
|| Get(elfHeader.e_phentsize) < sizeof(typename ElfClass::Phdr)) {
return false;
}
}
bool
ElfFile::_CheckElfHeader(Elf64_Ehdr& elfHeader)
{
return memcmp(elfHeader.e_ident, ELF_MAGIC, 4) == 0
&& elfHeader.e_ident[4] == ELFCLASS64
&& elfHeader.e_shoff > 0
&& elfHeader.e_shnum > 0
&& elfHeader.e_shentsize >= sizeof(Elf64_Shdr)
&& elfHeader.e_shstrndx != SHN_UNDEF
&& elfHeader.e_shstrndx < elfHeader.e_shnum
&& elfHeader.e_phoff > 0
&& elfHeader.e_phnum > 0
&& elfHeader.e_phentsize >= sizeof(Elf64_Phdr);
return true;
}

View File

@ -7,7 +7,9 @@
#include <sys/types.h>
#include <ByteOrder.h>
#include <SupportDefs.h>
#include <ObjectList.h>
#include <elf_private.h>
#include <util/DoublyLinkedList.h>
@ -15,16 +17,16 @@
#include "Types.h"
class ElfSection : public DoublyLinkedListLinkImpl<ElfSection> {
class ElfSection {
public:
ElfSection(const char* name, int fd,
off_t offset, off_t size,
uint64 offset, uint64 size,
target_addr_t loadAddress, uint32 flags);
~ElfSection();
const char* Name() const { return fName; }
off_t Offset() const { return fOffset; }
off_t Size() const { return fSize; }
uint64 Offset() const { return fOffset; }
uint64 Size() const { return fSize; }
const void* Data() const { return fData; }
target_addr_t LoadAddress() const
{ return fLoadAddress; }
@ -38,8 +40,8 @@ public:
private:
const char* fName;
int fFD;
off_t fOffset;
off_t fSize;
uint64 fOffset;
uint64 fSize;
void* fData;
target_addr_t fLoadAddress;
uint32 fFlags;
@ -47,25 +49,57 @@ private:
};
class ElfSegment : public DoublyLinkedListLinkImpl<ElfSegment> {
class ElfSegment {
public:
ElfSegment(off_t fileOffset, off_t fileSize,
target_addr_t loadAddress,
target_size_t loadSize, bool writable);
ElfSegment(uint32 type, uint64 fileOffset,
uint64 fileSize, target_addr_t loadAddress,
target_size_t loadSize, uint32 flags);
~ElfSegment();
off_t FileOffset() const { return fFileOffset; }
off_t FileSize() const { return fFileSize; }
uint32 Type() { return fType; }
uint64 FileOffset() const { return fFileOffset; }
uint64 FileSize() const { return fFileSize; }
target_addr_t LoadAddress() const { return fLoadAddress; }
target_size_t LoadSize() const { return fLoadSize; }
bool IsWritable() const { return fWritable; }
uint32 Flags() const { return fFlags; }
bool IsWritable() const
{ return (fFlags & PF_WRITE) != 0; }
private:
off_t fFileOffset;
off_t fFileSize;
uint64 fFileOffset;
uint64 fFileSize;
target_addr_t fLoadAddress;
target_size_t fLoadSize;
bool fWritable;
uint32 fType;
uint32 fFlags;
};
struct ElfClass32 {
typedef uint32 Address;
typedef uint32 Size;
typedef Elf32_Ehdr Ehdr;
typedef Elf32_Phdr Phdr;
typedef Elf32_Shdr Shdr;
typedef Elf32_Nhdr Nhdr;
typedef Elf32_Note_Team NoteTeam;
typedef Elf32_Note_Area_Entry NoteAreaEntry;
typedef Elf32_Note_Image_Entry NoteImageEntry;
typedef Elf32_Note_Thread_Entry NoteThreadEntry;
};
struct ElfClass64 {
typedef uint64 Address;
typedef uint64 Size;
typedef Elf64_Ehdr Ehdr;
typedef Elf64_Phdr Phdr;
typedef Elf64_Shdr Shdr;
typedef Elf64_Nhdr Nhdr;
typedef Elf64_Note_Team NoteTeam;
typedef Elf64_Note_Area_Entry NoteAreaEntry;
typedef Elf64_Note_Image_Entry NoteImageEntry;
typedef Elf64_Note_Thread_Entry NoteThreadEntry;
};
@ -78,31 +112,73 @@ public:
int FD() const { return fFD; }
bool Is64Bit() const { return f64Bit; }
uint16 Type() const { return fType; }
uint16 Machine() const { return fMachine; }
ElfSection* GetSection(const char* name);
void PutSection(ElfSection* section);
ElfSection* FindSection(const char* name) const;
int32 CountSegments() const
{ return fSegments.CountItems(); }
ElfSegment* SegmentAt(int32 index) const
{ return fSegments.ItemAt(index); }
ElfSegment* TextSegment() const;
ElfSegment* DataSegment() const;
private:
typedef DoublyLinkedList<ElfSection> SectionList;
typedef DoublyLinkedList<ElfSegment> SegmentList;
template<typename Value>
Value Get(const Value& value) const;
private:
template<typename Ehdr, typename Phdr, typename Shdr>
typedef BObjectList<ElfSection> SectionList;
typedef BObjectList<ElfSegment> SegmentList;
private:
template<typename ElfClass>
status_t _LoadFile(const char* fileName);
bool _CheckRange(off_t offset, off_t size) const;
static bool _CheckElfHeader(Elf32_Ehdr& elfHeader);
static bool _CheckElfHeader(Elf64_Ehdr& elfHeader);
bool _CheckRange(uint64 offset, uint64 size) const;
template<typename ElfClass>
bool _CheckElfHeader(
typename ElfClass::Ehdr& elfHeader);
static uint8 _Swap(const uint8& value)
{ return value; }
static uint16 _Swap(const uint16& value)
{ return (uint16)B_SWAP_INT16(value); }
static int32 _Swap(const int32& value)
{ return B_SWAP_INT32(value); }
static uint32 _Swap(const uint32& value)
{ return (uint32)B_SWAP_INT32(value); }
static int64 _Swap(const int64& value)
{ return B_SWAP_INT64(value); }
static uint64 _Swap(const uint64& value)
{ return (uint64)B_SWAP_INT64(value); }
private:
off_t fFileSize;
uint64 fFileSize;
int fFD;
uint16 fType;
uint16 fMachine;
bool f64Bit;
bool fSwappedByteOrder;
SectionList fSections;
SegmentList fSegments;
};
template<typename Value>
inline Value
ElfFile::Get(const Value& value) const
{
if (!fSwappedByteOrder)
return value;
return _Swap(value);
}
#endif // ELF_FILE_H