1f325ba9dSStephen Wilson //===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===//
2f325ba9dSStephen Wilson //
3f325ba9dSStephen Wilson //                     The LLVM Compiler Infrastructure
4f325ba9dSStephen Wilson //
5f325ba9dSStephen Wilson // This file is distributed under the University of Illinois Open Source
6f325ba9dSStephen Wilson // License. See LICENSE.TXT for details.
7f325ba9dSStephen Wilson //
8f325ba9dSStephen Wilson //===----------------------------------------------------------------------===//
9f325ba9dSStephen Wilson 
10f325ba9dSStephen Wilson #include <cstring>
11f325ba9dSStephen Wilson 
12f325ba9dSStephen Wilson #include "lldb/Core/DataExtractor.h"
13f325ba9dSStephen Wilson 
14f325ba9dSStephen Wilson #include "ELFHeader.h"
15f325ba9dSStephen Wilson 
16f325ba9dSStephen Wilson using namespace elf;
17f325ba9dSStephen Wilson using namespace lldb;
18f325ba9dSStephen Wilson using namespace llvm::ELF;
19f325ba9dSStephen Wilson 
20f325ba9dSStephen Wilson //------------------------------------------------------------------------------
21f325ba9dSStephen Wilson // Static utility functions.
22f325ba9dSStephen Wilson //
23f325ba9dSStephen Wilson // GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
24f325ba9dSStephen Wilson // with error handling code and provide for parsing a sequence of values.
25f325ba9dSStephen Wilson static bool
26f325ba9dSStephen Wilson GetMaxU64(const lldb_private::DataExtractor &data,
27*c7bece56SGreg Clayton           lldb::offset_t *offset,
28*c7bece56SGreg Clayton           uint64_t *value,
29*c7bece56SGreg Clayton           uint32_t byte_size)
30f325ba9dSStephen Wilson {
31*c7bece56SGreg Clayton     const lldb::offset_t saved_offset = *offset;
32f325ba9dSStephen Wilson     *value = data.GetMaxU64(offset, byte_size);
33f325ba9dSStephen Wilson     return *offset != saved_offset;
34f325ba9dSStephen Wilson }
35f325ba9dSStephen Wilson 
36f325ba9dSStephen Wilson static bool
37f325ba9dSStephen Wilson GetMaxU64(const lldb_private::DataExtractor &data,
38*c7bece56SGreg Clayton           lldb::offset_t *offset,
39*c7bece56SGreg Clayton           uint64_t *value,
40*c7bece56SGreg Clayton           uint32_t byte_size,
41f325ba9dSStephen Wilson           uint32_t count)
42f325ba9dSStephen Wilson {
43*c7bece56SGreg Clayton     lldb::offset_t saved_offset = *offset;
44f325ba9dSStephen Wilson 
45f325ba9dSStephen Wilson     for (uint32_t i = 0; i < count; ++i, ++value)
46f325ba9dSStephen Wilson     {
47f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, value, byte_size) == false)
48f325ba9dSStephen Wilson         {
49f325ba9dSStephen Wilson             *offset = saved_offset;
50f325ba9dSStephen Wilson             return false;
51f325ba9dSStephen Wilson         }
52f325ba9dSStephen Wilson     }
53f325ba9dSStephen Wilson     return true;
54f325ba9dSStephen Wilson }
55f325ba9dSStephen Wilson 
56f325ba9dSStephen Wilson static bool
57f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data,
58*c7bece56SGreg Clayton           lldb::offset_t *offset,
59*c7bece56SGreg Clayton           int64_t *value,
60*c7bece56SGreg Clayton           uint32_t byte_size)
61f325ba9dSStephen Wilson {
62*c7bece56SGreg Clayton     const lldb::offset_t saved_offset = *offset;
63f325ba9dSStephen Wilson     *value = data.GetMaxS64(offset, byte_size);
64f325ba9dSStephen Wilson     return *offset != saved_offset;
65f325ba9dSStephen Wilson }
66f325ba9dSStephen Wilson 
67f325ba9dSStephen Wilson static bool
68f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data,
69*c7bece56SGreg Clayton           lldb::offset_t *offset,
70*c7bece56SGreg Clayton           int64_t *value,
71*c7bece56SGreg Clayton           uint32_t byte_size,
72f325ba9dSStephen Wilson           uint32_t count)
73f325ba9dSStephen Wilson {
74*c7bece56SGreg Clayton     lldb::offset_t saved_offset = *offset;
75f325ba9dSStephen Wilson 
76f325ba9dSStephen Wilson     for (uint32_t i = 0; i < count; ++i, ++value)
77f325ba9dSStephen Wilson     {
78f325ba9dSStephen Wilson         if (GetMaxS64(data, offset, value, byte_size) == false)
79f325ba9dSStephen Wilson         {
80f325ba9dSStephen Wilson             *offset = saved_offset;
81f325ba9dSStephen Wilson             return false;
82f325ba9dSStephen Wilson         }
83f325ba9dSStephen Wilson     }
84f325ba9dSStephen Wilson     return true;
85f325ba9dSStephen Wilson }
86f325ba9dSStephen Wilson 
87f325ba9dSStephen Wilson //------------------------------------------------------------------------------
88f325ba9dSStephen Wilson // ELFHeader
89f325ba9dSStephen Wilson 
90f325ba9dSStephen Wilson ELFHeader::ELFHeader()
91f325ba9dSStephen Wilson {
92f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFHeader));
93f325ba9dSStephen Wilson }
94f325ba9dSStephen Wilson 
95f325ba9dSStephen Wilson ByteOrder
96f325ba9dSStephen Wilson ELFHeader::GetByteOrder() const
97f325ba9dSStephen Wilson {
98f325ba9dSStephen Wilson     if (e_ident[EI_DATA] == ELFDATA2MSB)
99f325ba9dSStephen Wilson         return eByteOrderBig;
100f325ba9dSStephen Wilson     if (e_ident[EI_DATA] == ELFDATA2LSB)
101f325ba9dSStephen Wilson         return eByteOrderLittle;
102f325ba9dSStephen Wilson     return eByteOrderInvalid;
103f325ba9dSStephen Wilson }
104f325ba9dSStephen Wilson 
105f325ba9dSStephen Wilson bool
106*c7bece56SGreg Clayton ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset)
107f325ba9dSStephen Wilson {
108f325ba9dSStephen Wilson     // Read e_ident.  This provides byte order and address size info.
109f325ba9dSStephen Wilson     if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
110f325ba9dSStephen Wilson         return false;
111f325ba9dSStephen Wilson 
112f325ba9dSStephen Wilson     const unsigned byte_size = Is32Bit() ? 4 : 8;
113f325ba9dSStephen Wilson     data.SetByteOrder(GetByteOrder());
114f325ba9dSStephen Wilson     data.SetAddressByteSize(byte_size);
115f325ba9dSStephen Wilson 
116f325ba9dSStephen Wilson     // Read e_type and e_machine.
117f325ba9dSStephen Wilson     if (data.GetU16(offset, &e_type, 2) == NULL)
118f325ba9dSStephen Wilson         return false;
119f325ba9dSStephen Wilson 
120f325ba9dSStephen Wilson     // Read e_version.
121f325ba9dSStephen Wilson     if (data.GetU32(offset, &e_version, 1) == NULL)
122f325ba9dSStephen Wilson         return false;
123f325ba9dSStephen Wilson 
124f325ba9dSStephen Wilson     // Read e_entry, e_phoff and e_shoff.
125f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
126f325ba9dSStephen Wilson         return false;
127f325ba9dSStephen Wilson 
128f325ba9dSStephen Wilson     // Read e_flags.
129f325ba9dSStephen Wilson     if (data.GetU32(offset, &e_flags, 1) == NULL)
130f325ba9dSStephen Wilson         return false;
131f325ba9dSStephen Wilson 
132f325ba9dSStephen Wilson     // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
133f325ba9dSStephen Wilson     // e_shstrndx.
134f325ba9dSStephen Wilson     if (data.GetU16(offset, &e_ehsize, 6) == NULL)
135f325ba9dSStephen Wilson         return false;
136f325ba9dSStephen Wilson 
137f325ba9dSStephen Wilson     return true;
138f325ba9dSStephen Wilson }
139f325ba9dSStephen Wilson 
140f325ba9dSStephen Wilson bool
141f325ba9dSStephen Wilson ELFHeader::MagicBytesMatch(const uint8_t *magic)
142f325ba9dSStephen Wilson {
143f325ba9dSStephen Wilson     return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
144f325ba9dSStephen Wilson }
145f325ba9dSStephen Wilson 
146f325ba9dSStephen Wilson unsigned
147f325ba9dSStephen Wilson ELFHeader::AddressSizeInBytes(const uint8_t *magic)
148f325ba9dSStephen Wilson {
149f325ba9dSStephen Wilson     unsigned address_size = 0;
150f325ba9dSStephen Wilson 
151f325ba9dSStephen Wilson     switch (magic[EI_CLASS])
152f325ba9dSStephen Wilson     {
153f325ba9dSStephen Wilson     case ELFCLASS32:
154f325ba9dSStephen Wilson         address_size = 4;
155f325ba9dSStephen Wilson         break;
156f325ba9dSStephen Wilson 
157f325ba9dSStephen Wilson     case ELFCLASS64:
158f325ba9dSStephen Wilson         address_size = 8;
159f325ba9dSStephen Wilson         break;
160f325ba9dSStephen Wilson     }
161f325ba9dSStephen Wilson     return address_size;
162f325ba9dSStephen Wilson }
163f325ba9dSStephen Wilson 
16443fe645bSStephen Wilson unsigned
16543fe645bSStephen Wilson ELFHeader::GetRelocationJumpSlotType() const
16643fe645bSStephen Wilson {
16743fe645bSStephen Wilson     unsigned slot = 0;
16843fe645bSStephen Wilson 
16943fe645bSStephen Wilson     switch (e_machine)
17043fe645bSStephen Wilson     {
17143fe645bSStephen Wilson     default:
17243fe645bSStephen Wilson         assert(false && "architecture not supported");
17343fe645bSStephen Wilson         break;
17443fe645bSStephen Wilson     case EM_386:
17543fe645bSStephen Wilson     case EM_486:
17643fe645bSStephen Wilson         slot = R_386_JUMP_SLOT;
17743fe645bSStephen Wilson         break;
17843fe645bSStephen Wilson     case EM_X86_64:
17943fe645bSStephen Wilson         slot = R_X86_64_JUMP_SLOT;
18043fe645bSStephen Wilson         break;
18143fe645bSStephen Wilson     case EM_ARM:
18243fe645bSStephen Wilson         slot = R_ARM_JUMP_SLOT;
18343fe645bSStephen Wilson         break;
18443fe645bSStephen Wilson     case EM_MBLAZE:
18543fe645bSStephen Wilson         slot = R_MICROBLAZE_JUMP_SLOT;
18643fe645bSStephen Wilson     }
18743fe645bSStephen Wilson 
18843fe645bSStephen Wilson     return slot;
18943fe645bSStephen Wilson }
19043fe645bSStephen Wilson 
191f325ba9dSStephen Wilson //------------------------------------------------------------------------------
192f325ba9dSStephen Wilson // ELFSectionHeader
193f325ba9dSStephen Wilson 
194f325ba9dSStephen Wilson ELFSectionHeader::ELFSectionHeader()
195f325ba9dSStephen Wilson {
196f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFSectionHeader));
197f325ba9dSStephen Wilson }
198f325ba9dSStephen Wilson 
199f325ba9dSStephen Wilson bool
200f325ba9dSStephen Wilson ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
201*c7bece56SGreg Clayton                         lldb::offset_t *offset)
202f325ba9dSStephen Wilson {
203f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
204f325ba9dSStephen Wilson 
205f325ba9dSStephen Wilson     // Read sh_name and sh_type.
206f325ba9dSStephen Wilson     if (data.GetU32(offset, &sh_name, 2) == NULL)
207f325ba9dSStephen Wilson         return false;
208f325ba9dSStephen Wilson 
209f325ba9dSStephen Wilson     // Read sh_flags.
210f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
211f325ba9dSStephen Wilson         return false;
212f325ba9dSStephen Wilson 
213f325ba9dSStephen Wilson     // Read sh_addr, sh_off and sh_size.
214f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
215f325ba9dSStephen Wilson         return false;
216f325ba9dSStephen Wilson 
217f325ba9dSStephen Wilson     // Read sh_link and sh_info.
218f325ba9dSStephen Wilson     if (data.GetU32(offset, &sh_link, 2) == NULL)
219f325ba9dSStephen Wilson         return false;
220f325ba9dSStephen Wilson 
221f325ba9dSStephen Wilson     // Read sh_addralign and sh_entsize.
222f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
223f325ba9dSStephen Wilson         return false;
224f325ba9dSStephen Wilson 
225f325ba9dSStephen Wilson     return true;
226f325ba9dSStephen Wilson }
227f325ba9dSStephen Wilson 
228f325ba9dSStephen Wilson //------------------------------------------------------------------------------
229f325ba9dSStephen Wilson // ELFSymbol
230f325ba9dSStephen Wilson 
231f325ba9dSStephen Wilson ELFSymbol::ELFSymbol()
232f325ba9dSStephen Wilson {
233f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFSymbol));
234f325ba9dSStephen Wilson }
235f325ba9dSStephen Wilson 
236f325ba9dSStephen Wilson bool
237*c7bece56SGreg Clayton ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
238f325ba9dSStephen Wilson {
239f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
240f325ba9dSStephen Wilson     const bool parsing_32 = byte_size == 4;
241f325ba9dSStephen Wilson 
242f325ba9dSStephen Wilson     // Read st_name.
243f325ba9dSStephen Wilson     if (data.GetU32(offset, &st_name, 1) == NULL)
244f325ba9dSStephen Wilson         return false;
245f325ba9dSStephen Wilson 
246f325ba9dSStephen Wilson     if (parsing_32)
247f325ba9dSStephen Wilson     {
248f325ba9dSStephen Wilson         // Read st_value and st_size.
249f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
250f325ba9dSStephen Wilson             return false;
251f325ba9dSStephen Wilson 
252f325ba9dSStephen Wilson         // Read st_info and st_other.
253f325ba9dSStephen Wilson         if (data.GetU8(offset, &st_info, 2) == NULL)
254f325ba9dSStephen Wilson             return false;
255f325ba9dSStephen Wilson 
256f325ba9dSStephen Wilson         // Read st_shndx.
257f325ba9dSStephen Wilson         if (data.GetU16(offset, &st_shndx, 1) == NULL)
258f325ba9dSStephen Wilson             return false;
259f325ba9dSStephen Wilson     }
260f325ba9dSStephen Wilson     else
261f325ba9dSStephen Wilson     {
262f325ba9dSStephen Wilson         // Read st_info and st_other.
263f325ba9dSStephen Wilson         if (data.GetU8(offset, &st_info, 2) == NULL)
264f325ba9dSStephen Wilson             return false;
265f325ba9dSStephen Wilson 
266f325ba9dSStephen Wilson         // Read st_shndx.
267f325ba9dSStephen Wilson         if (data.GetU16(offset, &st_shndx, 1) == NULL)
268f325ba9dSStephen Wilson             return false;
269f325ba9dSStephen Wilson 
270f325ba9dSStephen Wilson         // Read st_value and st_size.
271f325ba9dSStephen Wilson         if (data.GetU64(offset, &st_value, 2) == NULL)
272f325ba9dSStephen Wilson             return false;
273f325ba9dSStephen Wilson     }
274f325ba9dSStephen Wilson     return true;
275f325ba9dSStephen Wilson }
276f325ba9dSStephen Wilson 
277f325ba9dSStephen Wilson //------------------------------------------------------------------------------
278f325ba9dSStephen Wilson // ELFProgramHeader
279f325ba9dSStephen Wilson 
280f325ba9dSStephen Wilson ELFProgramHeader::ELFProgramHeader()
281f325ba9dSStephen Wilson {
282f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFProgramHeader));
283f325ba9dSStephen Wilson }
284f325ba9dSStephen Wilson 
285f325ba9dSStephen Wilson bool
286f325ba9dSStephen Wilson ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
287*c7bece56SGreg Clayton                         lldb::offset_t *offset)
288f325ba9dSStephen Wilson {
289f325ba9dSStephen Wilson     const uint32_t byte_size = data.GetAddressByteSize();
290f325ba9dSStephen Wilson     const bool parsing_32 = byte_size == 4;
291f325ba9dSStephen Wilson 
292f325ba9dSStephen Wilson     // Read p_type;
293f325ba9dSStephen Wilson     if (data.GetU32(offset, &p_type, 1) == NULL)
294f325ba9dSStephen Wilson         return false;
295f325ba9dSStephen Wilson 
296f325ba9dSStephen Wilson     if (parsing_32) {
297f325ba9dSStephen Wilson         // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
298f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
299f325ba9dSStephen Wilson             return false;
300f325ba9dSStephen Wilson 
301f325ba9dSStephen Wilson         // Read p_flags.
302f325ba9dSStephen Wilson         if (data.GetU32(offset, &p_flags, 1) == NULL)
303f325ba9dSStephen Wilson             return false;
304f325ba9dSStephen Wilson 
305f325ba9dSStephen Wilson         // Read p_align.
306f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_align, byte_size) == false)
307f325ba9dSStephen Wilson             return false;
308f325ba9dSStephen Wilson     }
309f325ba9dSStephen Wilson     else {
310f325ba9dSStephen Wilson         // Read p_flags.
311f325ba9dSStephen Wilson         if (data.GetU32(offset, &p_flags, 1) == NULL)
312f325ba9dSStephen Wilson             return false;
313f325ba9dSStephen Wilson 
314f325ba9dSStephen Wilson         // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
315f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
316f325ba9dSStephen Wilson             return false;
317f325ba9dSStephen Wilson     }
318f325ba9dSStephen Wilson 
319f325ba9dSStephen Wilson     return true;
320f325ba9dSStephen Wilson }
321f325ba9dSStephen Wilson 
322f325ba9dSStephen Wilson //------------------------------------------------------------------------------
323f325ba9dSStephen Wilson // ELFDynamic
324f325ba9dSStephen Wilson 
325f325ba9dSStephen Wilson ELFDynamic::ELFDynamic()
326f325ba9dSStephen Wilson {
327f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFDynamic));
328f325ba9dSStephen Wilson }
329f325ba9dSStephen Wilson 
330f325ba9dSStephen Wilson bool
331*c7bece56SGreg Clayton ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
332f325ba9dSStephen Wilson {
333f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
334f325ba9dSStephen Wilson     return GetMaxS64(data, offset, &d_tag, byte_size, 2);
335f325ba9dSStephen Wilson }
336f325ba9dSStephen Wilson 
33743fe645bSStephen Wilson //------------------------------------------------------------------------------
33843fe645bSStephen Wilson // ELFRel
33943fe645bSStephen Wilson 
34043fe645bSStephen Wilson ELFRel::ELFRel()
34143fe645bSStephen Wilson {
34243fe645bSStephen Wilson     memset(this, 0, sizeof(ELFRel));
34343fe645bSStephen Wilson }
34443fe645bSStephen Wilson 
34543fe645bSStephen Wilson bool
346*c7bece56SGreg Clayton ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
34743fe645bSStephen Wilson {
34843fe645bSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
34943fe645bSStephen Wilson 
35043fe645bSStephen Wilson     // Read r_offset and r_info.
35143fe645bSStephen Wilson     if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
35243fe645bSStephen Wilson         return false;
35343fe645bSStephen Wilson 
35443fe645bSStephen Wilson     return true;
35543fe645bSStephen Wilson }
35643fe645bSStephen Wilson 
35743fe645bSStephen Wilson //------------------------------------------------------------------------------
35843fe645bSStephen Wilson // ELFRela
35943fe645bSStephen Wilson 
36043fe645bSStephen Wilson ELFRela::ELFRela()
36143fe645bSStephen Wilson {
36243fe645bSStephen Wilson     memset(this, 0, sizeof(ELFRela));
36343fe645bSStephen Wilson }
36443fe645bSStephen Wilson 
36543fe645bSStephen Wilson bool
366*c7bece56SGreg Clayton ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
36743fe645bSStephen Wilson {
36843fe645bSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
36943fe645bSStephen Wilson 
37043fe645bSStephen Wilson     // Read r_offset and r_info.
37143fe645bSStephen Wilson     if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
37243fe645bSStephen Wilson         return false;
37343fe645bSStephen Wilson 
37443fe645bSStephen Wilson     // Read r_addend;
37543fe645bSStephen Wilson     if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
37643fe645bSStephen Wilson         return false;
37743fe645bSStephen Wilson 
37843fe645bSStephen Wilson     return true;
37943fe645bSStephen Wilson }
38043fe645bSStephen Wilson 
381f325ba9dSStephen Wilson 
382