• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "elf_handling.h"
18 
19 #include <cxxabi.h>
20 
21 using llvm::ELF::ELFDATA2MSB;
22 using llvm::ELF::EM_ARM;
23 using llvm::ELF::EM_MIPS;
24 using llvm::ELF::R_AARCH64_ABS64;
25 using llvm::ELF::R_AARCH64_RELATIVE;
26 using llvm::ELF::R_ARM_ABS32;
27 using llvm::ELF::R_ARM_RELATIVE;
28 using llvm::ELF::R_X86_64_64;
29 using llvm::ELF::R_X86_64_RELATIVE;
30 using llvm::ELF::R_MIPS_64;
31 using llvm::ELF::R_MIPS_REL32;
32 using llvm::ELF::R_MIPS_NONE;
33 using llvm::ELF::SHT_PROGBITS;
34 using llvm::ELF::SHT_REL;
35 using llvm::ELF::SHT_RELA;
36 using llvm::Expected;
37 using llvm::StringRef;
38 using llvm::dyn_cast;
39 using llvm::object::ELF32BEObjectFile;
40 using llvm::object::ELF32LEObjectFile;
41 using llvm::object::ELF64BEObjectFile;
42 using llvm::object::ELF64LEObjectFile;
43 using llvm::object::symbol_iterator;
44 using llvm::support::endian::read;
45 using llvm::outs;
46 using llvm::Error;
47 using llvm::make_unique;
48 
demangle(const std::string & MangledName)49 static std::string demangle(const std::string &MangledName) {
50      char *Str = __cxxabiv1::__cxa_demangle(
51              MangledName.c_str(),
52              nullptr,
53              0,
54              nullptr);
55      if (Str) {
56          std::string DemangledString(Str);
57          free(Str);
58          return DemangledString;
59      }
60      return "";
61 }
62 
~SharedObject()63 SharedObject::~SharedObject() {}
64 
65 template <typename ELFT>
createELFSharedObject(const ELFObjectFile<ELFT> * Objfile)66 static std::unique_ptr<SharedObject> createELFSharedObject(
67         const ELFObjectFile<ELFT> *Objfile) {
68     return make_unique<ELFSharedObject<ELFT>>(Objfile);
69 }
70 
createELFObjFile(const ObjectFile * Obj)71 static std::unique_ptr<SharedObject>createELFObjFile(const ObjectFile *Obj) {
72     if (const ELF32LEObjectFile *Objfile = dyn_cast<ELF32LEObjectFile>(Obj))
73         return createELFSharedObject(Objfile);
74     if (const ELF32BEObjectFile *Objfile = dyn_cast<ELF32BEObjectFile>(Obj))
75         return createELFSharedObject(Objfile);
76     if (const ELF64LEObjectFile *Objfile = dyn_cast<ELF64LEObjectFile>(Obj))
77         return createELFSharedObject(Objfile);
78     if (const ELF64BEObjectFile *Objfile = dyn_cast<ELF64BEObjectFile>(Obj))
79         return createELFSharedObject(Objfile);
80 
81     return nullptr;
82 }
83 
create(const ObjectFile * Obj)84 std::unique_ptr<SharedObject> SharedObject::create(const ObjectFile *Obj) {
85     std::unique_ptr<SharedObject> res(createELFObjFile(Obj));
86     if (res && res->getVTables()) {
87         return res;
88     }
89     return nullptr;
90 }
91 
92 template <typename ELFT>
~ELFSharedObject()93 ELFSharedObject<ELFT>::~ELFSharedObject() {}
94 
95 template <typename ELFT>
ELFSharedObject(const ELFObjectFile<ELFT> * Objfile)96 ELFSharedObject<ELFT>::ELFSharedObject(
97         const ELFObjectFile<ELFT> *Objfile)
98     : mObj(Objfile) {}
99 
100 template <typename ELFT>
cacheELFSections()101 bool ELFSharedObject<ELFT>::cacheELFSections() {
102     for (const SectionRef &ElfSection : mObj->sections()) {
103         const Elf_Shdr *ElfShdr =
104                 mObj->getSection(ElfSection.getRawDataRefImpl());
105         if (!ElfShdr) {
106             outs() << "Couldn't create elf shdr \n";
107             return false;
108         }
109         switch (ElfShdr->sh_type) {
110             case SHT_RELA:
111             case SHT_REL:
112                 mRelSectionRefs.emplace_back(ElfSection);
113                 break;
114             case SHT_PROGBITS:
115                 mProgBitSectionRefs.emplace_back(ElfSection);
116                 break;
117             default :
118                 // Any other section won't have information pertinent
119                 // to vtables. Relocation entries will have the virtual
120                 // functions' relocation information, the PROGBITS sections
121                 // will have the vtables themselves.
122                 break;
123         }
124     }
125     return true;
126 }
127 
128 template <typename ELFT>
printVTables() const129 void ELFSharedObject<ELFT>::printVTables() const {
130     for (const VTable &Vtable : mVTables) {
131         if (Vtable.getVTableSize() == 0)
132             continue;
133         outs() << Vtable.getDemangledName()
134                << "\n"
135                << Vtable.getMangledName()
136                << ": "
137                << Vtable.getVTableSize()
138                << " entries"
139                << "\n";
140         for (const VFunction &Vfunction : Vtable) {
141             outs() << Vfunction.getOffset()
142                    << "    (int (*)(...)) "
143                    << Vfunction.getDemangledName()
144                    << "\n";
145         }
146         outs() << "\n"
147                << "\n";
148     }
149 }
150 
151 template <typename ELFT>
getVTables()152 bool ELFSharedObject<ELFT>::getVTables() {
153     if (!cacheELFSections()) {
154         return false;
155     }
156     if (!initVTableRanges()) {
157         return true;
158     }
159     getVFunctions();
160     for (VTable &Vtable : mVTables) {
161         // Sort the functions by offset before displaying them since the order
162         // of functions appearing in relocation sections might change. That
163         // should not result in the vtable layout changing.
164         Vtable.sortVFunctions();
165     }
166     return true;
167 }
168 
169 template <typename ELFT>
initVTableRanges()170 bool ELFSharedObject<ELFT>::initVTableRanges() {
171     // Go through all the symbols in the dynsym / symtab sections
172     // and cache all the relevant symbols. i.e: symbols which correspond
173     // to either vtables or functions.
174 
175     std::vector<std::pair<SymbolRef, uint64_t>> SymsAndSizes =
176             computeSymbolSizes(*mObj);
177     for (std::pair<SymbolRef, uint64_t> &Pair : SymsAndSizes) {
178         SymbolRef Symbol = Pair.first;
179         SymbolRef::Type SymType = UnWrap(Symbol.getType());
180         uint64_t SymValue = Symbol.getValue();
181         StringRef SymName = UnWrap(Symbol.getName());
182         if (SymName.startswith("__ZTV") || SymName.startswith("_ZTV")) {
183             mVTables.emplace_back(
184                     SymName.str(),
185                     demangle(SymName.str()),
186                     Symbol.getValue(),
187                     Symbol.getValue() + Pair.second);
188         } else if (SymType == SymbolRef::ST_Function) {
189             std::map<uint64_t, std::vector<SymbolRef>>::iterator It =
190                     mAddrToSymbolRef.find(SymValue);
191             if (It == mAddrToSymbolRef.end()) {
192                 mAddrToSymbolRef.insert(std::make_pair(
193                         SymValue, std::vector<SymbolRef>(1, Symbol)));
194             } else {
195                 std::vector<SymbolRef> &SymVec = It->second;
196                 SymVec.emplace_back(Symbol);
197             }
198         }
199     }
200     if (mVTables.size() == 0) {
201         return false;
202     }
203     std::sort(mVTables.begin(), mVTables.end());
204     return true;
205 }
206 
207 template <typename ELFT>
getVFunctions()208 void ELFSharedObject<ELFT>::getVFunctions() {
209     for (const SectionRef &Section : mRelSectionRefs) {
210         for (const RelocationRef &Relocation : Section.relocations()) {
211             VTable *VtPtr = identifyVTable(Relocation.getOffset());
212             if (VtPtr != nullptr) {
213                 relocateSym(Relocation, Section, VtPtr);
214             }
215         }
216     }
217 }
218 
219 template <typename ELFT>
identifyVTable(uint64_t RelOffset)220 VTable *ELFSharedObject<ELFT>::identifyVTable(uint64_t RelOffset) {
221     typename std::vector<VTable>::iterator It;
222     It = std::lower_bound(mVTables.begin(), mVTables.end(), RelOffset);
223     if (It != mVTables.begin() && It->getStartAddr() != RelOffset) {
224         It--;
225     }
226     if (It->getEndAddr() >= RelOffset) {
227         return &(*It);
228     }
229     return nullptr;
230 }
231 
232 template <typename ELFT>
relocateSym(const RelocationRef & Relocation,const SectionRef & Section,VTable * Vtablep)233 void ELFSharedObject<ELFT>::relocateSym(
234         const RelocationRef &Relocation,
235         const SectionRef &Section,
236         VTable *Vtablep) {
237     const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader();
238     if (ElfHeader->e_machine == EM_MIPS) {
239         // bionic/linker/linker_mips.cpp , we handle only one type of
240         // relocation. Depending on if the symbol can be inferred from r_info we
241         // make it an absolute or a relative relocation.
242         if (!absoluteRelocation(Relocation, Vtablep)) {
243             relativeRelocation(Relocation, Section, Vtablep);
244         }
245     } else {
246         switch(Relocation.getType()) {
247             case R_AARCH64_RELATIVE:
248             case R_X86_64_RELATIVE:
249             case R_ARM_RELATIVE:
250             {
251                 // The return value is ignored since failure to relocate
252                 // does not mean a fatal error. It might be that the dynsym /
253                 // symbol-table does not have enough information to get the
254                 // symbol name. Like-wise for absolute relocations.
255                 relativeRelocation(Relocation, Section, Vtablep);
256                 break;
257             }
258             case R_AARCH64_ABS64:
259             case R_X86_64_64:
260             case R_ARM_ABS32:
261             {
262                 absoluteRelocation(Relocation, Vtablep);
263                 break;
264             }
265             default:
266                 break;
267         }
268     }
269 }
270 
271 template <typename ELFT>
absoluteRelocation(const RelocationRef & Relocation,VTable * Vtablep)272 bool ELFSharedObject<ELFT>::absoluteRelocation(
273         const RelocationRef &Relocation,
274         VTable *Vtablep) {
275     symbol_iterator Symi = Relocation.getSymbol();
276     if (Symi == mObj->symbol_end()) {
277         return false;
278     }
279     SymbolRef Symbol = *Symi;
280     uint64_t RelOffset = Relocation.getOffset();
281     StringRef SymbolName = UnWrap(Symbol.getName());
282     std::string DemangledName = demangle(SymbolName.str());
283     if (!DemangledName.empty()) {
284         Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset);
285         return true;
286     }
287     return false;
288 }
289 
290 template <typename ELFT>
relativeRelocation(const RelocationRef & Relocation,const SectionRef & Section,VTable * Vtablep)291 bool ELFSharedObject<ELFT>::relativeRelocation(
292         const RelocationRef &Relocation,
293         const SectionRef &Section,
294         VTable *Vtablep) {
295     uint64_t Addend = 0;
296     uint64_t RelOffset = Relocation.getOffset();
297     if (mObj->getSection(Section.getRawDataRefImpl())->sh_type == SHT_RELA) {
298         const Elf_Rela *Rela = mObj->getRela(Relocation.getRawDataRefImpl());
299         Addend = static_cast<uint64_t>(Rela->r_addend);
300     }
301 
302     if (Addend == 0) {
303         Addend = identifyAddend(Relocation.getOffset());
304     }
305 
306     std::map<uint64_t, std::vector<SymbolRef>>::iterator It =
307             mAddrToSymbolRef.find(Addend);
308     if (It == mAddrToSymbolRef.end()) {
309         return false;
310     }
311     SymbolRef Symbol = matchValueToSymbol(It->second, Vtablep);
312     StringRef SymbolName = UnWrap(Symbol.getName());
313     std::string DemangledName = demangle(SymbolName.str());
314     if (!DemangledName.empty()) {
315         Vtablep->addVFunction(SymbolName.str(), DemangledName, RelOffset);
316         return true;
317     }
318     return false;
319 }
320 
321 template <typename ELFT>
matchValueToSymbol(std::vector<SymbolRef> & SymVec,VTable * Vtablep)322 SymbolRef ELFSharedObject<ELFT>::matchValueToSymbol(
323         std::vector<SymbolRef> &SymVec,
324         VTable *Vtablep) {
325     constexpr size_t pos = sizeof("vtable for ") - 1;
326     const std::string ClassName(Vtablep->getDemangledName().substr(pos));
327     for (const SymbolRef &Symbol : SymVec) {
328         StringRef SymbolName = UnWrap(Symbol.getName());
329         if (SymbolName.str().find(ClassName) != std::string::npos)
330             return Symbol;
331     }
332     // Return the 1st Symbol by default.
333     return SymVec[0];
334 }
335 
336 template <typename ELFT>
identifyAddend(uint64_t ROffset)337 uint64_t ELFSharedObject<ELFT>::identifyAddend(uint64_t ROffset) {
338     for (const SectionRef &Section : mProgBitSectionRefs) {
339         uint64_t Begin = Section.getAddress();
340         uint64_t End = Section.getAddress() + Section.getSize();
341         if (ROffset >= Begin && ROffset <= End) {
342             return getAddendFromSection(Section, ROffset - Begin);
343         }
344     }
345     return 0;
346 }
347 
348 template <typename ELFT>
getAddendFromSection(const SectionRef & Section,uint64_t Offset)349 uint64_t ELFSharedObject<ELFT>::getAddendFromSection(
350         const SectionRef &Section,
351         uint64_t Offset) {
352     StringRef Contents;
353     if (Section.getContents(Contents))
354         return 0;
355     const unsigned char *Bytes = Contents.bytes_begin() + Offset;
356     uintX_t Addend = read<uintX_t, ELFT::TargetEndianness>(Bytes);
357     const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader();
358     if (ElfHeader->e_machine == EM_ARM ||
359         ElfHeader->e_machine == EM_MIPS) {
360         // Remove thumb flag as llvm suggests.
361         Addend &= ~1;
362     }
363     return static_cast<uint64_t>(Addend);
364 }
365 
VFunction(const std::string & MangledName,const std::string & DemangledName,uint64_t VFunctionOffset)366 VFunction::VFunction(
367         const std::string &MangledName,
368         const std::string &DemangledName,
369         uint64_t VFunctionOffset)
370     : mMangledName(MangledName),
371       mDemangledName(DemangledName),
372       mOffset(VFunctionOffset) {}
373 
getOffset() const374 uint64_t VFunction::getOffset() const {
375     return mOffset;
376 }
377 
getDemangledName() const378 const std::string &VFunction::getDemangledName() const {
379     return mDemangledName;
380 }
381 
getMangledName() const382 const std::string &VFunction::getMangledName() const {
383     return mMangledName;
384 }
385 
operator <(const VFunction & Vfunction) const386 bool VFunction::operator<(const VFunction &Vfunction) const {
387     return mOffset < Vfunction.getOffset();
388 }
389 
VTable(const std::string & MangledName,const std::string & DemangledName,uint64_t Begin,uint64_t End)390 VTable::VTable(
391         const std::string &MangledName,
392         const std::string &DemangledName,
393         uint64_t Begin,
394         uint64_t End)
395     : mMangledName(MangledName),
396       mDemangledName(DemangledName),
397       mStartAddr(Begin),
398       mEndAddr(End),
399       mBaseOffset(Begin) {}
400 
addVFunction(const std::string & MangledName,const std::string & DemangledName,uint64_t RelOffset)401 void VTable::addVFunction(
402         const std::string &MangledName,
403         const std::string &DemangledName,
404         uint64_t RelOffset) {
405     mFunctions.emplace_back(
406             MangledName,
407             DemangledName,
408             RelOffset - mBaseOffset);
409 }
410 
getDemangledName() const411 const std::string &VTable::getDemangledName() const {
412     return mDemangledName;
413 }
414 
getMangledName() const415 const std::string &VTable::getMangledName() const {
416     return mMangledName;
417 }
418 
getStartAddr() const419 uint64_t VTable::getStartAddr() const {
420     return mStartAddr;
421 }
422 
getEndAddr() const423 uint64_t VTable::getEndAddr() const {
424     return mEndAddr;
425 }
426 
getBaseOffset() const427 uint64_t VTable::getBaseOffset() const {
428     return mBaseOffset;
429 }
430 
getVTableSize() const431 uint64_t VTable::getVTableSize() const {
432     return mFunctions.size();
433 }
434 
begin() const435 VTable::func_iterator VTable::begin() const {
436     return mFunctions.cbegin();
437 }
438 
end() const439 VTable::func_iterator VTable::end() const {
440     return mFunctions.cend();
441 }
442 
operator <(const VTable & Vtable) const443 bool VTable::operator<(const VTable &Vtable) const {
444     return mStartAddr < Vtable.getStartAddr();
445 }
446 
operator <(const uint64_t ROffset) const447 bool VTable::operator<(const uint64_t ROffset) const {
448     return mStartAddr < ROffset;
449 }
450 
sortVFunctions()451 void VTable::sortVFunctions() {
452     std::sort(mFunctions.begin(), mFunctions.end());
453 }
454