]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
New upstream version 1.70.0+dfsg1
[rustc.git] / compiler / rustc_llvm / llvm-wrapper / SymbolWrapper.cpp
CommitLineData
487cf647
FG
1// Derived from code in LLVM, which is:
2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3// See https://llvm.org/LICENSE.txt for license information.
4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5
6// Derived from:
7// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
8// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
9
10#include "llvm/IR/LLVMContext.h"
11#include "llvm/Object/ObjectFile.h"
487cf647
FG
12
13using namespace llvm;
14using namespace llvm::sys;
15using namespace llvm::object;
16
17static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
18 Expected<uint32_t> SymFlagsOrErr = S.getFlags();
19 if (!SymFlagsOrErr)
20 // FIXME: Actually report errors helpfully.
21 report_fatal_error(SymFlagsOrErr.takeError());
22 if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
23 return false;
24 if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
25 return false;
26 if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
27 return false;
28 return true;
29}
30
31typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *);
32typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *);
33
34// Note: This is implemented in C++ instead of using the C api from Rust as IRObjectFile doesn't
35// implement getSymbolName, only printSymbolName, which is inaccessible from the C api.
36extern "C" void *LLVMRustGetSymbols(
37 char *BufPtr, size_t BufLen, void *State, LLVMRustGetSymbolsCallback Callback,
38 LLVMRustGetSymbolsErrorCallback ErrorCallback) {
39 std::unique_ptr<MemoryBuffer> Buf =
40 MemoryBuffer::getMemBuffer(StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"),
41 false);
42 SmallString<0> SymNameBuf;
43 raw_svector_ostream SymName(SymNameBuf);
44
45 // In the scenario when LLVMContext is populated SymbolicFile will contain a
46 // reference to it, thus SymbolicFile should be destroyed first.
47 LLVMContext Context;
48 std::unique_ptr<object::SymbolicFile> Obj;
49
50 const file_magic Type = identify_magic(Buf->getBuffer());
51 if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) {
52 return 0;
53 }
54
55 if (Type == file_magic::bitcode) {
56 auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
57 Buf->getMemBufferRef(), file_magic::bitcode, &Context);
58 if (!ObjOrErr) {
59 Error E = ObjOrErr.takeError();
60 SmallString<0> ErrorBuf;
61 raw_svector_ostream Error(ErrorBuf);
62 Error << E << '\0';
63 return ErrorCallback(Error.str().data());
64 }
65 Obj = std::move(*ObjOrErr);
66 } else {
67 auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef());
68 if (!ObjOrErr) {
69 Error E = ObjOrErr.takeError();
70 SmallString<0> ErrorBuf;
71 raw_svector_ostream Error(ErrorBuf);
72 Error << E << '\0';
73 return ErrorCallback(Error.str().data());
74 }
75 Obj = std::move(*ObjOrErr);
76 }
77
78
79 for (const object::BasicSymbolRef &S : Obj->symbols()) {
80 if (!isArchiveSymbol(S))
81 continue;
82 if (Error E = S.printName(SymName)) {
83 SmallString<0> ErrorBuf;
84 raw_svector_ostream Error(ErrorBuf);
85 Error << E << '\0';
86 return ErrorCallback(Error.str().data());
87 }
88 SymName << '\0';
89 if (void *E = Callback(State, SymNameBuf.str().data())) {
90 return E;
91 }
92 SymNameBuf.clear();
93 }
94 return 0;
95}