Skip to content

Commit bc85cf1

Browse files
committed
[TextAPI] Add support for TBDv5 Files to nm & tapi-diff
This includes handling of new attributes for symbols & rpath. In the event that an older format file is compared to tbd_v5, ignore these new attributes. Reviewed By: ributzka Differential Revision: https://reviews.llvm.org/D144529
1 parent 471c0e0 commit bc85cf1

File tree

13 files changed

+259
-49
lines changed

13 files changed

+259
-49
lines changed

llvm/include/llvm/Object/TapiFile.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/ADT/StringRef.h"
1717
#include "llvm/Object/Binary.h"
18+
#include "llvm/Object/ObjectFile.h"
1819
#include "llvm/Object/SymbolicFile.h"
1920
#include "llvm/Support/Error.h"
2021
#include "llvm/Support/MemoryBufferRef.h"
@@ -34,7 +35,7 @@ namespace object {
3435

3536
class TapiFile : public SymbolicFile {
3637
public:
37-
TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &interface,
38+
TapiFile(MemoryBufferRef Source, const MachO::InterfaceFile &Interface,
3839
MachO::Architecture Arch);
3940
~TapiFile() override;
4041

@@ -48,6 +49,8 @@ class TapiFile : public SymbolicFile {
4849

4950
basic_symbol_iterator symbol_end() const override;
5051

52+
Expected<SymbolRef::Type> getSymbolType(DataRefImpl DRI) const;
53+
5154
static bool classof(const Binary *v) { return v->isTapiFile(); }
5255

5356
bool is64Bit() const override { return MachO::is64Bit(Arch); }
@@ -57,9 +60,11 @@ class TapiFile : public SymbolicFile {
5760
StringRef Prefix;
5861
StringRef Name;
5962
uint32_t Flags;
63+
SymbolRef::Type Type;
6064

61-
constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags)
62-
: Prefix(Prefix), Name(Name), Flags(Flags) {}
65+
constexpr Symbol(StringRef Prefix, StringRef Name, uint32_t Flags,
66+
SymbolRef::Type Type)
67+
: Prefix(Prefix), Name(Name), Flags(Flags), Type(Type) {}
6368
};
6469

6570
std::vector<Symbol> Symbols;

llvm/include/llvm/TextAPI/Symbol.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,7 @@ class Symbol {
123123
void dump() const { dump(llvm::errs()); }
124124
#endif
125125

126-
bool operator==(const Symbol &O) const {
127-
return std::tie(Name, Kind, Targets, Flags) ==
128-
std::tie(O.Name, O.Kind, O.Targets, O.Flags);
129-
}
126+
bool operator==(const Symbol &O) const;
130127

131128
bool operator!=(const Symbol &O) const { return !(*this == O); }
132129

llvm/lib/BinaryFormat/Magic.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,14 @@ file_magic llvm::identify_magic(StringRef Magic) {
228228
return file_magic::coff_object;
229229
break;
230230

231-
case 0x2d: // YAML '-'
231+
case 0x2d: // YAML '-' MachO TBD.
232232
if (startswith(Magic, "--- !tapi") || startswith(Magic, "---\narchs:"))
233233
return file_magic::tapi_file;
234234
break;
235-
235+
case 0x7b: // JSON '{' MachO TBD.
236+
return file_magic::tapi_file;
237+
break;
238+
236239
case 'D': // DirectX container file - DXBC
237240
if (startswith(Magic, "DXBC"))
238241
return file_magic::dxcontainer_object;

llvm/lib/Object/TapiFile.cpp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,46 @@ static uint32_t getFlags(const Symbol *Sym) {
3737
return Flags;
3838
}
3939

40-
TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
40+
static SymbolRef::Type getType(const Symbol *Sym) {
41+
SymbolRef::Type Type = SymbolRef::ST_Unknown;
42+
if (Sym->isData())
43+
Type = SymbolRef::ST_Data;
44+
else if (Sym->isText())
45+
Type = SymbolRef::ST_Function;
46+
47+
return Type;
48+
}
49+
50+
TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
4151
Architecture Arch)
4252
: SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
43-
for (const auto *Symbol : interface.symbols()) {
53+
for (const auto *Symbol : Interface.symbols()) {
4454
if (!Symbol->getArchitectures().has(Arch))
4555
continue;
4656

4757
switch (Symbol->getKind()) {
4858
case SymbolKind::GlobalSymbol:
49-
Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol));
59+
Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol),
60+
::getType(Symbol));
5061
break;
5162
case SymbolKind::ObjectiveCClass:
52-
if (interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
63+
if (Interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
5364
Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
54-
getFlags(Symbol));
65+
getFlags(Symbol), ::getType(Symbol));
5566
} else {
5667
Symbols.emplace_back(ObjC2ClassNamePrefix, Symbol->getName(),
57-
getFlags(Symbol));
68+
getFlags(Symbol), ::getType(Symbol));
5869
Symbols.emplace_back(ObjC2MetaClassNamePrefix, Symbol->getName(),
59-
getFlags(Symbol));
70+
getFlags(Symbol), ::getType(Symbol));
6071
}
6172
break;
6273
case SymbolKind::ObjectiveCClassEHType:
6374
Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
64-
getFlags(Symbol));
75+
getFlags(Symbol), ::getType(Symbol));
6576
break;
6677
case SymbolKind::ObjectiveCInstanceVariable:
67-
Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(),
68-
getFlags(Symbol));
78+
Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(), getFlags(Symbol),
79+
::getType(Symbol));
6980
break;
7081
}
7182
}
@@ -82,6 +93,11 @@ Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const {
8293
return Error::success();
8394
}
8495

