LLVM: lib/ExecutionEngine/Orc/TargetProcess/LibraryResolver.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

15

17

25

26#include

27#include

28

29#define DEBUG_TYPE "orc-resolver"

30

32

35 LibPathResolver(S.PResolver

36 ? S.PResolver

38 ScanHelper(S.BasePaths, LibPathCache, LibPathResolver),

39 FB(S.FilterBuilder), LibMgr(),

40 ShouldScanCall(S.ShouldScanCall ? S.ShouldScanCall

42 scanBatchSize(S.ScanBatchSize) {

43

44 if (ScanHelper.getAllUnits().empty()) {

45 LLVM_DEBUG(dbgs() << "Warning: No base paths provided for scanning.\n");

46 }

47}

48

49std::unique_ptr

51 auto LR = std::make_unique(S);

52 return std::unique_ptr(

53 new LibraryResolutionDriver(std::move(LR)));

54}

55

57 LR->ScanHelper.addBasePath(Path, K);

58}

59

61 auto Lib = LR->LibMgr.getLibrary(Path);

63 return false;

64

66

67 return true;

68}

69

71 auto Lib = LR->LibMgr.getLibrary(Path);

73 return false;

74

76

77 return true;

78}

79

81 std::vectorstd::string Syms,

84 LR->searchSymbolsInLibraries(Syms, std::move(OnCompletion), Config);

85}

86

90 if (!FlagsOrErr) {

92 return true;

93 }

94

96

98 if ((IgnoreFlags & Filter::IgnoreUndefined) &&

100 return true;

101 if ((IgnoreFlags & Filter::IgnoreIndirect) &&

103 return true;

104 if ((IgnoreFlags & Filter::IgnoreWeak) &&

106 return true;

107

108 return false;

109}

110

113 if (Path.empty())

114 return false;

115

117

119 if (!ObjOrErr) {

120 std::string ErrMsg;

122 [&](const ErrorInfoBase &EIB) { ErrMsg = EIB.message(); });

123 LLVM_DEBUG(dbgs() << "Failed loading object file: " << Path

124 << "\nError: " << ErrMsg << "\n");

125 return false;

126 }

127

129

130 auto processSymbolRange =

132 for (const auto &Sym : Range) {

134 continue;

135

136 auto NameOrErr = Sym.getName();

137 if (!NameOrErr) {

139 continue;

140 }

141

143 if (Name.empty())

144 continue;

145

147 if (Res != EnumerateResult::Continue)

148 return Res;

149 }

150 return EnumerateResult::Continue;

151 };

152

153 EnumerateResult Res = processSymbolRange(Obj->symbols());

154 if (Res != EnumerateResult::Continue)

155 return Res == EnumerateResult::Stop;

156

157 if (Obj->isELF()) {

159 Res = processSymbolRange(ElfObj->getDynamicSymbolIterators());

160 if (Res != EnumerateResult::Continue)

161 return Res == EnumerateResult::Stop;

162 } else if (Obj->isCOFF()) {

164 for (auto I = CoffObj->export_directory_begin(),

165 E = CoffObj->export_directory_end();

166 I != E; ++I) {

168 if (I->getSymbolName(Name))

169 continue;

170 if (Name.empty())

171 continue;

172

174 if (Res != EnumerateResult::Continue)

175 return Res == EnumerateResult::Stop;

176 }

177 } else if (Obj->isMachO()) {

178 }

179

180 return true;

181}

182

184public:

186

188

190

191 inline bool allResolved() const { return Q.allResolved(); }

192

194

195private:

198};

199

200void LibraryResolver::resolveSymbolsInLibrary(

201 LibraryInfo &Lib, SymbolQuery &UnresolvedSymbols,

202 const SymbolEnumeratorOptions &Opts) {

204 << " in library : " << Lib.getFileName() << "\n";);

206

207 if (!UnresolvedSymbols.hasUnresolved()) {

209 << " — unresolved symbols exist.\n";);

210 return;

211 }

212

213 bool HasEnumerated = false;

