blob: a3e82390d262e5dda7aa55ca25eef113d7caf5f5 [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"
Greg Clayton9594f4c2013-04-13 23:17:23 +000013#include "lldb/Core/Section.h"
14#include "lldb/Core/Stream.h"
Stephen Wilsonf325ba92010-07-13 23:07:23 +000015
16#include "ELFHeader.h"
17
18using namespace elf;
19using namespace lldb;
20using namespace llvm::ELF;
21
22//------------------------------------------------------------------------------
23// Static utility functions.
24//
25// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
26// with error handling code and provide for parsing a sequence of values.
Kate Stoneb9c1b512016-09-06 20:57:50 +000027static bool GetMaxU64(const lldb_private::DataExtractor &data,
28 lldb::offset_t *offset, uint64_t *value,
29 uint32_t byte_size) {
30 const lldb::offset_t saved_offset = *offset;
31 *value = data.GetMaxU64(offset, byte_size);
32 return *offset != saved_offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000033}
34
Kate Stoneb9c1b512016-09-06 20:57:50 +000035static bool GetMaxU64(const lldb_private::DataExtractor &data,
36 lldb::offset_t *offset, uint64_t *value,
37 uint32_t byte_size, uint32_t count) {
38 lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000039
Kate Stoneb9c1b512016-09-06 20:57:50 +000040 for (uint32_t i = 0; i < count; ++i, ++value) {
41 if (GetMaxU64(data, offset, value, byte_size) == false) {
42 *offset = saved_offset;
43 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000044 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 }
46 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000047}
48
Kate Stoneb9c1b512016-09-06 20:57:50 +000049static bool GetMaxS64(const lldb_private::DataExtractor &data,
50 lldb::offset_t *offset, int64_t *value,
51 uint32_t byte_size) {
52 const lldb::offset_t saved_offset = *offset;
53 *value = data.GetMaxS64(offset, byte_size);
54 return *offset != saved_offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000055}
56
Kate Stoneb9c1b512016-09-06 20:57:50 +000057static bool GetMaxS64(const lldb_private::DataExtractor &data,
58 lldb::offset_t *offset, int64_t *value,
59 uint32_t byte_size, uint32_t count) {
60 lldb::offset_t saved_offset = *offset;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 for (uint32_t i = 0; i < count; ++i, ++value) {
63 if (GetMaxS64(data, offset, value, byte_size) == false) {
64 *offset = saved_offset;
65 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000066 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 }
68 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000069}
70
71//------------------------------------------------------------------------------
72// ELFHeader
73
Kate Stoneb9c1b512016-09-06 20:57:50 +000074ELFHeader::ELFHeader() { memset(this, 0, sizeof(ELFHeader)); }
75
76ByteOrder ELFHeader::GetByteOrder() const {
77 if (e_ident[EI_DATA] == ELFDATA2MSB)
78 return eByteOrderBig;
79 if (e_ident[EI_DATA] == ELFDATA2LSB)
80 return eByteOrderLittle;
81 return eByteOrderInvalid;
Stephen Wilsonf325ba92010-07-13 23:07:23 +000082}
83
Kate Stoneb9c1b512016-09-06 20:57:50 +000084bool ELFHeader::Parse(lldb_private::DataExtractor &data,
85 lldb::offset_t *offset) {
86 // Read e_ident. This provides byte order and address size info.
87 if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
88 return false;
89
90 const unsigned byte_size = Is32Bit() ? 4 : 8;
91 data.SetByteOrder(GetByteOrder());
92 data.SetAddressByteSize(byte_size);
93
94 // Read e_type and e_machine.
95 if (data.GetU16(offset, &e_type, 2) == NULL)
96 return false;
97
98 // Read e_version.
99 if (data.GetU32(offset, &e_version, 1) == NULL)
100 return false;
101
102 // Read e_entry, e_phoff and e_shoff.
103 if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
104 return false;
105
106 // Read e_flags.
107 if (data.GetU32(offset, &e_flags, 1) == NULL)
108 return false;
109
110 // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
111 // e_shstrndx.
112 if (data.GetU16(offset, &e_ehsize, 6) == NULL)
113 return false;
114
115 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000116}
117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118bool ELFHeader::MagicBytesMatch(const uint8_t *magic) {
119 return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000120}
121
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122unsigned ELFHeader::AddressSizeInBytes(const uint8_t *magic) {
123 unsigned address_size = 0;
124
125 switch (magic[EI_CLASS]) {
126 case ELFCLASS32:
127 address_size = 4;
128 break;
129
130 case ELFCLASS64:
131 address_size = 8;
132 break;
133 }
134 return address_size;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000135}
136
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137unsigned ELFHeader::GetRelocationJumpSlotType() const {
138 unsigned slot = 0;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000139
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 switch (e_machine) {
141 default:
142 assert(false && "architecture not supported");
143 break;
144 case EM_PPC:
145 slot = R_PPC_JMP_SLOT;
146 break;
147 case EM_PPC64:
148 slot = R_PPC64_JMP_SLOT;
149 break;
150 case EM_386:
151 case EM_IAMCU: // FIXME: is this correct?
152 slot = R_386_JUMP_SLOT;
153 break;
154 case EM_X86_64:
155 slot = R_X86_64_JUMP_SLOT;
156 break;
157 case EM_ARM:
158 slot = R_ARM_JUMP_SLOT;
159 break;
160 case EM_HEXAGON:
161 slot = R_HEX_JMP_SLOT;
162 break;
163 case EM_AARCH64:
164 slot = R_AARCH64_JUMP_SLOT;
165 break;
166 case EM_MIPS:
167 slot = R_MIPS_JUMP_SLOT;
168 break;
169 case EM_S390:
170 slot = R_390_JMP_SLOT;
171 break;
172 }
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174 return slot;
Stephen Wilson43fe6452011-03-30 15:59:12 +0000175}
176
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000177//------------------------------------------------------------------------------
178// ELFSectionHeader
179
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180ELFSectionHeader::ELFSectionHeader() {
181 memset(this, 0, sizeof(ELFSectionHeader));
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000182}
183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
185 lldb::offset_t *offset) {
186 const unsigned byte_size = data.GetAddressByteSize();
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188 // Read sh_name and sh_type.
189 if (data.GetU32(offset, &sh_name, 2) == NULL)
190 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000191
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192 // Read sh_flags.
193 if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
194 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000195
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 // Read sh_addr, sh_off and sh_size.
197 if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
198 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000199
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 // Read sh_link and sh_info.
201 if (data.GetU32(offset, &sh_link, 2) == NULL)
202 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000203
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 // Read sh_addralign and sh_entsize.
205 if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
206 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000207
Kate Stoneb9c1b512016-09-06 20:57:50 +0000208 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000209}
210
211//------------------------------------------------------------------------------
212// ELFSymbol
213
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214ELFSymbol::ELFSymbol() { memset(this, 0, sizeof(ELFSymbol)); }
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000215
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216#define ENUM_TO_CSTR(e) \
217 case e: \
218 return #e
Greg Clayton9594f4c2013-04-13 23:17:23 +0000219
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220const char *ELFSymbol::bindingToCString(unsigned char binding) {
221 switch (binding) {
Greg Clayton9594f4c2013-04-13 23:17:23 +0000222 ENUM_TO_CSTR(STB_LOCAL);
223 ENUM_TO_CSTR(STB_GLOBAL);
224 ENUM_TO_CSTR(STB_WEAK);
225 ENUM_TO_CSTR(STB_LOOS);
226 ENUM_TO_CSTR(STB_HIOS);
227 ENUM_TO_CSTR(STB_LOPROC);
228 ENUM_TO_CSTR(STB_HIPROC);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 }
230 return "";
Greg Clayton9594f4c2013-04-13 23:17:23 +0000231}
232
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233const char *ELFSymbol::typeToCString(unsigned char type) {
234 switch (type) {
Greg Clayton9594f4c2013-04-13 23:17:23 +0000235 ENUM_TO_CSTR(STT_NOTYPE);
236 ENUM_TO_CSTR(STT_OBJECT);
237 ENUM_TO_CSTR(STT_FUNC);
238 ENUM_TO_CSTR(STT_SECTION);
239 ENUM_TO_CSTR(STT_FILE);
240 ENUM_TO_CSTR(STT_COMMON);
241 ENUM_TO_CSTR(STT_TLS);
Greg Clayton9594f4c2013-04-13 23:17:23 +0000242 ENUM_TO_CSTR(STT_GNU_IFUNC);
Pavel Labatha6d0dd72015-06-23 17:15:14 +0000243 ENUM_TO_CSTR(STT_HIOS);
Greg Clayton9594f4c2013-04-13 23:17:23 +0000244 ENUM_TO_CSTR(STT_LOPROC);
245 ENUM_TO_CSTR(STT_HIPROC);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 }
247 return "";
Greg Clayton9594f4c2013-04-13 23:17:23 +0000248}
249
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250const char *ELFSymbol::sectionIndexToCString(
251 elf_half shndx, const lldb_private::SectionList *section_list) {
252 switch (shndx) {
Greg Clayton9594f4c2013-04-13 23:17:23 +0000253 ENUM_TO_CSTR(SHN_UNDEF);
254 ENUM_TO_CSTR(SHN_LOPROC);
255 ENUM_TO_CSTR(SHN_HIPROC);
256 ENUM_TO_CSTR(SHN_LOOS);
257 ENUM_TO_CSTR(SHN_HIOS);
258 ENUM_TO_CSTR(SHN_ABS);
259 ENUM_TO_CSTR(SHN_COMMON);
260 ENUM_TO_CSTR(SHN_XINDEX);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261 default: {
262 const lldb_private::Section *section =
263 section_list->GetSectionAtIndex(shndx).get();
264 if (section)
265 return section->GetName().AsCString("");
266 } break;
267 }
268 return "";
Greg Clayton9594f4c2013-04-13 23:17:23 +0000269}
270
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271void ELFSymbol::Dump(lldb_private::Stream *s, uint32_t idx,
272 const lldb_private::DataExtractor *strtab_data,
273 const lldb_private::SectionList *section_list) {
274 s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64
275 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
276 idx, st_value, st_size, st_name, st_info,
277 bindingToCString(getBinding()), typeToCString(getType()), st_other,
278 st_shndx, sectionIndexToCString(st_shndx, section_list),
279 strtab_data ? strtab_data->PeekCStr(st_name) : "");
Greg Clayton9594f4c2013-04-13 23:17:23 +0000280}
281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
283 lldb::offset_t *offset) {
284 const unsigned byte_size = data.GetAddressByteSize();
285 const bool parsing_32 = byte_size == 4;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000286
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 // Read st_name.
288 if (data.GetU32(offset, &st_name, 1) == NULL)
289 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 if (parsing_32) {
292 // Read st_value and st_size.
293 if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
294 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000295
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 // Read st_info and st_other.
297 if (data.GetU8(offset, &st_info, 2) == NULL)
298 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000299
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300 // Read st_shndx.
301 if (data.GetU16(offset, &st_shndx, 1) == NULL)
302 return false;
303 } else {
304 // Read st_info and st_other.
305 if (data.GetU8(offset, &st_info, 2) == NULL)
306 return false;
307
308 // Read st_shndx.
309 if (data.GetU16(offset, &st_shndx, 1) == NULL)
310 return false;
311
312 // Read st_value and st_size.
313 if (data.GetU64(offset, &st_value, 2) == NULL)
314 return false;
315 }
316 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000317}
318
319//------------------------------------------------------------------------------
320// ELFProgramHeader
321
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322ELFProgramHeader::ELFProgramHeader() {
323 memset(this, 0, sizeof(ELFProgramHeader));
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000324}
325
Kate Stoneb9c1b512016-09-06 20:57:50 +0000326bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
327 lldb::offset_t *offset) {
328 const uint32_t byte_size = data.GetAddressByteSize();
329 const bool parsing_32 = byte_size == 4;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000330
Kate Stoneb9c1b512016-09-06 20:57:50 +0000331 // Read p_type;
332 if (data.GetU32(offset, &p_type, 1) == NULL)
333 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000334
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 if (parsing_32) {
336 // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
337 if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
338 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000339
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 // Read p_flags.
341 if (data.GetU32(offset, &p_flags, 1) == NULL)
342 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000343
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344 // Read p_align.
345 if (GetMaxU64(data, offset, &p_align, byte_size) == false)
346 return false;
347 } else {
348 // Read p_flags.
349 if (data.GetU32(offset, &p_flags, 1) == NULL)
350 return false;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000351
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352 // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
353 if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
354 return false;
355 }
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000356
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 return true;
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000358}
359
360//------------------------------------------------------------------------------
361// ELFDynamic
362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363ELFDynamic::ELFDynamic() { memset(this, 0, sizeof(ELFDynamic)); }
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000364
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365bool ELFDynamic::Parse(const lldb_private::DataExtractor &data,
366 lldb::offset_t *offset) {
367 const unsigned byte_size = data.GetAddressByteSize();
368 return GetMaxS64(data, offset, &d_tag, byte_size, 2);
Stephen Wilsonf325ba92010-07-13 23:07:23 +0000369}
370
Stephen Wilson43fe6452011-03-30 15:59:12 +0000371//------------------------------------------------------------------------------
372// ELFRel
373
Kate Stoneb9c1b512016-09-06 20:57:50 +0000374ELFRel::ELFRel() { memset(this, 0, sizeof(ELFRel)); }
Stephen Wilson43fe6452011-03-30 15:59:12 +0000375
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376bool ELFRel::Parse(const lldb_private::DataExtractor &data,
377 lldb::offset_t *offset) {
378 const unsigned byte_size = data.GetAddressByteSize();
Stephen Wilson43fe6452011-03-30 15:59:12 +0000379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 // Read r_offset and r_info.
381 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
382 return false;
Stephen Wilson43fe6452011-03-30 15:59:12 +0000383
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 return true;
Stephen Wilson43fe6452011-03-30 15:59:12 +0000385}
386
387//------------------------------------------------------------------------------
388// ELFRela
389
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390ELFRela::ELFRela() { memset(this, 0, sizeof(ELFRela)); }
391
392bool ELFRela::Parse(const lldb_private::DataExtractor &data,
393 lldb::offset_t *offset) {
394 const unsigned byte_size = data.GetAddressByteSize();
395
396 // Read r_offset and r_info.
397 if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
398 return false;
399
400 // Read r_addend;
401 if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
402 return false;
403
404 return true;
Stephen Wilson43fe6452011-03-30 15:59:12 +0000405}