diff --git a/vndk/tools/vtable-dumper/Android.bp b/vndk/tools/vtable-dumper/Android.bp deleted file mode 100644 index 033c1e74a..000000000 --- a/vndk/tools/vtable-dumper/Android.bp +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2016 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -cc_binary_host { - name: "vndk-vtable-dumper", - - defaults: [ - "clang-defaults", - ], - - srcs: [ - "elf_handling.cpp", - "vndk_vtable_dumper.cpp", - ], - - cflags: [ - "-Wall", - "-Werror", - "-std=c++11", - ], - - shared_libs: [ - "libLLVM_android", - ], -} diff --git a/vndk/tools/vtable-dumper/OWNERS b/vndk/tools/vtable-dumper/OWNERS deleted file mode 100644 index bf26553e3..000000000 --- a/vndk/tools/vtable-dumper/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -andrewhsieh@google.com -loganchien@google.com -jchowdhary@google.com diff --git a/vndk/tools/vtable-dumper/elf_handling.cpp b/vndk/tools/vtable-dumper/elf_handling.cpp deleted file mode 100644 index d98bf460f..000000000 --- a/vndk/tools/vtable-dumper/elf_handling.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "elf_handling.h" - -#include - -using llvm::ELF::EM_386; -using llvm::ELF::EM_X86_64; -using llvm::ELF::EM_ARM; -using llvm::ELF::EM_AARCH64; -using llvm::ELF::EM_MIPS; - -using llvm::ELF::R_386_32; -using llvm::ELF::R_386_RELATIVE; -using llvm::ELF::R_X86_64_64; -using llvm::ELF::R_X86_64_RELATIVE; -using llvm::ELF::R_ARM_ABS32; -using llvm::ELF::R_ARM_RELATIVE; -using llvm::ELF::R_AARCH64_ABS64; -using llvm::ELF::R_AARCH64_RELATIVE; -using llvm::ELF::R_MIPS_64; -using llvm::ELF::R_MIPS_REL32; -using llvm::ELF::R_MIPS_NONE; - -using llvm::ELF::SHT_PROGBITS; -using llvm::ELF::SHT_REL; -using llvm::ELF::SHT_RELA; -using llvm::Expected; -using llvm::StringRef; -using llvm::dyn_cast; -using llvm::object::ELF32BEObjectFile; -using llvm::object::ELF32LEObjectFile; -using llvm::object::ELF64BEObjectFile; -using llvm::object::ELF64LEObjectFile; -using llvm::object::symbol_iterator; -using llvm::support::endian::read; -using llvm::outs; -using llvm::Error; -using llvm::make_unique; - -static std::string demangle(const std::string &MangledName) { - // If demangling result is NULL then MangledName may be __cxa_pure_virtual - // or __cxa_deleted_virtual or other C symbol names. - // __cxa_pure_virtual indicates a pure virtual function and - // __cxa_deleted_virtual indicates a deleted virtual function. (though - // this is very unlikely to happen) - // What we do here is to return MangledName when we cannot demangle it, - // assuming undemangable names are C symbols that don't need demangling. - char *Str = abi::__cxa_demangle(MangledName.c_str(), nullptr, nullptr, - nullptr); - if (Str) { - std::string DemangledName(Str); - free(Str); - return DemangledName; - } - return MangledName; -} - - -template -static std::unique_ptr createELFSharedObject( - const ELFObjectFile *Objfile) { - return make_unique>(Objfile); -} - -static std::unique_ptr createELFObjFile(const ObjectFile *Obj) { - if (const ELF32LEObjectFile *Objfile = dyn_cast(Obj)) - return createELFSharedObject(Objfile); - if (const ELF32BEObjectFile *Objfile = dyn_cast(Obj)) - return createELFSharedObject(Objfile); - if (const ELF64LEObjectFile *Objfile = dyn_cast(Obj)) - return createELFSharedObject(Objfile); - if (const ELF64BEObjectFile *Objfile = dyn_cast(Obj)) - return createELFSharedObject(Objfile); - - return nullptr; -} - -SharedObject::~SharedObject() {} - -std::unique_ptr SharedObject::create(const ObjectFile *Obj) { - std::unique_ptr res(createELFObjFile(Obj)); - if (res && res->getVTables()) { - return res; - } - return nullptr; -} - -template -ELFSharedObject::~ELFSharedObject() {} - -template -ELFSharedObject::ELFSharedObject( - const ELFObjectFile *Objfile) - : mObj(Objfile) {} - -template -bool ELFSharedObject::cacheELFSections() { - for (const SectionRef &ElfSection : mObj->sections()) { - const Elf_Shdr *ElfShdr = - mObj->getSection(ElfSection.getRawDataRefImpl()); - if (!ElfShdr) { - outs() << "Couldn't create elf shdr \n"; - return false; - } - switch (ElfShdr->sh_type) { - case SHT_RELA: - case SHT_REL: - mRelSectionRefs.emplace_back(ElfSection); - break; - case SHT_PROGBITS: - mProgBitSectionRefs.emplace_back(ElfSection); - break; - default : - // Any other section won't have information pertinent - // to vtables. Relocation entries will have the virtual - // functions' relocation information, the PROGBITS sections - // will have the vtables themselves. - break; - } - } - return true; -} - -template -void ELFSharedObject::printVTables(bool Mangled) const { - for (const VTable &Vtable : mVTables) { - if (Vtable.getVTableSize() == 0) - continue; - outs() << Vtable.getDemangledName() - << "\n" - << Vtable.getMangledName() - << ": " - << Vtable.getVTableSize() - << " entries" - << "\n"; - for (const VFunction &Vfunction : Vtable) { - std::string VfunctionName = (Mangled ? - Vfunction.getMangledName() : - Vfunction.getDemangledName()); - outs() << Vfunction.getOffset() - << " (int (*)(...)) " - << VfunctionName - << "\n"; - } - outs() << "\n" - << "\n"; - } -} - -template -bool ELFSharedObject::getVTables() { - if (!cacheELFSections()) { - return false; - } - if (!initVTableRanges()) { - return true; - } - getVFunctions(); - for (VTable &Vtable : mVTables) { - // Sort the functions by offset before displaying them since the order - // of functions appearing in relocation sections might change. That - // should not result in the vtable layout changing. - Vtable.sortVFunctions(); - } - return true; -} - -template -bool ELFSharedObject::initVTableRanges() { - // Go through all the symbols in the dynsym / symtab sections - // and cache all the relevant symbols. i.e: symbols which correspond - // to either vtables or functions. - - std::vector> SymsAndSizes = - computeSymbolSizes(*mObj); - for (std::pair &Pair : SymsAndSizes) { - SymbolRef Symbol = Pair.first; - SymbolRef::Type SymType = UnWrap(Symbol.getType()); - uint64_t SymValue = Symbol.getValue(); - StringRef SymName = UnWrap(Symbol.getName()); - if (SymName.startswith("__ZTV") || SymName.startswith("_ZTV")) { - mVTables.emplace_back( - SymName.str(), - demangle(SymName.str()), - Symbol.getValue(), - Symbol.getValue() + Pair.second); - } else if (SymType == SymbolRef::ST_Function) { - std::map>::iterator It = - mAddrToSymbolRef.find(SymValue); - if (It == mAddrToSymbolRef.end()) { - mAddrToSymbolRef.insert(std::make_pair( - SymValue, std::vector(1, Symbol))); - } else { - std::vector &SymVec = It->second; - SymVec.emplace_back(Symbol); - } - } - } - if (mVTables.size() == 0) { - return false; - } - std::sort(mVTables.begin(), mVTables.end()); - return true; -} - -template -void ELFSharedObject::getVFunctions() { - for (const SectionRef &Section : mRelSectionRefs) { - for (const RelocationRef &Relocation : Section.relocations()) { - VTable *VtPtr = identifyVTable(Relocation.getOffset()); - if (VtPtr != nullptr) { - relocateSym(Relocation, Section, VtPtr); - } - } - } -} - -template -VTable *ELFSharedObject::identifyVTable(uint64_t RelOffset) { - typename std::vector::iterator It; - It = std::lower_bound(mVTables.begin(), mVTables.end(), RelOffset); - if (It != mVTables.begin() && It->getStartAddr() != RelOffset) { - It--; - } - if (It->getStartAddr() <= RelOffset && It->getEndAddr() > RelOffset) { - return &(*It); - } - return nullptr; -} - -template -void ELFSharedObject::relocateSym( - const RelocationRef &Relocation, - const SectionRef &Section, - VTable *Vtablep) { - const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); - if (ElfHeader->e_machine == EM_MIPS) { - // bionic/linker/linker_mips.cpp , we handle only one type of - // relocation. Depending on if the symbol can be inferred from r_info we - // make it an absolute or a relative relocation. - if (!absoluteRelocation(Relocation, Vtablep)) { - relativeRelocation(Relocation, Section, Vtablep); - } - } else { - bool IsAbsoluteRelocation = false; - bool IsRelativeRelocation = false; - uint32_t RelocationType = Relocation.getType(); - switch (ElfHeader->e_machine) { - case EM_ARM: - IsAbsoluteRelocation = RelocationType == R_ARM_ABS32; - IsRelativeRelocation = RelocationType == R_ARM_RELATIVE; - break; - case EM_AARCH64: - IsAbsoluteRelocation = RelocationType == R_AARCH64_ABS64; - IsRelativeRelocation = RelocationType == R_AARCH64_RELATIVE; - break; - case EM_386: - IsAbsoluteRelocation = RelocationType == R_386_32; - IsRelativeRelocation = RelocationType == R_386_RELATIVE; - break; - case EM_X86_64: - IsAbsoluteRelocation = RelocationType == R_X86_64_64; - IsRelativeRelocation = RelocationType == R_X86_64_RELATIVE; - break; - default: - break; - } - // The return value is ignored since failure to relocate - // does not mean a fatal error. It might be that the dynsym / - // symbol-table does not have enough information to get the - // symbol name. Like-wise for absolute relocations. - if (IsAbsoluteRelocation) { - absoluteRelocation(Relocation, Vtablep); - } - if (IsRelativeRelocation) { - relativeRelocation(Relocation, Section, Vtablep); - } - } -} - -template -bool ELFSharedObject::absoluteRelocation( - const RelocationRef &Relocation, - VTable *Vtablep) { - symbol_iterator Symi = Relocation.getSymbol(); - if (Symi == mObj->symbol_end()) { - return false; - } - SymbolRef Symbol = *Symi; - uint64_t RelOffset = Relocation.getOffset(); - std::string SymbolName(UnWrap(Symbol.getName()).str()); - Vtablep->addVFunction(SymbolName, demangle(SymbolName), RelOffset); - return true; -} - -template -bool ELFSharedObject::relativeRelocation( - const RelocationRef &Relocation, - const SectionRef &Section, - VTable *Vtablep) { - uint64_t Addend = 0; - uint64_t RelOffset = Relocation.getOffset(); - if (mObj->getSection(Section.getRawDataRefImpl())->sh_type == SHT_RELA) { - const Elf_Rela *Rela = mObj->getRela(Relocation.getRawDataRefImpl()); - Addend = static_cast(Rela->r_addend); - } - - if (Addend == 0) { - Addend = identifyAddend(Relocation.getOffset()); - } - - std::map>::iterator It = - mAddrToSymbolRef.find(Addend); - if (It == mAddrToSymbolRef.end()) { - return false; - } - SymbolRef Symbol = matchValueToSymbol(It->second, Vtablep); - std::string SymbolName(UnWrap(Symbol.getName()).str()); - Vtablep->addVFunction(SymbolName, demangle(SymbolName), RelOffset); - return true; -} - -template -SymbolRef ELFSharedObject::matchValueToSymbol( - std::vector &SymVec, - VTable *Vtablep) { - constexpr size_t pos = sizeof("vtable for ") - 1; - const std::string ClassName(Vtablep->getDemangledName().substr(pos)); - for (const SymbolRef &Symbol : SymVec) { - StringRef SymbolName = UnWrap(Symbol.getName()); - if (demangle(SymbolName.str()).find(ClassName) != std::string::npos) { - return Symbol; - } - } - // Return the 1st Symbol by default. - return SymVec[0]; -} - -template -uint64_t ELFSharedObject::identifyAddend(uint64_t ROffset) { - for (const SectionRef &Section : mProgBitSectionRefs) { - uint64_t Begin = Section.getAddress(); - uint64_t End = Section.getAddress() + Section.getSize(); - if (ROffset >= Begin && ROffset < End) { - return getAddendFromSection(Section, ROffset - Begin); - } - } - return 0; -} - -template -uint64_t ELFSharedObject::getAddendFromSection( - const SectionRef &Section, - uint64_t Offset) { - StringRef Contents; - if (Section.getContents(Contents)) - return 0; - const unsigned char *Bytes = Contents.bytes_begin() + Offset; - uintX_t Addend = read(Bytes); - const Elf_Ehdr *ElfHeader = mObj->getELFFile()->getHeader(); - if (ElfHeader->e_machine == EM_ARM || - ElfHeader->e_machine == EM_MIPS) { - // Remove thumb flag as llvm suggests. - Addend &= ~1; - } - return static_cast(Addend); -} - -VFunction::VFunction( - const std::string &MangledName, - const std::string &DemangledName, - uint64_t VFunctionOffset) - : mMangledName(MangledName), - mDemangledName(DemangledName), - mOffset(VFunctionOffset) {} - -uint64_t VFunction::getOffset() const { - return mOffset; -} - -const std::string &VFunction::getDemangledName() const { - return mDemangledName; -} - -const std::string &VFunction::getMangledName() const { - return mMangledName; -} - -bool VFunction::operator<(const VFunction &Vfunction) const { - return mOffset < Vfunction.getOffset(); -} - -VTable::VTable( - const std::string &MangledName, - const std::string &DemangledName, - uint64_t Begin, - uint64_t End) - : mMangledName(MangledName), - mDemangledName(DemangledName), - mStartAddr(Begin), - mEndAddr(End), - mBaseOffset(Begin) {} - -void VTable::addVFunction( - const std::string &MangledName, - const std::string &DemangledName, - uint64_t RelOffset) { - mFunctions.emplace_back( - MangledName, - DemangledName, - RelOffset - mBaseOffset); -} - -const std::string &VTable::getDemangledName() const { - return mDemangledName; -} - -const std::string &VTable::getMangledName() const { - return mMangledName; -} - -uint64_t VTable::getStartAddr() const { - return mStartAddr; -} - -uint64_t VTable::getEndAddr() const { - return mEndAddr; -} - -uint64_t VTable::getBaseOffset() const { - return mBaseOffset; -} - -uint64_t VTable::getVTableSize() const { - return mFunctions.size(); -} - -VTable::func_iterator VTable::begin() const { - return mFunctions.cbegin(); -} - -VTable::func_iterator VTable::end() const { - return mFunctions.cend(); -} - -bool VTable::operator<(const VTable &Vtable) const { - return mStartAddr < Vtable.getStartAddr(); -} - -bool VTable::operator<(const uint64_t ROffset) const { - return mStartAddr < ROffset; -} - -void VTable::sortVFunctions() { - std::sort(mFunctions.begin(), mFunctions.end()); -} diff --git a/vndk/tools/vtable-dumper/elf_handling.h b/vndk/tools/vtable-dumper/elf_handling.h deleted file mode 100644 index 9ef91b429..000000000 --- a/vndk/tools/vtable-dumper/elf_handling.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ELF_HANDLING_H_ -#define ELF_HANDLING_H_ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -using llvm::object::ObjectFile; -using llvm::object::ELFObjectFile; -using llvm::object::SectionRef; -using llvm::object::RelocationRef; -using llvm::object::ELFFile; -using llvm::object::ELFType; -using llvm::object::ELFDataTypeTypedefHelper; -using llvm::object::SymbolRef; -using llvm::outs; - -class SharedObject { -public: - static std::unique_ptr create(const ObjectFile *); - /* Print mangled names if the argument is true; demangled if false. - */ - virtual void printVTables(bool) const = 0; - virtual ~SharedObject() = 0; -private: - virtual bool getVTables() = 0; -}; - -class VFunction { -public: - VFunction( - const std::string &, - const std::string &, - uint64_t); - - uint64_t getOffset() const; - bool operator<(const VFunction &) const; - const std::string &getMangledName() const; - const std::string &getDemangledName() const; -private: - std::string mMangledName; - std::string mDemangledName; - uint64_t mOffset; -}; - -class VTable { -public: - using func_iterator = std::vector::const_iterator; - VTable( - const std::string &, - const std::string &, - uint64_t, - uint64_t); - - uint64_t getStartAddr() const; - uint64_t getEndAddr() const; - uint64_t getBaseOffset() const; - uint64_t getVTableSize() const; - func_iterator begin() const; - func_iterator end() const; - const std::string &getMangledName() const; - const std::string &getDemangledName() const; - void sortVFunctions(); - void addVFunction( - const std::string &, - const std::string &, - uint64_t); - - bool operator<(const VTable &) const; - bool operator<(const uint64_t) const; -private: - std::vector mFunctions; - std::string mMangledName; - std::string mDemangledName; - /* This holds the range(st_value, st_value) through which the - * VTable spans. - */ - uint64_t mStartAddr; - uint64_t mEndAddr; - uint64_t mBaseOffset; -}; - -template -class ELFSharedObject : public SharedObject { -public: - void printVTables(bool) const override; - bool getVTables() override; - ~ELFSharedObject(); - ELFSharedObject(const ELFObjectFile *); - -private: - /* We need a sym value to SymbolRef map in case the relocation provides - * us with an addr instead of a sym index into dynsym / symtab. - */ - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) - typedef ELFFile ELFO; - typedef typename ELFO::Elf_Shdr Elf_Shdr; - typedef typename ELFO::Elf_Ehdr Elf_Ehdr; - typedef typename ELFO::Elf_Sym Elf_Sym; - typedef typename ELFO::Elf_Rela Elf_Rela; - typedef typename ELFO::uintX_t uintX_t; - std::map> mAddrToSymbolRef; - const ELFObjectFile *mObj; - /* We cache the relocation sections, to look through their relocations for - * vfunctions. Sections with type SHT_PROGBITS are cached since they contain - * vtables. We might need to peek at the contents of a vtable in cases of - * relative relocations. - */ - std::vector mRelSectionRefs; - std::vector mProgBitSectionRefs; - std::vector mVTables; - -private: - bool cacheELFSections(); - bool initVTableRanges(); - void getVFunctions(); - VTable *identifyVTable(uint64_t); - void relocateSym( - const RelocationRef &, - const SectionRef &, - VTable *); - - bool absoluteRelocation(const RelocationRef &, VTable *); - bool relativeRelocation( - const RelocationRef &, - const SectionRef &, - VTable *); - - uint64_t identifyAddend(uint64_t); - uint64_t getAddendFromSection(const SectionRef &, uint64_t); - SymbolRef matchValueToSymbol(std::vector &, VTable *); -}; - -template -static inline T UnWrap(llvm::Expected ValueOrError) { - if (!ValueOrError) { - outs() << "\nError: " - << llvm::toString(ValueOrError.takeError()) - << ".\n"; - outs().flush(); - exit(1); - } - return std::move(ValueOrError.get()); -} - - -#endif // ELF_HANDLING_H_ diff --git a/vndk/tools/vtable-dumper/tests/expected/arm/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/arm/libtest.so.txt deleted file mode 100644 index 24b0126f0..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/arm/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -8 (int (*)(...)) Alpha::getData(int*, int*, int) -12 (int (*)(...)) Alpha::~Alpha() -16 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -8 (int (*)(...)) Beta::getData(int*, int*, int) -12 (int (*)(...)) Beta::~Beta() -16 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -8 (int (*)(...)) Gamma::getData(int*, int*, int) -12 (int (*)(...)) Gamma::~Gamma() -16 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/expected/arm64/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/arm64/libtest.so.txt deleted file mode 100644 index 5a0ea37e9..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/arm64/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -16 (int (*)(...)) Alpha::getData(int*, int*, int) -24 (int (*)(...)) Alpha::~Alpha() -32 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -16 (int (*)(...)) Beta::getData(int*, int*, int) -24 (int (*)(...)) Beta::~Beta() -32 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -16 (int (*)(...)) Gamma::getData(int*, int*, int) -24 (int (*)(...)) Gamma::~Gamma() -32 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/expected/mips/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/mips/libtest.so.txt deleted file mode 100644 index 24b0126f0..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/mips/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -8 (int (*)(...)) Alpha::getData(int*, int*, int) -12 (int (*)(...)) Alpha::~Alpha() -16 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -8 (int (*)(...)) Beta::getData(int*, int*, int) -12 (int (*)(...)) Beta::~Beta() -16 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -8 (int (*)(...)) Gamma::getData(int*, int*, int) -12 (int (*)(...)) Gamma::~Gamma() -16 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/expected/mips64/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/mips64/libtest.so.txt deleted file mode 100644 index 5a0ea37e9..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/mips64/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -16 (int (*)(...)) Alpha::getData(int*, int*, int) -24 (int (*)(...)) Alpha::~Alpha() -32 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -16 (int (*)(...)) Beta::getData(int*, int*, int) -24 (int (*)(...)) Beta::~Beta() -32 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -16 (int (*)(...)) Gamma::getData(int*, int*, int) -24 (int (*)(...)) Gamma::~Gamma() -32 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/expected/x86/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/x86/libtest.so.txt deleted file mode 100644 index 24b0126f0..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/x86/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -8 (int (*)(...)) Alpha::getData(int*, int*, int) -12 (int (*)(...)) Alpha::~Alpha() -16 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -8 (int (*)(...)) Beta::getData(int*, int*, int) -12 (int (*)(...)) Beta::~Beta() -16 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -8 (int (*)(...)) Gamma::getData(int*, int*, int) -12 (int (*)(...)) Gamma::~Gamma() -16 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/expected/x86_64/libtest.so.txt b/vndk/tools/vtable-dumper/tests/expected/x86_64/libtest.so.txt deleted file mode 100644 index 5a0ea37e9..000000000 --- a/vndk/tools/vtable-dumper/tests/expected/x86_64/libtest.so.txt +++ /dev/null @@ -1,21 +0,0 @@ -vtable for Alpha -_ZTV5Alpha: 3 entries -16 (int (*)(...)) Alpha::getData(int*, int*, int) -24 (int (*)(...)) Alpha::~Alpha() -32 (int (*)(...)) Alpha::~Alpha() - - -vtable for Beta -_ZTV4Beta: 3 entries -16 (int (*)(...)) Beta::getData(int*, int*, int) -24 (int (*)(...)) Beta::~Beta() -32 (int (*)(...)) Beta::~Beta() - - -vtable for Gamma -_ZTV5Gamma: 3 entries -16 (int (*)(...)) Gamma::getData(int*, int*, int) -24 (int (*)(...)) Gamma::~Gamma() -32 (int (*)(...)) Gamma::~Gamma() - - diff --git a/vndk/tools/vtable-dumper/tests/test1.cpp b/vndk/tools/vtable-dumper/tests/test1.cpp deleted file mode 100644 index 606cd9836..000000000 --- a/vndk/tools/vtable-dumper/tests/test1.cpp +++ /dev/null @@ -1,32 +0,0 @@ -class Alpha { -public: - virtual void getData(int *src, int *dst, int data); - virtual ~Alpha() {}; -private: - int mPdata = 0; -}; - -class Beta : public Alpha { -public: - Beta(int data) : mCdata(data) {} - virtual void getData(int *src, int *dst, int data); - virtual ~Beta() {}; -private: - int mCdata = 1; -}; - -class Gamma : public Beta { -public: - Gamma(int data) : mGCdata(data), Beta(data) {} - virtual void getData(int *src, int *dst, int data); - virtual ~Gamma() {}; -private: - int mGCdata = 2; -}; - -void Alpha::getData(int *src, int *dst, int data) {} - -void Beta::getData(int *src, int *dst, int data) {} - -void Gamma::getData(int *src, int *dst, int data) {} - diff --git a/vndk/tools/vtable-dumper/tests/test_vndk_vtable_dumper.py b/vndk/tools/vtable-dumper/tests/test_vndk_vtable_dumper.py deleted file mode 100755 index c08e22948..000000000 --- a/vndk/tools/vtable-dumper/tests/test_vndk_vtable_dumper.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import collections -import difflib -import os -import subprocess -import sys -import tempfile - -"""Test vndk vtable dumper""" - -NDK_VERSION = 'r16' -API_LEVEL = 'android-24' - -LLVM_PREBUILTS_VERSION = 'clang-4691093' - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) -VNDK_VTABLE_DUMPER = 'vndk-vtable-dumper' - -def get_dirnames(path, n): - """Get directory, n directories before path""" - for i in range(n): - path = os.path.dirname(path) - return path - - -def get_prebuilts_host(): - """Get the host dir for prebuilts""" - if sys.platform.startswith('linux'): - return 'linux-x86' - if sys.platform.startswith('darwin'): - return 'darwin-x86' - raise NotImplementedError('unknown platform') - - -def get_prebuilts_gcc(android_build_top, arch, gcc_version): - """Get the path to gcc for the current platform""" - return os.path.join(android_build_top, 'prebuilts', 'gcc', - get_prebuilts_host(), arch, gcc_version) - -def get_prebuilts_clang(android_build_top): - """Get the path to prebuilt gcc for the current platform""" - return os.path.join(android_build_top, 'prebuilts', 'clang', 'host', - get_prebuilts_host(), LLVM_PREBUILTS_VERSION) - -def get_prebuilts_ndk(android_build_top, subdirs): - """Get the path to prebuilt ndk for the current platform and API level""" - return os.path.join(android_build_top, 'prebuilts', 'ndk', NDK_VERSION, - 'platforms', API_LEVEL, *subdirs) - -def run_cmd(cmd, verbose=False): - """Run the command given and print the command if verbose is True""" - if verbose: - print('RUN:', ' '.join(cmd), file=sys.stderr) - subprocess.check_call(cmd) - - -def run_output(cmd, verbose=False): - """Run the command given and print output of the command""" - if verbose: - print('RUN:', ' '.join(cmd), file=sys.stderr) - return subprocess.check_output(cmd, universal_newlines=True) - - -def run_vtable_dump(path, verbose=False): - """Run vndk vtable dumper""" - return run_output([VNDK_VTABLE_DUMPER, path], verbose) - - -class Target(object): - """Class representing a target: for eg: x86, arm64 etc""" - def __init__(self, name, triple, cflags, ldflags, gcc_toolchain_dir, - clang_dir, ndk_include, ndk_lib): - """Parameterized Constructor""" - self.name = name - self.target_triple = triple - self.target_cflags = cflags - self.target_ldflags = ldflags - - self.gcc_toolchain_dir = gcc_toolchain_dir - self.clang_dir = clang_dir - self.ndk_include = ndk_include - self.ndk_lib = ndk_lib - - def compile(self, obj_file, src_file, cflags, verbose=False): - """Compiles the given source files and produces a .o at obj_file""" - clangpp = os.path.join(self.clang_dir, 'bin', 'clang++') - - cmd = [clangpp, '-o', obj_file, '-c', src_file] - cmd.extend(['-fPIE', '-fPIC', '-fno-rtti', '-std=c++11']) - cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir]) - cmd.extend(['-target', self.target_triple]) - cmd.extend(['-isystem', self.ndk_include]) - cmd.extend(cflags) - cmd.extend(self.target_cflags) - run_cmd(cmd, verbose) - - def link(self, out_file, obj_files, ldflags, verbose=False): - """Link the given obj files to form a shared library""" - crtbegin = os.path.join(self.ndk_lib, 'crtbegin_so.o') - crtend = os.path.join(self.ndk_lib, 'crtend_so.o') - clangpp = os.path.join(self.clang_dir, 'bin', 'clang++') - - cmd = [clangpp, '-o', out_file] - cmd.extend(['-fPIE', '-fPIC', '-fno-rtti', '-Wl,--no-undefined', '-nostdlib']) - cmd.append('-L' + self.ndk_lib) - cmd.extend(['-gcc-toolchain', self.gcc_toolchain_dir]) - cmd.extend(['-target', self.target_triple]) - cmd.append(crtbegin) - cmd.extend(obj_files) - cmd.append(crtend) - cmd.extend(ldflags) - cmd.extend(self.target_ldflags) - run_cmd(cmd, verbose) - - -def create_targets(top): - """Create multiple targets objects, one for each architecture supported""" - return [ - Target('arm', 'arm-linux-androideabi', [],[], - get_prebuilts_gcc(top, 'arm', 'arm-linux-androideabi-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-arm', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-arm', 'usr', 'lib'])), - - Target('arm64', 'aarch64-linux-android', [], [], - get_prebuilts_gcc(top, 'aarch64', 'aarch64-linux-android-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-arm64', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-arm64', 'usr', 'lib'])), - - Target('mips', 'mipsel-linux-android', [], [], - get_prebuilts_gcc(top, 'mips', 'mips64el-linux-android-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-mips', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-mips', 'usr', 'lib'])), - - Target('mips64', 'mips64el-linux-android', - ['-march=mips64el', '-mcpu=mips64r6'], - ['-march=mips64el', '-mcpu=mips64r6'], - get_prebuilts_gcc(top, 'mips', 'mips64el-linux-android-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-mips64', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-mips64', 'usr', 'lib64'])), - - Target('x86', 'x86_64-linux-android', ['-m32'], ['-m32'], - get_prebuilts_gcc(top, 'x86', 'x86_64-linux-android-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-x86', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-x86', 'usr', 'lib'])), - - Target('x86_64', 'x86_64-linux-android', ['-m64'], ['-m64'], - get_prebuilts_gcc(top, 'x86', 'x86_64-linux-android-4.9'), - get_prebuilts_clang(top), - get_prebuilts_ndk(top, ['arch-x86_64', 'usr', 'include']), - get_prebuilts_ndk(top, ['arch-x86_64', 'usr', 'lib64'])), - ] - - -class TestRunner(object): - """Class to run the test""" - def __init__(self, expected_dir, test_dir, verbose): - """Parameterized constructor""" - self.expected_dir = expected_dir - self.test_dir = test_dir - self.verbose = verbose - self.num_errors = 0 - - def check_output(self, expected_file_path, actual): - """Compare the output of the test run and the expected output""" - actual = actual.splitlines(True) - with open(expected_file_path, 'r') as f: - expected = f.readlines() - if actual == expected: - return - for line in difflib.context_diff(expected, actual, - fromfile=expected_file_path, - tofile='actual'): - sys.stderr.write(line) - self.num_errors += 1 - - def run_test_for_target(self, target): - """Run the test for a specific target""" - print('Testing target', target.name, '...', file=sys.stderr) - - expected_dir = os.path.join(self.expected_dir, target.name) - - # Create test directory for this target. - test_dir = os.path.join(self.test_dir, target.name) - os.makedirs(test_dir, exist_ok=True) - - # Compile and test "libtest.so". - src_file = os.path.join(SCRIPT_DIR, 'test1.cpp') - obj_file = os.path.join(test_dir, 'test.o') - target.compile(obj_file, src_file, [], self.verbose) - - out_file = os.path.join(test_dir, 'libtest.so') - target.link(out_file, [obj_file], - ['-shared', '-lc', '-lgcc', '-lstdc++'], - self.verbose) - self.check_output(os.path.join(expected_dir, 'libtest.so.txt'), - run_vtable_dump(out_file, self.verbose)) - - def run_test(self, targets): - """Run test fo all targets""" - for target in targets: - self.run_test_for_target(target) - - -def main(): - """ Set up and run test""" - # Parse command line arguments. - parser = argparse.ArgumentParser() - parser.add_argument('--verbose', '-v', action='store_true') - parser.add_argument('--android-build-top', help='path to android build top') - parser.add_argument('--test-dir', - help='directory for temporary files') - parser.add_argument('--expected-dir', help='directory with expected output') - args = parser.parse_args() - - # Find ${ANDROID_BUILD_TOP}. - if args.android_build_top: - android_build_top = args.android_build_top - else: - android_build_top = get_dirnames(SCRIPT_DIR, 5) - - # Find expected output directory. - if args.expected_dir: - expected_dir = args.expected_dir - else: - expected_dir = os.path.join(SCRIPT_DIR, 'expected') - - # Load compilation targets. - targets = create_targets(android_build_top) - - # Run tests. - if args.test_dir: - os.makedirs(args.test_dir, exist_ok=True) - runner = TestRunner(expected_dir, args.test_dir, args.verbose) - runner.run_test(targets) - else: - with tempfile.TemporaryDirectory() as test_dir: - runner = TestRunner(expected_dir, test_dir, args.verbose) - runner.run_test(targets) - - if runner.num_errors: - print('FAILED:', runner.num_errors, 'test(s) failed', file=sys.stderr) - else: - print('SUCCESS', file=sys.stderr) - - return 1 if runner.num_errors else 0 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/vndk/tools/vtable-dumper/vndk_vtable_dumper.cpp b/vndk/tools/vtable-dumper/vndk_vtable_dumper.cpp deleted file mode 100644 index 0f79c2dab..000000000 --- a/vndk/tools/vtable-dumper/vndk_vtable_dumper.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "elf_handling.h" - -#include - -using llvm::Expected; -using llvm::StringMapEntry; -using llvm::cl::Hidden; -using llvm::cl::Option; -using llvm::cl::OptionCategory; -using llvm::cl::ParseCommandLineOptions; -using llvm::cl::Positional; -using llvm::cl::Required; -using llvm::cl::SetVersionPrinter; -using llvm::cl::cat; -using llvm::cl::desc; -using llvm::cl::getRegisteredOptions; -using llvm::cl::opt; -using llvm::dyn_cast; -using llvm::object::ObjectFile; -using llvm::object::OwningBinary; -using llvm::outs; - -OptionCategory VTableDumperCategory("vndk-vtable-dumper options"); - -opt FilePath( - Positional, Required, cat(VTableDumperCategory), - desc("shared_library.so")); - -opt Mangled( - "mangled", cat(VTableDumperCategory), - desc("Show mangled symbol names")); - -static void HideIrrelevantCommandLineOptions() { - for (StringMapEntry