blob: d9cac0d06b3e08dafa64d155fc0caddbe683c681 [file] [log] [blame]
Stephen Wilsonf325ba92010-07-13 23:07:23 +00001//===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <cstring>
11
12#include "lldb/Core/DataExtractor.h"
13
14#include "ELFHeader.h"
15
16using namespace elf;
17using namespace lldb;
18using namespace llvm::ELF;
19
20//------------------------------------------------------------------------------
21// Static utility functions.
22//
23// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
24// with error handling code and provide for parsing a sequence of values.
25static bool
Greg Claytonc7bece562013-01-25 18:06:21 +000026GetMaxU64(const lldb_private::DataExtractor &data,
27 lldb::offset_t *offset,
28 uint64_t *value,
29 uint32_t byte_size)
Stephen Wilsonf325ba92010-07-13 23:07:23 +000030{
Greg Claytonc7bece562013-01-25 18:06:21 +000031 const lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000032 *value = data.GetMaxU64(offset, byte_size);
33 return *offset != saved_offset;
34}
35
36static bool
37GetMaxU64(const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +000038 lldb::offset_t *offset,
39 uint64_t *value,
40 uint32_t byte_size,
Stephen Wilsonf325ba92010-07-13 23:07:23 +000041 uint32_t count)
42{
Greg Claytonc7bece562013-01-25 18:06:21 +000043 lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000044
45 for (uint32_t i = 0; i < count; ++i, ++value)
46 {
47 if (GetMaxU64(data, offset, value, byte_size) == false)
48 {
49 *offset = saved_offset;
50 return false;
51 }
52 }
53 return true;
54}
55
56static bool
57GetMaxS64(const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +000058 lldb::offset_t *offset,
59 int64_t *value,
60 uint32_t byte_size)
Stephen Wilsonf325ba92010-07-13 23:07:23 +000061{
Greg Claytonc7bece562013-01-25 18:06:21 +000062 const lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000063 *value = data.GetMaxS64(offset, byte_size);
64 return *offset != saved_offset;
65}
66
67static bool
68GetMaxS64(const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +000069 lldb::offset_t *offset,
70 int64_t *value,
71 uint32_t byte_size,
Stephen Wilsonf325ba92010-07-13 23:07:23 +000072 uint32_t count)
73{
Greg Claytonc7bece562013-01-25 18:06:21 +000074 lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000075
76 for (uint32_t i = 0; i < count; ++i, ++value)
77 {
78 if (GetMaxS64(data, offset, value, byte_size) == false)
79 {
80 *offset = saved_offset;
81 return false;
82 }
83 }
84 return true;
85}
86
87//------------------------------------------------------------------------------
88// ELFHeader
89
90ELFHeader::ELFHeader()
91{
92 memset(this, 0, sizeof(ELFHeader));
93}
94
95ByteOrder
96ELFHeader::GetByteOrder() const
97{
98 if (e_ident[EI_DATA] == ELFDATA2MSB)
99 return eByteOrderBig;
100 if (e_ident[EI_DATA] == ELFDATA2LSB)
101 return eByteOrderLittle;
102 return eByteOrderInvalid;
103}
104
105bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000106ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000107{
108 // Read e_ident. This provides byte order and address size info.
109 if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
110 return false;
111
112 const unsigned byte_size = Is32Bit() ? 4 : 8;
113 data.SetByteOrder(GetByteOrder());
114 data.SetAddressByteSize(byte_size);
115
116 // Read e_type and e_machine.
117 if (data.GetU16(offset, &e_type, 2) == NULL)
118 return false;
119
120 // Read e_version.
121 if (data.GetU32(offset, &e_version, 1) == NULL)
122 return false;
123
124 // Read e_entry, e_phoff and e_shoff.
125 if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
126 return false;
127
128 // Read e_flags.
129 if (data.GetU32(offset, &e_flags, 1) == NULL)
130 return false;
131
132 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
133 // e_shstrndx.
134 if (data.GetU16(offset, &e_ehsize, 6) == NULL)
135 return false;
136
137 return true;
138}
139
140bool
141ELFHeader::MagicBytesMatch(const uint8_t *magic)
142{
143 return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
144}
145
146unsigned
147ELFHeader::AddressSizeInBytes(const uint8_t *magic)
148{
149 unsigned address_size = 0;
150
151 switch (magic[EI_CLASS])
152 {
153 case ELFCLASS32:
154 address_size = 4;
155 break;
156
157 case ELFCLASS64:
158 address_size = 8;
159 break;
160 }
161 return address_size;
162}
163
Stephen Wilson43fe6452011-03-30 15:59:12 +0000164unsigned
165ELFHeader::GetRelocationJumpSlotType() const
166{
167 unsigned slot = 0;
168
169 switch (e_machine)
170 {
171 default:
172 assert(false && "architecture not supported");
173 break;
174 case EM_386:
175 case EM_486:
176 slot = R_386_JUMP_SLOT;
177 break;
178 case EM_X86_64:
179 slot = R_X86_64_JUMP_SLOT;
180 break;
181 case EM_ARM:
182 slot = R_ARM_JUMP_SLOT;
183 break;
184 case EM_MBLAZE:
185 slot = R_MICROBLAZE_JUMP_SLOT;
186 }
187
188 return slot;
189}
190
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000191//------------------------------------------------------------------------------
192// ELFSectionHeader
193
194ELFSectionHeader::ELFSectionHeader()
195{
196 memset(this, 0, sizeof(ELFSectionHeader));
197}
198
199bool
200ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +0000201 lldb::offset_t *offset)
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000202{
203 const unsigned byte_size = data.GetAddressByteSize();
204
205 // Read sh_name and sh_type.
206 if (data.GetU32(offset, &sh_name, 2) == NULL)
207 return false;
208
209 // Read sh_flags.
210 if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
211 return false;
212
213 // Read sh_addr, sh_off and sh_size.
214 if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
215 return false;
216
217 // Read sh_link and sh_info.
218 if (data.GetU32(offset, &sh_link, 2) == NULL)
219 return false;
220
221 // Read sh_addralign and sh_entsize.
222 if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
223 return false;
224
225 return true;
226}
227
228//------------------------------------------------------------------------------
229// ELFSymbol
230
231ELFSymbol::ELFSymbol()
232{
233 memset(this, 0, sizeof(ELFSymbol));
234}
235
236bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000237ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000238{
239 const unsigned byte_size = data.GetAddressByteSize();
240 const bool parsing_32 = byte_size == 4;
241
242 // Read st_name.
243 if (data.GetU32(offset, &st_name, 1) == NULL)
244 return false;
245
246 if (parsing_32)
247 {
248 // Read st_value and st_size.
249 if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
250 return false;
251
252 // Read st_info and st_other.
253 if (data.GetU8(offset, &st_info, 2) == NULL)
254 return false;
255
256 // Read st_shndx.
257 if (data.GetU16(offset, &st_shndx, 1) == NULL)
258 return false;
259 }
260 else
261 {
262 // Read st_info and st_other.
263 if (data.GetU8(offset, &st_info, 2) == NULL)
264 return false;
265
266 // Read st_shndx.
267 if (data.GetU16(offset, &st_shndx, 1) == NULL)
268 return false;
269
270 // Read st_value and st_size.
271 if (data.GetU64(offset, &st_value, 2) == NULL)
272 return false;
273 }
274 return true;
275}
276
277//------------------------------------------------------------------------------
278// ELFProgramHeader
279
280ELFProgramHeader::ELFProgramHeader()
281{
282 memset(this, 0, sizeof(ELFProgramHeader));
283}
284
285bool
286ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +0000287 lldb::offset_t *offset)
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000288{
289 const uint32_t byte_size = data.GetAddressByteSize();
290 const bool parsing_32 = byte_size == 4;
291
292 // Read p_type;
293 if (data.GetU32(offset, &p_type, 1) == NULL)
294 return false;
295
296 if (parsing_32) {
297 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
298 if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
299 return false;
300
301 // Read p_flags.
302 if (data.GetU32(offset, &p_flags, 1) == NULL)
303 return false;
304
305 // Read p_align.
306 if (GetMaxU64(data, offset, &p_align, byte_size) == false)
307 return false;
308 }
309 else {
310 // Read p_flags.
311 if (data.GetU32(offset, &p_flags, 1) == NULL)
312 return false;
313
314 // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
315 if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
316 return false;
317 }
318
319 return true;
320}
321
322//------------------------------------------------------------------------------
323// ELFDynamic
324
325ELFDynamic::ELFDynamic()
326{
327 memset(this, 0, sizeof(ELFDynamic));
328}
329
330bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000331ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000332{
333 const unsigned byte_size = data.GetAddressByteSize();
334 return GetMaxS64(data, offset, &d_tag, byte_size, 2);
335}
336
Stephen Wilson43fe6452011-03-30 15:59:12 +0000337//------------------------------------------------------------------------------
338// ELFRel
339
340ELFRel::ELFRel()
341{
342 memset(this, 0, sizeof(ELFRel));
343}
344
345bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000346ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Stephen Wilson43fe6452011-03-30 15:59:12 +0000347{
348 const unsigned byte_size = data.GetAddressByteSize();
349
350 // Read r_offset and r_info.
351 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
352 return false;
353
354 return true;
355}
356
357//------------------------------------------------------------------------------
358// ELFRela
359
360ELFRela::ELFRela()
361{
362 memset(this, 0, sizeof(ELFRela));
363}
364
365bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000366ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
Stephen Wilson43fe6452011-03-30 15:59:12 +0000367{
368 const unsigned byte_size = data.GetAddressByteSize();
369
370 // Read r_offset and r_info.
371 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
372 return false;
373
374 // Read r_addend;
375 if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
376 return false;
377
378 return true;
379}
380
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000381