xref: /haiku/headers/private/debugger/elf/ElfFile.h (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
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 
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 
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 
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 
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 
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 
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 
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 
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
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