Skip to content

Commit

Permalink
[InstallAPI] Add support for aliased exports (#88750)
Browse files Browse the repository at this point in the history
Apple's ld supports alias_lists, described as
```
     -alias_list filename
             The specified filename contains a list of aliases. The symbol name and its alias are on one
             line, separated by whitespace.  Lines starting with # are ignored.
```
To handle this for installapi-produced TBD files, pass along the same
input and account for it in verification.
  • Loading branch information
cyndyishida committed Apr 18, 2024
1 parent 353322f commit 4c18681
Show file tree
Hide file tree
Showing 12 changed files with 572 additions and 8 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def err_no_matching_target : Error<"no matching target found for target variant
def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">;
def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">;
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
def err_cannot_read_alias_list : Error<"could not read alias list '%0': %1">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,7 @@ def end_no_unused_arguments : Flag<["--"], "end-no-unused-arguments">,
def interface_stub_version_EQ : JoinedOrSeparate<["-"], "interface-stub-version=">,
Visibility<[ClangOption, CC1Option]>;
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
def alias_list : Separate<["-"], "alias_list">, Flags<[LinkerInput]>;
def extract_api : Flag<["-"], "extract-api">,
Visibility<[ClangOption, CC1Option]>, Group<Action_Group>,
HelpText<"Extract API information">;
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
DylibVerifier() = default;

DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports,
DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered,
bool Demangle, StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode),
Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath),
AliasMap Aliases, DiagnosticsEngine *Diag,
VerificationMode Mode, bool Zippered, bool Demangle,
StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)),
Aliases(std::move(Aliases)), Mode(Mode), Zippered(Zippered),
Demangle(Demangle), DSYMPath(DSYMPath),
Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {}

Result verify(GlobalRecord *R, const FrontendAttrs *FA);
Expand All @@ -104,7 +106,7 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
void setTarget(const Target &T);

/// Release ownership over exports.
std::unique_ptr<SymbolSet> getExports() { return std::move(Exports); }
std::unique_ptr<SymbolSet> takeExports();

/// Get result of verification.
Result getState() const { return Ctx.FrontendState; }
Expand Down Expand Up @@ -189,6 +191,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Reexported interfaces apart of the library.
ReexportedInterfaces Reexports;

// Symbol aliases.
AliasMap Aliases;

// Controls what class of violations to report.
VerificationMode Mode = VerificationMode::Invalid;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"

using AliasMap = llvm::MachO::AliasMap;
using Architecture = llvm::MachO::Architecture;
using ArchitectureSet = llvm::MachO::ArchitectureSet;
using SymbolFlags = llvm::MachO::SymbolFlags;
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/InstallAPI/DylibVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,11 @@ void DylibVerifier::visitSymbolInDylib(const Record &R, SymbolContext &SymCtx) {
return;
}

if (Aliases.count({SymbolName.str(), SymCtx.Kind})) {
updateState(Result::Valid);
return;
}

// All checks at this point classify as some kind of violation.
// The different verification modes dictate whether they are reported to the
// user.
Expand Down Expand Up @@ -973,5 +978,24 @@ bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
return true;
}

std::unique_ptr<SymbolSet> DylibVerifier::takeExports() {
for (const auto &[Alias, Base] : Aliases) {
TargetList Targets;
SymbolFlags Flags = SymbolFlags::None;
if (const Symbol *Sym = Exports->findSymbol(Base.second, Base.first)) {
Flags = Sym->getFlags();
Targets = {Sym->targets().begin(), Sym->targets().end()};
}

Record R(Alias.first, RecordLinkage::Exported, Flags);
SymbolContext SymCtx;
SymCtx.SymbolName = Alias.first;
SymCtx.Kind = Alias.second;
addSymbol(&R, SymCtx, std::move(Targets));
}

return std::move(Exports);
}

} // namespace installapi
} // namespace clang

0 comments on commit 4c18681

Please sign in to comment.