2009-06-14 16:53:29 +04:00
|
|
|
/*
|
2010-11-02 23:03:11 +03:00
|
|
|
* Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
|
2009-06-14 16:53:29 +04:00
|
|
|
* Distributed under the terms of the MIT License.
|
|
|
|
*/
|
|
|
|
#ifndef ELF_FILE_H
|
|
|
|
#define ELF_FILE_H
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
#include <ByteOrder.h>
|
2009-06-14 16:53:29 +04:00
|
|
|
#include <SupportDefs.h>
|
2016-04-24 19:34:07 +03:00
|
|
|
#include <ObjectList.h>
|
2009-06-14 16:53:29 +04:00
|
|
|
|
2015-10-26 20:43:44 +03:00
|
|
|
#include <elf_private.h>
|
2009-06-14 16:53:29 +04:00
|
|
|
#include <util/DoublyLinkedList.h>
|
|
|
|
|
2009-06-30 02:38:15 +04:00
|
|
|
#include "Types.h"
|
|
|
|
|
2009-06-14 16:53:29 +04:00
|
|
|
|
2016-04-29 23:31:59 +03:00
|
|
|
class ElfSymbolLookup;
|
|
|
|
class ElfSymbolLookupSource;
|
|
|
|
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
class ElfSection {
|
2009-06-14 16:53:29 +04:00
|
|
|
public:
|
2016-05-22 18:09:12 +03:00
|
|
|
ElfSection(const char* name, uint32 type,
|
|
|
|
int fd, uint64 offset, uint64 size,
|
|
|
|
target_addr_t loadAddress, uint32 flags,
|
|
|
|
uint32 linkIndex);
|
2009-06-14 16:53:29 +04:00
|
|
|
~ElfSection();
|
|
|
|
|
|
|
|
const char* Name() const { return fName; }
|
2016-05-22 18:09:12 +03:00
|
|
|
uint32 Type() const { return fType; }
|
2016-04-24 19:34:07 +03:00
|
|
|
uint64 Offset() const { return fOffset; }
|
|
|
|
uint64 Size() const { return fSize; }
|
2009-06-14 16:53:29 +04:00
|
|
|
const void* Data() const { return fData; }
|
2010-11-02 23:03:11 +03:00
|
|
|
target_addr_t LoadAddress() const
|
|
|
|
{ return fLoadAddress; }
|
|
|
|
bool IsWritable() const
|
|
|
|
{ return (fFlags & SHF_WRITE) != 0; }
|
2009-06-14 16:53:29 +04:00
|
|
|
|
|
|
|
status_t Load();
|
|
|
|
void Unload();
|
2016-05-22 18:09:12 +03:00
|
|
|
bool IsLoaded() const { return fLoadCount > 0; }
|
|
|
|
uint32 LinkIndex() const { return fLinkIndex; }
|
2009-06-14 16:53:29 +04:00
|
|
|
|
|
|
|
private:
|
|
|
|
const char* fName;
|
2016-05-22 18:09:12 +03:00
|
|
|
uint32 fType;
|
2009-06-14 16:53:29 +04:00
|
|
|
int fFD;
|
2016-04-24 19:34:07 +03:00
|
|
|
uint64 fOffset;
|
|
|
|
uint64 fSize;
|
2009-06-14 16:53:29 +04:00
|
|
|
void* fData;
|
2010-11-02 23:03:11 +03:00
|
|
|
target_addr_t fLoadAddress;
|
|
|
|
uint32 fFlags;
|
2009-06-14 16:53:29 +04:00
|
|
|
int32 fLoadCount;
|
2016-05-22 18:09:12 +03:00
|
|
|
uint32 fLinkIndex;
|
2009-06-14 16:53:29 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
class ElfSegment {
|
2009-06-30 02:38:15 +04:00
|
|
|
public:
|
2016-04-24 19:34:07 +03:00
|
|
|
ElfSegment(uint32 type, uint64 fileOffset,
|
|
|
|
uint64 fileSize, target_addr_t loadAddress,
|
|
|
|
target_size_t loadSize, uint32 flags);
|
2009-06-30 02:38:15 +04:00
|
|
|
~ElfSegment();
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
uint32 Type() { return fType; }
|
|
|
|
uint64 FileOffset() const { return fFileOffset; }
|
|
|
|
uint64 FileSize() const { return fFileSize; }
|
2009-06-30 02:38:15 +04:00
|
|
|
target_addr_t LoadAddress() const { return fLoadAddress; }
|
|
|
|
target_size_t LoadSize() const { return fLoadSize; }
|
2016-04-24 19:34:07 +03:00
|
|
|
uint32 Flags() const { return fFlags; }
|
|
|
|
bool IsWritable() const
|
|
|
|
{ return (fFlags & PF_WRITE) != 0; }
|
2009-06-30 02:38:15 +04:00
|
|
|
|
|
|
|
private:
|
2016-04-24 19:34:07 +03:00
|
|
|
uint64 fFileOffset;
|
|
|
|
uint64 fFileSize;
|
2009-06-30 02:38:15 +04:00
|
|
|
target_addr_t fLoadAddress;
|
|
|
|
target_size_t fLoadSize;
|
2016-04-24 19:34:07 +03:00
|
|
|
uint32 fType;
|
|
|
|
uint32 fFlags;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct ElfClass32 {
|
|
|
|
typedef uint32 Address;
|
|
|
|
typedef uint32 Size;
|
|
|
|
typedef Elf32_Ehdr Ehdr;
|
|
|
|
typedef Elf32_Phdr Phdr;
|
|
|
|
typedef Elf32_Shdr Shdr;
|
2016-04-29 23:31:59 +03:00
|
|
|
typedef Elf32_Sym Sym;
|
2016-04-24 19:34:07 +03:00
|
|
|
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;
|
2016-04-29 23:31:59 +03:00
|
|
|
typedef Elf64_Sym Sym;
|
2016-04-24 19:34:07 +03:00
|
|
|
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;
|
2009-06-30 02:38:15 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-06-14 16:53:29 +04:00
|
|
|
class ElfFile {
|
|
|
|
public:
|
|
|
|
ElfFile();
|
|
|
|
~ElfFile();
|
|
|
|
|
|
|
|
status_t Init(const char* fileName);
|
|
|
|
|
2009-06-30 02:38:15 +04:00
|
|
|
int FD() const { return fFD; }
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
bool Is64Bit() const { return f64Bit; }
|
2016-04-29 23:31:59 +03:00
|
|
|
bool IsByteOrderSwapped() const
|
|
|
|
{ return fSwappedByteOrder; }
|
2016-04-24 19:34:07 +03:00
|
|
|
uint16 Type() const { return fType; }
|
|
|
|
uint16 Machine() const { return fMachine; }
|
|
|
|
|
2016-05-22 18:09:12 +03:00
|
|
|
int32 CountSection() const
|
|
|
|
{ return fSections.CountItems(); }
|
|
|
|
ElfSection* SectionAt(int32 index) const
|
|
|
|
{ return fSections.ItemAt(index); }
|
2009-06-14 16:53:29 +04:00
|
|
|
ElfSection* GetSection(const char* name);
|
|
|
|
void PutSection(ElfSection* section);
|
2010-12-13 17:05:44 +03:00
|
|
|
ElfSection* FindSection(const char* name) const;
|
2016-05-22 18:09:12 +03:00
|
|
|
ElfSection* FindSection(uint32 type) const;
|
2009-06-14 16:53:29 +04:00
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
int32 CountSegments() const
|
|
|
|
{ return fSegments.CountItems(); }
|
|
|
|
ElfSegment* SegmentAt(int32 index) const
|
|
|
|
{ return fSegments.ItemAt(index); }
|
|
|
|
|
2009-06-30 02:38:15 +04:00
|
|
|
ElfSegment* TextSegment() const;
|
|
|
|
ElfSegment* DataSegment() const;
|
|
|
|
|
2016-04-29 23:31:59 +03:00
|
|
|
ElfSymbolLookupSource* CreateSymbolLookupSource(uint64 fileOffset,
|
|
|
|
uint64 fileLength,
|
|
|
|
uint64 memoryAddress) const;
|
2016-05-22 18:09:12 +03:00
|
|
|
status_t CreateSymbolLookup(uint64 textDelta,
|
|
|
|
ElfSymbolLookup*& _lookup) const;
|
2016-04-29 23:31:59 +03:00
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
template<typename Value>
|
2016-04-29 23:31:59 +03:00
|
|
|
Value Get(const Value& value) const
|
2016-04-30 00:02:39 +03:00
|
|
|
{ return StaticGet(value,
|
|
|
|
fSwappedByteOrder); }
|
2016-04-24 19:34:07 +03:00
|
|
|
|
2016-04-29 23:31:59 +03:00
|
|
|
template<typename Value>
|
2016-04-30 00:02:39 +03:00
|
|
|
static Value StaticGet(const Value& value,
|
2016-04-29 23:31:59 +03:00
|
|
|
bool swappedByteOrder);
|
2016-04-24 19:34:07 +03:00
|
|
|
|
2009-06-14 16:53:29 +04:00
|
|
|
private:
|
2016-04-29 23:31:59 +03:00
|
|
|
struct SymbolLookupSource;
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
typedef BObjectList<ElfSection> SectionList;
|
|
|
|
typedef BObjectList<ElfSegment> SegmentList;
|
2009-06-14 16:53:29 +04:00
|
|
|
|
|
|
|
private:
|
2016-04-24 19:34:07 +03:00
|
|
|
template<typename ElfClass>
|
2012-12-19 23:54:20 +04:00
|
|
|
status_t _LoadFile(const char* fileName);
|
|
|
|
|
2016-05-22 18:09:12 +03:00
|
|
|
bool _FindSymbolSections(ElfSection*& _symbolSection,
|
|
|
|
ElfSection*& _stringSection,
|
|
|
|
uint32 type) const;
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
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); }
|
2009-06-14 16:53:29 +04:00
|
|
|
|
|
|
|
private:
|
2016-04-24 19:34:07 +03:00
|
|
|
uint64 fFileSize;
|
2009-06-14 16:53:29 +04:00
|
|
|
int fFD;
|
2016-04-24 19:34:07 +03:00
|
|
|
uint16 fType;
|
|
|
|
uint16 fMachine;
|
|
|
|
bool f64Bit;
|
|
|
|
bool fSwappedByteOrder;
|
2009-06-14 16:53:29 +04:00
|
|
|
SectionList fSections;
|
2009-06-30 02:38:15 +04:00
|
|
|
SegmentList fSegments;
|
2009-06-14 16:53:29 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-04-24 19:34:07 +03:00
|
|
|
template<typename Value>
|
2016-04-29 23:31:59 +03:00
|
|
|
/*static*/ inline Value
|
2016-04-30 00:02:39 +03:00
|
|
|
ElfFile::StaticGet(const Value& value, bool swappedByteOrder)
|
2016-04-24 19:34:07 +03:00
|
|
|
{
|
2016-04-29 23:31:59 +03:00
|
|
|
if (!swappedByteOrder)
|
2016-04-24 19:34:07 +03:00
|
|
|
return value;
|
|
|
|
return _Swap(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-14 16:53:29 +04:00
|
|
|
#endif // ELF_FILE_H
|