1//===-- 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#include "lldb/Core/Section.h"
14#include "lldb/Core/Stream.h"
15
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.
27static bool
28GetMaxU64(const lldb_private::DataExtractor &data,
29          lldb::offset_t *offset,
30          uint64_t *value,
31          uint32_t byte_size)
32{
33    const lldb::offset_t saved_offset = *offset;
34    *value = data.GetMaxU64(offset, byte_size);
35    return *offset != saved_offset;
36}
37
38static bool
39GetMaxU64(const lldb_private::DataExtractor &data,
40          lldb::offset_t *offset,
41          uint64_t *value,
42          uint32_t byte_size,
43          uint32_t count)
44{
45    lldb::offset_t saved_offset = *offset;
46
47    for (uint32_t i = 0; i < count; ++i, ++value)
48    {
49        if (GetMaxU64(data, offset, value, byte_size) == false)
50        {
51            *offset = saved_offset;
52            return false;
53        }
54    }
55    return true;
56}
57
58static bool
59GetMaxS64(const lldb_private::DataExtractor &data,
60          lldb::offset_t *offset,
61          int64_t *value,
62          uint32_t byte_size)
63{
64    const lldb::offset_t saved_offset = *offset;
65    *value = data.GetMaxS64(offset, byte_size);
66    return *offset != saved_offset;
67}
68
69static bool
70GetMaxS64(const lldb_private::DataExtractor &data,
71          lldb::offset_t *offset,
72          int64_t *value,
73          uint32_t byte_size,
74          uint32_t count)
75{
76    lldb::offset_t saved_offset = *offset;
77
78    for (uint32_t i = 0; i < count; ++i, ++value)
79    {
80        if (GetMaxS64(data, offset, value, byte_size) == false)
81        {
82            *offset = saved_offset;
83            return false;
84        }
85    }
86    return true;
87}
88
89//------------------------------------------------------------------------------
90// ELFHeader
91
92ELFHeader::ELFHeader()
93{
94    memset(this, 0, sizeof(ELFHeader));
95}
96
97ByteOrder
98ELFHeader::GetByteOrder() const
99{
100    if (e_ident[EI_DATA] == ELFDATA2MSB)
101        return eByteOrderBig;
102    if (e_ident[EI_DATA] == ELFDATA2LSB)
103        return eByteOrderLittle;
104    return eByteOrderInvalid;
105}
106
107bool
108ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
109{
110    // Read e_ident.  This provides byte order and address size info.
111    if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
112        return false;
113
114    const unsigned byte_size = Is32Bit() ? 4 : 8;
115    data.SetByteOrder(GetByteOrder());
116    data.SetAddressByteSize(byte_size);
117
118    // Read e_type and e_machine.
119    if (data.GetU16(offset, &e_type, 2) == NULL)
120        return false;
121
122    // Read e_version.
123    if (data.GetU32(offset, &e_version, 1) == NULL)
124        return false;
125
126    // Read e_entry, e_phoff and e_shoff.
127    if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
128        return false;
129
130    // Read e_flags.
131    if (data.GetU32(offset, &e_flags, 1) == NULL)
132        return false;
133
134    // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
135    // e_shstrndx.
136    if (data.GetU16(offset, &e_ehsize, 6) == NULL)
137        return false;
138
139    return true;
140}
141
142bool
143ELFHeader::MagicBytesMatch(const uint8_t *magic)
144{
145    return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
146}
147
148unsigned
149ELFHeader::AddressSizeInBytes(const uint8_t *magic)
150{
151    unsigned address_size = 0;
152
153    switch (magic[EI_CLASS])
154    {
155    case ELFCLASS32:
156        address_size = 4;
157        break;
158
159    case ELFCLASS64:
160        address_size = 8;
161        break;
162    }
163    return address_size;
164}
165
166unsigned
167ELFHeader::GetRelocationJumpSlotType() const
168{
169    unsigned slot = 0;
170
171    switch (e_machine)
172    {
173    default:
174        assert(false && "architecture not supported");
175        break;
176    case EM_386:
177    case EM_486:
178        slot = R_386_JUMP_SLOT;
179        break;
180    case EM_X86_64:
181        slot = R_X86_64_JUMP_SLOT;
182        break;
183    case EM_ARM:
184        slot = R_ARM_JUMP_SLOT;
185        break;
186    }
187
188    return slot;
189}
190
191//------------------------------------------------------------------------------
192// ELFSectionHeader
193
194ELFSectionHeader::ELFSectionHeader()
195{
196    memset(this, 0, sizeof(ELFSectionHeader));
197}
198
199bool
200ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
201                        lldb::offset_t *offset)
202{
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
236#define ENUM_TO_CSTR(e) case e: return #e
237
238const char *
239ELFSymbol::bindingToCString(unsigned char binding)
240{
241    switch (binding)
242    {
243    ENUM_TO_CSTR(STB_LOCAL);
244    ENUM_TO_CSTR(STB_GLOBAL);
245    ENUM_TO_CSTR(STB_WEAK);
246    ENUM_TO_CSTR(STB_LOOS);
247    ENUM_TO_CSTR(STB_HIOS);
248    ENUM_TO_CSTR(STB_LOPROC);
249    ENUM_TO_CSTR(STB_HIPROC);
250    }
251    return "";
252}
253
254const char *
255ELFSymbol::typeToCString(unsigned char type)
256{
257    switch (type)
258    {
259    ENUM_TO_CSTR(STT_NOTYPE);
260    ENUM_TO_CSTR(STT_OBJECT);
261    ENUM_TO_CSTR(STT_FUNC);
262    ENUM_TO_CSTR(STT_SECTION);
263    ENUM_TO_CSTR(STT_FILE);
264    ENUM_TO_CSTR(STT_COMMON);
265    ENUM_TO_CSTR(STT_TLS);
266    ENUM_TO_CSTR(STT_LOOS);
267    ENUM_TO_CSTR(STT_HIOS);
268    ENUM_TO_CSTR(STT_GNU_IFUNC);
269    ENUM_TO_CSTR(STT_LOPROC);
270    ENUM_TO_CSTR(STT_HIPROC);
271    }
272    return "";
273}
274
275const char *
276ELFSymbol::sectionIndexToCString (elf_half shndx,
277                                  const lldb_private::SectionList *section_list)
278{
279    switch (shndx)
280    {
281    ENUM_TO_CSTR(SHN_UNDEF);
282    ENUM_TO_CSTR(SHN_LOPROC);
283    ENUM_TO_CSTR(SHN_HIPROC);
284    ENUM_TO_CSTR(SHN_LOOS);
285    ENUM_TO_CSTR(SHN_HIOS);
286    ENUM_TO_CSTR(SHN_ABS);
287    ENUM_TO_CSTR(SHN_COMMON);
288    ENUM_TO_CSTR(SHN_XINDEX);
289    default:
290        {
291            const lldb_private::Section *section = section_list->GetSectionAtIndex(shndx).get();
292            if (section)
293                return section->GetName().AsCString("");
294        }
295        break;
296    }
297    return "";
298}
299
300void
301ELFSymbol::Dump (lldb_private::Stream *s,
302                 uint32_t idx,
303                 const lldb_private::DataExtractor *strtab_data,
304                 const lldb_private::SectionList *section_list)
305{
306    s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
307              idx,
308              st_value,
309              st_size,
310              st_name,
311              st_info,
312              bindingToCString (getBinding()),
313              typeToCString (getType()),
314              st_other,
315              st_shndx,
316              sectionIndexToCString (st_shndx, section_list),
317              strtab_data ? strtab_data->PeekCStr(st_name) : "");
318}
319
320bool
321ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
322{
323    const unsigned byte_size = data.GetAddressByteSize();
324    const bool parsing_32 = byte_size == 4;
325
326    // Read st_name.
327    if (data.GetU32(offset, &st_name, 1) == NULL)
328        return false;
329
330    if (parsing_32)
331    {
332        // Read st_value and st_size.
333        if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
334            return false;
335
336        // Read st_info and st_other.
337        if (data.GetU8(offset, &st_info, 2) == NULL)
338            return false;
339
340        // Read st_shndx.
341        if (data.GetU16(offset, &st_shndx, 1) == NULL)
342            return false;
343    }
344    else
345    {
346        // Read st_info and st_other.
347        if (data.GetU8(offset, &st_info, 2) == NULL)
348            return false;
349
350        // Read st_shndx.
351        if (data.GetU16(offset, &st_shndx, 1) == NULL)
352            return false;
353
354        // Read st_value and st_size.
355        if (data.GetU64(offset, &st_value, 2) == NULL)
356            return false;
357    }
358    return true;
359}
360
361//------------------------------------------------------------------------------
362// ELFProgramHeader
363
364ELFProgramHeader::ELFProgramHeader()
365{
366    memset(this, 0, sizeof(ELFProgramHeader));
367}
368
369bool
370ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
371                        lldb::offset_t *offset)
372{
373    const uint32_t byte_size = data.GetAddressByteSize();
374    const bool parsing_32 = byte_size == 4;
375
376    // Read p_type;
377    if (data.GetU32(offset, &p_type, 1) == NULL)
378        return false;
379
380    if (parsing_32) {
381        // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
382        if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
383            return false;
384
385        // Read p_flags.
386        if (data.GetU32(offset, &p_flags, 1) == NULL)
387            return false;
388
389        // Read p_align.
390        if (GetMaxU64(data, offset, &p_align, byte_size) == false)
391            return false;
392    }
393    else {
394        // Read p_flags.
395        if (data.GetU32(offset, &p_flags, 1) == NULL)
396            return false;
397
398        // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
399        if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
400            return false;
401    }
402
403    return true;
404}
405
406//------------------------------------------------------------------------------
407// ELFDynamic
408
409ELFDynamic::ELFDynamic()
410{
411    memset(this, 0, sizeof(ELFDynamic));
412}
413
414bool
415ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
416{
417    const unsigned byte_size = data.GetAddressByteSize();
418    return GetMaxS64(data, offset, &d_tag, byte_size, 2);
419}
420
421//------------------------------------------------------------------------------
422// ELFRel
423
424ELFRel::ELFRel()
425{
426    memset(this, 0, sizeof(ELFRel));
427}
428
429bool
430ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
431{
432    const unsigned byte_size = data.GetAddressByteSize();
433
434    // Read r_offset and r_info.
435    if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
436        return false;
437
438    return true;
439}
440
441//------------------------------------------------------------------------------
442// ELFRela
443
444ELFRela::ELFRela()
445{
446    memset(this, 0, sizeof(ELFRela));
447}
448
449bool
450ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
451{
452    const unsigned byte_size = data.GetAddressByteSize();
453
454    // Read r_offset and r_info.
455    if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
456        return false;
457
458    // Read r_addend;
459    if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
460        return false;
461
462    return true;
463}
464
465
466