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,
27f325ba9dSStephen Wilson           uint32_t *offset, uint64_t *value, uint32_t byte_size)
28f325ba9dSStephen Wilson {
29f325ba9dSStephen Wilson     const uint32_t saved_offset = *offset;
30f325ba9dSStephen Wilson     *value = data.GetMaxU64(offset, byte_size);
31f325ba9dSStephen Wilson     return *offset != saved_offset;
32f325ba9dSStephen Wilson }
33f325ba9dSStephen Wilson 
34f325ba9dSStephen Wilson static bool
35f325ba9dSStephen Wilson GetMaxU64(const lldb_private::DataExtractor &data,
36f325ba9dSStephen Wilson           uint32_t *offset, uint64_t *value, uint32_t byte_size,
37f325ba9dSStephen Wilson           uint32_t count)
38f325ba9dSStephen Wilson {
39f325ba9dSStephen Wilson     uint32_t saved_offset = *offset;
40f325ba9dSStephen Wilson 
41f325ba9dSStephen Wilson     for (uint32_t i = 0; i < count; ++i, ++value)
42f325ba9dSStephen Wilson     {
43f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, value, byte_size) == false)
44f325ba9dSStephen Wilson         {
45f325ba9dSStephen Wilson             *offset = saved_offset;
46f325ba9dSStephen Wilson             return false;
47f325ba9dSStephen Wilson         }
48f325ba9dSStephen Wilson     }
49f325ba9dSStephen Wilson     return true;
50f325ba9dSStephen Wilson }
51f325ba9dSStephen Wilson 
52f325ba9dSStephen Wilson static bool
53f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data,
54f325ba9dSStephen Wilson           uint32_t *offset, int64_t *value, uint32_t byte_size)
55f325ba9dSStephen Wilson {
56f325ba9dSStephen Wilson     const uint32_t saved_offset = *offset;
57f325ba9dSStephen Wilson     *value = data.GetMaxS64(offset, byte_size);
58f325ba9dSStephen Wilson     return *offset != saved_offset;
59f325ba9dSStephen Wilson }
60f325ba9dSStephen Wilson 
61f325ba9dSStephen Wilson static bool
62f325ba9dSStephen Wilson GetMaxS64(const lldb_private::DataExtractor &data,
63f325ba9dSStephen Wilson           uint32_t *offset, int64_t *value, uint32_t byte_size,
64f325ba9dSStephen Wilson           uint32_t count)
65f325ba9dSStephen Wilson {
66f325ba9dSStephen Wilson     uint32_t saved_offset = *offset;
67f325ba9dSStephen Wilson 
68f325ba9dSStephen Wilson     for (uint32_t i = 0; i < count; ++i, ++value)
69f325ba9dSStephen Wilson     {
70f325ba9dSStephen Wilson         if (GetMaxS64(data, offset, value, byte_size) == false)
71f325ba9dSStephen Wilson         {
72f325ba9dSStephen Wilson             *offset = saved_offset;
73f325ba9dSStephen Wilson             return false;
74f325ba9dSStephen Wilson         }
75f325ba9dSStephen Wilson     }
76f325ba9dSStephen Wilson     return true;
77f325ba9dSStephen Wilson }
78f325ba9dSStephen Wilson 
79f325ba9dSStephen Wilson //------------------------------------------------------------------------------
80f325ba9dSStephen Wilson // ELFHeader
81f325ba9dSStephen Wilson 
82f325ba9dSStephen Wilson ELFHeader::ELFHeader()
83f325ba9dSStephen Wilson {
84f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFHeader));
85f325ba9dSStephen Wilson }
86f325ba9dSStephen Wilson 
87f325ba9dSStephen Wilson ByteOrder
88f325ba9dSStephen Wilson ELFHeader::GetByteOrder() const
89f325ba9dSStephen Wilson {
90f325ba9dSStephen Wilson     if (e_ident[EI_DATA] == ELFDATA2MSB)
91f325ba9dSStephen Wilson         return eByteOrderBig;
92f325ba9dSStephen Wilson     if (e_ident[EI_DATA] == ELFDATA2LSB)
93f325ba9dSStephen Wilson         return eByteOrderLittle;
94f325ba9dSStephen Wilson     return eByteOrderInvalid;
95f325ba9dSStephen Wilson }
96f325ba9dSStephen Wilson 
97f325ba9dSStephen Wilson bool
98f325ba9dSStephen Wilson ELFHeader::Parse(lldb_private::DataExtractor &data, uint32_t *offset)
99f325ba9dSStephen Wilson {
100f325ba9dSStephen Wilson     // Read e_ident.  This provides byte order and address size info.
101f325ba9dSStephen Wilson     if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
102f325ba9dSStephen Wilson         return false;
103f325ba9dSStephen Wilson 
104f325ba9dSStephen Wilson     const unsigned byte_size = Is32Bit() ? 4 : 8;
105f325ba9dSStephen Wilson     data.SetByteOrder(GetByteOrder());
106f325ba9dSStephen Wilson     data.SetAddressByteSize(byte_size);
107f325ba9dSStephen Wilson 
108f325ba9dSStephen Wilson     // Read e_type and e_machine.
109f325ba9dSStephen Wilson     if (data.GetU16(offset, &e_type, 2) == NULL)
110f325ba9dSStephen Wilson         return false;
111f325ba9dSStephen Wilson 
112f325ba9dSStephen Wilson     // Read e_version.
113f325ba9dSStephen Wilson     if (data.GetU32(offset, &e_version, 1) == NULL)
114f325ba9dSStephen Wilson         return false;
115f325ba9dSStephen Wilson 
116f325ba9dSStephen Wilson     // Read e_entry, e_phoff and e_shoff.
117f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
118f325ba9dSStephen Wilson         return false;
119f325ba9dSStephen Wilson 
120f325ba9dSStephen Wilson     // Read e_flags.
121f325ba9dSStephen Wilson     if (data.GetU32(offset, &e_flags, 1) == NULL)
122f325ba9dSStephen Wilson         return false;
123f325ba9dSStephen Wilson 
124f325ba9dSStephen Wilson     // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
125f325ba9dSStephen Wilson     // e_shstrndx.
126f325ba9dSStephen Wilson     if (data.GetU16(offset, &e_ehsize, 6) == NULL)
127f325ba9dSStephen Wilson         return false;
128f325ba9dSStephen Wilson 
129f325ba9dSStephen Wilson     return true;
130f325ba9dSStephen Wilson }
131f325ba9dSStephen Wilson 
132f325ba9dSStephen Wilson bool
133f325ba9dSStephen Wilson ELFHeader::MagicBytesMatch(const uint8_t *magic)
134f325ba9dSStephen Wilson {
135f325ba9dSStephen Wilson     return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
136f325ba9dSStephen Wilson }
137f325ba9dSStephen Wilson 
138f325ba9dSStephen Wilson unsigned
139f325ba9dSStephen Wilson ELFHeader::AddressSizeInBytes(const uint8_t *magic)
140f325ba9dSStephen Wilson {
141f325ba9dSStephen Wilson     unsigned address_size = 0;
142f325ba9dSStephen Wilson 
143f325ba9dSStephen Wilson     switch (magic[EI_CLASS])
144f325ba9dSStephen Wilson     {
145f325ba9dSStephen Wilson     case ELFCLASS32:
146f325ba9dSStephen Wilson         address_size = 4;
147f325ba9dSStephen Wilson         break;
148f325ba9dSStephen Wilson 
149f325ba9dSStephen Wilson     case ELFCLASS64:
150f325ba9dSStephen Wilson         address_size = 8;
151f325ba9dSStephen Wilson         break;
152f325ba9dSStephen Wilson     }
153f325ba9dSStephen Wilson     return address_size;
154f325ba9dSStephen Wilson }
155f325ba9dSStephen Wilson 
156*43fe645bSStephen Wilson unsigned
157*43fe645bSStephen Wilson ELFHeader::GetRelocationJumpSlotType() const
158*43fe645bSStephen Wilson {
159*43fe645bSStephen Wilson     unsigned slot = 0;
160*43fe645bSStephen Wilson 
161*43fe645bSStephen Wilson     switch (e_machine)
162*43fe645bSStephen Wilson     {
163*43fe645bSStephen Wilson     default:
164*43fe645bSStephen Wilson         assert(false && "architecture not supported");
165*43fe645bSStephen Wilson         break;
166*43fe645bSStephen Wilson     case EM_386:
167*43fe645bSStephen Wilson     case EM_486:
168*43fe645bSStephen Wilson         slot = R_386_JUMP_SLOT;
169*43fe645bSStephen Wilson         break;
170*43fe645bSStephen Wilson     case EM_X86_64:
171*43fe645bSStephen Wilson         slot = R_X86_64_JUMP_SLOT;
172*43fe645bSStephen Wilson         break;
173*43fe645bSStephen Wilson     case EM_ARM:
174*43fe645bSStephen Wilson         slot = R_ARM_JUMP_SLOT;
175*43fe645bSStephen Wilson         break;
176*43fe645bSStephen Wilson     case EM_MBLAZE:
177*43fe645bSStephen Wilson         slot = R_MICROBLAZE_JUMP_SLOT;
178*43fe645bSStephen Wilson     }
179*43fe645bSStephen Wilson 
180*43fe645bSStephen Wilson     return slot;
181*43fe645bSStephen Wilson }
182*43fe645bSStephen Wilson 
183f325ba9dSStephen Wilson //------------------------------------------------------------------------------
184f325ba9dSStephen Wilson // ELFSectionHeader
185f325ba9dSStephen Wilson 
186f325ba9dSStephen Wilson ELFSectionHeader::ELFSectionHeader()
187f325ba9dSStephen Wilson {
188f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFSectionHeader));
189f325ba9dSStephen Wilson }
190f325ba9dSStephen Wilson 
191f325ba9dSStephen Wilson bool
192f325ba9dSStephen Wilson ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
193f325ba9dSStephen Wilson                         uint32_t *offset)
194f325ba9dSStephen Wilson {
195f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
196f325ba9dSStephen Wilson 
197f325ba9dSStephen Wilson     // Read sh_name and sh_type.
198f325ba9dSStephen Wilson     if (data.GetU32(offset, &sh_name, 2) == NULL)
199f325ba9dSStephen Wilson         return false;
200f325ba9dSStephen Wilson 
201f325ba9dSStephen Wilson     // Read sh_flags.
202f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
203f325ba9dSStephen Wilson         return false;
204f325ba9dSStephen Wilson 
205f325ba9dSStephen Wilson     // Read sh_addr, sh_off and sh_size.
206f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
207f325ba9dSStephen Wilson         return false;
208f325ba9dSStephen Wilson 
209f325ba9dSStephen Wilson     // Read sh_link and sh_info.
210f325ba9dSStephen Wilson     if (data.GetU32(offset, &sh_link, 2) == NULL)
211f325ba9dSStephen Wilson         return false;
212f325ba9dSStephen Wilson 
213f325ba9dSStephen Wilson     // Read sh_addralign and sh_entsize.
214f325ba9dSStephen Wilson     if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
215f325ba9dSStephen Wilson         return false;
216f325ba9dSStephen Wilson 
217f325ba9dSStephen Wilson     return true;
218f325ba9dSStephen Wilson }
219f325ba9dSStephen Wilson 
220f325ba9dSStephen Wilson //------------------------------------------------------------------------------
221f325ba9dSStephen Wilson // ELFSymbol
222f325ba9dSStephen Wilson 
223f325ba9dSStephen Wilson ELFSymbol::ELFSymbol()
224f325ba9dSStephen Wilson {
225f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFSymbol));
226f325ba9dSStephen Wilson }
227f325ba9dSStephen Wilson 
228f325ba9dSStephen Wilson bool
229f325ba9dSStephen Wilson ELFSymbol::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
230f325ba9dSStephen Wilson {
231f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
232f325ba9dSStephen Wilson     const bool parsing_32 = byte_size == 4;
233f325ba9dSStephen Wilson 
234f325ba9dSStephen Wilson     // Read st_name.
235f325ba9dSStephen Wilson     if (data.GetU32(offset, &st_name, 1) == NULL)
236f325ba9dSStephen Wilson         return false;
237f325ba9dSStephen Wilson 
238f325ba9dSStephen Wilson     if (parsing_32)
239f325ba9dSStephen Wilson     {
240f325ba9dSStephen Wilson         // Read st_value and st_size.
241f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
242f325ba9dSStephen Wilson             return false;
243f325ba9dSStephen Wilson 
244f325ba9dSStephen Wilson         // Read st_info and st_other.
245f325ba9dSStephen Wilson         if (data.GetU8(offset, &st_info, 2) == NULL)
246f325ba9dSStephen Wilson             return false;
247f325ba9dSStephen Wilson 
248f325ba9dSStephen Wilson         // Read st_shndx.
249f325ba9dSStephen Wilson         if (data.GetU16(offset, &st_shndx, 1) == NULL)
250f325ba9dSStephen Wilson             return false;
251f325ba9dSStephen Wilson     }
252f325ba9dSStephen Wilson     else
253f325ba9dSStephen Wilson     {
254f325ba9dSStephen Wilson         // Read st_info and st_other.
255f325ba9dSStephen Wilson         if (data.GetU8(offset, &st_info, 2) == NULL)
256f325ba9dSStephen Wilson             return false;
257f325ba9dSStephen Wilson 
258f325ba9dSStephen Wilson         // Read st_shndx.
259f325ba9dSStephen Wilson         if (data.GetU16(offset, &st_shndx, 1) == NULL)
260f325ba9dSStephen Wilson             return false;
261f325ba9dSStephen Wilson 
262f325ba9dSStephen Wilson         // Read st_value and st_size.
263f325ba9dSStephen Wilson         if (data.GetU64(offset, &st_value, 2) == NULL)
264f325ba9dSStephen Wilson             return false;
265f325ba9dSStephen Wilson     }
266f325ba9dSStephen Wilson     return true;
267f325ba9dSStephen Wilson }
268f325ba9dSStephen Wilson 
269f325ba9dSStephen Wilson //------------------------------------------------------------------------------
270f325ba9dSStephen Wilson // ELFProgramHeader
271f325ba9dSStephen Wilson 
272f325ba9dSStephen Wilson ELFProgramHeader::ELFProgramHeader()
273f325ba9dSStephen Wilson {
274f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFProgramHeader));
275f325ba9dSStephen Wilson }
276f325ba9dSStephen Wilson 
277f325ba9dSStephen Wilson bool
278f325ba9dSStephen Wilson ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
279f325ba9dSStephen Wilson                         uint32_t *offset)
280f325ba9dSStephen Wilson {
281f325ba9dSStephen Wilson     const uint32_t byte_size = data.GetAddressByteSize();
282f325ba9dSStephen Wilson     const bool parsing_32 = byte_size == 4;
283f325ba9dSStephen Wilson 
284f325ba9dSStephen Wilson     // Read p_type;
285f325ba9dSStephen Wilson     if (data.GetU32(offset, &p_type, 1) == NULL)
286f325ba9dSStephen Wilson         return false;
287f325ba9dSStephen Wilson 
288f325ba9dSStephen Wilson     if (parsing_32) {
289f325ba9dSStephen Wilson         // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
290f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
291f325ba9dSStephen Wilson             return false;
292f325ba9dSStephen Wilson 
293f325ba9dSStephen Wilson         // Read p_flags.
294f325ba9dSStephen Wilson         if (data.GetU32(offset, &p_flags, 1) == NULL)
295f325ba9dSStephen Wilson             return false;
296f325ba9dSStephen Wilson 
297f325ba9dSStephen Wilson         // Read p_align.
298f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_align, byte_size) == false)
299f325ba9dSStephen Wilson             return false;
300f325ba9dSStephen Wilson     }
301f325ba9dSStephen Wilson     else {
302f325ba9dSStephen Wilson         // Read p_flags.
303f325ba9dSStephen Wilson         if (data.GetU32(offset, &p_flags, 1) == NULL)
304f325ba9dSStephen Wilson             return false;
305f325ba9dSStephen Wilson 
306f325ba9dSStephen Wilson         // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
307f325ba9dSStephen Wilson         if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
308f325ba9dSStephen Wilson             return false;
309f325ba9dSStephen Wilson     }
310f325ba9dSStephen Wilson 
311f325ba9dSStephen Wilson     return true;
312f325ba9dSStephen Wilson }
313f325ba9dSStephen Wilson 
314f325ba9dSStephen Wilson //------------------------------------------------------------------------------
315f325ba9dSStephen Wilson // ELFDynamic
316f325ba9dSStephen Wilson 
317f325ba9dSStephen Wilson ELFDynamic::ELFDynamic()
318f325ba9dSStephen Wilson {
319f325ba9dSStephen Wilson     memset(this, 0, sizeof(ELFDynamic));
320f325ba9dSStephen Wilson }
321f325ba9dSStephen Wilson 
322f325ba9dSStephen Wilson bool
323f325ba9dSStephen Wilson ELFDynamic::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
324f325ba9dSStephen Wilson {
325f325ba9dSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
326f325ba9dSStephen Wilson     return GetMaxS64(data, offset, &d_tag, byte_size, 2);
327f325ba9dSStephen Wilson }
328f325ba9dSStephen Wilson 
329*43fe645bSStephen Wilson //------------------------------------------------------------------------------
330*43fe645bSStephen Wilson // ELFRel
331*43fe645bSStephen Wilson 
332*43fe645bSStephen Wilson ELFRel::ELFRel()
333*43fe645bSStephen Wilson {
334*43fe645bSStephen Wilson     memset(this, 0, sizeof(ELFRel));
335*43fe645bSStephen Wilson }
336*43fe645bSStephen Wilson 
337*43fe645bSStephen Wilson bool
338*43fe645bSStephen Wilson ELFRel::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
339*43fe645bSStephen Wilson {
340*43fe645bSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
341*43fe645bSStephen Wilson 
342*43fe645bSStephen Wilson     // Read r_offset and r_info.
343*43fe645bSStephen Wilson     if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
344*43fe645bSStephen Wilson         return false;
345*43fe645bSStephen Wilson 
346*43fe645bSStephen Wilson     return true;
347*43fe645bSStephen Wilson }
348*43fe645bSStephen Wilson 
349*43fe645bSStephen Wilson //------------------------------------------------------------------------------
350*43fe645bSStephen Wilson // ELFRela
351*43fe645bSStephen Wilson 
352*43fe645bSStephen Wilson ELFRela::ELFRela()
353*43fe645bSStephen Wilson {
354*43fe645bSStephen Wilson     memset(this, 0, sizeof(ELFRela));
355*43fe645bSStephen Wilson }
356*43fe645bSStephen Wilson 
357*43fe645bSStephen Wilson bool
358*43fe645bSStephen Wilson ELFRela::Parse(const lldb_private::DataExtractor &data, uint32_t *offset)
359*43fe645bSStephen Wilson {
360*43fe645bSStephen Wilson     const unsigned byte_size = data.GetAddressByteSize();
361*43fe645bSStephen Wilson 
362*43fe645bSStephen Wilson     // Read r_offset and r_info.
363*43fe645bSStephen Wilson     if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
364*43fe645bSStephen Wilson         return false;
365*43fe645bSStephen Wilson 
366*43fe645bSStephen Wilson     // Read r_addend;
367*43fe645bSStephen Wilson     if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
368*43fe645bSStephen Wilson         return false;
369*43fe645bSStephen Wilson 
370*43fe645bSStephen Wilson     return true;
371*43fe645bSStephen Wilson }
372*43fe645bSStephen Wilson 
373f325ba9dSStephen Wilson 
374