forked from OSchip/llvm-project
[Object] Add tapi files to object
Summary: The intention for this is to allow reading and printing symbols out from llvm-nm. Tapi file, and Tapi universal follow a similiar format to their respective MachO Object format. The tests are dependent on llvm-nm processing tbd files which is why its in D66160 Reviewers: ributzka, steven_wu, lhames Reviewed By: ributzka, lhames Subscribers: mgorny, hiraditya, dexonsmith, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66159 llvm-svn: 369600
This commit is contained in:
parent
78e6507b0a
commit
c20d1f90b5
|
@ -42,7 +42,9 @@ protected:
|
|||
ID_Archive,
|
||||
ID_MachOUniversalBinary,
|
||||
ID_COFFImportFile,
|
||||
ID_IR, // LLVM IR
|
||||
ID_IR, // LLVM IR
|
||||
ID_TapiUniversal, // Text-based Dynamic Library Stub file.
|
||||
ID_TapiFile, // Text-based Dynamic Library Stub file.
|
||||
|
||||
ID_Minidump,
|
||||
|
||||
|
@ -101,16 +103,18 @@ public:
|
|||
return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
|
||||
}
|
||||
|
||||
bool isSymbolic() const { return isIR() || isObject() || isCOFFImportFile(); }
|
||||
|
||||
bool isArchive() const {
|
||||
return TypeID == ID_Archive;
|
||||
bool isSymbolic() const {
|
||||
return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
|
||||
}
|
||||
|
||||
bool isArchive() const { return TypeID == ID_Archive; }
|
||||
|
||||
bool isMachOUniversalBinary() const {
|
||||
return TypeID == ID_MachOUniversalBinary;
|
||||
}
|
||||
|
||||
bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
|
||||
|
||||
bool isELF() const {
|
||||
return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
|
||||
}
|
||||
|
@ -137,6 +141,8 @@ public:
|
|||
|
||||
bool isMinidump() const { return TypeID == ID_Minidump; }
|
||||
|
||||
bool isTapiFile() const { return TypeID == ID_TapiFile; }
|
||||
|
||||
bool isLittleEndian() const {
|
||||
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
|
||||
TypeID == ID_MachO32B || TypeID == ID_MachO64B);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
//===- TapiFile.h - Text-based Dynamic Library Stub -------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the TapiFile interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_OBJECT_TAPI_FILE_H
|
||||
#define LLVM_OBJECT_TAPI_FILE_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/TextAPI/MachO/InterfaceFile.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
|
||||
class TapiFile : public SymbolicFile {
|
||||
public:
|
||||
TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface,
|
||||
MachO::Architecture Arch);
|
||||
~TapiFile() override;
|
||||
|
||||
void moveSymbolNext(DataRefImpl &DRI) const override;
|
||||
|
||||
Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override;
|
||||
|
||||
uint32_t getSymbolFlags(DataRefImpl DRI) const override;
|
||||
|
||||
basic_symbol_iterator symbol_begin() const override;
|
||||
|
||||
basic_symbol_iterator symbol_end() const override;
|
||||
|
||||
static bool classof(const Binary *v) { return v->isTapiFile(); }
|
||||
|
||||
private:
|
||||
struct Symbol {
|
||||
StringRef Prefix;
|
||||
StringRef Name;
|
||||
uint32_t Flags;
|
||||
|
||||
constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags)
|
||||
: Prefix(Prefix), Name(Name), Flags(Flags) {}
|
||||
};
|
||||
|
||||
std::vector<Symbol> Symbols;
|
||||
};
|
||||
|
||||
} // end namespace object.
|
||||
} // end namespace llvm.
|
||||
|
||||
#endif // LLVM_OBJECT_TAPI_FILE_H
|
|
@ -0,0 +1,109 @@
|
|||
//===-- TapiUniversal.h - Text-based Dynamic Library Stub -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the TapiUniversal interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_OBJECT_TAPI_UNIVERSAL_H
|
||||
#define LLVM_OBJECT_TAPI_UNIVERSAL_H
|
||||
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/TapiFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/TextAPI/MachO/Architecture.h"
|
||||
#include "llvm/TextAPI/MachO/InterfaceFile.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
|
||||
class TapiUniversal : public Binary {
|
||||
public:
|
||||
class ObjectForArch {
|
||||
const TapiUniversal *Parent;
|
||||
int Index;
|
||||
|
||||
public:
|
||||
ObjectForArch(const TapiUniversal *Parent, int Index)
|
||||
: Parent(Parent), Index(Index) {}
|
||||
|
||||
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
|
||||
|
||||
bool operator==(const ObjectForArch &Other) const {
|
||||
return (Parent == Other.Parent) && (Index == Other.Index);
|
||||
}
|
||||
|
||||
uint32_t getCPUType() const {
|
||||
auto Result =
|
||||
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]);
|
||||
return Result.first;
|
||||
}
|
||||
|
||||
uint32_t getCPUSubType() const {
|
||||
auto Result =
|
||||
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]);
|
||||
return Result.second;
|
||||
}
|
||||
|
||||
std::string getArchFlagName() const {
|
||||
return MachO::getArchitectureName(Parent->Architectures[Index]);
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const;
|
||||
};
|
||||
|
||||
class object_iterator {
|
||||
ObjectForArch Obj;
|
||||
|
||||
public:
|
||||
object_iterator(const ObjectForArch &Obj) : Obj(Obj) {}
|
||||
const ObjectForArch *operator->() const { return &Obj; }
|
||||
const ObjectForArch &operator*() const { return Obj; }
|
||||
|
||||
bool operator==(const object_iterator &Other) const {
|
||||
return Obj == Other.Obj;
|
||||
}
|
||||
bool operator!=(const object_iterator &Other) const {
|
||||
return !(*this == Other);
|
||||
}
|
||||
|
||||
object_iterator &operator++() { // Preincrement
|
||||
Obj = Obj.getNext();
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
TapiUniversal(MemoryBufferRef Source, Error &Err);
|
||||
static Expected<std::unique_ptr<TapiUniversal>>
|
||||
create(MemoryBufferRef Source);
|
||||
~TapiUniversal() override;
|
||||
|
||||
object_iterator begin_objects() const { return ObjectForArch(this, 0); }
|
||||
object_iterator end_objects() const {
|
||||
return ObjectForArch(this, Architectures.size());
|
||||
}
|
||||
|
||||
iterator_range<object_iterator> objects() const {
|
||||
return make_range(begin_objects(), end_objects());
|
||||
}
|
||||
|
||||
uint32_t getNumberOfObjects() const { return Architectures.size(); }
|
||||
|
||||
// Cast methods.
|
||||
static bool classof(const Binary *v) { return v->isTapiUniversal(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<MachO::InterfaceFile> ParsedFile;
|
||||
std::vector<MachO::Architecture> Architectures;
|
||||
};
|
||||
|
||||
} // end namespace object.
|
||||
} // end namespace llvm.
|
||||
|
||||
#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/Object/MachOUniversal.h"
|
||||
#include "llvm/Object/Minidump.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Object/TapiUniversal.h"
|
||||
#include "llvm/Object/WindowsResource.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
@ -87,8 +88,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
|
|||
case file_magic::minidump:
|
||||
return MinidumpFile::create(Buffer);
|
||||
case file_magic::tapi_file:
|
||||
// Placeholder until TAPI is supported for lib/Object
|
||||
return errorCodeToError(object_error::invalid_file_type);
|
||||
return TapiUniversal::create(Buffer);
|
||||
}
|
||||
llvm_unreachable("Unexpected Binary File Type");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ add_llvm_library(LLVMObject
|
|||
RelocationResolver.cpp
|
||||
SymbolicFile.cpp
|
||||
SymbolSize.cpp
|
||||
TapiFile.cpp
|
||||
TapiUniversal.cpp
|
||||
WasmObjectFile.cpp
|
||||
WindowsMachineFlag.cpp
|
||||
WindowsResource.cpp
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
type = Library
|
||||
name = Object
|
||||
parent = Libraries
|
||||
required_libraries = BitReader Core MC BinaryFormat MCParser Support
|
||||
required_libraries = BitReader Core MC BinaryFormat MCParser Support TextAPI
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
//===- TapiFile.cpp -------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the Text-based Dynamcic Library Stub format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Object/TapiFile.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace MachO;
|
||||
using namespace object;
|
||||
|
||||
static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
|
||||
static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
|
||||
static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
|
||||
static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
|
||||
static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
|
||||
|
||||
static uint32_t getFlags(const Symbol *Sym) {
|
||||
uint32_t Flags = BasicSymbolRef::SF_Global;
|
||||
if (Sym->isUndefined())
|
||||
Flags |= BasicSymbolRef::SF_Undefined;
|
||||
else
|
||||
Flags |= BasicSymbolRef::SF_Exported;
|
||||
|
||||
if (Sym->isWeakDefined() || Sym->isWeakReferenced())
|
||||
Flags |= BasicSymbolRef::SF_Weak;
|
||||
|
||||
return Flags;
|
||||
}
|
||||
|
||||
TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
|
||||
Architecture Arch)
|
||||
: SymbolicFile(ID_TapiFile, Source) {
|
||||
for (const auto *Symbol : interface.symbols()) {
|
||||
if (!Symbol->getArchitectures().has(Arch))
|
||||
continue;
|
||||
|
||||
auto PlatformKind = interface.getPlatform();
|
||||
switch (Symbol->getKind()) {
|
||||
case SymbolKind::GlobalSymbol:
|
||||
Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
|
||||
break;
|
||||
case SymbolKind::ObjectiveCClass:
|
||||
if (PlatformKind == PlatformKind::macOS && Arch == AK_i386) {
|
||||
Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
|
||||
getFlags(Symbol));
|
||||
} else {
|
||||
Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
|
||||
getFlags(Symbol));
|
||||
Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
|
||||
getFlags(Symbol));
|
||||
}
|
||||
break;
|
||||
case SymbolKind::ObjectiveCClassEHType:
|
||||
Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
|
||||
getFlags(Symbol));
|
||||
break;
|
||||
case SymbolKind::ObjectiveCInstanceVariable:
|
||||
Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
|
||||
getFlags(Symbol));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TapiFile::~TapiFile() = default;
|
||||
|
||||
void TapiFile::moveSymbolNext(DataRefImpl &DRI) const {
|
||||
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
|
||||
DRI.p = reinterpret_cast<uintptr_t>(++Sym);
|
||||
}
|
||||
|
||||
Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
|
||||
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
|
||||
OS << Sym->Prefix << Sym->Name;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const {
|
||||
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
|
||||
return Sym->Flags;
|
||||
}
|
||||
|
||||
basic_symbol_iterator TapiFile::symbol_begin() const {
|
||||
DataRefImpl DRI;
|
||||
DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.begin());
|
||||
return BasicSymbolRef{DRI, this};
|
||||
}
|
||||
|
||||
basic_symbol_iterator TapiFile::symbol_end() const {
|
||||
DataRefImpl DRI;
|
||||
DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.end());
|
||||
return BasicSymbolRef{DRI, this};
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//===- TapiUniversal.cpp --------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the Text-based Dynamic Library Stub format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Object/TapiUniversal.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/TextAPI/MachO/TextAPIReader.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace MachO;
|
||||
using namespace object;
|
||||
|
||||
TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err)
|
||||
: Binary(ID_TapiUniversal, Source) {
|
||||
auto Result = TextAPIReader::get(Source);
|
||||
ErrorAsOutParameter ErrAsOuParam(&Err);
|
||||
if (!Result) {
|
||||
Err = Result.takeError();
|
||||
return;
|
||||
}
|
||||
ParsedFile = std::move(Result.get());
|
||||
|
||||
auto Archs = ParsedFile->getArchitectures();
|
||||
for (auto Arch : Archs)
|
||||
Architectures.emplace_back(Arch);
|
||||
}
|
||||
|
||||
TapiUniversal::~TapiUniversal() = default;
|
||||
|
||||
Expected<std::unique_ptr<TapiFile>>
|
||||
TapiUniversal::ObjectForArch::getAsObjectFile() const {
|
||||
return std::unique_ptr<TapiFile>(new TapiFile(Parent->getMemoryBufferRef(),
|
||||
*Parent->ParsedFile.get(),
|
||||
Parent->Architectures[Index]));
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<TapiUniversal>>
|
||||
TapiUniversal::create(MemoryBufferRef Source) {
|
||||
Error Err = Error::success();
|
||||
std::unique_ptr<TapiUniversal> Ret(new TapiUniversal(Source, Err));
|
||||
if (Err)
|
||||
return std::move(Err);
|
||||
return std::move(Ret);
|
||||
}
|
Loading…
Reference in New Issue