96+
Expected<SymbolRef::Type> TapiFile::getSymbolType(DataRefImpl DRI) const {
97+
assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
98+
return Symbols[DRI.d.a].Type;
99+
}
100+
85101
Expected<uint32_t> TapiFile::getSymbolFlags(DataRefImpl DRI) const {
86102
assert(DRI.d.a < Symbols.size() && "Attempt to access symbol out of bounds");
87103
return Symbols[DRI.d.a].Flags;

llvm/lib/TextAPI/InterfaceFile.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
141141
Documents.insert(Pos, Document);
142142
}
143143

144+
static bool isYAMLTextStub(const FileType &Kind) {
145+
return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
146+
}
147+
144148
bool InterfaceFile::operator==(const InterfaceFile &O) const {
145149
if (Targets != O.Targets)
146150
return false;
@@ -165,6 +169,13 @@ bool InterfaceFile::operator==(const InterfaceFile &O) const {
165169
return false;
166170
if (Symbols != O.Symbols)
167171
return false;
172+
// Don't compare run search paths for older filetypes that cannot express
173+
// them.
174+
if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
175+
if (RPaths != O.RPaths)
176+
return false;
177+
}
178+
168179
if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
169180
O.Documents.end(),
170181
[](const std::shared_ptr<InterfaceFile> LHS,

llvm/lib/TextAPI/Symbol.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,24 @@ Symbol::targets(ArchitectureSet Architectures) const {
5454
return make_filter_range(Targets, FN);
5555
}
5656

57+
bool Symbol::operator==(const Symbol &O) const {
58+
// Older Tapi files do not express all these symbol flags. In those
59+
// cases, ignore those differences.
60+
auto RemoveFlag = [](const Symbol &Sym, SymbolFlags &Flag) {
61+
if (Sym.isData())
62+
Flag &= ~SymbolFlags::Data;
63+
if (Sym.isText())
64+
Flag &= ~SymbolFlags::Text;
65+
};
66+
SymbolFlags LHSFlags = Flags;
67+
SymbolFlags RHSFlags = O.Flags;
68+
if ((!O.isData() && !O.isText()) || (!isData() && !isText())) {
69+
RemoveFlag(*this, LHSFlags);
70+
RemoveFlag(O, RHSFlags);
71+
}
72+
return std::tie(Name, Kind, Targets, LHSFlags) ==
73+
std::tie(O.Name, O.Kind, O.Targets, RHSFlags);
74+
}
75+
5776
} // end namespace MachO.
5877
} // end namespace llvm.

llvm/test/Object/Inputs/tapi-v5.tbd

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"main_library": {
3+
"current_versions": [
4+
{
5+
"version": "1.2.3"
6+
}
7+
],
8+
"exported_symbols": [
9+
{
10+
"data": {
11+
"global": [
12+
"_publicGlobalVariable",
13+
"_extraGlobalAPI1",
14+
"_privateGlobalVariable"
15+
],
16+
"objc_class": [
17+
"SubClass",
18+
"Basic6",
19+
"Basic1",
20+
"Base",
21+
"Basic3",
22+
"FooClass",
23+
"Basic4",
24+
"ExternalManagedObject"
25+
],
26+
"objc_eh_type": [
27+
"SubClass",
28+
"Base"
29+
],
30+
"objc_ivar": [
31+
"Basic4.ivar2",
32+
"Basic4.ivar1",
33+
"Basic4_2.ivar2"
34+
],
35+
"weak": [
36+
"_weakPrivateGlobalVariable",
37+
"_weakPublicGlobalVariable"
38+
]
39+
}
40+
},
41+
{
42+
"text": {
43+
"global": [
44+
"_publicGlobalFunc"
45+
]
46+
}
47+
}
48+
],
49+
"flags": [
50+
{
51+
"attributes": [
52+
"not_app_extension_safe"
53+
]
54+
}
55+
],
56+
"install_names": [
57+
{
58+
"name": "/System/Library/Frameworks/Simple.framework/Versions/A/Simple"
59+
}
60+
],
61+
"target_info": [
62+
{
63+
"min_deployment": "10.10",
64+
"target": "x86_64-macos"
65+
},
66+
{
67+
"min_deployment": "10.10",
68+
"target": "arm64-macos"
69+
}
70+
]
71+
},
72+
"tapi_tbd_version": 5
73+
}

llvm/test/Object/nm-tapi.test

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ RUN: | FileCheck %s -check-prefix V4
1313
RUN: llvm-nm %p/Inputs/tapi-v4-watchos.tbd \
1414
RUN: | FileCheck %s -check-prefix V4-WATCH
1515

