Skip to content

Commit c20d1f9

Browse files
committed
[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
1 parent 78e6507 commit c20d1f9

File tree

8 files changed

+343
-8
lines changed

8 files changed

+343
-8
lines changed

llvm/include/llvm/Object/Binary.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class Binary {
4242
ID_Archive,
4343
ID_MachOUniversalBinary,
4444
ID_COFFImportFile,
45-
ID_IR, // LLVM IR
45+
ID_IR, // LLVM IR
46+
ID_TapiUniversal, // Text-based Dynamic Library Stub file.
47+
ID_TapiFile, // Text-based Dynamic Library Stub file.
4648

4749
ID_Minidump,
4850

@@ -101,16 +103,18 @@ class Binary {
101103
return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
102104
}
103105

104-
bool isSymbolic() const { return isIR() || isObject() || isCOFFImportFile(); }
105-
106-
bool isArchive() const {
107-
return TypeID == ID_Archive;
106+
bool isSymbolic() const {
107+
return isIR() || isObject() || isCOFFImportFile() || isTapiFile();
108108
}
109109

110+
bool isArchive() const { return TypeID == ID_Archive; }
111+
110112
bool isMachOUniversalBinary() const {
111113
return TypeID == ID_MachOUniversalBinary;
112114
}
113115

116+
bool isTapiUniversal() const { return TypeID == ID_TapiUniversal; }
117+
114118
bool isELF() const {
115119
return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B;
116120
}
@@ -137,6 +141,8 @@ class Binary {
137141

138142
bool isMinidump() const { return TypeID == ID_Minidump; }
139143

144+
bool isTapiFile() const { return TypeID == ID_TapiFile; }
145+
140146
bool isLittleEndian() const {
141147
return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B ||
142148
TypeID == ID_MachO32B || TypeID == ID_MachO64B);

llvm/include/llvm/Object/TapiFile.h

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===- TapiFile.h - Text-based Dynamic Library Stub -------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file declares the TapiFile interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_OBJECT_TAPI_FILE_H
14+
#define LLVM_OBJECT_TAPI_FILE_H
15+
16+
#include "llvm/ADT/StringRef.h"
17+
#include "llvm/ADT/iterator_range.h"
18+
#include "llvm/Object/SymbolicFile.h"
19+
#include "llvm/Support/Error.h"
20+
#include "llvm/Support/MemoryBuffer.h"
21+
#include "llvm/TextAPI/MachO/InterfaceFile.h"
22+
23+
namespace llvm {
24+
namespace object {
25+
26+
class TapiFile : public SymbolicFile {
27+
public:
28+
TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface,
29+
MachO::Architecture Arch);
30+
~TapiFile() override;
31+
32+
void moveSymbolNext(DataRefImpl &DRI) const override;
33+
34+
Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override;
35+
36+
uint32_t getSymbolFlags(DataRefImpl DRI) const override;
37+
38+
basic_symbol_iterator symbol_begin() const override;
39+
40+
basic_symbol_iterator symbol_end() const override;
41+
42+
static bool classof(const Binary *v) { return v->isTapiFile(); }
43+
44+
private:
45+
struct Symbol {
46+
StringRef Prefix;
47+
StringRef Name;
48+
uint32_t Flags;
49+
50+
constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags)
51+
: Prefix(Prefix), Name(Name), Flags(Flags) {}
52+
};
53+
54+
std::vector<Symbol> Symbols;
55+
};
56+
57+
} // end namespace object.
58+
} // end namespace llvm.
59+
60+
#endif // LLVM_OBJECT_TAPI_FILE_H
+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//===-- TapiUniversal.h - Text-based Dynamic Library Stub -------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file declares the TapiUniversal interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_OBJECT_TAPI_UNIVERSAL_H
14+
#define LLVM_OBJECT_TAPI_UNIVERSAL_H
15+
16+
#include "llvm/Object/Binary.h"
17+
#include "llvm/Object/TapiFile.h"
18+
#include "llvm/Support/Error.h"
19+
#include "llvm/Support/MemoryBuffer.h"
20+
#include "llvm/TextAPI/MachO/Architecture.h"
21+
#include "llvm/TextAPI/MachO/InterfaceFile.h"
22+
23+
namespace llvm {
24+
namespace object {
25+
26+
class TapiUniversal : public Binary {
27+
public:
28+
class ObjectForArch {
29+
const TapiUniversal *Parent;
30+
int Index;
31+
32+
public:
33+
ObjectForArch(const TapiUniversal *Parent, int Index)
34+
: Parent(Parent), Index(Index) {}
35+
36+
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
37+
38+
bool operator==(const ObjectForArch &Other) const {
39+
return (Parent == Other.Parent) && (Index == Other.Index);
40+
}
41+
42+
uint32_t getCPUType() const {
43+
auto Result =
44+
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]);
45+
return Result.first;
46+
}
47+
48+
uint32_t getCPUSubType() const {
49+
auto Result =
50+
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]);
51+
return Result.second;
52+
}
53+
54+
std::string getArchFlagName() const {
55+
return MachO::getArchitectureName(Parent->Architectures[Index]);
56+
}
57+
58+
Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const;
59+
};
60+
61+
class object_iterator {
62+
ObjectForArch Obj;
63+
64+
public:
65+
object_iterator(const ObjectForArch &Obj) : Obj(Obj) {}
66+
const ObjectForArch *operator->() const { return &Obj; }
67+
const ObjectForArch &operator*() const { return Obj; }
68+
69+
bool operator==(const object_iterator &Other) const {
70+
return Obj == Other.Obj;
71+
}
72+
bool operator!=(const object_iterator &Other) const {
73+
return !(*this == Other);
74+
}
75+
76+
object_iterator &operator++() { // Preincrement
77+
Obj = Obj.getNext();
78+
return *this;
79+
}
80+
};
81+
82+
TapiUniversal(MemoryBufferRef Source, Error &Err);
83+
static Expected<std::unique_ptr<TapiUniversal>>
84+
create(MemoryBufferRef Source);
85+
~TapiUniversal() override;
86+
87+
object_iterator begin_objects() const { return ObjectForArch(this, 0); }
88+
object_iterator end_objects() const {
89+
return ObjectForArch(this, Architectures.size());
90+
}
91+
92+
iterator_range<object_iterator> objects() const {
93+
return make_range(begin_objects(), end_objects());
94+
}
95+
96+
uint32_t getNumberOfObjects() const { return Architectures.size(); }
97+
98+
// Cast methods.
99+
static bool classof(const Binary *v) { return v->isTapiUniversal(); }
100+
101+
private:
102+
std::unique_ptr<MachO::InterfaceFile> ParsedFile;
103+
std::vector<MachO::Architecture> Architectures;
104+
};
105+
106+
} // end namespace object.
107+
} // end namespace llvm.
108+
109+
#endif // LLVM_OBJECT_TAPI_UNIVERSAL_H

