llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: None (dlav-sc) <details> <summary>Changes</summary> To make function calls inside lldb expressions ABI support, JIT engine support are required. This patch augments corresponding functionality to RISCV ABI and implements RISCV relocation resolver in JIT, which allows to make function calls with integer and void function arguments and return value. Also it adds RISCV specific DirectToIndirectFunctionCallsReplacement IR pass, that allows to make assembly jumps at any 64bit address without RISCV large code model, which has not been implemented yet. This pass is needed, because jitted code contains more that +-2GB jumps, which are not available in RISCV without large code model now. Fixed tests: ``` TestCallThatRestarts.ExprCommandThatRestartsTestCase TestMainThreadExit.ThreadExitTestCase TestSBValuePersist.SBValuePersistTestCase TestThisClassTypeMixing.TestCase Test11588.Issue11581TestCase TestExprsChar.ExprCharTestCase TestExpressions.TestExpressions TestCallWithTimeout.ExprCommandWithTimeoutsTestCase TestInlineNamespace.TestInlineNamespace TestInlineNamespaceAlias.TestInlineNamespace TestSetValues.SetValuesTestCase TestValueAPIAddressOfVoidStar.ValueAPIVoidStarTestCase TestXValuePrinting.ExprXValuePrintingTestCase lldbsuite.test.lldbtest.TestRedefinitionsInInlines lldbsuite.test.lldbtest.TestVirtualOverload TestSetValues.SetValuesTestCase TestExprs.BasicExprCommandsTestCase TestExprHelpExamples.Radar9673644TestCase TestExprEntryBP.ExprEntryBPTestCase TestExprInsideLambdas.ExprInsideLambdaTestCase TestConstStaticIntegralMemberInt128.TestCase TestDWIMPrint.TestCase TestCPPStaticMembers.TestCase TestNestedPersistentTypes.NestedPersistentTypesTestCase TestSaveJITObjects.SaveJITObjectsTestCase TestNamespaceLookup.NamespaceLookupTestCase TestCCallingConventions.TestCase TestCppTypedef.TestCppTypedef TestUnwindExpression.UnwindFromExpressionTest TestCxxChar8_t.CxxChar8_tTestCase TestCallCPPFunction.CallCPPFunctionTestCase TestExprDoesntBlock.ExprDoesntDeadlockTestCase TestEnumTypes.EnumTypesTestCase TestAnonymous.AnonymousTestCase ``` --- Patch is 35.55 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/99336.diff 15 Files Affected: - (modified) lldb/include/lldb/Core/Architecture.h (+12) - (modified) lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp (+82-7) - (modified) lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h (+3) - (modified) lldb/source/Plugins/Architecture/CMakeLists.txt (+1) - (added) lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp (+55) - (added) lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h (+34) - (added) lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt (+12) - (added) lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.cpp (+194) - (added) lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.h (+58) - (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp (+23) - (added) lldb/test/API/riscv/expressions/Makefile (+3) - (added) lldb/test/API/riscv/expressions/TestExpressions.py (+88) - (added) lldb/test/API/riscv/expressions/main.cpp (+51) - (modified) llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp (+152-3) - (modified) llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h (+7) ``````````diff diff --git a/lldb/include/lldb/Core/Architecture.h b/lldb/include/lldb/Core/Architecture.h index b6fc1a20e1e69..ca6a9207d8012 100644 --- a/lldb/include/lldb/Core/Architecture.h +++ b/lldb/include/lldb/Core/Architecture.h @@ -12,6 +12,7 @@ #include "lldb/Core/PluginInterface.h" #include "lldb/Target/DynamicRegisterInfo.h" #include "lldb/Target/MemoryTagManager.h" +#include "llvm/IR/LegacyPassManager.h" namespace lldb_private { @@ -129,6 +130,17 @@ class Architecture : public PluginInterface { RegisterContext ®_context) const { return false; } + + // Takes a Pass Manager and adds passes for this Architecture that should be + // run before IRForTarget + virtual std::unique_ptr<llvm::legacy::PassManager> + GetArchitectureCustomPasses(const ExecutionContext &exe_ctx, + const llvm::StringRef expr) const { + return nullptr; + } + + static constexpr llvm::StringLiteral s_target_incompatibility_marker = + "target_incompatibility_detected"; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp index 6395f5bb5bd9b..f3edee1dd6dc1 100644 --- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp +++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp @@ -10,7 +10,9 @@ #include <array> #include <limits> +#include <sstream> +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DerivedTypes.h" #include "lldb/Core/PluginManager.h" @@ -19,6 +21,7 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/RegisterValue.h" #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString() @@ -163,11 +166,83 @@ TotalArgsSizeInWords(bool is_rv64, return total_size; } +static bool UpdateRegister(RegisterContext *reg_ctx, + const lldb::RegisterKind reg_kind, + const uint32_t reg_num, const addr_t value) { + Log *log = GetLog(LLDBLog::Expressions); + + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num); + + LLDB_LOG(log, "Writing %s: 0x%" PRIx64, reg_info->name, + static_cast<uint64_t>(value)); + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) { + LLDB_LOG(log, "Writing %s: failed", reg_info->name); + return false; + } + return true; +} + +static void LogInitInfo(Log *log, const Thread &thread, addr_t sp, + addr_t func_addr, addr_t return_addr, + const llvm::ArrayRef<addr_t> args) { + assert(log); + std::stringstream ss; + ss << "ABISysV_riscv::PrepareTrivialCall" + << " (tid = 0x%" << std::hex << thread.GetID() << ", sp = 0x%" << sp + << ", func_addr = 0x%" << func_addr << ", return_addr = 0x%" + << return_addr; + + for (auto &&[idx, arg] : enumerate(args)) + ss << ", arg" << std::dec << idx << " = 0x%" << std::hex << arg; + ss << ")"; + log->PutString(ss.str()); +} + bool ABISysV_riscv::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, llvm::ArrayRef<addr_t> args) const { - // TODO: Implement - return false; + Log *log = GetLog(LLDBLog::Expressions); + if (log) + LogInitInfo(log, thread, sp, func_addr, return_addr, args); + + const auto reg_ctx_sp = thread.GetRegisterContext(); + if (!reg_ctx_sp) { + LLDB_LOG(log, "Failed to get RegisterContext"); + return false; + } + + if (args.size() > s_regs_for_args_count) { + LLDB_LOG(log, "Function has %lu arguments, but only %lu are allowed!", + args.size(), s_regs_for_args_count); + return false; + } + + // Write arguments to registers + for (auto &&[idx, arg] : enumerate(args)) { + const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx); + LLDB_LOG(log, "About to write arg%lu (0x%" PRIx64 ") into %s", idx, arg, + reg_info->name); + + if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) { + LLDB_LOG(log, "Failed to write arg%lu (0x%" PRIx64 ") into %s", idx, arg, + reg_info->name); + return false; + } + } + + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, func_addr)) + return false; + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, sp)) + return false; + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA, return_addr)) + return false; + + LLDB_LOG(log, "ABISysV_riscv::%s: success", __func__); + return true; } bool ABISysV_riscv::PrepareTrivialCall( @@ -221,14 +296,14 @@ bool ABISysV_riscv::PrepareTrivialCall( assert(prototype.getFunctionNumParams() == args.size()); const size_t num_args = args.size(); - const size_t regs_for_args_count = 8U; const size_t num_args_in_regs = - num_args > regs_for_args_count ? regs_for_args_count : num_args; + num_args > s_regs_for_args_count ? s_regs_for_args_count : num_args; // Number of arguments passed on stack. size_t args_size = TotalArgsSizeInWords(m_is_rv64, args); - auto on_stack = - args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count; + auto on_stack = args_size <= s_regs_for_args_count + ? 0 + : args_size - s_regs_for_args_count; auto offset = on_stack * word_size; uint8_t reg_value[8]; @@ -259,7 +334,7 @@ bool ABISysV_riscv::PrepareTrivialCall( ++reg_index; } - if (reg_index < regs_for_args_count || size == 0) + if (reg_index < s_regs_for_args_count || size == 0) continue; // Remaining arguments are passed on the stack. diff --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h index d8cf008dbb0bf..04ec018c8a718 100644 --- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h +++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h @@ -124,6 +124,9 @@ class ABISysV_riscv : public lldb_private::RegInfoBasedABI { using lldb_private::RegInfoBasedABI::RegInfoBasedABI; // Call CreateInstance // instead. bool m_is_rv64; // true if target is riscv64; false if target is riscv32 + static constexpr size_t s_regs_for_args_count = + 8U; // number of argument registers (the base integer calling convention + // provides 8 argument registers, a0-a7) }; #endif // liblldb_ABISysV_riscv_h_ diff --git a/lldb/source/Plugins/Architecture/CMakeLists.txt b/lldb/source/Plugins/Architecture/CMakeLists.txt index 9ed8edf70af3f..78cdaa0bdf2d4 100644 --- a/lldb/source/Plugins/Architecture/CMakeLists.txt +++ b/lldb/source/Plugins/Architecture/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(Arm) add_subdirectory(Mips) add_subdirectory(PPC64) add_subdirectory(AArch64) +add_subdirectory(RISCV) diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp new file mode 100644 index 0000000000000..e4608b41bd787 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp @@ -0,0 +1,55 @@ +//===-- ArchitectureRISCV.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 "Plugins/Architecture/RISCV/ArchitectureRISCV.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ArchSpec.h" + +#include "llvm/IR/LegacyPassManager.h" + +#include "DirectToIndirectFCR.h" + +using namespace lldb_private; +using namespace lldb; + +LLDB_PLUGIN_DEFINE(ArchitectureRISCV) + +void ArchitectureRISCV::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "RISCV-specific algorithms", + &ArchitectureRISCV::Create); +} + +void ArchitectureRISCV::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureRISCV::Create); +} + +std::unique_ptr<Architecture> ArchitectureRISCV::Create(const ArchSpec &arch) { + if (!arch.GetTriple().isRISCV()) + return nullptr; + return std::unique_ptr<Architecture>(new ArchitectureRISCV()); +} + +void ArchitectureRISCV::OverrideStopInfo(Thread &thread) const {} + +std::unique_ptr<llvm::legacy::PassManager> +ArchitectureRISCV::GetArchitectureCustomPasses( + const ExecutionContext &exe_ctx, const llvm::StringRef expr) const { + // LLDB generates additional support functions like + // '_$__lldb_valid_pointer_check', that do not require custom passes + if (expr != "$__lldb_expr") + return nullptr; + + std::unique_ptr<llvm::legacy::PassManager> custom_passes = + std::make_unique<llvm::legacy::PassManager>(); + auto *P = createDirectToIndirectFCR(exe_ctx); + custom_passes->add(P); + return custom_passes; +} diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h new file mode 100644 index 0000000000000..6ef6c62de5f27 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h @@ -0,0 +1,34 @@ +//===-- ArchitectureRISCV.h -------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureRISCV : public Architecture { +public: + static llvm::StringRef GetPluginNameStatic() { return "riscv"; } + static void Initialize(); + static void Terminate(); + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + void OverrideStopInfo(Thread &thread) const override; + + std::unique_ptr<llvm::legacy::PassManager> + GetArchitectureCustomPasses(const ExecutionContext &exe_ctx, + const llvm::StringRef expr) const override; + +private: + static std::unique_ptr<Architecture> Create(const ArchSpec &arch); + ArchitectureRISCV() = default; +}; + +} // namespace lldb_private diff --git a/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt b/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt new file mode 100644 index 0000000000000..f2545eb35b000 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt @@ -0,0 +1,12 @@ +add_lldb_library(lldbPluginArchitectureRISCV PLUGIN + ArchitectureRISCV.cpp + DirectToIndirectFCR.cpp + + LINK_LIBS + lldbPluginProcessUtility + lldbCore + lldbTarget + lldbUtility + LINK_COMPONENTS + Support + ) diff --git a/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.cpp b/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.cpp new file mode 100644 index 0000000000000..71d3001fc06e8 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.cpp @@ -0,0 +1,194 @@ +//===--- DirectToIndirectFCR.cpp - RISC-V specific pass -------------------===// +// +// 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/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "llvm/InitializePasses.h" +#include "llvm/Support/Casting.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +#include "Plugins/Architecture/RISCV/DirectToIndirectFCR.h" + +#include "lldb/Core/Architecture.h" +#include "lldb/Core/Module.h" +#include "lldb/Symbol/Symtab.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" + +#include <optional> + +using namespace llvm; +using namespace lldb_private; + +namespace { +std::string GetValueTypeStr(const llvm::Type *value_ty) { + assert(value_ty); + std::string str_type; + llvm::raw_string_ostream rso(str_type); + value_ty->print(rso); + return rso.str(); +} + +template <typename... Args> void LogMessage(const char *msg, Args &&...args) { + Log *log = GetLog(LLDBLog::Expressions); + LLDB_LOG(log, msg, std::forward<Args>(args)...); +} +} // namespace + +bool DirectToIndirectFCR::canBeReplaced(const llvm::CallInst *ci) { + assert(ci); + auto *return_value_ty = ci->getType(); + if (!(return_value_ty->isIntegerTy() || return_value_ty->isVoidTy())) { + LogMessage("DirectToIndirectFCR: function {0} has unsupported " + "return type ({1})\n", + ci->getCalledFunction()->getName(), + GetValueTypeStr(return_value_ty)); + return false; + } + + const auto *arg = llvm::find_if_not(ci->args(), [](const auto &arg) { + const auto *type = arg->getType(); + return type->isIntegerTy(); + }); + + if (arg != ci->arg_end()) { + LogMessage("DirectToIndirectFCR: argument {0} of {1} function " + "has unsupported type ({2})\n", + (*arg)->getName(), ci->getCalledFunction()->getName(), + GetValueTypeStr((*arg)->getType())); + return false; + } + return true; +} + +std::vector<llvm::Value *> +DirectToIndirectFCR::getFunctionArgsAsValues(const llvm::CallInst *ci) { + assert(ci); + std::vector<llvm::Value *> args{}; + llvm::transform(ci->args(), std::back_inserter(args), + [](const auto &arg) { return arg.get(); }); + return args; +} + +std::optional<lldb::addr_t> +DirectToIndirectFCR::getFunctionAddress(const llvm::CallInst *ci) const { + auto *target = m_exe_ctx.GetTargetPtr(); + const auto &lldb_module_sp = target->GetExecutableModule(); + const auto &symtab = lldb_module_sp->GetSymtab(); + const llvm::StringRef name = ci->getCalledFunction()->getName(); + + // eSymbolTypeCode: we try to find function + // eDebugNo: not a debug symbol + // eVisibilityExtern: function from extern module + const auto *symbol = symtab->FindFirstSymbolWithNameAndType( + ConstString(name), lldb::SymbolType::eSymbolTypeCode, + Symtab::Debug::eDebugNo, Symtab::Visibility::eVisibilityExtern); + if (!symbol) { + LogMessage("DirectToIndirectFCR: can't find {0} in symtab\n", name); + return std::nullopt; + } + + lldb::addr_t addr = symbol->GetLoadAddress(target); + LogMessage("DirectToIndirectFCR: found address ({0}) of symbol {1}\n", addr, + name); + return addr; +} + +llvm::CallInst *DirectToIndirectFCR::getInstReplace(llvm::CallInst *ci) const { + assert(ci); + + std::optional<lldb::addr_t> addr_or_null = getFunctionAddress(ci); + if (!addr_or_null.has_value()) + return nullptr; + + lldb::addr_t addr = addr_or_null.value(); + + llvm::IRBuilder<> builder(ci); + + std::vector<llvm::Value *> args = getFunctionArgsAsValues(ci); + llvm::Constant *func_addr = builder.getInt64(addr); + llvm::PointerType *ptr_func_ty = builder.getPtrTy(); + auto *cast = builder.CreateIntToPtr(func_addr, ptr_func_ty); + auto *new_inst = + builder.CreateCall(ci->getFunctionType(), cast, ArrayRef(args)); + return new_inst; +} + +DirectToIndirectFCR::DirectToIndirectFCR(const ExecutionContext &exe_ctx) + : FunctionPass(ID), m_exe_ctx{exe_ctx} {} + +DirectToIndirectFCR::~DirectToIndirectFCR() = default; + +bool DirectToIndirectFCR::runOnFunction(llvm::Function &func) { + bool has_irreplaceable = + llvm::any_of(instructions(func), [this](llvm::Instruction &inst) { + llvm::CallInst *ci = dyn_cast<llvm::CallInst>(&inst); + if (!ci || ci->getCalledFunction()->isIntrinsic() || + (DirectToIndirectFCR::canBeReplaced(ci) && + getFunctionAddress(ci).has_value())) + return false; + return true; + }); + + if (has_irreplaceable) { + func.getParent()->getOrInsertNamedMetadata( + Architecture::s_target_incompatibility_marker); + return false; + } + + std::vector<std::reference_wrapper<llvm::Instruction>> + replaceable_function_calls{}; + llvm::copy_if(instructions(func), + std::back_inserter(replaceable_function_calls), + [](llvm::Instruction &inst) { + llvm::CallInst *ci = dyn_cast<llvm::CallInst>(&inst); + if (ci && !ci->getCalledFunction()->isIntrinsic()) + return true; + return false; + }); + + if (replaceable_function_calls.empty()) + return false; + + std::vector<std::pair<llvm::CallInst *, llvm::CallInst *>> replaces; + llvm::transform(replaceable_function_calls, std::back_inserter(replaces), + [this](std::reference_wrapper<llvm::Instruction> inst) + -> std::pair<llvm::CallInst *, llvm::CallInst *> { + llvm::CallInst *ci = cast<llvm::CallInst>(&(inst.get())); + llvm::CallInst *new_inst = getInstReplace(ci); + return {ci, new_inst}; + }); + + for (auto &&[from, to] : replaces) { + from->replaceAllUsesWith(to); + from->eraseFromParent(); + } + + return true; +} + +llvm::StringRef DirectToIndirectFCR::getPassName() const { + return "Transform function calls to calls by address"; +} + +char DirectToIndirectFCR::ID = 0; + +llvm::FunctionPass * +lldb_private::createDirectToIndirectFCR(const ExecutionContext &exe_ctx) { + return new DirectToIndirectFCR(exe_ctx); +} diff --git a/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.h b/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.h new file mode 100644 index 0000000000000..5ac5820bd95a0 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/DirectToIndirectFCR.h @@ -0,0 +1,58 @@ +//===--- DirectToIndirectFCR.h - RISC-V specific pass ---------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "lldb/lldb-types.h" + +#include "llvm/IR/Instructions.h" +#include "llvm/Pass.h" + +namespace lldb_private { + +class ExecutionContext; + +// During the lldb expression execution lldb wraps a user expression, jittes +// fabricated code and then puts it into the stack memory. Thus, if user tried +// to make a function call there will be a jump from a stack address to a code +// sections's address. RISC-V Architecture doesn't have a large code model yet +// and can make only a +-2GiB jumps, but in 64-bit architecture a distance +// between stack addresses and code sections's addresses is longer. Therefore, +// relocations resolver obtains an invalid address. To avoid such problem, this +// pass should be used. It replaces function calls with appropriate function's +// addresses explicitly. By doing so it removes relocations related to function +// calls. This pass should be cosidered as temprorary solution until a large +// code model will be approved. +class DirectToIndirectFCR : public llvm::FunctionPass { + + static bool canBeReplaced(const llvm::CallInst *ci); + + static std::vector<llvm::Value *> + getFunctionArgsAsValues(const llvm::CallInst *ci); + + std::optional<lldb::addr_t> + getFunctionAddress(const llvm::CallInst *ci) const; + + llvm::CallInst *getInstReplace(llvm::CallInst *ci) const; + +public: + static char ID; + + DirectToIndirectFCR(const ExecutionContext &exe_ctx); + ~DirectT... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/99336 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits