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
20 class ElfSymbolLookup;
21 class ElfSymbolLookupSource;
22
23
24 class ElfSection {
25 public:
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
Name()32 const char* Name() const { return fName; }
Type()33 uint32 Type() const { return fType; }
Offset()34 uint64 Offset() const { return fOffset; }
Size()35 uint64 Size() const { return fSize; }
Data()36 const void* Data() const { return fData; }
LoadAddress()37 target_addr_t LoadAddress() const
38 { return fLoadAddress; }
IsWritable()39 bool IsWritable() const
40 { return (fFlags & SHF_WRITE) != 0; }
41
42 status_t Load();
43 void Unload();
IsLoaded()44 bool IsLoaded() const { return fLoadCount > 0; }
LinkIndex()45 uint32 LinkIndex() const { return fLinkIndex; }
46
47 private:
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
61 class ElfSegment {
62 public:
63 ElfSegment(uint32 type, uint64 fileOffset,
64 uint64 fileSize, target_addr_t loadAddress,
65 target_size_t loadSize, uint32 flags);
66 ~ElfSegment();
67
Type()68 uint32 Type() { return fType; }
FileOffset()69 uint64 FileOffset() const { return fFileOffset; }
FileSize()70 uint64 FileSize() const { return fFileSize; }
LoadAddress()71 target_addr_t LoadAddress() const { return fLoadAddress; }
LoadSize()72 target_size_t LoadSize() const { return fLoadSize; }
Flags()73 uint32 Flags() const { return fFlags; }
IsWritable()74 bool IsWritable() const
75 { return (fFlags & PF_WRITE) != 0; }
76
77 private:
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
87 struct 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
102 struct 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
117 class ElfFile {
118 public:
119 ElfFile();
120 ~ElfFile();
121
122 status_t Init(const char* fileName);
123
FD()124 int FD() const { return fFD; }
125
Is64Bit()126 bool Is64Bit() const { return f64Bit; }
IsByteOrderSwapped()127 bool IsByteOrderSwapped() const
128 { return fSwappedByteOrder; }
Type()129 uint16 Type() const { return fType; }
Machine()130 uint16 Machine() const { return fMachine; }
131
CountSection()132 int32 CountSection() const
133 { return fSections.CountItems(); }
SectionAt(int32 index)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
CountSegments()141 int32 CountSegments() const
142 { return fSegments.CountItems(); }
SegmentAt(int32 index)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>
Get(const Value & 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
164 private:
165 struct SymbolLookupSource;
166
167 typedef BObjectList<ElfSection> SectionList;
168 typedef BObjectList<ElfSegment> SegmentList;
169
170 private:
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
_Swap(const uint8 & value)184 static uint8 _Swap(const uint8& value)
185 { return value; }
_Swap(const uint16 & value)186 static uint16 _Swap(const uint16& value)
187 { return (uint16)B_SWAP_INT16(value); }
_Swap(const int32 & value)188 static int32 _Swap(const int32& value)
189 { return B_SWAP_INT32(value); }
_Swap(const uint32 & value)190 static uint32 _Swap(const uint32& value)
191 { return (uint32)B_SWAP_INT32(value); }
_Swap(const int64 & value)192 static int64 _Swap(const int64& value)
193 { return B_SWAP_INT64(value); }
_Swap(const uint64 & value)194 static uint64 _Swap(const uint64& value)
195 { return (uint64)B_SWAP_INT64(value); }
196
197 private:
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
209 template<typename Value>
210 /*static*/ inline Value
StaticGet(const Value & value,bool swappedByteOrder)211 ElfFile::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