16+
RUN: llvm-nm %p/Inputs/tapi-v5.tbd \
17+
RUN: | FileCheck %s -check-prefix V5
18+
1619
V1: /u/l/libfoo.dylib (for architecture armv7):
1720
V1-NEXT: 00000000 S _sym
1821
V1: /u/l/libfoo.dylib (for architecture armv7s):
@@ -64,3 +67,61 @@ V4-WATCH: /u/l/libFoo.dylib (for architecture armv7k)
6467
V4-WATCH-NEXT: 00000000 S _sym1
6568
V4-WATCH: /u/l/libFoo.dylib (for architecture arm64_32)
6669
V4-WATCH-NEXT: 00000000 S _sym1
70+
71+
V5: /System/Library/Frameworks/Simple.framework/Versions/A/Simple (for architecture x86_64):
72+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Base
73+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic1
74+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic3
75+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic4
76+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic6
77+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_ExternalManagedObject
78+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_FooClass
79+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_SubClass
80+
V5-NEXT: 0000000000000000 D _OBJC_EHTYPE_$_Base
81+
V5-NEXT: 0000000000000000 D _OBJC_EHTYPE_$_SubClass
82+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4.ivar1
83+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4.ivar2
84+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4_2.ivar2
85+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Base
86+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic1
87+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic3
88+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic4
89+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic6
90+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_ExternalManagedObject
91+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_FooClass
92+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_SubClass
93+
V5-NEXT: 0000000000000000 D _extraGlobalAPI1
94+
V5-NEXT: 0000000000000000 D _privateGlobalVariable
95+
V5-NEXT: 0000000000000000 T _publicGlobalFunc
96+
V5-NEXT: 0000000000000000 D _publicGlobalVariable
97+
V5-NEXT: 0000000000000000 W _weakPrivateGlobalVariable
98+
V5-NEXT: 0000000000000000 W _weakPublicGlobalVariable
99+
100+
V5: /System/Library/Frameworks/Simple.framework/Versions/A/Simple (for architecture arm64):
101+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Base
102+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic1
103+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic3
104+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic4
105+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_Basic6
106+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_ExternalManagedObject
107+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_FooClass
108+
V5-NEXT: 0000000000000000 D _OBJC_CLASS_$_SubClass
109+
V5-NEXT: 0000000000000000 D _OBJC_EHTYPE_$_Base
110+
V5-NEXT: 0000000000000000 D _OBJC_EHTYPE_$_SubClass
111+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4.ivar1
112+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4.ivar2
113+
V5-NEXT: 0000000000000000 D _OBJC_IVAR_$_Basic4_2.ivar2
114+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Base
115+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic1
116+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic3
117+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic4
118+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_Basic6
119+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_ExternalManagedObject
120+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_FooClass
121+
V5-NEXT: 0000000000000000 D _OBJC_METACLASS_$_SubClass
122+
V5-NEXT: 0000000000000000 D _extraGlobalAPI1
123+
V5-NEXT: 0000000000000000 D _privateGlobalVariable
124+
V5-NEXT: 0000000000000000 T _publicGlobalFunc
125+
V5-NEXT: 0000000000000000 D _publicGlobalVariable
126+
V5-NEXT: 0000000000000000 W _weakPrivateGlobalVariable
127+
V5-NEXT: 0000000000000000 W _weakPublicGlobalVariable
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: rm -rf %t
2+
; RUN: split-file %s %t
3+
; RUN: llvm-tapi-diff %t/Simple_v5.tbd %t/Simple_v5.tbd 2>&1 | FileCheck %s --allow-empty
4+
; RUN: llvm-tapi-diff %t/Simple_v5.tbd %t/Simple_v4.tbd 2>&1 | FileCheck %s --allow-empty
5+
6+
; CHECK-NOT: error:
7+
; CHECK-NOT: warning:
8+
9+
//--- Simple_v4.tbd
10+
--- !tapi-tbd
11+
tbd-version: 4
12+
targets: [ x86_64-macos, arm64-macos ]
13+
flags: [ not_app_extension_safe ]
14+
install-name: '@rpath/libFake.dylib'
15+
exports:
16+
- targets: [ x86_64-macos, arm64-macos ]
17+
symbols: [ _foo ]
18+
...
19+
20+
//--- Simple_v5.tbd
21+
{"main_library":{"exported_symbols":[{"text":{"global":["_foo"]}}],"flags":[{"attributes":["not_app_extension_safe"]}],"install_names":[{"name":"@rpath/libFake.dylib"}],"target_info":[{"min_deployment":"13","target":"x86_64-macos"},{"min_deployment":"13","target":"arm64-macos"}]},"tapi_tbd_version":5}

llvm/tools/llvm-nm/llvm-nm.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,15 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
10291029
}
10301030

10311031
static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
1032-
return 's';
1032+
auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
1033+
switch (Type) {
1034+
case SymbolRef::ST_Data:
1035+
return 'd';
1036+
case SymbolRef::ST_Function:
1037+
return 't';
1038+
default:
1039+
return 's';
1040+
}
10331041
}
10341042

10351043
static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {

0 commit comments

Comments
 (0)