|
10 | 10 |
|
11 | 11 | #include <array>
|
12 | 12 | #include <limits>
|
| 13 | +#include <sstream> |
13 | 14 |
|
| 15 | +#include "llvm/ADT/STLExtras.h" |
14 | 16 | #include "llvm/IR/DerivedTypes.h"
|
15 | 17 |
|
16 | 18 | #include "Utility/RISCV_DWARF_Registers.h"
|
|
20 | 22 | #include "lldb/Target/RegisterContext.h"
|
21 | 23 | #include "lldb/Target/StackFrame.h"
|
22 | 24 | #include "lldb/Target/Thread.h"
|
| 25 | +#include "lldb/Utility/LLDBLog.h" |
23 | 26 | #include "lldb/Utility/RegisterValue.h"
|
24 | 27 |
|
25 | 28 | #define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
|
@@ -164,11 +167,83 @@ TotalArgsSizeInWords(bool is_rv64,
|
164 | 167 | return total_size;
|
165 | 168 | }
|
166 | 169 |
|
| 170 | +static bool UpdateRegister(RegisterContext *reg_ctx, |
| 171 | + const lldb::RegisterKind reg_kind, |
| 172 | + const uint32_t reg_num, const addr_t value) { |
| 173 | + Log *log = GetLog(LLDBLog::Expressions); |
| 174 | + |
| 175 | + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(reg_kind, reg_num); |
| 176 | + |
| 177 | + LLDB_LOG(log, "Writing %s: 0x%" PRIx64, reg_info->name, |
| 178 | + static_cast<uint64_t>(value)); |
| 179 | + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, value)) { |
| 180 | + LLDB_LOG(log, "Writing %s: failed", reg_info->name); |
| 181 | + return false; |
| 182 | + } |
| 183 | + return true; |
| 184 | +} |
| 185 | + |
| 186 | +static void LogInitInfo(Log *log, const Thread &thread, addr_t sp, |
| 187 | + addr_t func_addr, addr_t return_addr, |
| 188 | + const llvm::ArrayRef<addr_t> args) { |
| 189 | + assert(log); |
| 190 | + std::stringstream ss; |
| 191 | + ss << "ABISysV_riscv::PrepareTrivialCall" |
| 192 | + << " (tid = 0x%" << std::hex << thread.GetID() << ", sp = 0x%" << sp |
| 193 | + << ", func_addr = 0x%" << func_addr << ", return_addr = 0x%" |
| 194 | + << return_addr; |
| 195 | + |
| 196 | + for (auto &&[idx, arg] : enumerate(args)) |
| 197 | + ss << ", arg" << std::dec << idx << " = 0x%" << std::hex << arg; |
| 198 | + ss << ")"; |
| 199 | + log->PutString(ss.str()); |
| 200 | +} |
| 201 | + |
167 | 202 | bool ABISysV_riscv::PrepareTrivialCall(Thread &thread, addr_t sp,
|
168 | 203 | addr_t func_addr, addr_t return_addr,
|
169 | 204 | llvm::ArrayRef<addr_t> args) const {
|
170 |
| - // TODO: Implement |
171 |
| - return false; |
| 205 | + Log *log = GetLog(LLDBLog::Expressions); |
| 206 | + if (log) |
| 207 | + LogInitInfo(log, thread, sp, func_addr, return_addr, args); |
| 208 | + |
| 209 | + const auto reg_ctx_sp = thread.GetRegisterContext(); |
| 210 | + if (!reg_ctx_sp) { |
| 211 | + LLDB_LOG(log, "Failed to get RegisterContext"); |
| 212 | + return false; |
| 213 | + } |
| 214 | + |
| 215 | + if (args.size() > s_regs_for_args_count) { |
| 216 | + LLDB_LOG(log, "Function has %lu arguments, but only %lu are allowed!", |
| 217 | + args.size(), s_regs_for_args_count); |
| 218 | + return false; |
| 219 | + } |
| 220 | + |
| 221 | + // Write arguments to registers |
| 222 | + for (auto &&[idx, arg] : enumerate(args)) { |
| 223 | + const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo( |
| 224 | + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + idx); |
| 225 | + LLDB_LOG(log, "About to write arg%lu (0x%" PRIx64 ") into %s", idx, arg, |
| 226 | + reg_info->name); |
| 227 | + |
| 228 | + if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) { |
| 229 | + LLDB_LOG(log, "Failed to write arg%lu (0x%" PRIx64 ") into %s", idx, arg, |
| 230 | + reg_info->name); |
| 231 | + return false; |
| 232 | + } |
| 233 | + } |
| 234 | + |
| 235 | + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, |
| 236 | + LLDB_REGNUM_GENERIC_PC, func_addr)) |
| 237 | + return false; |
| 238 | + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, |
| 239 | + LLDB_REGNUM_GENERIC_SP, sp)) |
| 240 | + return false; |
| 241 | + if (!UpdateRegister(reg_ctx_sp.get(), eRegisterKindGeneric, |
| 242 | + LLDB_REGNUM_GENERIC_RA, return_addr)) |
| 243 | + return false; |
| 244 | + |
| 245 | + LLDB_LOG(log, "ABISysV_riscv::%s: success", __func__); |
| 246 | + return true; |
172 | 247 | }
|
173 | 248 |
|
174 | 249 | bool ABISysV_riscv::PrepareTrivialCall(
|
@@ -222,14 +297,14 @@ bool ABISysV_riscv::PrepareTrivialCall(
|
222 | 297 | assert(prototype.getFunctionNumParams() == args.size());
|
223 | 298 |
|
224 | 299 | const size_t num_args = args.size();
|
225 |
| - const size_t regs_for_args_count = 8U; |
226 | 300 | const size_t num_args_in_regs =
|
227 |
| - num_args > regs_for_args_count ? regs_for_args_count : num_args; |
| 301 | + num_args > s_regs_for_args_count ? s_regs_for_args_count : num_args; |
228 | 302 |
|
229 | 303 | // Number of arguments passed on stack.
|
230 | 304 | size_t args_size = TotalArgsSizeInWords(m_is_rv64, args);
|
231 |
| - auto on_stack = |
232 |
| - args_size <= regs_for_args_count ? 0 : args_size - regs_for_args_count; |
| 305 | + auto on_stack = args_size <= s_regs_for_args_count |
| 306 | + ? 0 |
| 307 | + : args_size - s_regs_for_args_count; |
233 | 308 | auto offset = on_stack * word_size;
|
234 | 309 |
|
235 | 310 | uint8_t reg_value[8];
|
@@ -260,7 +335,7 @@ bool ABISysV_riscv::PrepareTrivialCall(
|
260 | 335 | ++reg_index;
|
261 | 336 | }
|
262 | 337 |
|
263 |
| - if (reg_index < regs_for_args_count || size == 0) |
| 338 | + if (reg_index < s_regs_for_args_count || size == 0) |
264 | 339 | continue;
|
265 | 340 |
|
266 | 341 | // Remaining arguments are passed on the stack.
|
|
0 commit comments