214 auto enumerateSymbolsIfNeeded = [&]() {

215 if (HasEnumerated)

216 return;

217

218 HasEnumerated = true;

219

220 LLVM_DEBUG(dbgs() << "Enumerating symbols in library: " << Lib.getFullPath()

221 << "\n";);

222 SymbolEnumerator::enumerateSymbols(

223 Lib.getFullPath(),

224 [&](StringRef sym) {

225 DiscoveredSymbols.insert(sym);

226 return EnumerateResult::Continue;

227 },

228 Opts);

229 };

230

231 if (Lib.hasFilter()) {

232 LLVM_DEBUG(dbgs() << "Building filter for library: " << Lib.getFullPath()

233 << "\n";);

234 enumerateSymbolsIfNeeded();

235 if (DiscoveredSymbols.empty()) {

236 LLVM_DEBUG(dbgs() << " No symbols and remove library : "

237 << Lib.getFullPath() << "\n";);

238 LibMgr.removeLibrary(Lib.getFullPath());

239 return;

240 }

241 SmallVector SymbolVec;

242 SymbolVec.reserve(DiscoveredSymbols.size());

243 for (const auto &KV : DiscoveredSymbols)

244 SymbolVec.push_back(KV.first());

245

246 Lib.ensureFilterBuilt(FB, SymbolVec);

248 dbgs() << "DiscoveredSymbols : " << DiscoveredSymbols.size() << "\n";

249 for (const auto &KV : DiscoveredSymbols)

250 dbgs() << "DiscoveredSymbols : " << KV.first() << "\n";

251 });

252 }

253

254 const auto &Unresolved = UnresolvedSymbols.getUnresolvedSymbols();

255 bool HadAnySym = false;

256 LLVM_DEBUG(dbgs() << "Total unresolved symbols : " << Unresolved.size()

257 << "\n";);

258 for (const auto &Sym : Unresolved) {

259 if (Lib.mayContain(Sym)) {

261 << "' in library: " << Lib.getFullPath() << "\n";);

262 enumerateSymbolsIfNeeded();

263 if (DiscoveredSymbols.count(Sym) > 0) {

265 << " in library: " << Lib.getFullPath() << "\n";);

266 UnresolvedSymbols.resolve(Sym, Lib.getFullPath());

267 HadAnySym = true;

268 }

269 }

270 }

271

272 using LibraryState = LibraryManager::LibState;

273 if (HadAnySym && Lib.getState() != LibraryState::Loaded)

274 Lib.setState(LibraryState::Queried);

275}

276

278 std::vectorstd::string &SymbolList, OnSearchComplete OnComplete,

281

283 using LibraryType = PathType;

284 auto tryResolveFrom = [&](LibraryState S, LibraryType K) {

285 LLVM_DEBUG(dbgs() << "Trying resolve from state=" << static_cast<int>(S)

286 << " type=" << static_cast<int>(K) << "\n";);

287

289 while (!Ctx.allResolved()) {

290 std::vector<std::shared_ptr> Libs;

291 LibMgr.getLibraries(S, K, Libs, [&](const LibraryInfo &Lib) {

292 return !Ctx.hasSearched(&Lib);

293 });

294

295 if (Libs.empty() && !scanLibrariesIfNeeded(K, scanBatchSize))

296 break;

297

298 for (auto &Lib : Libs) {

299

300 resolveSymbolsInLibrary(*Lib, Ctx.query(), Config.Options);

301 Ctx.markSearched(Lib.get());

302

303 if (Ctx.allResolved())

304 return;

305 }

306 }

307 };

308

309 for (const auto &[St, Ty] : Config.Policy.Plan) {

310 tryResolveFrom(St, Ty);

312 break;

313 }

314

315

317 dbgs() << "Search complete.\n";

319 dbgs() << "Resolved Symbol:" << r->Name << " -> " << r->ResolvedLibPath

320 << "\n";

321 });

322

323 OnComplete(Q);

324}

325

326bool LibraryResolver::scanLibrariesIfNeeded(PathType PK, size_t BatchSize) {

327 LLVM_DEBUG(dbgs() << "LibraryResolver::scanLibrariesIfNeeded: Scanning for "

328 << (PK == PathType::User ? "User" : "System")

329 << " libraries\n";);

330 if (!ScanHelper.leftToScan(PK))

331 return false;

332

333 LibraryScanner Scanner(ScanHelper, LibMgr, ShouldScanCall);

334 Scanner.scanNext(PK, BatchSize);

335 return true;

336}

