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> &regs) {
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> &regs) {
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