llvm/lib/Object/Binary.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/Object/MachOUniversal.h"
1919
#include "llvm/Object/Minidump.h"
2020
#include "llvm/Object/ObjectFile.h"
21+
#include "llvm/Object/TapiUniversal.h"
2122
#include "llvm/Object/WindowsResource.h"
2223
#include "llvm/Support/Error.h"
2324
#include "llvm/Support/ErrorHandling.h"
@@ -87,8 +88,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
8788
case file_magic::minidump:
8889
return MinidumpFile::create(Buffer);
8990
case file_magic::tapi_file:
90-
// Placeholder until TAPI is supported for lib/Object
91-
return errorCodeToError(object_error::invalid_file_type);
91+
return TapiUniversal::create(Buffer);
9292
}
9393
llvm_unreachable("Unexpected Binary File Type");
9494
}

llvm/lib/Object/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ add_llvm_library(LLVMObject
2121
RelocationResolver.cpp
2222
SymbolicFile.cpp
2323
SymbolSize.cpp
24+
TapiFile.cpp
25+
TapiUniversal.cpp
2426
WasmObjectFile.cpp
2527
WindowsMachineFlag.cpp
2628
WindowsResource.cpp

llvm/lib/Object/LLVMBuild.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
type = Library
1919
name = Object
2020
parent = Libraries
21-
required_libraries = BitReader Core MC BinaryFormat MCParser Support
21+
required_libraries = BitReader Core MC BinaryFormat MCParser Support TextAPI

llvm/lib/Object/TapiFile.cpp

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===- TapiFile.cpp -------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the Text-based Dynamcic Library Stub format.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/Object/TapiFile.h"
14+
#include "llvm/ADT/StringRef.h"
15+
#include "llvm/Object/Error.h"
16+
#include "llvm/Support/MemoryBuffer.h"
17+
18+
using namespace llvm;
19+
using namespace MachO;
20+
using namespace object;
21+
22+
static constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
23+
static constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
24+
static constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
25+
static constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
26+
static constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
27+
28+
static uint32_t getFlags(const Symbol *Sym) {
29+
uint32_t Flags = BasicSymbolRef::SF_Global;
30+
if (Sym->isUndefined())
31+
Flags |= BasicSymbolRef::SF_Undefined;
32+
else
33+
Flags |= BasicSymbolRef::SF_Exported;
34+
35+
if (Sym->isWeakDefined() || Sym->isWeakReferenced())
36+
Flags |= BasicSymbolRef::SF_Weak;
37+
38+
return Flags;
39+
}
40+
41+
TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
42+
Architecture Arch)
43+
: SymbolicFile(ID_TapiFile, Source) {
44+
for (const auto *Symbol : interface.symbols()) {
45+
if (!Symbol->getArchitectures().has(Arch))
46+
continue;
47+
48+
auto PlatformKind = interface.getPlatform();
49+
switch (Symbol->getKind()) {
50+
case SymbolKind::GlobalSymbol:
51+
Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
52+
break;
53+
case SymbolKind::ObjectiveCClass:
54+
if (PlatformKind == PlatformKind::macOS && Arch == AK_i386) {
55+
Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
56+
getFlags(Symbol));
57+
} else {
58+
Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
59+
getFlags(Symbol));
60+
Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
61+
getFlags(Symbol));
62+
}
63+
break;
64+
case SymbolKind::ObjectiveCClassEHType:
65+
Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
66+
getFlags(Symbol));
67+
break;
68+
case SymbolKind::ObjectiveCInstanceVariable:
69+
Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
70+
getFlags(Symbol));
71+
break;
72+
}
73+
}
74+
}
75+
76+
TapiFile::~TapiFile() = default;
77+
78+
void TapiFile::moveSymbolNext(DataRefImpl &DRI) const {
79+
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
80+
DRI.p = reinterpret_cast<uintptr_t>(++Sym);
81+
}
82+
83+
Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
84+
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
85+
OS << Sym->Prefix << Sym->Name;
86+
return Error::success();
87+
}
88+
89+
uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const {
90+
const auto *Sym = reinterpret_cast<const Symbol *>(DRI.p);
91+
return Sym->Flags;
92+
}
93+
94+
basic_symbol_iterator TapiFile::symbol_begin() const {
95+
DataRefImpl DRI;
96+
DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.begin());
97+
return BasicSymbolRef{DRI, this};
98+
}
99+
100+
basic_symbol_iterator TapiFile::symbol_end() const {
101+
DataRefImpl DRI;
102+
DRI.p = reinterpret_cast<uintptr_t>(&*Symbols.end());
103+
return BasicSymbolRef{DRI, this};
104+
}

0 commit comments

Comments
 (0)