xref: /llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (revision 3afa33ced69087e3a5d7d2742d255cb58342d9d4)
1 //===-- ObjectFileELF.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 "ObjectFileELF.h"
11 
12 #include <assert.h>
13 
14 #include <algorithm>
15 
16 #include <stdint.h>
17 #include "elf.h"
18 #include "lldb/Core/DataBuffer.h"
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/PluginManager.h"
21 #include "lldb/Core/Section.h"
22 #include "lldb/Core/Stream.h"
23 #include "lldb/Symbol/ObjectFile.h"
24 
25 #define CASE_AND_STREAM(s, def, width)  case def: s->Printf("%-*s", width, #def); break;
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 using namespace std;
30 
31 
32 void
33 ObjectFileELF::Initialize()
34 {
35     PluginManager::RegisterPlugin (GetPluginNameStatic(),
36                                    GetPluginDescriptionStatic(),
37                                    CreateInstance);
38 }
39 
40 void
41 ObjectFileELF::Terminate()
42 {
43     PluginManager::UnregisterPlugin (CreateInstance);
44 }
45 
46 
47 const char *
48 ObjectFileELF::GetPluginNameStatic()
49 {
50     return "object-file.elf32";
51 }
52 
53 const char *
54 ObjectFileELF::GetPluginDescriptionStatic()
55 {
56     return "ELF object file reader (32-bit).";
57 }
58 
59 
60 ObjectFile *
61 ObjectFileELF::CreateInstance (Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length)
62 {
63     if (ObjectFileELF::MagicBytesMatch(dataSP))
64     {
65         std::auto_ptr<ObjectFile> objfile_ap(new ObjectFileELF (module, dataSP, file, offset, length));
66         if (objfile_ap.get() && objfile_ap->ParseHeader())
67             return objfile_ap.release();
68     }
69     return NULL;
70 }
71 
72 bool
73 ObjectFileELF::MagicBytesMatch (DataBufferSP& dataSP)
74 {
75     DataExtractor data(dataSP, eByteOrderHost, 4);
76     const uint8_t* magic = data.PeekData(0, 4);
77     if (magic != NULL)
78     {
79         return magic[EI_MAG0] == 0x7f
80             && magic[EI_MAG1] == 'E'
81             && magic[EI_MAG2] == 'L'
82             && magic[EI_MAG3] == 'F';
83     }
84     return false;
85 }
86 
87 
88 ObjectFileELF::ObjectFileELF(Module* module, DataBufferSP& dataSP, const FileSpec* file, addr_t offset, addr_t length) :
89     ObjectFile (module, file, offset, length, dataSP),
90     m_header(),
91     m_program_headers(),
92     m_section_headers(),
93     m_sections_ap(),
94     m_symtab_ap(),
95     m_shstr_data()
96 {
97     if (file)
98         m_file = *file;
99     ::bzero (&m_header, sizeof(m_header));
100 }
101 
102 
103 ObjectFileELF::~ObjectFileELF()
104 {
105 }
106 
107 ByteOrder
108 ObjectFileELF::GetByteOrder () const
109 {
110     if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
111         return eByteOrderBig;
112     if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
113         return eByteOrderLittle;
114     return eByteOrderInvalid;
115 }
116 
117 size_t
118 ObjectFileELF::GetAddressByteSize () const
119 {
120     return m_data.GetAddressByteSize();
121 }
122 
123 bool
124 ObjectFileELF::ParseHeader ()
125 {
126     m_data.SetAddressByteSize(4);
127     uint32_t offset = GetOffset();
128     if (m_data.GetU8(&offset, m_header.e_ident, EI_NIDENT) == NULL)
129         return false;
130 
131     m_data.SetByteOrder(GetByteOrder());
132 
133     // Read e_type and e_machine
134     if (m_data.GetU16(&offset, &m_header.e_type, 2) == NULL)
135         return false;
136 
137     // read e_version, e_entry, e_phoff, e_shoff, e_flags
138     if (m_data.GetU32(&offset, &m_header.e_version, 5) == NULL)
139         return false;
140 
141     // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx
142     if (m_data.GetU16(&offset, &m_header.e_ehsize, 6) == NULL)
143         return false;
144 
145     return true;
146 }
147 
148 bool
149 ObjectFileELF::GetUUID (UUID* uuid)
150 {
151     return false;
152 }
153 
154 uint32_t
155 ObjectFileELF::GetDependentModules(FileSpecList& files)
156 {
157     return 0;
158 }
159 
160 //----------------------------------------------------------------------
161 // ParseProgramHeaders
162 //----------------------------------------------------------------------
163 size_t
164 ObjectFileELF::ParseProgramHeaders()
165 {
166     // We have already parsed the program headers
167     if (!m_program_headers.empty())
168         return m_program_headers.size();
169 
170     uint32_t offset = 0;
171     if (m_header.e_phnum > 0)
172     {
173         m_program_headers.resize(m_header.e_phnum);
174 
175         if (m_program_headers.size() != m_header.e_phnum)
176             return 0;
177 
178         const size_t byte_size = m_header.e_phnum * m_header.e_phentsize;
179         DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_phoff, byte_size));
180 
181         if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
182             return 0;
183 
184         DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
185 
186         uint32_t idx;
187         for (idx = 0; idx < m_header.e_phnum; ++idx)
188         {
189             if (data.GetU32(&offset, &m_program_headers[idx].p_type, 8) == NULL)
190                 return 0;
191         }
192         if (idx < m_program_headers.size())
193             m_program_headers.resize(idx);
194     }
195 
196     return m_program_headers.size();
197 }
198 
199 
200 //----------------------------------------------------------------------
201 // ParseSectionHeaders
202 //----------------------------------------------------------------------
203 size_t
204 ObjectFileELF::ParseSectionHeaders()
205 {
206     // We have already parsed the section headers
207     if (!m_section_headers.empty())
208         return m_section_headers.size();
209 
210     if (m_header.e_shnum > 0)
211     {
212         uint32_t offset = 0;
213 
214         m_section_headers.resize(m_header.e_shnum);
215 
216         if (m_section_headers.size() != m_header.e_shnum)
217             return 0;
218 
219         const size_t byte_size = m_header.e_shnum * m_header.e_shentsize;
220         DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_header.e_shoff, byte_size));
221 
222         if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
223             return 0;
224 
225         DataExtractor data(buffer_sp, m_data.GetByteOrder(), m_data.GetAddressByteSize());
226 
227         uint32_t idx;
228         for (idx = 0; idx < m_header.e_shnum; ++idx)
229         {
230             if (data.GetU32(&offset, &m_section_headers[idx].sh_name, 10) == NULL)
231                 break;
232         }
233         if (idx < m_section_headers.size())
234             m_section_headers.resize(idx);
235     }
236 
237     return m_section_headers.size();
238 }
239 
240 size_t
241 ObjectFileELF::GetSectionHeaderStringTable()
242 {
243     if (m_shstr_data.GetByteSize() == 0)
244     {
245         if (m_header.e_shstrndx && m_header.e_shstrndx < m_section_headers.size())
246         {
247             const size_t byte_size = m_section_headers[m_header.e_shstrndx].sh_size;
248             DataBufferSP buffer_sp(m_file.ReadFileContents(m_offset + m_section_headers[m_header.e_shstrndx].sh_offset, byte_size));
249 
250             if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
251                 return 0;
252 
253             m_shstr_data.SetData(buffer_sp);
254         }
255     }
256     return m_shstr_data.GetByteSize();
257 }
258 
259 uint32_t
260 ObjectFileELF::GetSectionIndexByName(const char *name)
261 {
262     if (ParseSectionHeaders() && GetSectionHeaderStringTable())
263     {
264         uint32_t offset = 1;    // Skip leading NULL string at offset 0;
265         while (m_shstr_data.ValidOffset(offset))
266         {
267             uint32_t sh_name = offset;  // Save offset in case we find a match
268             const char* sectionHeaderName = m_shstr_data.GetCStr(&offset);
269             if (sectionHeaderName)
270             {
271                 if (strcmp(name, sectionHeaderName) == 0)
272                 {
273                     SectionHeaderCollIter pos;
274                     for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos)
275                     {
276                         if ( (*pos).sh_name == sh_name )
277                         {
278                             // section indexes are 1 based
279                             return std::distance(m_section_headers.begin(), pos) + 1;
280                         }
281                     }
282                     return UINT32_MAX;
283                 }
284             }
285             else
286             {
287                 return UINT32_MAX;
288             }
289         }
290     }
291 
292     return UINT32_MAX;
293 }
294 
295 SectionList *
296 ObjectFileELF::GetSectionList()
297 {
298     if (m_sections_ap.get() == NULL)
299     {
300         m_sections_ap.reset(new SectionList());
301         if (ParseSectionHeaders() && GetSectionHeaderStringTable())
302         {
303             uint32_t sh_idx = 0;
304             const size_t num_sections = m_section_headers.size();
305             for (sh_idx = 0; sh_idx < num_sections; ++sh_idx)
306             {
307                 ConstString section_name(m_shstr_data.PeekCStr(m_section_headers[sh_idx].sh_name));
308                 uint64_t section_file_size = m_section_headers[sh_idx].sh_type == SHT_NOBITS ? 0 : m_section_headers[sh_idx].sh_size;
309                 SectionSP section_sp(new Section(NULL,                                  // Parent section
310                                                  GetModule(),                           // Module to which this section belongs
311                                                  sh_idx + 1,                            // Section ID is the 1 based
312                                                  section_name,                          // Name of this section
313                                                  eSectionTypeOther,  // TODO: fill this in appropriately for ELF...
314                                                  m_section_headers[sh_idx].sh_addr,     // File VM address
315                                                  m_section_headers[sh_idx].sh_size,     // VM size in bytes of this section
316                                                  m_section_headers[sh_idx].sh_offset,   // Offset to the data for this section in the file
317                                                  section_file_size,                     // Size in bytes of this section as found in the the file
318                                                  m_section_headers[sh_idx].sh_flags));  // Flags for this section
319                 if (section_sp.get())
320                     m_sections_ap->AddSection(section_sp);
321 
322             }
323         }
324     }
325     return m_sections_ap.get();
326 }
327 
328 static void
329 ParseSymbols (Symtab *symtab, SectionList *section_list, const Elf32_Shdr &symtab_shdr, const DataExtractor& symtab_data, const DataExtractor& strtab_data)
330 {
331     assert (sizeof(Elf32_Sym) == symtab_shdr.sh_entsize);
332     const uint32_t num_symbols = symtab_data.GetByteSize() / sizeof(Elf32_Sym);
333     uint32_t offset = 0;
334     Elf32_Sym symbol;
335     uint32_t i;
336     static ConstString text_section_name(".text");
337     static ConstString init_section_name(".init");
338     static ConstString fini_section_name(".fini");
339     static ConstString ctors_section_name(".ctors");
340     static ConstString dtors_section_name(".dtors");
341 
342     static ConstString data_section_name(".data");
343     static ConstString rodata_section_name(".rodata");
344     static ConstString rodata1_section_name(".rodata1");
345     static ConstString data2_section_name(".data1");
346     static ConstString bss_section_name(".bss");
347 
348     for (i=0; i<num_symbols; ++i)
349     {
350     //  if (symtab_data.GetU32(&offset, &symbol.st_name, 3) == 0)
351     //      break;
352 
353         if (!symtab_data.ValidOffsetForDataOfSize(offset, sizeof(Elf32_Sym)))
354             break;
355 
356         symbol.st_name  = symtab_data.GetU32 (&offset);
357         symbol.st_value = symtab_data.GetU32 (&offset);
358         symbol.st_size  = symtab_data.GetU32 (&offset);
359         symbol.st_info  = symtab_data.GetU8  (&offset);
360         symbol.st_other = symtab_data.GetU8  (&offset);
361         symbol.st_shndx = symtab_data.GetU16 (&offset);
362 
363         Section * symbol_section = NULL;
364         SymbolType symbol_type = eSymbolTypeInvalid;
365 
366         switch (symbol.st_shndx)
367         {
368         case SHN_ABS:
369             symbol_type = eSymbolTypeAbsolute;
370             break;
371         case SHN_UNDEF:
372             symbol_type = eSymbolTypeUndefined;
373             break;
374         default:
375             symbol_section = section_list->GetSectionAtIndex (symbol.st_shndx).get();
376             break;
377         }
378 
379         switch (ELF32_ST_BIND (symbol.st_info))
380         {
381         default:
382         case STT_NOTYPE:
383             // The symbol's type is not specified.
384             break;
385 
386         case STT_OBJECT:
387             // The symbol is associated with a data object, such as a variable, an array, etc.
388             symbol_type == eSymbolTypeData;
389             break;
390 
391         case STT_FUNC:
392             // The symbol is associated with a function or other executable code.
393             symbol_type == eSymbolTypeCode;
394             break;
395 
396         case STT_SECTION:
397             // The symbol is associated with a section. Symbol table entries of
398             // this type exist primarily for relocation and normally have
399             // STB_LOCAL binding.
400             break;
401 
402         case STT_FILE:
403             // Conventionally, the symbol's name gives the name of the source
404             // file associated with the object file. A file symbol has STB_LOCAL
405             // binding, its section index is SHN_ABS, and it precedes the other
406             // STB_LOCAL symbols for the file, if it is present.
407             symbol_type == eSymbolTypeObjectFile;
408             break;
409         }
410 
411         if (symbol_type == eSymbolTypeInvalid)
412         {
413             if (symbol_section)
414             {
415                 const ConstString &sect_name = symbol_section->GetName();
416                 if (sect_name == text_section_name ||
417                     sect_name == init_section_name ||
418                     sect_name == fini_section_name ||
419                     sect_name == ctors_section_name ||
420                     sect_name == dtors_section_name)
421                 {
422                     symbol_type = eSymbolTypeCode;
423                 }
424                 else
425                 if (sect_name == data_section_name ||
426                     sect_name == data2_section_name ||
427                     sect_name == rodata_section_name ||
428                     sect_name == rodata1_section_name ||
429                     sect_name == bss_section_name)
430                 {
431                     symbol_type = eSymbolTypeData;
432                 }
433             }
434         }
435 
436         uint64_t symbol_value = symbol.st_value;
437         if (symbol_section != NULL)
438             symbol_value -= symbol_section->GetFileAddress();
439         const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
440 
441         Symbol dc_symbol(i,             // ID is the original symbol table index
442                         symbol_name,    // symbol name
443                         false,          // Is the symbol name mangled?
444                         symbol_type,    // type of this symbol
445                         ELF32_ST_BIND (symbol.st_info) == STB_GLOBAL,   // Is this globally visible?
446                         false,          // Is this symbol debug info?
447                         false,          // Is this symbol a trampoline?
448                         false,          // Is this symbol artificial?
449                         symbol_section, // section pointer if symbol_value is an offset within a section, else NULL
450                         symbol_value,   // offset from section if section is non-NULL, else the value for this symbol
451                         symbol.st_size, // size in bytes of this symbol
452                         symbol.st_other << 8 | symbol.st_info); // symbol flags
453         symtab->AddSymbol(dc_symbol);
454     }
455 }
456 
457 
458 Symtab *
459 ObjectFileELF::GetSymtab()
460 {
461     if (m_symtab_ap.get() == NULL)
462     {
463         m_symtab_ap.reset(new Symtab(this));
464 
465         if (ParseSectionHeaders() && GetSectionHeaderStringTable())
466         {
467             uint32_t symtab_idx = UINT32_MAX;
468             uint32_t dynsym_idx = UINT32_MAX;
469             uint32_t sh_idx = 0;
470             const size_t num_sections = m_section_headers.size();
471             for (sh_idx = 0; sh_idx < num_sections; ++sh_idx)
472             {
473                 if (m_section_headers[sh_idx].sh_type == SHT_SYMTAB)
474                 {
475                     symtab_idx = sh_idx;
476                     break;
477                 }
478                 if (m_section_headers[sh_idx].sh_type == SHT_DYNSYM)
479                 {
480                     dynsym_idx = sh_idx;
481                 }
482             }
483 
484             SectionList *section_list = NULL;
485             static ConstString g_symtab(".symtab");
486             static ConstString g_strtab(".strtab");
487             static ConstString g_dynsym(".dynsym");
488             static ConstString g_dynstr(".dynstr");
489             // Check if we found a full symbol table?
490             if (symtab_idx < num_sections)
491             {
492                 section_list = GetSectionList();
493                 if (section_list)
494                 {
495                     Section *symtab_section = section_list->FindSectionByName(g_symtab).get();
496                     Section *strtab_section = section_list->FindSectionByName(g_strtab).get();
497                     if (symtab_section && strtab_section)
498                     {
499                         DataExtractor symtab_data;
500                         DataExtractor strtab_data;
501                         if (symtab_section->ReadSectionDataFromObjectFile (this, symtab_data) > 0 &&
502                             strtab_section->ReadSectionDataFromObjectFile (this, strtab_data) > 0)
503                         {
504                             ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[symtab_idx], symtab_data, strtab_data);
505                         }
506                     }
507                 }
508             }
509             // Check if we found a reduced symbol table that gets used for dynamic linking?
510             else if (dynsym_idx < num_sections)
511             {
512                 section_list = GetSectionList();
513                 if (section_list)
514                 {
515                     Section *dynsym_section = section_list->FindSectionByName(g_dynsym).get();
516                     Section *dynstr_section = section_list->FindSectionByName(g_dynstr).get();
517                     if (dynsym_section && dynstr_section)
518                     {
519                         DataExtractor dynsym_data;
520                         DataExtractor dynstr_data;
521                         if (dynsym_section->ReadSectionDataFromObjectFile (this, dynsym_data) > 0 &&
522                             dynstr_section->ReadSectionDataFromObjectFile (this, dynstr_data) > 0)
523                         {
524                             ParseSymbols (m_symtab_ap.get(), section_list, m_section_headers[dynsym_idx], dynsym_data, dynstr_data);
525                         }
526                     }
527                 }
528             }
529         }
530     }
531     return m_symtab_ap.get();
532 }
533 
534 //
535 ////----------------------------------------------------------------------
536 //// GetNListSymtab
537 ////----------------------------------------------------------------------
538 //bool
539 //ELF32RuntimeFileParser::GetNListSymtab(BinaryDataRef& stabs_data, BinaryDataRef& stabstr_data, bool locals_only, uint32_t& value_size)
540 //{
541 //  value_size = 4; // Size in bytes of the nlist n_value member
542 //  return  GetSectionInfo(GetSectionIndexByName(".stab"), NULL, NULL, NULL, NULL, NULL, NULL, &stabs_data, NULL) &&
543 //          GetSectionInfo(GetSectionIndexByName(".stabstr"), NULL, NULL, NULL, NULL, NULL, NULL, &stabstr_data, NULL);
544 //}
545 //
546 //===----------------------------------------------------------------------===//
547 // Dump
548 //
549 // Dump the specifics of the runtime file container (such as any headers
550 // segments, sections, etc).
551 //----------------------------------------------------------------------
552 void
553 ObjectFileELF::Dump(Stream *s)
554 {
555     DumpELFHeader(s, m_header);
556     s->EOL();
557     DumpELFProgramHeaders(s);
558     s->EOL();
559     DumpELFSectionHeaders(s);
560     s->EOL();
561     SectionList *section_list = GetSectionList();
562     if (section_list)
563         section_list->Dump(s, NULL, true);
564     Symtab *symtab = GetSymtab();
565     if (symtab)
566         symtab->Dump(s, NULL);
567     s->EOL();
568 }
569 
570 //----------------------------------------------------------------------
571 // DumpELFHeader
572 //
573 // Dump the ELF header to the specified output stream
574 //----------------------------------------------------------------------
575 void
576 ObjectFileELF::DumpELFHeader(Stream *s, const Elf32_Ehdr& header)
577 {
578 
579     s->PutCString ("ELF Header\n");
580     s->Printf ("e_ident[EI_MAG0   ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
581     s->Printf ("e_ident[EI_MAG1   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]);
582     s->Printf ("e_ident[EI_MAG2   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]);
583     s->Printf ("e_ident[EI_MAG3   ] = 0x%2.2x '%c'\n", header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]);
584     s->Printf ("e_ident[EI_CLASS  ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
585     s->Printf ("e_ident[EI_DATA   ] = 0x%2.2x ", header.e_ident[EI_DATA]);
586     DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
587     s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
588     s->Printf ("e_ident[EI_PAD    ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
589 
590     s->Printf("e_type      = 0x%4.4x ", header.e_type);
591     DumpELFHeader_e_type(s, header.e_type);
592     s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
593     s->Printf("e_version   = 0x%8.8x\n", header.e_version);
594     s->Printf("e_entry     = 0x%8.8x\n", header.e_entry);
595     s->Printf("e_phoff     = 0x%8.8x\n", header.e_phoff);
596     s->Printf("e_shoff     = 0x%8.8x\n", header.e_shoff);
597     s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
598     s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
599     s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
600     s->Printf("e_phnum     = 0x%4.4x\n", header.e_phnum);
601     s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
602     s->Printf("e_shnum     = 0x%4.4x\n", header.e_shnum);
603     s->Printf("e_shstrndx  = 0x%4.4x\n", header.e_shstrndx);
604 }
605 
606 //----------------------------------------------------------------------
607 // DumpELFHeader_e_type
608 //
609 // Dump an token value for the ELF header member e_type
610 //----------------------------------------------------------------------
611 void
612 ObjectFileELF::DumpELFHeader_e_type(Stream *s, uint16_t e_type)
613 {
614     switch (e_type)
615     {
616     case ET_NONE:   *s << "ET_NONE"; break;
617     case ET_REL:    *s << "ET_REL"; break;
618     case ET_EXEC:   *s << "ET_EXEC"; break;
619     case ET_DYN:    *s << "ET_DYN"; break;
620     case ET_CORE:   *s << "ET_CORE"; break;
621     default:
622         break;
623     }
624 }
625 
626 //----------------------------------------------------------------------
627 // DumpELFHeader_e_ident_EI_DATA
628 //
629 // Dump an token value for the ELF header member e_ident[EI_DATA]
630 //----------------------------------------------------------------------
631 void
632 ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, uint16_t ei_data)
633 {
634     switch (ei_data)
635     {
636     case ELFDATANONE:   *s << "ELFDATANONE"; break;
637     case ELFDATA2LSB:   *s << "ELFDATA2LSB - Little Endian"; break;
638     case ELFDATA2MSB:   *s << "ELFDATA2MSB - Big Endian"; break;
639     default:
640         break;
641     }
642 }
643 
644 
645 //----------------------------------------------------------------------
646 // DumpELFProgramHeader
647 //
648 // Dump a single ELF program header to the specified output stream
649 //----------------------------------------------------------------------
650 void
651 ObjectFileELF::DumpELFProgramHeader(Stream *s, const Elf32_Phdr& ph)
652 {
653     DumpELFProgramHeader_p_type(s, ph.p_type);
654     s->Printf(" %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x (", ph.p_offset, ph.p_vaddr, ph.p_paddr, ph.p_filesz, ph.p_memsz, ph.p_flags);
655     DumpELFProgramHeader_p_flags(s, ph.p_flags);
656     s->Printf(") %8.8x", ph.p_align);
657 }
658 
659 //----------------------------------------------------------------------
660 // DumpELFProgramHeader_p_type
661 //
662 // Dump an token value for the ELF program header member p_type which
663 // describes the type of the program header
664 //----------------------------------------------------------------------
665 void
666 ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, Elf32_Word p_type)
667 {
668     const int kStrWidth = 10;
669     switch (p_type)
670     {
671     CASE_AND_STREAM(s, PT_NULL      , kStrWidth);
672     CASE_AND_STREAM(s, PT_LOAD      , kStrWidth);
673     CASE_AND_STREAM(s, PT_DYNAMIC   , kStrWidth);
674     CASE_AND_STREAM(s, PT_INTERP    , kStrWidth);
675     CASE_AND_STREAM(s, PT_NOTE      , kStrWidth);
676     CASE_AND_STREAM(s, PT_SHLIB     , kStrWidth);
677     CASE_AND_STREAM(s, PT_PHDR      , kStrWidth);
678     default:
679         s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
680         break;
681     }
682 }
683 
684 
685 //----------------------------------------------------------------------
686 // DumpELFProgramHeader_p_flags
687 //
688 // Dump an token value for the ELF program header member p_flags
689 //----------------------------------------------------------------------
690 void
691 ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, Elf32_Word p_flags)
692 {
693     *s  << ((p_flags & PF_X) ? "PF_X" : "    ")
694         << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
695         << ((p_flags & PF_W) ? "PF_W" : "    ")
696         << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
697         << ((p_flags & PF_R) ? "PF_R" : "    ");
698 }
699 
700 //----------------------------------------------------------------------
701 // DumpELFProgramHeaders
702 //
703 // Dump all of the ELF program header to the specified output stream
704 //----------------------------------------------------------------------
705 void
706 ObjectFileELF::DumpELFProgramHeaders(Stream *s)
707 {
708     if (ParseProgramHeaders())
709     {
710         s->PutCString("Program Headers\n");
711         s->PutCString("IDX  p_type     p_offset p_vaddr  p_paddr  p_filesz p_memsz  p_flags                   p_align\n");
712         s->PutCString("==== ---------- -------- -------- -------- -------- -------- ------------------------- --------\n");
713 
714         uint32_t idx = 0;
715         ProgramHeaderCollConstIter pos;
716 
717         for (pos = m_program_headers.begin(); pos != m_program_headers.end(); ++pos, ++idx)
718         {
719             s->Printf ("[%2u] ", idx);
720             ObjectFileELF::DumpELFProgramHeader(s, *pos);
721             s->EOL();
722         }
723     }
724 }
725 
726 
727 //----------------------------------------------------------------------
728 // DumpELFSectionHeader
729 //
730 // Dump a single ELF section header to the specified output stream
731 //----------------------------------------------------------------------
732 void
733 ObjectFileELF::DumpELFSectionHeader(Stream *s, const Elf32_Shdr& sh)
734 {
735     s->Printf ("%8.8x ", sh.sh_name);
736     DumpELFSectionHeader_sh_type(s, sh.sh_type);
737     s->Printf (" %8.8x (", sh.sh_flags);
738     DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
739     s->Printf (") %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x %8.8x",
740                 sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_addralign, sh.sh_entsize);
741 }
742 
743 //----------------------------------------------------------------------
744 // DumpELFSectionHeader_sh_type
745 //
746 // Dump an token value for the ELF section header member sh_type which
747 // describes the type of the section
748 //----------------------------------------------------------------------
749 void
750 ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, Elf32_Word sh_type)
751 {
752     const int kStrWidth = 12;
753     switch (sh_type)
754     {
755     CASE_AND_STREAM(s, SHT_NULL     , kStrWidth);
756     CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth);
757     CASE_AND_STREAM(s, SHT_SYMTAB   , kStrWidth);
758     CASE_AND_STREAM(s, SHT_STRTAB   , kStrWidth);
759     CASE_AND_STREAM(s, SHT_RELA     , kStrWidth);
760     CASE_AND_STREAM(s, SHT_HASH     , kStrWidth);
761     CASE_AND_STREAM(s, SHT_DYNAMIC  , kStrWidth);
762     CASE_AND_STREAM(s, SHT_NOTE     , kStrWidth);
763     CASE_AND_STREAM(s, SHT_NOBITS   , kStrWidth);
764     CASE_AND_STREAM(s, SHT_REL      , kStrWidth);
765     CASE_AND_STREAM(s, SHT_SHLIB    , kStrWidth);
766     CASE_AND_STREAM(s, SHT_DYNSYM   , kStrWidth);
767     CASE_AND_STREAM(s, SHT_LOPROC   , kStrWidth);
768     CASE_AND_STREAM(s, SHT_HIPROC   , kStrWidth);
769     CASE_AND_STREAM(s, SHT_LOUSER   , kStrWidth);
770     CASE_AND_STREAM(s, SHT_HIUSER   , kStrWidth);
771     default:
772         s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
773         break;
774     }
775 }
776 
777 
778 //----------------------------------------------------------------------
779 // DumpELFSectionHeader_sh_flags
780 //
781 // Dump an token value for the ELF section header member sh_flags
782 //----------------------------------------------------------------------
783 void
784 ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, Elf32_Word sh_flags)
785 {
786     *s  << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
787         << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
788         << ((sh_flags & SHF_ALLOC) ? "ALLOC" : "     ")
789         << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
790         << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : "         ");
791 }
792 //----------------------------------------------------------------------
793 // DumpELFSectionHeaders
794 //
795 // Dump all of the ELF section header to the specified output stream
796 //----------------------------------------------------------------------
797 void
798 ObjectFileELF::DumpELFSectionHeaders(Stream *s)
799 {
800     if (ParseSectionHeaders() && GetSectionHeaderStringTable())
801     {
802         s->PutCString("Section Headers\n");
803         s->PutCString("IDX  name     type         flags                            addr     offset   size     link     info     addralgn entsize  Name\n");
804         s->PutCString("==== -------- ------------ -------------------------------- -------- -------- -------- -------- -------- -------- -------- ====================\n");
805 
806         uint32_t idx = 0;
807         SectionHeaderCollConstIter pos;
808 
809         for (pos = m_section_headers.begin(); pos != m_section_headers.end(); ++pos, ++idx)
810         {
811             s->Printf ("[%2u] ", idx);
812             ObjectFileELF::DumpELFSectionHeader(s, *pos);
813             const char* section_name = m_shstr_data.PeekCStr(pos->sh_name);
814             if (section_name)
815                 *s << ' ' << section_name << "\n";
816         }
817     }
818 }
819 
820 bool
821 ObjectFileELF::GetTargetTriple (ConstString &target_triple)
822 {
823     static ConstString g_target_triple;
824 
825     if (g_target_triple)
826     {
827         target_triple = g_target_triple;
828     }
829     else
830     {
831         std::string triple;
832         switch (m_header.e_machine)
833         {
834         case EM_SPARC:  triple.assign("sparc-"); break;
835         case EM_386:    triple.assign("i386-"); break;
836         case EM_68K:    triple.assign("68k-"); break;
837         case EM_88K:    triple.assign("88k-"); break;
838         case EM_860:    triple.assign("i860-"); break;
839         case EM_MIPS:   triple.assign("mips-"); break;
840         case EM_PPC:    triple.assign("powerpc-"); break;
841         case EM_PPC64:  triple.assign("powerpc64-"); break;
842         case EM_ARM:    triple.assign("arm-"); break;
843         }
844         // TODO: determine if there is a vendor in the ELF? Default to "linux" for now
845         triple += "linux-";
846         // TODO: determine if there is an OS in the ELF? Default to "gnu" for now
847         triple += "gnu";
848         g_target_triple.SetCString(triple.c_str());
849         target_triple = g_target_triple;
850     }
851     return !target_triple.IsEmpty();
852 }
853 
854 
855 //------------------------------------------------------------------
856 // PluginInterface protocol
857 //------------------------------------------------------------------
858 const char *
859 ObjectFileELF::GetPluginName()
860 {
861     return "ObjectFileELF";
862 }
863 
864 const char *
865 ObjectFileELF::GetShortPluginName()
866 {
867     return GetPluginNameStatic();
868 }
869 
870 uint32_t
871 ObjectFileELF::GetPluginVersion()
872 {
873     return 1;
874 }
875 
876 void
877 ObjectFileELF::GetPluginCommandHelp (const char *command, Stream *strm)
878 {
879 }
880 
881 Error
882 ObjectFileELF::ExecutePluginCommand (Args &command, Stream *strm)
883 {
884     Error error;
885     error.SetErrorString("No plug-in command are currently supported.");
886     return error;
887 }
888 
889 Log *
890 ObjectFileELF::EnablePluginLogging (Stream *strm, Args &command)
891 {
892     return NULL;
893 }
894 
895 
896 
897