ObjectFileELF.cpp revision 1240b9152b87cd0fd0d418794213f34b4b273dd2
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 <cassert>
13#include <algorithm>
14
15#include "lldb/Core/DataBuffer.h"
16#include "lldb/Core/Error.h"
17#include "lldb/Core/FileSpecList.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Core/Section.h"
20#include "lldb/Core/Stream.h"
21
22#define CASE_AND_STREAM(s, def, width)                  \
23    case def: s->Printf("%-*s", width, #def); break;
24
25using namespace lldb;
26using namespace lldb_private;
27using namespace elf;
28using namespace llvm::ELF;
29
30//------------------------------------------------------------------
31// Static methods.
32//------------------------------------------------------------------
33void
34ObjectFileELF::Initialize()
35{
36    PluginManager::RegisterPlugin(GetPluginNameStatic(),
37                                  GetPluginDescriptionStatic(),
38                                  CreateInstance);
39}
40
41void
42ObjectFileELF::Terminate()
43{
44    PluginManager::UnregisterPlugin(CreateInstance);
45}
46
47const char *
48ObjectFileELF::GetPluginNameStatic()
49{
50    return "object-file.elf";
51}
52
53const char *
54ObjectFileELF::GetPluginDescriptionStatic()
55{
56    return "ELF object file reader.";
57}
58
59ObjectFile *
60ObjectFileELF::CreateInstance(Module *module,
61                              DataBufferSP &data_sp,
62                              const FileSpec *file, addr_t offset,
63                              addr_t length)
64{
65    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + offset))
66    {
67        const uint8_t *magic = data_sp->GetBytes() + offset;
68        if (ELFHeader::MagicBytesMatch(magic))
69        {
70            unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
71            if (address_size == 4 || address_size == 8)
72            {
73                std::auto_ptr<ObjectFile> objfile_ap(
74                    new ObjectFileELF(module, data_sp, file, offset, length));
75                if (objfile_ap->ParseHeader())
76                    return objfile_ap.release();
77            }
78        }
79    }
80    return NULL;
81}
82
83//------------------------------------------------------------------
84// PluginInterface protocol
85//------------------------------------------------------------------
86const char *
87ObjectFileELF::GetPluginName()
88{
89    return "ObjectFileELF";
90}
91
92const char *
93ObjectFileELF::GetShortPluginName()
94{
95    return GetPluginNameStatic();
96}
97
98uint32_t
99ObjectFileELF::GetPluginVersion()
100{
101    return m_plugin_version;
102}
103
104void
105ObjectFileELF::GetPluginCommandHelp(const char *command, Stream *strm)
106{
107}
108
109Error
110ObjectFileELF::ExecutePluginCommand(Args &command, Stream *strm)
111{
112    Error error;
113    error.SetErrorString("No plug-in commands are currently supported.");
114    return error;
115}
116
117Log *
118ObjectFileELF::EnablePluginLogging(Stream *strm, Args &command)
119{
120    return NULL;
121}
122
123//------------------------------------------------------------------
124// ObjectFile protocol
125//------------------------------------------------------------------
126
127ObjectFileELF::ObjectFileELF(Module* module, DataBufferSP& dataSP,
128                             const FileSpec* file, addr_t offset,
129                             addr_t length)
130    : ObjectFile(module, file, offset, length, dataSP),
131      m_header(),
132      m_program_headers(),
133      m_section_headers(),
134      m_sections_ap(),
135      m_symtab_ap(),
136      m_filespec_ap(),
137      m_shstr_data()
138{
139    if (file)
140        m_file = *file;
141    ::memset(&m_header, 0, sizeof(m_header));
142}
143
144ObjectFileELF::~ObjectFileELF()
145{
146}
147
148bool
149ObjectFileELF::IsExecutable() const
150{
151    return m_header.e_type == ET_EXEC;
152}
153
154ByteOrder
155ObjectFileELF::GetByteOrder() const
156{
157    if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
158        return eByteOrderBig;
159    if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
160        return eByteOrderLittle;
161    return eByteOrderInvalid;
162}
163
164size_t
165ObjectFileELF::GetAddressByteSize() const
166{
167    return m_data.GetAddressByteSize();
168}
169
170unsigned
171ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
172{
173    return std::distance(m_section_headers.begin(), I) + 1;
174}
175
176unsigned
177ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const
178{
179    return std::distance(m_section_headers.begin(), I) + 1;
180}
181
182bool
183ObjectFileELF::ParseHeader()
184{
185    uint32_t offset = GetOffset();
186    return m_header.Parse(m_data, &offset);
187}
188
189bool
190ObjectFileELF::GetUUID(UUID* uuid)
191{
192    // FIXME: Return MD5 sum here.  See comment in ObjectFile.h.
193    return false;
194}
195
196uint32_t
197ObjectFileELF::GetDependentModules(FileSpecList &files)
198{
199    size_t num_modules = ParseDependentModules();
200    uint32_t num_specs = 0;
201
202    for (unsigned i = 0; i < num_modules; ++i)
203    {
204        if (files.AppendIfUnique(m_filespec_ap->GetFileSpecAtIndex(i)))
205            num_specs++;
206    }
207
208    return num_specs;
209}
210
211//----------------------------------------------------------------------
212// ParseDependentModules
213//----------------------------------------------------------------------
214size_t
215ObjectFileELF::ParseDependentModules()
216{
217    if (m_filespec_ap.get())
218        return m_filespec_ap->GetSize();
219
220    m_filespec_ap.reset(new FileSpecList());
221
222    if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
223        return 0;
224
225    // Locate the dynamic table.
226    user_id_t dynsym_id = 0;
227    user_id_t dynstr_id = 0;
228    for (SectionHeaderCollIter I = m_section_headers.begin();
229         I != m_section_headers.end(); ++I)
230    {
231        if (I->sh_type == SHT_DYNAMIC)
232        {
233            dynsym_id = SectionIndex(I);
234            dynstr_id = I->sh_link + 1; // Section ID's are 1 based.
235            break;
236        }
237    }
238
239    if (!(dynsym_id && dynstr_id))
240        return 0;
241
242    SectionList *section_list = GetSectionList();
243    if (!section_list)
244        return 0;
245
246    // Resolve and load the dynamic table entries and corresponding string
247    // table.
248    Section *dynsym = section_list->FindSectionByID(dynsym_id).get();
249    Section *dynstr = section_list->FindSectionByID(dynstr_id).get();
250    if (!(dynsym && dynstr))
251        return 0;
252
253    DataExtractor dynsym_data;
254    DataExtractor dynstr_data;
255    if (dynsym->ReadSectionDataFromObjectFile(this, dynsym_data) &&
256        dynstr->ReadSectionDataFromObjectFile(this, dynstr_data))
257    {
258        ELFDynamic symbol;
259        const unsigned section_size = dynsym_data.GetByteSize();
260        unsigned offset = 0;
261
262        // The only type of entries we are concerned with are tagged DT_NEEDED,
263        // yielding the name of a required library.
264        while (offset < section_size)
265        {
266            if (!symbol.Parse(dynsym_data, &offset))
267                break;
268
269            if (symbol.d_tag != DT_NEEDED)
270                continue;
271
272            uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
273            const char *lib_name = dynstr_data.PeekCStr(str_index);
274            m_filespec_ap->Append(FileSpec(lib_name));
275        }
276    }
277
278    return m_filespec_ap->GetSize();
279}
280
281//----------------------------------------------------------------------
282// ParseProgramHeaders
283//----------------------------------------------------------------------
284size_t
285ObjectFileELF::ParseProgramHeaders()
286{
287    // We have already parsed the program headers
288    if (!m_program_headers.empty())
289        return m_program_headers.size();
290
291    // If there are no program headers to read we are done.
292    if (m_header.e_phnum == 0)
293        return 0;
294
295    m_program_headers.resize(m_header.e_phnum);
296    if (m_program_headers.size() != m_header.e_phnum)
297        return 0;
298
299    const size_t ph_size = m_header.e_phnum * m_header.e_phentsize;
300    const elf_off ph_offset = m_offset + m_header.e_phoff;
301    DataBufferSP buffer_sp(m_file.ReadFileContents(ph_offset, ph_size));
302
303    if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != ph_size)
304        return 0;
305
306    DataExtractor data(buffer_sp, m_data.GetByteOrder(),
307                       m_data.GetAddressByteSize());
308
309    uint32_t idx;
310    uint32_t offset;
311    for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
312    {
313        if (m_program_headers[idx].Parse(data, &offset) == false)
314            break;
315    }
316
317    if (idx < m_program_headers.size())
318        m_program_headers.resize(idx);
319
320    return m_program_headers.size();
321}
322
323//----------------------------------------------------------------------
324// ParseSectionHeaders
325//----------------------------------------------------------------------
326size_t
327ObjectFileELF::ParseSectionHeaders()
328{
329    // We have already parsed the section headers
330    if (!m_section_headers.empty())
331        return m_section_headers.size();
332
333    // If there are no section headers we are done.
334    if (m_header.e_shnum == 0)
335        return 0;
336
337    m_section_headers.resize(m_header.e_shnum);
338    if (m_section_headers.size() != m_header.e_shnum)
339        return 0;
340
341    const size_t sh_size = m_header.e_shnum * m_header.e_shentsize;
342    const elf_off sh_offset = m_offset + m_header.e_shoff;
343    DataBufferSP buffer_sp(m_file.ReadFileContents(sh_offset, sh_size));
344
345    if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != sh_size)
346        return 0;
347
348    DataExtractor data(buffer_sp,
349                       m_data.GetByteOrder(),
350                       m_data.GetAddressByteSize());
351
352    uint32_t idx;
353    uint32_t offset;
354    for (idx = 0, offset = 0; idx < m_header.e_shnum; ++idx)
355    {
356        if (m_section_headers[idx].Parse(data, &offset) == false)
357            break;
358    }
359    if (idx < m_section_headers.size())
360        m_section_headers.resize(idx);
361
362    return m_section_headers.size();
363}
364
365size_t
366ObjectFileELF::GetSectionHeaderStringTable()
367{
368    if (m_shstr_data.GetByteSize() == 0)
369    {
370        const unsigned strtab_idx = m_header.e_shstrndx;
371
372        if (strtab_idx && strtab_idx < m_section_headers.size())
373        {
374            const ELFSectionHeader &sheader = m_section_headers[strtab_idx];
375            const size_t byte_size = sheader.sh_size;
376            const Elf64_Off offset = m_offset + sheader.sh_offset;
377            DataBufferSP buffer_sp(m_file.ReadFileContents(offset, byte_size));
378
379            if (buffer_sp.get() == NULL || buffer_sp->GetByteSize() != byte_size)
380                return 0;
381
382            m_shstr_data.SetData(buffer_sp);
383        }
384    }
385    return m_shstr_data.GetByteSize();
386}
387
388lldb::user_id_t
389ObjectFileELF::GetSectionIndexByName(const char *name)
390{
391    if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
392        return 0;
393
394    // Search the collection of section headers for one with a matching name.
395    for (SectionHeaderCollIter I = m_section_headers.begin();
396         I != m_section_headers.end(); ++I)
397    {
398        const char *sectionName = m_shstr_data.PeekCStr(I->sh_name);
399
400        if (!sectionName)
401            return 0;
402
403        if (strcmp(name, sectionName) != 0)
404            continue;
405
406        return SectionIndex(I);
407    }
408
409    return 0;
410}
411
412SectionList *
413ObjectFileELF::GetSectionList()
414{
415    if (m_sections_ap.get())
416        return m_sections_ap.get();
417
418    if (ParseSectionHeaders() && GetSectionHeaderStringTable())
419    {
420        m_sections_ap.reset(new SectionList());
421
422        for (SectionHeaderCollIter I = m_section_headers.begin();
423             I != m_section_headers.end(); ++I)
424        {
425            const ELFSectionHeader &header = *I;
426
427            ConstString name(m_shstr_data.PeekCStr(header.sh_name));
428            uint64_t size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
429
430            static ConstString g_sect_name_text (".text");
431            static ConstString g_sect_name_data (".data");
432            static ConstString g_sect_name_bss (".bss");
433            static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");
434            static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");
435            static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");
436            static ConstString g_sect_name_dwarf_debug_info (".debug_info");
437            static ConstString g_sect_name_dwarf_debug_line (".debug_line");
438            static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");
439            static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo");
440            static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");
441            static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");
442            static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");
443            static ConstString g_sect_name_dwarf_debug_str (".debug_str");
444            static ConstString g_sect_name_eh_frame (".eh_frame");
445
446            SectionType sect_type = eSectionTypeOther;
447
448            if      (name == g_sect_name_text)                  sect_type = eSectionTypeCode;
449            else if (name == g_sect_name_data)                  sect_type = eSectionTypeData;
450            else if (name == g_sect_name_bss)                   sect_type = eSectionTypeZeroFill;
451            else if (name == g_sect_name_dwarf_debug_abbrev)    sect_type = eSectionTypeDWARFDebugAbbrev;
452            else if (name == g_sect_name_dwarf_debug_aranges)   sect_type = eSectionTypeDWARFDebugAranges;
453            else if (name == g_sect_name_dwarf_debug_frame)     sect_type = eSectionTypeDWARFDebugFrame;
454            else if (name == g_sect_name_dwarf_debug_info)      sect_type = eSectionTypeDWARFDebugInfo;
455            else if (name == g_sect_name_dwarf_debug_line)      sect_type = eSectionTypeDWARFDebugLine;
456            else if (name == g_sect_name_dwarf_debug_loc)       sect_type = eSectionTypeDWARFDebugLoc;
457            else if (name == g_sect_name_dwarf_debug_macinfo)   sect_type = eSectionTypeDWARFDebugMacInfo;
458            else if (name == g_sect_name_dwarf_debug_pubnames)  sect_type = eSectionTypeDWARFDebugPubNames;
459            else if (name == g_sect_name_dwarf_debug_pubtypes)  sect_type = eSectionTypeDWARFDebugPubTypes;
460            else if (name == g_sect_name_dwarf_debug_ranges)    sect_type = eSectionTypeDWARFDebugRanges;
461            else if (name == g_sect_name_dwarf_debug_str)       sect_type = eSectionTypeDWARFDebugStr;
462            else if (name == g_sect_name_eh_frame)              sect_type = eSectionTypeEHFrame;
463
464
465            SectionSP section(new Section(
466                0,                  // Parent section.
467                GetModule(),        // Module to which this section belongs.
468                SectionIndex(I),    // Section ID.
469                name,               // Section name.
470                sect_type,          // Section type.
471                header.sh_addr,     // VM address.
472                header.sh_size,     // VM size in bytes of this section.
473                header.sh_offset,   // Offset of this section in the file.
474                size,               // Size of the section as found in the file.
475                header.sh_flags));  // Flags for this section.
476
477            m_sections_ap->AddSection(section);
478        }
479    }
480
481    return m_sections_ap.get();
482}
483
484static void
485ParseSymbols(Symtab *symtab, SectionList *section_list,
486             const ELFSectionHeader &symtab_shdr,
487             const DataExtractor &symtab_data,
488             const DataExtractor &strtab_data)
489{
490    ELFSymbol symbol;
491    uint32_t offset = 0;
492    const unsigned numSymbols =
493        symtab_data.GetByteSize() / symtab_shdr.sh_entsize;
494
495    static ConstString text_section_name(".text");
496    static ConstString init_section_name(".init");
497    static ConstString fini_section_name(".fini");
498    static ConstString ctors_section_name(".ctors");
499    static ConstString dtors_section_name(".dtors");
500
501    static ConstString data_section_name(".data");
502    static ConstString rodata_section_name(".rodata");
503    static ConstString rodata1_section_name(".rodata1");
504    static ConstString data2_section_name(".data1");
505    static ConstString bss_section_name(".bss");
506
507    for (unsigned i = 0; i < numSymbols; ++i)
508    {
509        if (symbol.Parse(symtab_data, &offset) == false)
510            break;
511
512        Section *symbol_section = NULL;
513        SymbolType symbol_type = eSymbolTypeInvalid;
514        Elf64_Half symbol_idx = symbol.st_shndx;
515
516        switch (symbol_idx)
517        {
518        case SHN_ABS:
519            symbol_type = eSymbolTypeAbsolute;
520            break;
521        case SHN_UNDEF:
522            symbol_type = eSymbolTypeUndefined;
523            break;
524        default:
525            symbol_section = section_list->GetSectionAtIndex(symbol_idx).get();
526            break;
527        }
528
529        switch (symbol.getType())
530        {
531        default:
532        case STT_NOTYPE:
533            // The symbol's type is not specified.
534            break;
535
536        case STT_OBJECT:
537            // The symbol is associated with a data object, such as a variable,
538            // an array, etc.
539            symbol_type = eSymbolTypeData;
540            break;
541
542        case STT_FUNC:
543            // The symbol is associated with a function or other executable code.
544            symbol_type = eSymbolTypeCode;
545            break;
546
547        case STT_SECTION:
548            // The symbol is associated with a section. Symbol table entries of
549            // this type exist primarily for relocation and normally have
550            // STB_LOCAL binding.
551            break;
552
553        case STT_FILE:
554            // Conventionally, the symbol's name gives the name of the source
555            // file associated with the object file. A file symbol has STB_LOCAL
556            // binding, its section index is SHN_ABS, and it precedes the other
557            // STB_LOCAL symbols for the file, if it is present.
558            symbol_type = eSymbolTypeObjectFile;
559            break;
560        }
561
562        if (symbol_type == eSymbolTypeInvalid)
563        {
564            if (symbol_section)
565            {
566                const ConstString &sect_name = symbol_section->GetName();
567                if (sect_name == text_section_name ||
568                    sect_name == init_section_name ||
569                    sect_name == fini_section_name ||
570                    sect_name == ctors_section_name ||
571                    sect_name == dtors_section_name)
572                {
573                    symbol_type = eSymbolTypeCode;
574                }
575                else if (sect_name == data_section_name ||
576                         sect_name == data2_section_name ||
577                         sect_name == rodata_section_name ||
578                         sect_name == rodata1_section_name ||
579                         sect_name == bss_section_name)
580                {
581                    symbol_type = eSymbolTypeData;
582                }
583            }
584        }
585
586        uint64_t symbol_value = symbol.st_value;
587        if (symbol_section != NULL)
588            symbol_value -= symbol_section->GetFileAddress();
589        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
590        bool is_global = symbol.getBinding() == STB_GLOBAL;
591        uint32_t flags = symbol.st_other << 8 | symbol.st_info;
592
593        Symbol dc_symbol(
594            i,               // ID is the original symbol table index.
595            symbol_name,     // Symbol name.
596            false,           // Is the symbol name mangled?
597            symbol_type,     // Type of this symbol
598            is_global,       // Is this globally visible?
599            false,           // Is this symbol debug info?
600            false,           // Is this symbol a trampoline?
601            false,           // Is this symbol artificial?
602            symbol_section,  // Section in which this symbol is defined or null.
603            symbol_value,    // Offset in section or symbol value.
604            symbol.st_size,  // Size in bytes of this symbol.
605            flags);          // Symbol flags.
606        symtab->AddSymbol(dc_symbol);
607    }
608}
609
610void
611ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
612                                const ELFSectionHeader &symtab_hdr,
613                                user_id_t symtab_id)
614{
615    assert(symtab_hdr.sh_type == SHT_SYMTAB ||
616           symtab_hdr.sh_type == SHT_DYNSYM);
617
618    // Parse in the section list if needed.
619    SectionList *section_list = GetSectionList();
620    if (!section_list)
621        return;
622
623    // Section ID's are ones based.
624    user_id_t strtab_id = symtab_hdr.sh_link + 1;
625
626    Section *symtab = section_list->FindSectionByID(symtab_id).get();
627    Section *strtab = section_list->FindSectionByID(strtab_id).get();
628    if (symtab && strtab)
629    {
630        DataExtractor symtab_data;
631        DataExtractor strtab_data;
632        if (symtab->ReadSectionDataFromObjectFile(this, symtab_data) &&
633            strtab->ReadSectionDataFromObjectFile(this, strtab_data))
634        {
635            ParseSymbols(symbol_table, section_list, symtab_hdr,
636                         symtab_data, strtab_data);
637        }
638    }
639}
640
641Symtab *
642ObjectFileELF::GetSymtab()
643{
644    if (m_symtab_ap.get())
645        return m_symtab_ap.get();
646
647    Symtab *symbol_table = new Symtab(this);
648    m_symtab_ap.reset(symbol_table);
649
650    if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
651        return symbol_table;
652
653    // Locate and parse all linker symbol tables.
654    for (SectionHeaderCollIter I = m_section_headers.begin();
655         I != m_section_headers.end(); ++I)
656    {
657        if (I->sh_type == SHT_SYMTAB)
658        {
659            const ELFSectionHeader &symtab_section = *I;
660            user_id_t section_id = SectionIndex(I);
661            ParseSymbolTable(symbol_table, symtab_section, section_id);
662        }
663    }
664
665    return symbol_table;
666}
667
668//===----------------------------------------------------------------------===//
669// Dump
670//
671// Dump the specifics of the runtime file container (such as any headers
672// segments, sections, etc).
673//----------------------------------------------------------------------
674void
675ObjectFileELF::Dump(Stream *s)
676{
677    DumpELFHeader(s, m_header);
678    s->EOL();
679    DumpELFProgramHeaders(s);
680    s->EOL();
681    DumpELFSectionHeaders(s);
682    s->EOL();
683    SectionList *section_list = GetSectionList();
684    if (section_list)
685        section_list->Dump(s, NULL, true);
686    Symtab *symtab = GetSymtab();
687    if (symtab)
688        symtab->Dump(s, NULL);
689    s->EOL();
690    DumpDependentModules(s);
691    s->EOL();
692}
693
694//----------------------------------------------------------------------
695// DumpELFHeader
696//
697// Dump the ELF header to the specified output stream
698//----------------------------------------------------------------------
699void
700ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header)
701{
702    s->PutCString("ELF Header\n");
703    s->Printf("e_ident[EI_MAG0   ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
704    s->Printf("e_ident[EI_MAG1   ] = 0x%2.2x '%c'\n",
705              header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]);
706    s->Printf("e_ident[EI_MAG2   ] = 0x%2.2x '%c'\n",
707              header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]);
708    s->Printf("e_ident[EI_MAG3   ] = 0x%2.2x '%c'\n",
709              header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]);
710
711    s->Printf("e_ident[EI_CLASS  ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
712    s->Printf("e_ident[EI_DATA   ] = 0x%2.2x ", header.e_ident[EI_DATA]);
713    DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
714    s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
715    s->Printf ("e_ident[EI_PAD    ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
716
717    s->Printf("e_type      = 0x%4.4x ", header.e_type);
718    DumpELFHeader_e_type(s, header.e_type);
719    s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
720    s->Printf("e_version   = 0x%8.8x\n", header.e_version);
721    s->Printf("e_entry     = 0x%8.8lx\n", header.e_entry);
722    s->Printf("e_phoff     = 0x%8.8lx\n", header.e_phoff);
723    s->Printf("e_shoff     = 0x%8.8lx\n", header.e_shoff);
724    s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
725    s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
726    s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
727    s->Printf("e_phnum     = 0x%4.4x\n", header.e_phnum);
728    s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
729    s->Printf("e_shnum     = 0x%4.4x\n", header.e_shnum);
730    s->Printf("e_shstrndx  = 0x%4.4x\n", header.e_shstrndx);
731}
732
733//----------------------------------------------------------------------
734// DumpELFHeader_e_type
735//
736// Dump an token value for the ELF header member e_type
737//----------------------------------------------------------------------
738void
739ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type)
740{
741    switch (e_type)
742    {
743    case ET_NONE:   *s << "ET_NONE"; break;
744    case ET_REL:    *s << "ET_REL"; break;
745    case ET_EXEC:   *s << "ET_EXEC"; break;
746    case ET_DYN:    *s << "ET_DYN"; break;
747    case ET_CORE:   *s << "ET_CORE"; break;
748    default:
749        break;
750    }
751}
752
753//----------------------------------------------------------------------
754// DumpELFHeader_e_ident_EI_DATA
755//
756// Dump an token value for the ELF header member e_ident[EI_DATA]
757//----------------------------------------------------------------------
758void
759ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, unsigned char ei_data)
760{
761    switch (ei_data)
762    {
763    case ELFDATANONE:   *s << "ELFDATANONE"; break;
764    case ELFDATA2LSB:   *s << "ELFDATA2LSB - Little Endian"; break;
765    case ELFDATA2MSB:   *s << "ELFDATA2MSB - Big Endian"; break;
766    default:
767        break;
768    }
769}
770
771
772//----------------------------------------------------------------------
773// DumpELFProgramHeader
774//
775// Dump a single ELF program header to the specified output stream
776//----------------------------------------------------------------------
777void
778ObjectFileELF::DumpELFProgramHeader(Stream *s, const ELFProgramHeader &ph)
779{
780    DumpELFProgramHeader_p_type(s, ph.p_type);
781    s->Printf(" %8.8lx %8.8lx %8.8lx", ph.p_offset, ph.p_vaddr, ph.p_paddr);
782    s->Printf(" %8.8lx %8.8lx %8.8lx (", ph.p_filesz, ph.p_memsz, ph.p_flags);
783
784    DumpELFProgramHeader_p_flags(s, ph.p_flags);
785    s->Printf(") %8.8x", ph.p_align);
786}
787
788//----------------------------------------------------------------------
789// DumpELFProgramHeader_p_type
790//
791// Dump an token value for the ELF program header member p_type which
792// describes the type of the program header
793// ----------------------------------------------------------------------
794void
795ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
796{
797    const int kStrWidth = 10;
798    switch (p_type)
799    {
800    CASE_AND_STREAM(s, PT_NULL      , kStrWidth);
801    CASE_AND_STREAM(s, PT_LOAD      , kStrWidth);
802    CASE_AND_STREAM(s, PT_DYNAMIC   , kStrWidth);
803    CASE_AND_STREAM(s, PT_INTERP    , kStrWidth);
804    CASE_AND_STREAM(s, PT_NOTE      , kStrWidth);
805    CASE_AND_STREAM(s, PT_SHLIB     , kStrWidth);
806    CASE_AND_STREAM(s, PT_PHDR      , kStrWidth);
807    default:
808        s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
809        break;
810    }
811}
812
813
814//----------------------------------------------------------------------
815// DumpELFProgramHeader_p_flags
816//
817// Dump an token value for the ELF program header member p_flags
818//----------------------------------------------------------------------
819void
820ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags)
821{
822    *s  << ((p_flags & PF_X) ? "PF_X" : "    ")
823        << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
824        << ((p_flags & PF_W) ? "PF_W" : "    ")
825        << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
826        << ((p_flags & PF_R) ? "PF_R" : "    ");
827}
828
829//----------------------------------------------------------------------
830// DumpELFProgramHeaders
831//
832// Dump all of the ELF program header to the specified output stream
833//----------------------------------------------------------------------
834void
835ObjectFileELF::DumpELFProgramHeaders(Stream *s)
836{
837    if (ParseProgramHeaders())
838    {
839        s->PutCString("Program Headers\n");
840        s->PutCString("IDX  p_type     p_offset p_vaddr  p_paddr  "
841                      "p_filesz p_memsz  p_flags                   p_align\n");
842        s->PutCString("==== ---------- -------- -------- -------- "
843                      "-------- -------- ------------------------- --------\n");
844
845        uint32_t idx = 0;
846        for (ProgramHeaderCollConstIter I = m_program_headers.begin();
847             I != m_program_headers.end(); ++I, ++idx)
848        {
849            s->Printf("[%2u] ", idx);
850            ObjectFileELF::DumpELFProgramHeader(s, *I);
851            s->EOL();
852        }
853    }
854}
855
856//----------------------------------------------------------------------
857// DumpELFSectionHeader
858//
859// Dump a single ELF section header to the specified output stream
860//----------------------------------------------------------------------
861void
862ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeader &sh)
863{
864    s->Printf("%8.8x ", sh.sh_name);
865    DumpELFSectionHeader_sh_type(s, sh.sh_type);
866    s->Printf(" %8.8lx (", sh.sh_flags);
867    DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
868    s->Printf(") %8.8lx %8.8lx %8.8lx", sh.sh_addr, sh.sh_offset, sh.sh_size);
869    s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
870    s->Printf(" %8.8lx %8.8lx", sh.sh_addralign, sh.sh_entsize);
871}
872
873//----------------------------------------------------------------------
874// DumpELFSectionHeader_sh_type
875//
876// Dump an token value for the ELF section header member sh_type which
877// describes the type of the section
878//----------------------------------------------------------------------
879void
880ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type)
881{
882    const int kStrWidth = 12;
883    switch (sh_type)
884    {
885    CASE_AND_STREAM(s, SHT_NULL     , kStrWidth);
886    CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth);
887    CASE_AND_STREAM(s, SHT_SYMTAB   , kStrWidth);
888    CASE_AND_STREAM(s, SHT_STRTAB   , kStrWidth);
889    CASE_AND_STREAM(s, SHT_RELA     , kStrWidth);
890    CASE_AND_STREAM(s, SHT_HASH     , kStrWidth);
891    CASE_AND_STREAM(s, SHT_DYNAMIC  , kStrWidth);
892    CASE_AND_STREAM(s, SHT_NOTE     , kStrWidth);
893    CASE_AND_STREAM(s, SHT_NOBITS   , kStrWidth);
894    CASE_AND_STREAM(s, SHT_REL      , kStrWidth);
895    CASE_AND_STREAM(s, SHT_SHLIB    , kStrWidth);
896    CASE_AND_STREAM(s, SHT_DYNSYM   , kStrWidth);
897    CASE_AND_STREAM(s, SHT_LOPROC   , kStrWidth);
898    CASE_AND_STREAM(s, SHT_HIPROC   , kStrWidth);
899    CASE_AND_STREAM(s, SHT_LOUSER   , kStrWidth);
900    CASE_AND_STREAM(s, SHT_HIUSER   , kStrWidth);
901    default:
902        s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
903        break;
904    }
905}
906
907//----------------------------------------------------------------------
908// DumpELFSectionHeader_sh_flags
909//
910// Dump an token value for the ELF section header member sh_flags
911//----------------------------------------------------------------------
912void
913ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_word sh_flags)
914{
915    *s  << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
916        << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
917        << ((sh_flags & SHF_ALLOC) ? "ALLOC" : "     ")
918        << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
919        << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : "         ");
920}
921
922//----------------------------------------------------------------------
923// DumpELFSectionHeaders
924//
925// Dump all of the ELF section header to the specified output stream
926//----------------------------------------------------------------------
927void
928ObjectFileELF::DumpELFSectionHeaders(Stream *s)
929{
930    if (!(ParseSectionHeaders() && GetSectionHeaderStringTable()))
931        return;
932
933    s->PutCString("Section Headers\n");
934    s->PutCString("IDX  name     type         flags                            "
935                  "addr     offset   size     link     info     addralgn "
936                  "entsize  Name\n");
937    s->PutCString("==== -------- ------------ -------------------------------- "
938                  "-------- -------- -------- -------- -------- -------- "
939                  "-------- ====================\n");
940
941    uint32_t idx = 0;
942    for (SectionHeaderCollConstIter I = m_section_headers.begin();
943         I != m_section_headers.end(); ++I, ++idx)
944    {
945        s->Printf("[%2u] ", idx);
946        ObjectFileELF::DumpELFSectionHeader(s, *I);
947        const char* section_name = m_shstr_data.PeekCStr(I->sh_name);
948        if (section_name)
949            *s << ' ' << section_name << "\n";
950    }
951}
952
953void
954ObjectFileELF::DumpDependentModules(lldb_private::Stream *s)
955{
956    size_t num_modules = ParseDependentModules();
957
958    if (num_modules > 0)
959    {
960        s->PutCString("Dependent Modules:\n");
961        for (unsigned i = 0; i < num_modules; ++i)
962        {
963            const FileSpec &spec = m_filespec_ap->GetFileSpecAtIndex(i);
964            s->Printf("   %s\n", spec.GetFilename().GetCString());
965        }
966    }
967}
968
969bool
970ObjectFileELF::GetTargetTriple(ConstString &target_triple)
971{
972    static ConstString g_target_triple;
973
974    if (g_target_triple)
975    {
976        target_triple = g_target_triple;
977        return true;
978    }
979
980    std::string triple;
981    switch (m_header.e_machine)
982    {
983    default:
984        assert(false && "Unexpected machine type.");
985        break;
986    case EM_SPARC:  triple.assign("sparc-"); break;
987    case EM_386:    triple.assign("i386-"); break;
988    case EM_68K:    triple.assign("68k-"); break;
989    case EM_88K:    triple.assign("88k-"); break;
990    case EM_860:    triple.assign("i860-"); break;
991    case EM_MIPS:   triple.assign("mips-"); break;
992    case EM_PPC:    triple.assign("powerpc-"); break;
993    case EM_PPC64:  triple.assign("powerpc64-"); break;
994    case EM_ARM:    triple.assign("arm-"); break;
995    case EM_X86_64: triple.assign("x86_64-"); break;
996    }
997    // TODO: determine if there is a vendor in the ELF? Default to "linux" for now
998    triple += "linux-";
999    // TODO: determine if there is an OS in the ELF? Default to "gnu" for now
1000    triple += "gnu";
1001    g_target_triple.SetCString(triple.c_str());
1002    target_triple = g_target_triple;
1003
1004    return true;
1005}
1006
1007