123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- //===---------------------- RemoteObjectLayerTest.cpp ---------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
- #include "llvm/ExecutionEngine/Orc/NullResolver.h"
- #include "llvm/ExecutionEngine/Orc/RemoteObjectLayer.h"
- #include "OrcTestCommon.h"
- #include "QueueChannel.h"
- #include "gtest/gtest.h"
- using namespace llvm;
- using namespace llvm::orc;
- namespace {
- class MockObjectLayer {
- public:
- using ObjHandleT = uint64_t;
- using ObjectPtr = std::unique_ptr<MemoryBuffer>;
- using LookupFn = std::function<JITSymbol(StringRef, bool)>;
- using SymbolLookupTable = std::map<ObjHandleT, LookupFn>;
- using AddObjectFtor =
- std::function<Expected<ObjHandleT>(ObjectPtr, SymbolLookupTable&)>;
- class ObjectNotFound : public remote::ResourceNotFound<ObjHandleT> {
- public:
- ObjectNotFound(ObjHandleT H) : ResourceNotFound(H, "Object handle") {}
- };
- MockObjectLayer(AddObjectFtor AddObject)
- : AddObject(std::move(AddObject)) {}
- Expected<ObjHandleT> addObject(ObjectPtr Obj,
- std::shared_ptr<JITSymbolResolver> Resolver) {
- return AddObject(std::move(Obj), SymTab);
- }
- Error removeObject(ObjHandleT H) {
- if (SymTab.count(H))
- return Error::success();
- else
- return make_error<ObjectNotFound>(H);
- }
- JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
- for (auto KV : SymTab) {
- if (auto Sym = KV.second(Name, ExportedSymbolsOnly))
- return Sym;
- else if (auto Err = Sym.takeError())
- return std::move(Err);
- }
- return JITSymbol(nullptr);
- }
- JITSymbol findSymbolIn(ObjHandleT H, StringRef Name,
- bool ExportedSymbolsOnly) {
- auto LI = SymTab.find(H);
- if (LI != SymTab.end())
- return LI->second(Name, ExportedSymbolsOnly);
- else
- return make_error<ObjectNotFound>(H);
- }
- Error emitAndFinalize(ObjHandleT H) {
- if (SymTab.count(H))
- return Error::success();
- else
- return make_error<ObjectNotFound>(H);
- }
- private:
- AddObjectFtor AddObject;
- SymbolLookupTable SymTab;
- };
- using RPCEndpoint = rpc::SingleThreadedRPCEndpoint<rpc::RawByteChannel>;
- MockObjectLayer::ObjectPtr createTestObject() {
- OrcNativeTarget::initialize();
- auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());
- if (!TM)
- return nullptr;
- LLVMContext Ctx;
- ModuleBuilder MB(Ctx, TM->getTargetTriple().str(), "TestModule");
- MB.getModule()->setDataLayout(TM->createDataLayout());
- auto *Main = MB.createFunctionDecl(
- FunctionType::get(Type::getInt32Ty(Ctx),
- {Type::getInt32Ty(Ctx),
- Type::getInt8PtrTy(Ctx)->getPointerTo()},
- false),
- "main");
- Main->getBasicBlockList().push_back(BasicBlock::Create(Ctx));
- IRBuilder<> B(&Main->back());
- B.CreateRet(ConstantInt::getSigned(Type::getInt32Ty(Ctx), 42));
- SimpleCompiler IRCompiler(*TM);
- return IRCompiler(*MB.getModule());
- }
- TEST(RemoteObjectLayer, AddObject) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError = [](Error Err) {
- logAllUnhandledErrors(std::move(Err), llvm::errs());
- };
- // Copy the bytes out of the test object: the copy will be used to verify
- // that the original is correctly transmitted over RPC to the mock layer.
- StringRef ObjBytes = TestObject->getBuffer();
- std::vector<char> ObjContents(ObjBytes.size());
- std::copy(ObjBytes.begin(), ObjBytes.end(), ObjContents.begin());
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- MockObjectLayer BaseLayer(
- [&ObjContents](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- // Check that the received object file content matches the original.
- StringRef RPCObjContents = Obj->getBuffer();
- EXPECT_EQ(RPCObjContents.size(), ObjContents.size())
- << "RPC'd object file has incorrect size";
- EXPECT_TRUE(std::equal(RPCObjContents.begin(), RPCObjContents.end(),
- ObjContents.begin()))
- << "RPC'd object file content does not match original content";
- return 1;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, AddObjectFailure) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError =
- [](Error Err) {
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
- << "Expected error string to be \"AddObjectFailure - Test Message\"";
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab)
- -> Expected<MockObjectLayer::ObjHandleT> {
- return make_error<StringError>("AddObjectFailure - Test Message",
- inconvertibleErrorCode());
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto HandleOrErr = Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>());
- EXPECT_FALSE(HandleOrErr) << "Expected error from addObject";
- auto ErrMsg = toString(HandleOrErr.takeError());
- EXPECT_EQ(ErrMsg, "AddObjectFailure - Test Message")
- << "Expected error string to be \"AddObjectFailure - Test Message\"";
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, RemoveObject) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError = [](Error Err) {
- logAllUnhandledErrors(std::move(Err), llvm::errs());
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- SymTab[1] = MockObjectLayer::LookupFn();
- return 1;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto H = cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- cantFail(Client.removeObject(H));
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, RemoveObjectFailure) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError =
- [](Error Err) {
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Object handle 42 not found")
- << "Expected error string to be \"Object handle 42 not found\"";
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- // AddObject lambda does not update symbol table, so removeObject will treat
- // this as a bad object handle.
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- return 42;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto H = cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- auto Err = Client.removeObject(H);
- EXPECT_TRUE(!!Err) << "Expected error from removeObject";
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Object handle 42 not found")
- << "Expected error string to be \"Object handle 42 not found\"";
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, FindSymbol) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError =
- [](Error Err) {
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
- << "Expected error string to be \"Object handle 42 not found\"";
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- // AddObject lambda does not update symbol table, so removeObject will treat
- // this as a bad object handle.
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- SymTab[42] =
- [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
- if (Name == "foobar")
- return JITSymbol(0x12348765, JITSymbolFlags::Exported);
- if (Name == "badsymbol")
- return make_error<JITSymbolNotFound>(Name);
- return nullptr;
- };
- return 42;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- // Check that we can find and materialize a valid symbol.
- auto Sym1 = Client.findSymbol("foobar", true);
- EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
- EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
- << "Symbol 'foobar' does not return the correct address";
- {
- // Check that we can return a symbol containing an error.
- auto Sym2 = Client.findSymbol("badsymbol", true);
- EXPECT_FALSE(!!Sym2) << "Symbol 'badsymbol' should not be findable";
- auto Err = Sym2.takeError();
- EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Could not find symbol 'badsymbol'")
- << "Expected symbol-not-found error for Sym2";
- }
- {
- // Check that we can return a 'null' symbol.
- auto Sym3 = Client.findSymbol("baz", true);
- EXPECT_FALSE(!!Sym3) << "Symbol 'baz' should convert to false";
- auto Err = Sym3.takeError();
- EXPECT_FALSE(!!Err) << "Symbol 'baz' should not contain an error";
- }
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, FindSymbolIn) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError =
- [](Error Err) {
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
- << "Expected error string to be \"Object handle 42 not found\"";
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- // AddObject lambda does not update symbol table, so removeObject will treat
- // this as a bad object handle.
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- SymTab[42] =
- [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
- if (Name == "foobar")
- return JITSymbol(0x12348765, JITSymbolFlags::Exported);
- return make_error<JITSymbolNotFound>(Name);
- };
- // Dummy symbol table entry - this should not be visible to
- // findSymbolIn.
- SymTab[43] =
- [](StringRef Name, bool ExportedSymbolsOnly) -> JITSymbol {
- if (Name == "barbaz")
- return JITSymbol(0xdeadbeef, JITSymbolFlags::Exported);
- return make_error<JITSymbolNotFound>(Name);
- };
- return 42;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto H = cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- auto Sym1 = Client.findSymbolIn(H, "foobar", true);
- EXPECT_TRUE(!!Sym1) << "Symbol 'foobar' should be findable";
- EXPECT_EQ(cantFail(Sym1.getAddress()), 0x12348765ULL)
- << "Symbol 'foobar' does not return the correct address";
- auto Sym2 = Client.findSymbolIn(H, "barbaz", true);
- EXPECT_FALSE(!!Sym2) << "Symbol 'barbaz' should not be findable";
- auto Err = Sym2.takeError();
- EXPECT_TRUE(!!Err) << "Sym2 should contain an error value";
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Could not find symbol 'barbaz'")
- << "Expected symbol-not-found error for Sym2";
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, EmitAndFinalize) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError = [](Error Err) {
- logAllUnhandledErrors(std::move(Err), llvm::errs());
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- SymTab[1] = MockObjectLayer::LookupFn();
- return 1;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto H = cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- auto Err = Client.emitAndFinalize(H);
- EXPECT_FALSE(!!Err) << "emitAndFinalize should work";
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- TEST(RemoteObjectLayer, EmitAndFinalizeFailure) {
- llvm::orc::rpc::registerStringError<rpc::RawByteChannel>();
- auto TestObject = createTestObject();
- if (!TestObject)
- return;
- auto Channels = createPairedQueueChannels();
- auto ReportError =
- [](Error Err) {
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Object handle 1 not found")
- << "Expected bad handle error";
- };
- RPCEndpoint ClientEP(*Channels.first, true);
- RemoteObjectClientLayer<RPCEndpoint> Client(AcknowledgeORCv1Deprecation,
- ClientEP, ReportError);
- RPCEndpoint ServerEP(*Channels.second, true);
- MockObjectLayer BaseLayer(
- [](MockObjectLayer::ObjectPtr Obj,
- MockObjectLayer::SymbolLookupTable &SymTab) {
- return 1;
- });
- RemoteObjectServerLayer<MockObjectLayer, RPCEndpoint> Server(
- AcknowledgeORCv1Deprecation, BaseLayer, ServerEP, ReportError);
- bool Finished = false;
- ServerEP.addHandler<remote::utils::TerminateSession>(
- [&]() { Finished = true; }
- );
- auto ServerThread =
- std::thread([&]() {
- while (!Finished)
- cantFail(ServerEP.handleOne());
- });
- auto H = cantFail(Client.addObject(std::move(TestObject),
- std::make_shared<NullLegacyResolver>()));
- auto Err = Client.emitAndFinalize(H);
- EXPECT_TRUE(!!Err) << "emitAndFinalize should work";
- auto ErrMsg = toString(std::move(Err));
- EXPECT_EQ(ErrMsg, "Object handle 1 not found")
- << "emitAndFinalize returned incorrect error";
- cantFail(ClientEP.callB<remote::utils::TerminateSession>());
- ServerThread.join();
- }
- }
|