1 /*
2     Copyright (C) 2013-2014 Volker Krause <vkrause@kde.org>
3 
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU Library General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or (at your
7     option) any later version.
8 
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
12     License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 #include "elfdefinitions.h" // must come first before <elf.h>
19 #define _ELF_H_
20 #include "indexvisitor.h"
21 
22 #include <elf/elffile.h>
23 #include <elf/elffileset.h>
24 #include <elf/elfgnusymbolversionrequirement.h>
25 #include <dwarf/dwarfcudie.h>
26 
27 #include <elf.h>
28 
doVisit(ElfFileSet * fileSet,int row) const29 IndexVisitor::type IndexVisitor::doVisit(ElfFileSet* fileSet, int row) const
30 {
31     return qMakePair<void*, ElfNodeVariant::Type>(fileSet->file(row), ElfNodeVariant::File);
32 }
33 
doVisit(ElfFile * file,int row) const34 IndexVisitor::type IndexVisitor::doVisit(ElfFile* file, int row) const
35 {
36     ElfSection *section = file->section<ElfSection>(row);
37     void *internalPointer = section;
38     ElfNodeVariant::Type type;
39     switch (section->header()->type()) {
40         case SHT_SYMTAB:
41         case SHT_DYNSYM:
42             type = ElfNodeVariant::SymbolTableSection;
43             break;
44         case SHT_DYNAMIC:
45             type = ElfNodeVariant::DynamicSection;
46             break;
47         case SHT_NOTE:
48             type = ElfNodeVariant::NoteSection;
49             break;
50         case SHT_REL:
51         case SHT_RELA:
52             type = ElfNodeVariant::RelocationSection;
53             break;
54         case SHT_GNU_verdef:
55             type = ElfNodeVariant::VersionDefinitionSection;
56             break;
57         case SHT_GNU_verneed:
58             type = ElfNodeVariant::VersionRequirementsSection;
59             break;
60         case SHT_HASH:
61         case SHT_GNU_HASH:
62             type = ElfNodeVariant::HashSection;
63             break;
64         case SHT_PROGBITS:
65             if (strcmp(section->header()->name(), ".plt") == 0) {
66                 type = ElfNodeVariant::PltSection;
67                 break;
68             } else if ((section->header()->flags() & SHF_WRITE) && strncmp(section->header()->name(), ".got", 4) == 0) {
69                 type = ElfNodeVariant::GotSection;
70                 break;
71             } else if (strcmp(section->header()->name(), ".gnu_debuglink") == 0) {
72                 type = ElfNodeVariant::DebugLinkSection;
73                 break;
74             }
75             // else fallthrough
76         default:
77             if (strcmp(section->header()->name(), ".debug_info") == 0) {
78                 type = ElfNodeVariant::DwarfInfo;
79                 internalPointer = file->dwarfInfo();
80             } else {
81                 type = ElfNodeVariant::Section;
82             }
83     }
84     return qMakePair(internalPointer, type);
85 }
86 
doVisit(ElfSymbolTableSection * symtab,int row) const87 IndexVisitor::type IndexVisitor::doVisit(ElfSymbolTableSection* symtab, int row) const
88 {
89     const auto entry = symtab->entry(row);
90     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::SymbolTableEntry);
91 }
92 
doVisit(ElfDynamicSection * section,int row) const93 IndexVisitor::type IndexVisitor::doVisit(ElfDynamicSection* section, int row) const
94 {
95     const auto entry = section->entry(row);
96     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::DynamicEntry);
97 }
98 
doVisit(ElfGNUSymbolVersionDefinitionsSection * section,int row) const99 IndexVisitor::type IndexVisitor::doVisit(ElfGNUSymbolVersionDefinitionsSection *section, int row) const
100 {
101     const auto entry = section->definition(row);
102     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::VersionDefinitionEntry);
103 }
104 
doVisit(ElfGNUSymbolVersionDefinition * verDef,int row) const105 IndexVisitor::type IndexVisitor::doVisit(ElfGNUSymbolVersionDefinition *verDef, int row) const
106 {
107     const auto auxEntry = verDef->auxiliaryEntry(row);
108     return qMakePair<void*, ElfNodeVariant::Type>(auxEntry, ElfNodeVariant::VersionDefinitionAuxiliaryEntry);
109 }
110 
doVisit(ElfGNUSymbolVersionRequirementsSection * section,int row) const111 IndexVisitor::type IndexVisitor::doVisit(ElfGNUSymbolVersionRequirementsSection *section, int row) const
112 {
113     const auto entry = section->requirement(row);
114     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::VersionRequirementEntry);
115 }
116 
doVisit(ElfGNUSymbolVersionRequirement * verNeed,int row) const117 IndexVisitor::type IndexVisitor::doVisit(ElfGNUSymbolVersionRequirement *verNeed, int row) const
118 {
119     const auto auxEntry = verNeed->auxiliaryEntry(row);
120     return qMakePair<void*, ElfNodeVariant::Type>(auxEntry, ElfNodeVariant::VersionRequirementAuxiliaryEntry);
121 }
122 
doVisit(ElfGotSection * section,int row) const123 IndexVisitor::type IndexVisitor::doVisit(ElfGotSection *section, int row) const
124 {
125     const auto entry = section->entry(row);
126     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::GotEntry);
127 }
128 
doVisit(ElfNoteSection * section,int row) const129 IndexVisitor::type IndexVisitor::doVisit(ElfNoteSection *section, int row) const
130 {
131     const auto entry = section->entry(row);
132     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::NoteEntry);
133 }
134 
doVisit(ElfPltSection * section,int row) const135 IndexVisitor::type IndexVisitor::doVisit(ElfPltSection *section, int row) const
136 {
137     const auto entry = section->entry(row);
138     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::PltEntry);
139 }
140 
doVisit(ElfRelocationSection * section,int row) const141 IndexVisitor::type IndexVisitor::doVisit(ElfRelocationSection* section, int row) const
142 {
143     const auto entry = section->entry(row);
144     return qMakePair<void*, ElfNodeVariant::Type>(entry, ElfNodeVariant::RelocationEntry);
145 }
146 
doVisit(DwarfInfo * info,int row) const147 IndexVisitor::type IndexVisitor::doVisit(DwarfInfo* info, int row) const
148 {
149     auto cuDie = info->compilationUnits().at(row);
150     return qMakePair<void*, ElfNodeVariant::Type>(cuDie, ElfNodeVariant::DwarfDie);
151 }
152 
doVisit(DwarfDie * die,int row) const153 QPair< void*, ElfNodeVariant::Type > IndexVisitor::doVisit(DwarfDie* die, int row) const
154 {
155     DwarfDie *childDie = die->children().at(row);
156     return qMakePair<void*, ElfNodeVariant::Type>(childDie, ElfNodeVariant::DwarfDie);
157 }
158