337

338bool LibraryResolver::symbolExistsInLibrary(const LibraryInfo &Lib,

340 std::vectorstd::string *AllSyms) {

341 SymbolEnumeratorOptions Opts;

342 return symbolExistsInLibrary(Lib, SymName, AllSyms, Opts);

343}

344

345bool LibraryResolver::symbolExistsInLibrary(

346 const LibraryInfo &Lib, StringRef SymName,

347 std::vectorstd::string *AllSyms, const SymbolEnumeratorOptions &Opts) {

348 bool Found = false;

349

350 SymbolEnumerator::enumerateSymbols(

351 Lib.getFullPath(),

352 [&](StringRef Sym) {

353 if (AllSyms)

354 AllSyms->emplace_back(Sym.str());

355

356 if (Sym == SymName) {

357 Found = true;

358 }

359

360 return EnumerateResult::Continue;

361 },

362 Opts);

363

364 return Found;

365}

366

367}

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

StringSet - A set-like wrapper for the StringMap.

Implements a dense probed hash-table based set.

Base class for error info classes.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

StringRef - Represent a constant reference to a string, i.e.

StringSet - A wrapper for StringMap that provides set-like functionality.

Expected< uint32_t > getFlags() const

Get symbol flags (bitwise OR of SymbolRef::Flags)

This class is the base class for all object file types.

iterator_range< symbol_iterator > symbol_iterator_range

This is a value type class that represents a single symbol in the list of symbols in the object file.

void resolveSymbols(std::vector< std::string > Symbols, LibraryResolver::OnSearchComplete OnCompletion, const SearchConfig &Config=SearchConfig())

Definition LibraryResolver.cpp:80

void addScanPath(const std::string &Path, PathType Kind)

Definition LibraryResolver.cpp:56

bool markLibraryLoaded(StringRef Path)

Definition LibraryResolver.cpp:60

static std::unique_ptr< LibraryResolutionDriver > create(const LibraryResolver::Setup &S)

Definition LibraryResolver.cpp:50

bool markLibraryUnLoaded(StringRef Path)

Definition LibraryResolver.cpp:70

std::function< EnumerateResult(StringRef Sym)> OnEachSymbolFn

static bool enumerateSymbols(StringRef Path, OnEachSymbolFn OnEach, const SymbolEnumeratorOptions &Opts)

Definition LibraryResolver.cpp:111

Tracks a set of symbols and the libraries where they are resolved.

std::vector< const Result * > getAllResults() const

unique_function< void(SymbolQuery &)> OnSearchComplete

void searchSymbolsInLibraries(std::vector< std::string > &SymList, OnSearchComplete OnComplete, const SearchConfig &Config=SearchConfig())

Definition LibraryResolver.cpp:277

Scans libraries, resolves dependencies, and registers them.

Loads an object file and provides access to it.

Expected< object::ObjectFile & > getObjectFile()

Get the loaded object file, or return an error if loading failed.

Resolves file system paths with optional caching of results.

Definition LibraryResolver.cpp:183

bool hasSearched(const LibraryInfo *Lib) const

Definition LibraryResolver.cpp:187

void markSearched(const LibraryInfo *Lib)

Definition LibraryResolver.cpp:189

SymbolQuery & query()

Definition LibraryResolver.cpp:193

bool allResolved() const

Definition LibraryResolver.cpp:191

SymbolSearchContext(SymbolQuery &Q)

Definition LibraryResolver.cpp:185

LibraryManager::LibraryInfo LibraryInfo

static bool shouldIgnoreSymbol(const object::SymbolRef &Sym, uint32_t IgnoreFlags)

Definition LibraryResolver.cpp:87

LibraryResolver::SymbolQuery SymbolQuery

void handleAllErrors(Error E, HandlerTs &&... Handlers)

Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

void consumeError(Error Err)

Consume a Error without doing anything.

Implement std::hash so that hash_code can be used in STL containers.

SymbolEnumeratorOptions Options

std::vector< SearchPlanEntry > Plan