180814287SRaphael Isemann //===-- ABI.cpp -----------------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
930fdc8d8SChris Lattner #include "lldb/Target/ABI.h"
1030fdc8d8SChris Lattner #include "lldb/Core/PluginManager.h"
1173ca05a2SJim Ingham #include "lldb/Core/Value.h"
1273ca05a2SJim Ingham #include "lldb/Core/ValueObjectConstResult.h"
134dc0acc9SAlex Langford #include "lldb/Expression/ExpressionVariable.h"
14a1e5dc86SGreg Clayton #include "lldb/Symbol/CompilerType.h"
158f1f9a1bSSean Callanan #include "lldb/Symbol/TypeSystem.h"
16ef651600SJim Ingham #include "lldb/Target/Target.h"
1773ca05a2SJim Ingham #include "lldb/Target/Thread.h"
18*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
19d0b44dbeSPavel Labath #include "lldb/Utility/Log.h"
2089b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
218f95a82bSJonas Devlieghere #include <cctype>
2230fdc8d8SChris Lattner
2330fdc8d8SChris Lattner using namespace lldb;
2430fdc8d8SChris Lattner using namespace lldb_private;
2530fdc8d8SChris Lattner
2631f1d2f5SGreg Clayton ABISP
FindPlugin(lldb::ProcessSP process_sp,const ArchSpec & arch)2743294c9fSJason Molenda ABI::FindPlugin(lldb::ProcessSP process_sp, const ArchSpec &arch) {
2831f1d2f5SGreg Clayton ABISP abi_sp;
2930fdc8d8SChris Lattner ABICreateInstance create_callback;
3030fdc8d8SChris Lattner
3130fdc8d8SChris Lattner for (uint32_t idx = 0;
32b9c1b51eSKate Stone (create_callback = PluginManager::GetABICreateCallbackAtIndex(idx)) !=
33b9c1b51eSKate Stone nullptr;
34b9c1b51eSKate Stone ++idx) {
3543294c9fSJason Molenda abi_sp = create_callback(process_sp, arch);
3630fdc8d8SChris Lattner
3731f1d2f5SGreg Clayton if (abi_sp)
3831f1d2f5SGreg Clayton return abi_sp;
3930fdc8d8SChris Lattner }
4031f1d2f5SGreg Clayton abi_sp.reset();
4131f1d2f5SGreg Clayton return abi_sp;
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner
449394d772SEugene Zelenko ABI::~ABI() = default;
4556d9a1b3SGreg Clayton
GetRegisterInfoByName(llvm::StringRef name,RegisterInfo & info)4624e07570SRaphael Isemann bool RegInfoBasedABI::GetRegisterInfoByName(llvm::StringRef name,
4724e07570SRaphael Isemann RegisterInfo &info) {
4856d9a1b3SGreg Clayton uint32_t count = 0;
4956d9a1b3SGreg Clayton const RegisterInfo *register_info_array = GetRegisterInfoArray(count);
50b9c1b51eSKate Stone if (register_info_array) {
5156d9a1b3SGreg Clayton uint32_t i;
52b9c1b51eSKate Stone for (i = 0; i < count; ++i) {
53b0060c3aSRaphael Isemann const char *reg_name = register_info_array[i].name;
5424e07570SRaphael Isemann if (reg_name == name) {
5556d9a1b3SGreg Clayton info = register_info_array[i];
5656d9a1b3SGreg Clayton return true;
5756d9a1b3SGreg Clayton }
5856d9a1b3SGreg Clayton }
59b9c1b51eSKate Stone for (i = 0; i < count; ++i) {
60b0060c3aSRaphael Isemann const char *reg_alt_name = register_info_array[i].alt_name;
6124e07570SRaphael Isemann if (reg_alt_name == name) {
6256d9a1b3SGreg Clayton info = register_info_array[i];
6356d9a1b3SGreg Clayton return true;
6456d9a1b3SGreg Clayton }
6556d9a1b3SGreg Clayton }
6656d9a1b3SGreg Clayton }
6756d9a1b3SGreg Clayton return false;
6856d9a1b3SGreg Clayton }
6956d9a1b3SGreg Clayton
GetReturnValueObject(Thread & thread,CompilerType & ast_type,bool persistent) const70b9c1b51eSKate Stone ValueObjectSP ABI::GetReturnValueObject(Thread &thread, CompilerType &ast_type,
71b9c1b51eSKate Stone bool persistent) const {
7273ca05a2SJim Ingham if (!ast_type.IsValid())
7373ca05a2SJim Ingham return ValueObjectSP();
7473ca05a2SJim Ingham
75ef651600SJim Ingham ValueObjectSP return_valobj_sp;
7673ca05a2SJim Ingham
77ef651600SJim Ingham return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type);
78ef651600SJim Ingham if (!return_valobj_sp)
79ef651600SJim Ingham return return_valobj_sp;
80ef651600SJim Ingham
81ef651600SJim Ingham // Now turn this into a persistent variable.
82b9c1b51eSKate Stone // FIXME: This code is duplicated from Target::EvaluateExpression, and it is
83b9c1b51eSKate Stone // used in similar form in a couple
84b9c1b51eSKate Stone // of other places. Figure out the correct Create function to do all this
85b9c1b51eSKate Stone // work.
86ef651600SJim Ingham
87b9c1b51eSKate Stone if (persistent) {
885435f780SAdrian Prantl Target &target = *thread.CalculateTarget();
89b9c1b51eSKate Stone PersistentExpressionState *persistent_expression_state =
905435f780SAdrian Prantl target.GetPersistentExpressionStateForLanguage(
91b9c1b51eSKate Stone ast_type.GetMinimumLanguage());
92b92bd753SSean Callanan
93b92bd753SSean Callanan if (!persistent_expression_state)
94e9331a56SAdrian Prantl return {};
95b92bd753SSean Callanan
9603219f7fSAdrian Prantl ConstString persistent_variable_name =
9767d67ebeSJim Ingham persistent_expression_state->GetNextPersistentVariableName();
98ef651600SJim Ingham
99ef651600SJim Ingham lldb::ValueObjectSP const_valobj_sp;
100ef651600SJim Ingham
101ef651600SJim Ingham // Check in case our value is already a constant value
102b9c1b51eSKate Stone if (return_valobj_sp->GetIsConstant()) {
103ef651600SJim Ingham const_valobj_sp = return_valobj_sp;
104ef651600SJim Ingham const_valobj_sp->SetName(persistent_variable_name);
105b9c1b51eSKate Stone } else
106b9c1b51eSKate Stone const_valobj_sp =
107b9c1b51eSKate Stone return_valobj_sp->CreateConstantValue(persistent_variable_name);
108ef651600SJim Ingham
109ef651600SJim Ingham lldb::ValueObjectSP live_valobj_sp = return_valobj_sp;
110ef651600SJim Ingham
111ef651600SJim Ingham return_valobj_sp = const_valobj_sp;
112ef651600SJim Ingham
113e574f8b3SAlex Langford ExpressionVariableSP expr_variable_sp(
114b9c1b51eSKate Stone persistent_expression_state->CreatePersistentVariable(
115b9c1b51eSKate Stone return_valobj_sp));
116ef651600SJim Ingham
117e574f8b3SAlex Langford assert(expr_variable_sp);
118ef651600SJim Ingham
119ef651600SJim Ingham // Set flags and live data as appropriate
120ef651600SJim Ingham
121ef651600SJim Ingham const Value &result_value = live_valobj_sp->GetValue();
122ef651600SJim Ingham
123b9c1b51eSKate Stone switch (result_value.GetValueType()) {
124057efa99SAdrian Prantl case Value::ValueType::Invalid:
125057efa99SAdrian Prantl return {};
126057efa99SAdrian Prantl case Value::ValueType::HostAddress:
127057efa99SAdrian Prantl case Value::ValueType::FileAddress:
128057efa99SAdrian Prantl // we odon't do anything with these for now
129ef651600SJim Ingham break;
130057efa99SAdrian Prantl case Value::ValueType::Scalar:
131e574f8b3SAlex Langford expr_variable_sp->m_flags |=
1324dc0acc9SAlex Langford ExpressionVariable::EVIsFreezeDried;
133e574f8b3SAlex Langford expr_variable_sp->m_flags |=
1344dc0acc9SAlex Langford ExpressionVariable::EVIsLLDBAllocated;
135e574f8b3SAlex Langford expr_variable_sp->m_flags |=
1364dc0acc9SAlex Langford ExpressionVariable::EVNeedsAllocation;
137ef651600SJim Ingham break;
138057efa99SAdrian Prantl case Value::ValueType::LoadAddress:
139e574f8b3SAlex Langford expr_variable_sp->m_live_sp = live_valobj_sp;
140e574f8b3SAlex Langford expr_variable_sp->m_flags |=
1414dc0acc9SAlex Langford ExpressionVariable::EVIsProgramReference;
142ef651600SJim Ingham break;
143ef651600SJim Ingham }
144ef651600SJim Ingham
145e574f8b3SAlex Langford return_valobj_sp = expr_variable_sp->GetValueObject();
146ef651600SJim Ingham }
147ef651600SJim Ingham return return_valobj_sp;
14873ca05a2SJim Ingham }
14973ca05a2SJim Ingham
GetReturnValueObject(Thread & thread,llvm::Type & ast_type,bool persistent) const150b9c1b51eSKate Stone ValueObjectSP ABI::GetReturnValueObject(Thread &thread, llvm::Type &ast_type,
151b9c1b51eSKate Stone bool persistent) const {
1522526ee5aSDeepak Panickal ValueObjectSP return_valobj_sp;
1532526ee5aSDeepak Panickal return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type);
1542526ee5aSDeepak Panickal return return_valobj_sp;
1552526ee5aSDeepak Panickal }
15673ca05a2SJim Ingham
1572526ee5aSDeepak Panickal // specialized to work with llvm IR types
1582526ee5aSDeepak Panickal //
1592526ee5aSDeepak Panickal // for now we will specify a default implementation so that we don't need to
1602526ee5aSDeepak Panickal // modify other ABIs
GetReturnValueObjectImpl(Thread & thread,llvm::Type & ir_type) const161b9c1b51eSKate Stone lldb::ValueObjectSP ABI::GetReturnValueObjectImpl(Thread &thread,
162b9c1b51eSKate Stone llvm::Type &ir_type) const {
1632526ee5aSDeepak Panickal ValueObjectSP return_valobj_sp;
1642526ee5aSDeepak Panickal
1652526ee5aSDeepak Panickal /* this is a dummy and will only be called if an ABI does not override this */
1662526ee5aSDeepak Panickal
1672526ee5aSDeepak Panickal return return_valobj_sp;
1682526ee5aSDeepak Panickal }
1692526ee5aSDeepak Panickal
PrepareTrivialCall(Thread & thread,lldb::addr_t sp,lldb::addr_t functionAddress,lldb::addr_t returnAddress,llvm::Type & returntype,llvm::ArrayRef<ABI::CallArgument> args) const170b9c1b51eSKate Stone bool ABI::PrepareTrivialCall(Thread &thread, lldb::addr_t sp,
1712526ee5aSDeepak Panickal lldb::addr_t functionAddress,
172b9c1b51eSKate Stone lldb::addr_t returnAddress, llvm::Type &returntype,
173b9c1b51eSKate Stone llvm::ArrayRef<ABI::CallArgument> args) const {
1742526ee5aSDeepak Panickal // dummy prepare trivial call
175a322f36cSDavid Blaikie llvm_unreachable("Should never get here!");
1762526ee5aSDeepak Panickal }
1777311bb34SUlrich Weigand
GetFallbackRegisterLocation(const RegisterInfo * reg_info,UnwindPlan::Row::RegisterLocation & unwind_regloc)178b9c1b51eSKate Stone bool ABI::GetFallbackRegisterLocation(
179b9c1b51eSKate Stone const RegisterInfo *reg_info,
180b9c1b51eSKate Stone UnwindPlan::Row::RegisterLocation &unwind_regloc) {
18105097246SAdrian Prantl // Did the UnwindPlan fail to give us the caller's stack pointer? The stack
18205097246SAdrian Prantl // pointer is defined to be the same as THIS frame's CFA, so return the CFA
18305097246SAdrian Prantl // value as the caller's stack pointer. This is true on x86-32/x86-64 at
18405097246SAdrian Prantl // least.
185b9c1b51eSKate Stone if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) {
1867311bb34SUlrich Weigand unwind_regloc.SetIsCFAPlusOffset(0);
1877311bb34SUlrich Weigand return true;
1887311bb34SUlrich Weigand }
1897311bb34SUlrich Weigand
190b9c1b51eSKate Stone // If a volatile register is being requested, we don't want to forward the
19105097246SAdrian Prantl // next frame's register contents up the stack -- the register is not
19205097246SAdrian Prantl // retrievable at this frame.
193b9c1b51eSKate Stone if (RegisterIsVolatile(reg_info)) {
1947311bb34SUlrich Weigand unwind_regloc.SetUndefined();
1957311bb34SUlrich Weigand return true;
1967311bb34SUlrich Weigand }
1977311bb34SUlrich Weigand
1987311bb34SUlrich Weigand return false;
1997311bb34SUlrich Weigand }
200d0b44dbeSPavel Labath
MakeMCRegisterInfo(const ArchSpec & arch)201d0b44dbeSPavel Labath std::unique_ptr<llvm::MCRegisterInfo> ABI::MakeMCRegisterInfo(const ArchSpec &arch) {
202d0b44dbeSPavel Labath std::string triple = arch.GetTriple().getTriple();
203d0b44dbeSPavel Labath std::string lookup_error;
204d0b44dbeSPavel Labath const llvm::Target *target =
205d0b44dbeSPavel Labath llvm::TargetRegistry::lookupTarget(triple, lookup_error);
206d0b44dbeSPavel Labath if (!target) {
207a007a6d8SPavel Labath LLDB_LOG(GetLog(LLDBLog::Process),
208d0b44dbeSPavel Labath "Failed to create an llvm target for {0}: {1}", triple,
209d0b44dbeSPavel Labath lookup_error);
210d0b44dbeSPavel Labath return nullptr;
211d0b44dbeSPavel Labath }
212d0b44dbeSPavel Labath std::unique_ptr<llvm::MCRegisterInfo> info_up(
213d0b44dbeSPavel Labath target->createMCRegInfo(triple));
214d0b44dbeSPavel Labath assert(info_up);
215d0b44dbeSPavel Labath return info_up;
216d0b44dbeSPavel Labath }
2172b8db387SPavel Labath
AugmentRegisterInfo(std::vector<DynamicRegisterInfo::Register> & regs)21858492191SMichał Górny void RegInfoBasedABI::AugmentRegisterInfo(
21958492191SMichał Górny std::vector<DynamicRegisterInfo::Register> ®s) {
22058492191SMichał Górny for (DynamicRegisterInfo::Register &info : regs) {
22158492191SMichał Górny if (info.regnum_ehframe != LLDB_INVALID_REGNUM &&
22258492191SMichał Górny info.regnum_dwarf != LLDB_INVALID_REGNUM)
22358492191SMichał Górny continue;
2242b8db387SPavel Labath
2252b8db387SPavel Labath RegisterInfo abi_info;
22658492191SMichał Górny if (!GetRegisterInfoByName(info.name.GetStringRef(), abi_info))
22758492191SMichał Górny continue;
2282b8db387SPavel Labath
22958492191SMichał Górny if (info.regnum_ehframe == LLDB_INVALID_REGNUM)
23058492191SMichał Górny info.regnum_ehframe = abi_info.kinds[eRegisterKindEHFrame];
23158492191SMichał Górny if (info.regnum_dwarf == LLDB_INVALID_REGNUM)
23258492191SMichał Górny info.regnum_dwarf = abi_info.kinds[eRegisterKindDWARF];
23358492191SMichał Górny if (info.regnum_generic == LLDB_INVALID_REGNUM)
23458492191SMichał Górny info.regnum_generic = abi_info.kinds[eRegisterKindGeneric];
23558492191SMichał Górny }
2362b8db387SPavel Labath }
23707355c1cSPavel Labath
AugmentRegisterInfo(std::vector<DynamicRegisterInfo::Register> & regs)23858492191SMichał Górny void MCBasedABI::AugmentRegisterInfo(
23958492191SMichał Górny std::vector<DynamicRegisterInfo::Register> ®s) {
24058492191SMichał Górny for (DynamicRegisterInfo::Register &info : regs) {
24107355c1cSPavel Labath uint32_t eh, dwarf;
24258492191SMichał Górny std::tie(eh, dwarf) = GetEHAndDWARFNums(info.name.GetStringRef());
24307355c1cSPavel Labath
24458492191SMichał Górny if (info.regnum_ehframe == LLDB_INVALID_REGNUM)
24558492191SMichał Górny info.regnum_ehframe = eh;
24658492191SMichał Górny if (info.regnum_dwarf == LLDB_INVALID_REGNUM)
24758492191SMichał Górny info.regnum_dwarf = dwarf;
24858492191SMichał Górny if (info.regnum_generic == LLDB_INVALID_REGNUM)
24958492191SMichał Górny info.regnum_generic = GetGenericNum(info.name.GetStringRef());
25058492191SMichał Górny }
25107355c1cSPavel Labath }
25207355c1cSPavel Labath
25307355c1cSPavel Labath std::pair<uint32_t, uint32_t>
GetEHAndDWARFNums(llvm::StringRef name)25407355c1cSPavel Labath MCBasedABI::GetEHAndDWARFNums(llvm::StringRef name) {
25507355c1cSPavel Labath std::string mc_name = GetMCName(name.str());
256b2d64b69SPavel Labath for (char &c : mc_name)
257b2d64b69SPavel Labath c = std::toupper(c);
25807355c1cSPavel Labath int eh = -1;
25907355c1cSPavel Labath int dwarf = -1;
26007355c1cSPavel Labath for (unsigned reg = 0; reg < m_mc_register_info_up->getNumRegs(); ++reg) {
26107355c1cSPavel Labath if (m_mc_register_info_up->getName(reg) == mc_name) {
26207355c1cSPavel Labath eh = m_mc_register_info_up->getDwarfRegNum(reg, /*isEH=*/true);
26307355c1cSPavel Labath dwarf = m_mc_register_info_up->getDwarfRegNum(reg, /*isEH=*/false);
26407355c1cSPavel Labath break;
26507355c1cSPavel Labath }
26607355c1cSPavel Labath }
26707355c1cSPavel Labath return std::pair<uint32_t, uint32_t>(eh == -1 ? LLDB_INVALID_REGNUM : eh,
26807355c1cSPavel Labath dwarf == -1 ? LLDB_INVALID_REGNUM
26907355c1cSPavel Labath : dwarf);
27007355c1cSPavel Labath }
27107355c1cSPavel Labath
MapRegisterName(std::string & name,llvm::StringRef from_prefix,llvm::StringRef to_prefix)27207355c1cSPavel Labath void MCBasedABI::MapRegisterName(std::string &name, llvm::StringRef from_prefix,
27307355c1cSPavel Labath llvm::StringRef to_prefix) {
27407355c1cSPavel Labath llvm::StringRef name_ref = name;
27507355c1cSPavel Labath if (!name_ref.consume_front(from_prefix))
27607355c1cSPavel Labath return;
27707355c1cSPavel Labath uint64_t _;
27807355c1cSPavel Labath if (name_ref.empty() || to_integer(name_ref, _, 10))
27907355c1cSPavel Labath name = (to_prefix + name_ref).str();
28007355c1cSPavel Labath }
281