1/*
2 * Copyright 2009-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef ELF_FILE_H
6#define ELF_FILE_H
7
8#include <sys/types.h>
9
10#include <ByteOrder.h>
11#include <SupportDefs.h>
12#include <ObjectList.h>
13
14#include <elf_private.h>
15#include <util/DoublyLinkedList.h>
16
17#include "Types.h"
18
19
20class ElfSymbolLookup;
21class ElfSymbolLookupSource;
22
23
24class ElfSection {
25public:
26								ElfSection(const char* name, uint32 type,
27									int fd, uint64 offset, uint64 size,
28									target_addr_t loadAddress, uint32 flags,
29									uint32 linkIndex);
30								~ElfSection();
31
32			const char*			Name() const	{ return fName; }
33			uint32				Type() const	{ return fType; }
34			uint64				Offset() const	{ return fOffset; }
35			uint64				Size() const	{ return fSize; }
36			const void*			Data() const	{ return fData; }
37			target_addr_t		LoadAddress() const
38									{ return fLoadAddress; }
39			bool				IsWritable() const
40									{ return (fFlags & SHF_WRITE) != 0; }
41
42			status_t			Load();
43			void				Unload();
44			bool				IsLoaded() const	{ return fLoadCount > 0; }
45			uint32				LinkIndex() const	{ return fLinkIndex; }
46
47private:
48			const char*			fName;
49			uint32				fType;
50			int					fFD;
51			uint64				fOffset;
52			uint64				fSize;
53			void*				fData;
54			target_addr_t		fLoadAddress;
55			uint32				fFlags;
56			int32				fLoadCount;
57			uint32				fLinkIndex;
58};
59
60
61class ElfSegment {
62public:
63								ElfSegment(uint32 type, uint64 fileOffset,
64									uint64 fileSize, target_addr_t loadAddress,
65									target_size_t loadSize, uint32 flags);
66								~ElfSegment();
67
68			uint32				Type()				{ return fType; }
69			uint64				FileOffset() const	{ return fFileOffset; }
70			uint64				FileSize() const	{ return fFileSize; }
71			target_addr_t		LoadAddress() const	{ return fLoadAddress; }
72			target_size_t		LoadSize() const	{ return fLoadSize; }
73			uint32				Flags() const		{ return fFlags; }
74			bool				IsWritable() const
75									{ return (fFlags & PF_WRITE) != 0; }
76
77private:
78			uint64				fFileOffset;
79			uint64				fFileSize;
80			target_addr_t		fLoadAddress;
81			target_size_t		fLoadSize;
82			uint32				fType;
83			uint32				fFlags;
84};
85
86
87struct ElfClass32 {
88	typedef uint32					Address;
89	typedef uint32					Size;
90	typedef Elf32_Ehdr				Ehdr;
91	typedef Elf32_Phdr				Phdr;
92	typedef Elf32_Shdr				Shdr;
93	typedef Elf32_Sym				Sym;
94	typedef Elf32_Nhdr				Nhdr;
95	typedef Elf32_Note_Team			NoteTeam;
96	typedef Elf32_Note_Area_Entry	NoteAreaEntry;
97	typedef Elf32_Note_Image_Entry	NoteImageEntry;
98	typedef Elf32_Note_Thread_Entry	NoteThreadEntry;
99};
100
101
102struct ElfClass64 {
103	typedef uint64					Address;
104	typedef uint64					Size;
105	typedef Elf64_Ehdr				Ehdr;
106	typedef Elf64_Phdr				Phdr;
107	typedef Elf64_Shdr				Shdr;
108	typedef Elf64_Sym				Sym;
109	typedef Elf64_Nhdr				Nhdr;
110	typedef Elf64_Note_Team			NoteTeam;
111	typedef Elf64_Note_Area_Entry	NoteAreaEntry;
112	typedef Elf64_Note_Image_Entry	NoteImageEntry;
113	typedef Elf64_Note_Thread_Entry	NoteThreadEntry;
114};
115
116
117class ElfFile {
118public:
119								ElfFile();
120								~ElfFile();
121
122			status_t			Init(const char* fileName);
123
124			int					FD() const	{ return fFD; }
125
126			bool				Is64Bit() const	{ return f64Bit; }
127			bool				IsByteOrderSwapped() const
128									{ return fSwappedByteOrder; }
129			uint16				Type() const	{ return fType; }
130			uint16				Machine() const	{ return fMachine; }
131
132			int32				CountSection() const
133									{ return fSections.CountItems(); }
134			ElfSection*			SectionAt(int32 index) const
135									{ return fSections.ItemAt(index); }
136			ElfSection*			GetSection(const char* name);
137			void				PutSection(ElfSection* section);
138			ElfSection*			FindSection(const char* name) const;
139			ElfSection*			FindSection(uint32 type) const;
140
141			int32				CountSegments() const
142									{ return fSegments.CountItems(); }
143			ElfSegment*			SegmentAt(int32 index) const
144									{ return fSegments.ItemAt(index); }
145
146			ElfSegment*			TextSegment() const;
147			ElfSegment*			DataSegment() const;
148
149			ElfSymbolLookupSource* CreateSymbolLookupSource(uint64 fileOffset,
150									uint64 fileLength,
151									uint64 memoryAddress) const;
152			status_t			CreateSymbolLookup(uint64 textDelta,
153									ElfSymbolLookup*& _lookup) const;
154
155			template<typename Value>
156			Value				Get(const Value& value) const
157									{ return StaticGet(value,
158										fSwappedByteOrder); }
159
160	template<typename Value>
161	static	Value				StaticGet(const Value& value,
162									bool swappedByteOrder);
163
164private:
165			struct SymbolLookupSource;
166
167			typedef BObjectList<ElfSection> SectionList;
168			typedef BObjectList<ElfSegment> SegmentList;
169
170private:
171			template<typename ElfClass>
172			status_t			_LoadFile(const char* fileName);
173
174			bool				_FindSymbolSections(ElfSection*& _symbolSection,
175									ElfSection*& _stringSection,
176									uint32 type) const;
177
178			bool				_CheckRange(uint64 offset, uint64 size) const;
179
180			template<typename ElfClass>
181			bool				_CheckElfHeader(
182									typename ElfClass::Ehdr& elfHeader);
183
184	static	uint8				_Swap(const uint8& value)
185									{ return value; }
186	static	uint16				_Swap(const uint16& value)
187									{ return (uint16)B_SWAP_INT16(value); }
188	static	int32				_Swap(const int32& value)
189									{ return B_SWAP_INT32(value); }
190	static	uint32				_Swap(const uint32& value)
191									{ return (uint32)B_SWAP_INT32(value); }
192	static	int64				_Swap(const int64& value)
193									{ return B_SWAP_INT64(value); }
194	static	uint64				_Swap(const uint64& value)
195									{ return (uint64)B_SWAP_INT64(value); }
196
197private:
198			uint64				fFileSize;
199			int					fFD;
200			uint16				fType;
201			uint16				fMachine;
202			bool				f64Bit;
203			bool				fSwappedByteOrder;
204			SectionList			fSections;
205			SegmentList			fSegments;
206};
207
208
209template<typename Value>
210/*static*/ inline Value
211ElfFile::StaticGet(const Value& value, bool swappedByteOrder)
212{
213	if (!swappedByteOrder)
214		return value;
215	return _Swap(value);
216}
217
218
219#endif	// ELF_FILE_H
220