1 | //===-- ABISysV_ppc64.cpp -------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "ABISysV_ppc64.h" |
10 | |
11 | #include "llvm/ADT/STLExtras.h" |
12 | #include "llvm/TargetParser/Triple.h" |
13 | |
14 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
15 | #include "Utility/PPC64LE_DWARF_Registers.h" |
16 | #include "Utility/PPC64_DWARF_Registers.h" |
17 | #include "lldb/Core/Module.h" |
18 | #include "lldb/Core/PluginManager.h" |
19 | #include "lldb/Core/Value.h" |
20 | #include "lldb/Core/ValueObjectConstResult.h" |
21 | #include "lldb/Core/ValueObjectMemory.h" |
22 | #include "lldb/Core/ValueObjectRegister.h" |
23 | #include "lldb/Symbol/UnwindPlan.h" |
24 | #include "lldb/Target/Process.h" |
25 | #include "lldb/Target/RegisterContext.h" |
26 | #include "lldb/Target/StackFrame.h" |
27 | #include "lldb/Target/Target.h" |
28 | #include "lldb/Target/Thread.h" |
29 | #include "lldb/Utility/ConstString.h" |
30 | #include "lldb/Utility/DataExtractor.h" |
31 | #include "lldb/Utility/LLDBLog.h" |
32 | #include "lldb/Utility/Log.h" |
33 | #include "lldb/Utility/RegisterValue.h" |
34 | #include "lldb/Utility/Status.h" |
35 | |
36 | #include "clang/AST/ASTContext.h" |
37 | #include "clang/AST/Attr.h" |
38 | #include "clang/AST/Decl.h" |
39 | |
40 | #define DECLARE_REGISTER_INFOS_PPC64_STRUCT |
41 | #include "Plugins/Process/Utility/RegisterInfos_ppc64.h" |
42 | #undef DECLARE_REGISTER_INFOS_PPC64_STRUCT |
43 | |
44 | #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT |
45 | #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h" |
46 | #undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT |
47 | #include <optional> |
48 | |
49 | using namespace lldb; |
50 | using namespace lldb_private; |
51 | |
52 | LLDB_PLUGIN_DEFINE(ABISysV_ppc64) |
53 | |
54 | const lldb_private::RegisterInfo * |
55 | ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) { |
56 | if (GetByteOrder() == lldb::eByteOrderLittle) { |
57 | count = std::size(g_register_infos_ppc64le); |
58 | return g_register_infos_ppc64le; |
59 | } else { |
60 | count = std::size(g_register_infos_ppc64); |
61 | return g_register_infos_ppc64; |
62 | } |
63 | } |
64 | |
65 | size_t ABISysV_ppc64::GetRedZoneSize() const { return 224; } |
66 | |
67 | lldb::ByteOrder ABISysV_ppc64::GetByteOrder() const { |
68 | return GetProcessSP()->GetByteOrder(); |
69 | } |
70 | |
71 | // Static Functions |
72 | |
73 | ABISP |
74 | ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, |
75 | const ArchSpec &arch) { |
76 | if (arch.GetTriple().isPPC64()) |
77 | return ABISP( |
78 | new ABISysV_ppc64(std::move(process_sp), MakeMCRegisterInfo(arch))); |
79 | return ABISP(); |
80 | } |
81 | |
82 | bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp, |
83 | addr_t func_addr, addr_t return_addr, |
84 | llvm::ArrayRef<addr_t> args) const { |
85 | Log *log = GetLog(mask: LLDBLog::Expressions); |
86 | |
87 | if (log) { |
88 | StreamString s; |
89 | s.Printf(format: "ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 |
90 | ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 |
91 | ", return_addr = 0x%" PRIx64, |
92 | thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, |
93 | (uint64_t)return_addr); |
94 | |
95 | for (size_t i = 0; i < args.size(); ++i) |
96 | s.Printf(format: ", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), |
97 | args[i]); |
98 | s.PutCString(cstr: ")" ); |
99 | log->PutString(str: s.GetString()); |
100 | } |
101 | |
102 | RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
103 | if (!reg_ctx) |
104 | return false; |
105 | |
106 | const RegisterInfo *reg_info = nullptr; |
107 | |
108 | if (args.size() > 8) // TODO handle more than 8 arguments |
109 | return false; |
110 | |
111 | for (size_t i = 0; i < args.size(); ++i) { |
112 | reg_info = reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, |
113 | LLDB_REGNUM_GENERIC_ARG1 + i); |
114 | LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s" , |
115 | static_cast<uint64_t>(i + 1), args[i], reg_info->name); |
116 | if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, uval: args[i])) |
117 | return false; |
118 | } |
119 | |
120 | // First, align the SP |
121 | |
122 | LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, |
123 | (uint64_t)sp, (uint64_t)(sp & ~0xfull)); |
124 | |
125 | sp &= ~(0xfull); // 16-byte alignment |
126 | |
127 | sp -= 544; // allocate frame to save TOC, RA and SP. |
128 | |
129 | Status error; |
130 | uint64_t reg_value; |
131 | const RegisterInfo *pc_reg_info = |
132 | reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); |
133 | const RegisterInfo *sp_reg_info = |
134 | reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); |
135 | ProcessSP process_sp(thread.GetProcess()); |
136 | const RegisterInfo *lr_reg_info = |
137 | reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); |
138 | const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(reg: 2); |
139 | const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(reg: 12); |
140 | |
141 | // Save return address onto the stack. |
142 | LLDB_LOGF(log, |
143 | "Pushing the return address onto the stack: 0x%" PRIx64 |
144 | "(+16): 0x%" PRIx64, |
145 | (uint64_t)sp, (uint64_t)return_addr); |
146 | if (!process_sp->WritePointerToMemory(vm_addr: sp + 16, ptr_value: return_addr, error)) |
147 | return false; |
148 | |
149 | // Write the return address to link register. |
150 | LLDB_LOGF(log, "Writing LR: 0x%" PRIx64, (uint64_t)return_addr); |
151 | if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: lr_reg_info, uval: return_addr)) |
152 | return false; |
153 | |
154 | // Write target address to %r12 register. |
155 | LLDB_LOGF(log, "Writing R12: 0x%" PRIx64, (uint64_t)func_addr); |
156 | if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: r12_reg_info, uval: func_addr)) |
157 | return false; |
158 | |
159 | // Read TOC pointer value. |
160 | reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_info: r2_reg_info, fail_value: 0); |
161 | |
162 | // Write TOC pointer onto the stack. |
163 | uint64_t stack_offset; |
164 | if (GetByteOrder() == lldb::eByteOrderLittle) |
165 | stack_offset = 24; |
166 | else |
167 | stack_offset = 40; |
168 | |
169 | LLDB_LOGF(log, "Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64, |
170 | (uint64_t)(sp + stack_offset), (int)stack_offset, |
171 | (uint64_t)reg_value); |
172 | if (!process_sp->WritePointerToMemory(vm_addr: sp + stack_offset, ptr_value: reg_value, error)) |
173 | return false; |
174 | |
175 | // Read the current SP value. |
176 | reg_value = reg_ctx->ReadRegisterAsUnsigned(reg_info: sp_reg_info, fail_value: 0); |
177 | |
178 | // Save current SP onto the stack. |
179 | LLDB_LOGF(log, "Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp, |
180 | (uint64_t)reg_value); |
181 | if (!process_sp->WritePointerToMemory(vm_addr: sp, ptr_value: reg_value, error)) |
182 | return false; |
183 | |
184 | // %r1 is set to the actual stack value. |
185 | LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp); |
186 | |
187 | if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: sp_reg_info, uval: sp)) |
188 | return false; |
189 | |
190 | // %pc is set to the address of the called function. |
191 | |
192 | LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr); |
193 | |
194 | if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: pc_reg_info, uval: func_addr)) |
195 | return false; |
196 | |
197 | return true; |
198 | } |
199 | |
200 | static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, |
201 | bool is_signed, Thread &thread, |
202 | uint32_t *argument_register_ids, |
203 | unsigned int ¤t_argument_register, |
204 | addr_t ¤t_stack_argument) { |
205 | if (bit_width > 64) |
206 | return false; // Scalar can't hold large integer arguments |
207 | |
208 | if (current_argument_register < 6) { |
209 | scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned( |
210 | reg: argument_register_ids[current_argument_register], fail_value: 0); |
211 | current_argument_register++; |
212 | if (is_signed) |
213 | scalar.SignExtend(bit_pos: bit_width); |
214 | } else { |
215 | uint32_t byte_size = (bit_width + (8 - 1)) / 8; |
216 | Status error; |
217 | if (thread.GetProcess()->ReadScalarIntegerFromMemory( |
218 | addr: current_stack_argument, byte_size, is_signed, scalar, error)) { |
219 | current_stack_argument += byte_size; |
220 | return true; |
221 | } |
222 | return false; |
223 | } |
224 | return true; |
225 | } |
226 | |
227 | bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const { |
228 | unsigned int num_values = values.GetSize(); |
229 | unsigned int value_index; |
230 | |
231 | // Extract the register context so we can read arguments from registers |
232 | |
233 | RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
234 | |
235 | if (!reg_ctx) |
236 | return false; |
237 | |
238 | // Get the pointer to the first stack argument so we have a place to start |
239 | // when reading data |
240 | |
241 | addr_t sp = reg_ctx->GetSP(fail_value: 0); |
242 | |
243 | if (!sp) |
244 | return false; |
245 | |
246 | uint64_t stack_offset; |
247 | if (GetByteOrder() == lldb::eByteOrderLittle) |
248 | stack_offset = 32; |
249 | else |
250 | stack_offset = 48; |
251 | |
252 | // jump over return address. |
253 | addr_t current_stack_argument = sp + stack_offset; |
254 | uint32_t argument_register_ids[8]; |
255 | |
256 | for (size_t i = 0; i < 8; ++i) { |
257 | argument_register_ids[i] = |
258 | reg_ctx |
259 | ->GetRegisterInfo(reg_kind: eRegisterKindGeneric, |
260 | LLDB_REGNUM_GENERIC_ARG1 + i) |
261 | ->kinds[eRegisterKindLLDB]; |
262 | } |
263 | |
264 | unsigned int current_argument_register = 0; |
265 | |
266 | for (value_index = 0; value_index < num_values; ++value_index) { |
267 | Value *value = values.GetValueAtIndex(idx: value_index); |
268 | |
269 | if (!value) |
270 | return false; |
271 | |
272 | // We currently only support extracting values with Clang QualTypes. Do we |
273 | // care about others? |
274 | CompilerType compiler_type = value->GetCompilerType(); |
275 | std::optional<uint64_t> bit_size = compiler_type.GetBitSize(exe_scope: &thread); |
276 | if (!bit_size) |
277 | return false; |
278 | bool is_signed; |
279 | |
280 | if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { |
281 | ReadIntegerArgument(scalar&: value->GetScalar(), bit_width: *bit_size, is_signed, thread, |
282 | argument_register_ids, current_argument_register, |
283 | current_stack_argument); |
284 | } else if (compiler_type.IsPointerType()) { |
285 | ReadIntegerArgument(scalar&: value->GetScalar(), bit_width: *bit_size, is_signed: false, thread, |
286 | argument_register_ids, current_argument_register, |
287 | current_stack_argument); |
288 | } |
289 | } |
290 | |
291 | return true; |
292 | } |
293 | |
294 | Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, |
295 | lldb::ValueObjectSP &new_value_sp) { |
296 | Status error; |
297 | if (!new_value_sp) { |
298 | error.SetErrorString("Empty value object for return value." ); |
299 | return error; |
300 | } |
301 | |
302 | CompilerType compiler_type = new_value_sp->GetCompilerType(); |
303 | if (!compiler_type) { |
304 | error.SetErrorString("Null clang type for return value." ); |
305 | return error; |
306 | } |
307 | |
308 | Thread *thread = frame_sp->GetThread().get(); |
309 | |
310 | bool is_signed; |
311 | uint32_t count; |
312 | bool is_complex; |
313 | |
314 | RegisterContext *reg_ctx = thread->GetRegisterContext().get(); |
315 | |
316 | bool set_it_simple = false; |
317 | if (compiler_type.IsIntegerOrEnumerationType(is_signed) || |
318 | compiler_type.IsPointerType()) { |
319 | const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name: "r3" , start_idx: 0); |
320 | |
321 | DataExtractor data; |
322 | Status data_error; |
323 | size_t num_bytes = new_value_sp->GetData(data, error&: data_error); |
324 | if (data_error.Fail()) { |
325 | error.SetErrorStringWithFormat( |
326 | "Couldn't convert return value to raw data: %s" , |
327 | data_error.AsCString()); |
328 | return error; |
329 | } |
330 | lldb::offset_t offset = 0; |
331 | if (num_bytes <= 8) { |
332 | uint64_t raw_value = data.GetMaxU64(offset_ptr: &offset, byte_size: num_bytes); |
333 | |
334 | if (reg_ctx->WriteRegisterFromUnsigned(reg_info, uval: raw_value)) |
335 | set_it_simple = true; |
336 | } else { |
337 | error.SetErrorString("We don't support returning longer than 64 bit " |
338 | "integer values at present." ); |
339 | } |
340 | } else if (compiler_type.IsFloatingPointType(count, is_complex)) { |
341 | if (is_complex) |
342 | error.SetErrorString( |
343 | "We don't support returning complex values at present" ); |
344 | else { |
345 | std::optional<uint64_t> bit_width = |
346 | compiler_type.GetBitSize(exe_scope: frame_sp.get()); |
347 | if (!bit_width) { |
348 | error.SetErrorString("can't get size of type" ); |
349 | return error; |
350 | } |
351 | if (*bit_width <= 64) { |
352 | DataExtractor data; |
353 | Status data_error; |
354 | size_t num_bytes = new_value_sp->GetData(data, error&: data_error); |
355 | if (data_error.Fail()) { |
356 | error.SetErrorStringWithFormat( |
357 | "Couldn't convert return value to raw data: %s" , |
358 | data_error.AsCString()); |
359 | return error; |
360 | } |
361 | |
362 | unsigned char buffer[16]; |
363 | ByteOrder byte_order = data.GetByteOrder(); |
364 | |
365 | data.CopyByteOrderedData(src_offset: 0, src_len: num_bytes, dst: buffer, dst_len: 16, dst_byte_order: byte_order); |
366 | set_it_simple = true; |
367 | } else { |
368 | // FIXME - don't know how to do 80 bit long doubles yet. |
369 | error.SetErrorString( |
370 | "We don't support returning float values > 64 bits at present" ); |
371 | } |
372 | } |
373 | } |
374 | |
375 | if (!set_it_simple) { |
376 | // Okay we've got a structure or something that doesn't fit in a simple |
377 | // register. We should figure out where it really goes, but we don't |
378 | // support this yet. |
379 | error.SetErrorString("We only support setting simple integer and float " |
380 | "return types at present." ); |
381 | } |
382 | |
383 | return error; |
384 | } |
385 | |
386 | // |
387 | // ReturnValueExtractor |
388 | // |
389 | |
390 | namespace { |
391 | |
392 | #define LOG_PREFIX "ReturnValueExtractor: " |
393 | |
394 | class { |
395 | // This class represents a register, from which data may be extracted. |
396 | // |
397 | // It may be constructed by directly specifying its index (where 0 is the |
398 | // first register used to return values) or by specifying the offset of a |
399 | // given struct field, in which case the appropriated register index will be |
400 | // calculated. |
401 | class { |
402 | public: |
403 | enum { |
404 | , // General Purpose Register |
405 | // Floating Point Register |
406 | }; |
407 | |
408 | // main constructor |
409 | // |
410 | // offs - field offset in struct |
411 | (Type ty, uint32_t index, uint32_t offs, RegisterContext *reg_ctx, |
412 | ByteOrder byte_order) |
413 | : m_index(index), m_offs(offs % sizeof(uint64_t)), |
414 | m_avail(sizeof(uint64_t) - m_offs), m_type(ty), m_reg_ctx(reg_ctx), |
415 | m_byte_order(byte_order) {} |
416 | |
417 | // explicit index, no offset |
418 | (Type ty, uint32_t index, RegisterContext *reg_ctx, |
419 | ByteOrder byte_order) |
420 | : Register(ty, index, 0, reg_ctx, byte_order) {} |
421 | |
422 | // GPR, calculate index from offs |
423 | (uint32_t offs, RegisterContext *reg_ctx, ByteOrder byte_order) |
424 | : Register(GPR, offs / sizeof(uint64_t), offs, reg_ctx, byte_order) {} |
425 | |
426 | uint32_t () const { return m_index; } |
427 | |
428 | // register offset where data is located |
429 | uint32_t () const { return m_offs; } |
430 | |
431 | // available bytes in this register |
432 | uint32_t () const { return m_avail; } |
433 | |
434 | bool () const { |
435 | if (m_index > 7) { |
436 | LLDB_LOG(m_log, LOG_PREFIX |
437 | "No more than 8 registers should be used to return values" ); |
438 | return false; |
439 | } |
440 | return true; |
441 | } |
442 | |
443 | std::string () const { |
444 | if (m_type == GPR) |
445 | return ("r" + llvm::Twine(m_index + 3)).str(); |
446 | else |
447 | return ("f" + llvm::Twine(m_index + 1)).str(); |
448 | } |
449 | |
450 | // get raw register data |
451 | bool (uint64_t &raw_data) { |
452 | const RegisterInfo *reg_info = |
453 | m_reg_ctx->GetRegisterInfoByName(reg_name: GetName()); |
454 | if (!reg_info) { |
455 | LLDB_LOG(m_log, LOG_PREFIX "Failed to get RegisterInfo" ); |
456 | return false; |
457 | } |
458 | |
459 | RegisterValue reg_val; |
460 | if (!m_reg_ctx->ReadRegister(reg_info, reg_value&: reg_val)) { |
461 | LLDB_LOG(m_log, LOG_PREFIX "ReadRegister() failed" ); |
462 | return false; |
463 | } |
464 | |
465 | Status error; |
466 | uint32_t rc = reg_val.GetAsMemoryData( |
467 | reg_info: *reg_info, dst: &raw_data, dst_len: sizeof(raw_data), dst_byte_order: m_byte_order, error); |
468 | if (rc != sizeof(raw_data)) { |
469 | LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed" ); |
470 | return false; |
471 | } |
472 | |
473 | return true; |
474 | } |
475 | |
476 | private: |
477 | uint32_t ; |
478 | uint32_t ; |
479 | uint32_t ; |
480 | Type ; |
481 | RegisterContext *; |
482 | ByteOrder ; |
483 | Log * = GetLog(mask: LLDBLog::Expressions); |
484 | }; |
485 | |
486 | Register (uint32_t index) const { |
487 | return Register(Register::GPR, index, m_reg_ctx, m_byte_order); |
488 | } |
489 | |
490 | Register (uint32_t index) const { |
491 | return Register(Register::FPR, index, m_reg_ctx, m_byte_order); |
492 | } |
493 | |
494 | Register (uint32_t offs) const { |
495 | return Register(offs, m_reg_ctx, m_byte_order); |
496 | } |
497 | |
498 | public: |
499 | // factory |
500 | static llvm::Expected<ReturnValueExtractor> (Thread &thread, |
501 | CompilerType &type) { |
502 | RegisterContext *reg_ctx = thread.GetRegisterContext().get(); |
503 | if (!reg_ctx) |
504 | return llvm::make_error<llvm::StringError>( |
505 | LOG_PREFIX "Failed to get RegisterContext" , |
506 | Args: llvm::inconvertibleErrorCode()); |
507 | |
508 | ProcessSP process_sp = thread.GetProcess(); |
509 | if (!process_sp) |
510 | return llvm::make_error<llvm::StringError>( |
511 | LOG_PREFIX "GetProcess() failed" , Args: llvm::inconvertibleErrorCode()); |
512 | |
513 | return ReturnValueExtractor(thread, type, reg_ctx, process_sp); |
514 | } |
515 | |
516 | // main method: get value of the type specified at construction time |
517 | ValueObjectSP () { |
518 | const uint32_t type_flags = m_type.GetTypeInfo(); |
519 | |
520 | // call the appropriate type handler |
521 | ValueSP value_sp; |
522 | ValueObjectSP valobj_sp; |
523 | if (type_flags & eTypeIsScalar) { |
524 | if (type_flags & eTypeIsInteger) { |
525 | value_sp = GetIntegerValue(reg_index: 0); |
526 | } else if (type_flags & eTypeIsFloat) { |
527 | if (type_flags & eTypeIsComplex) { |
528 | LLDB_LOG(m_log, LOG_PREFIX "Complex numbers are not supported yet" ); |
529 | return ValueObjectSP(); |
530 | } else { |
531 | value_sp = GetFloatValue(type&: m_type, reg_index: 0); |
532 | } |
533 | } |
534 | } else if (type_flags & eTypeIsPointer) { |
535 | value_sp = GetPointerValue(reg_index: 0); |
536 | } |
537 | |
538 | if (value_sp) { |
539 | valobj_sp = ValueObjectConstResult::Create( |
540 | exe_scope: m_thread.GetStackFrameAtIndex(idx: 0).get(), value&: *value_sp, name: ConstString("" )); |
541 | } else if (type_flags & eTypeIsVector) { |
542 | valobj_sp = GetVectorValueObject(); |
543 | } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) { |
544 | valobj_sp = GetStructValueObject(); |
545 | } |
546 | |
547 | return valobj_sp; |
548 | } |
549 | |
550 | private: |
551 | // data |
552 | Thread &; |
553 | CompilerType &; |
554 | uint64_t ; |
555 | std::unique_ptr<DataBufferHeap> ; |
556 | int32_t = 0; |
557 | int32_t = 0; |
558 | bool = false; |
559 | Log * = GetLog(mask: LLDBLog::Expressions); |
560 | RegisterContext *; |
561 | ProcessSP ; |
562 | ByteOrder ; |
563 | uint32_t ; |
564 | |
565 | // methods |
566 | |
567 | // constructor |
568 | (Thread &thread, CompilerType &type, |
569 | RegisterContext *reg_ctx, ProcessSP process_sp) |
570 | : m_thread(thread), m_type(type), |
571 | m_byte_size(m_type.GetByteSize(exe_scope: &thread).value_or(u: 0)), |
572 | m_data_up(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx), |
573 | m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()), |
574 | m_addr_size( |
575 | process_sp->GetTarget().GetArchitecture().GetAddressByteSize()) {} |
576 | |
577 | // build a new scalar value |
578 | ValueSP (CompilerType &type) { |
579 | ValueSP value_sp(new Value); |
580 | value_sp->SetCompilerType(type); |
581 | value_sp->SetValueType(Value::ValueType::Scalar); |
582 | return value_sp; |
583 | } |
584 | |
585 | // get an integer value in the specified register |
586 | ValueSP (uint32_t reg_index) { |
587 | uint64_t raw_value; |
588 | auto reg = GetGPR(index: reg_index); |
589 | if (!reg.GetRawData(raw_data&: raw_value)) |
590 | return ValueSP(); |
591 | |
592 | // build value from data |
593 | ValueSP value_sp(NewScalarValue(type&: m_type)); |
594 | |
595 | uint32_t type_flags = m_type.GetTypeInfo(); |
596 | bool is_signed = (type_flags & eTypeIsSigned) != 0; |
597 | |
598 | switch (m_byte_size) { |
599 | case sizeof(uint64_t): |
600 | if (is_signed) |
601 | value_sp->GetScalar() = (int64_t)(raw_value); |
602 | else |
603 | value_sp->GetScalar() = (uint64_t)(raw_value); |
604 | break; |
605 | |
606 | case sizeof(uint32_t): |
607 | if (is_signed) |
608 | value_sp->GetScalar() = (int32_t)(raw_value & UINT32_MAX); |
609 | else |
610 | value_sp->GetScalar() = (uint32_t)(raw_value & UINT32_MAX); |
611 | break; |
612 | |
613 | case sizeof(uint16_t): |
614 | if (is_signed) |
615 | value_sp->GetScalar() = (int16_t)(raw_value & UINT16_MAX); |
616 | else |
617 | value_sp->GetScalar() = (uint16_t)(raw_value & UINT16_MAX); |
618 | break; |
619 | |
620 | case sizeof(uint8_t): |
621 | if (is_signed) |
622 | value_sp->GetScalar() = (int8_t)(raw_value & UINT8_MAX); |
623 | else |
624 | value_sp->GetScalar() = (uint8_t)(raw_value & UINT8_MAX); |
625 | break; |
626 | |
627 | default: |
628 | llvm_unreachable("Invalid integer size" ); |
629 | } |
630 | |
631 | return value_sp; |
632 | } |
633 | |
634 | // get a floating point value on the specified register |
635 | ValueSP (CompilerType &type, uint32_t reg_index) { |
636 | uint64_t raw_data; |
637 | auto reg = GetFPR(index: reg_index); |
638 | if (!reg.GetRawData(raw_data)) |
639 | return {}; |
640 | |
641 | // build value from data |
642 | ValueSP value_sp(NewScalarValue(type)); |
643 | |
644 | DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size); |
645 | |
646 | offset_t offset = 0; |
647 | std::optional<uint64_t> byte_size = type.GetByteSize(exe_scope: m_process_sp.get()); |
648 | if (!byte_size) |
649 | return {}; |
650 | switch (*byte_size) { |
651 | case sizeof(float): |
652 | value_sp->GetScalar() = (float)de.GetDouble(offset_ptr: &offset); |
653 | break; |
654 | |
655 | case sizeof(double): |
656 | value_sp->GetScalar() = de.GetDouble(offset_ptr: &offset); |
657 | break; |
658 | |
659 | default: |
660 | llvm_unreachable("Invalid floating point size" ); |
661 | } |
662 | |
663 | return value_sp; |
664 | } |
665 | |
666 | // get pointer value from register |
667 | ValueSP (uint32_t reg_index) { |
668 | uint64_t raw_data; |
669 | auto reg = GetGPR(index: reg_index); |
670 | if (!reg.GetRawData(raw_data)) |
671 | return ValueSP(); |
672 | |
673 | // build value from raw data |
674 | ValueSP value_sp(NewScalarValue(type&: m_type)); |
675 | value_sp->GetScalar() = raw_data; |
676 | return value_sp; |
677 | } |
678 | |
679 | // build the ValueObject from our data buffer |
680 | ValueObjectSP () { |
681 | DataExtractor de(DataBufferSP(m_data_up.release()), m_byte_order, |
682 | m_addr_size); |
683 | return ValueObjectConstResult::Create(exe_scope: &m_thread, compiler_type: m_type, name: ConstString("" ), |
684 | data: de); |
685 | } |
686 | |
687 | // get a vector return value |
688 | ValueObjectSP () { |
689 | const uint32_t MAX_VRS = 2; |
690 | |
691 | // get first V register used to return values |
692 | const RegisterInfo *vr[MAX_VRS]; |
693 | vr[0] = m_reg_ctx->GetRegisterInfoByName(reg_name: "vr2" ); |
694 | if (!vr[0]) { |
695 | LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr2 RegisterInfo" ); |
696 | return ValueObjectSP(); |
697 | } |
698 | |
699 | const uint32_t vr_size = vr[0]->byte_size; |
700 | size_t vrs = 1; |
701 | if (m_byte_size > 2 * vr_size) { |
702 | LLDB_LOG( |
703 | m_log, LOG_PREFIX |
704 | "Returning vectors that don't fit in 2 VR regs is not supported" ); |
705 | return ValueObjectSP(); |
706 | } |
707 | |
708 | // load vr3, if needed |
709 | if (m_byte_size > vr_size) { |
710 | vrs++; |
711 | vr[1] = m_reg_ctx->GetRegisterInfoByName(reg_name: "vr3" ); |
712 | if (!vr[1]) { |
713 | LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr3 RegisterInfo" ); |
714 | return ValueObjectSP(); |
715 | } |
716 | } |
717 | |
718 | // Get the whole contents of vector registers and let the logic here |
719 | // arrange the data properly. |
720 | |
721 | RegisterValue vr_val[MAX_VRS]; |
722 | Status error; |
723 | std::unique_ptr<DataBufferHeap> vr_data( |
724 | new DataBufferHeap(vrs * vr_size, 0)); |
725 | |
726 | for (uint32_t i = 0; i < vrs; i++) { |
727 | if (!m_reg_ctx->ReadRegister(reg_info: vr[i], reg_value&: vr_val[i])) { |
728 | LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents" ); |
729 | return ValueObjectSP(); |
730 | } |
731 | if (!vr_val[i].GetAsMemoryData(reg_info: *vr[i], dst: vr_data->GetBytes() + i * vr_size, |
732 | dst_len: vr_size, dst_byte_order: m_byte_order, error)) { |
733 | LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes" ); |
734 | return ValueObjectSP(); |
735 | } |
736 | } |
737 | |
738 | // The compiler generated code seems to always put the vector elements at |
739 | // the end of the vector register, in case they don't occupy all of it. |
740 | // This offset variable handles this. |
741 | uint32_t offs = 0; |
742 | if (m_byte_size < vr_size) |
743 | offs = vr_size - m_byte_size; |
744 | |
745 | // copy extracted data to our buffer |
746 | memcpy(dest: m_data_up->GetBytes(), src: vr_data->GetBytes() + offs, n: m_byte_size); |
747 | return BuildValueObject(); |
748 | } |
749 | |
750 | // get a struct return value |
751 | ValueObjectSP () { |
752 | // case 1: get from stack |
753 | if (m_byte_size > 2 * sizeof(uint64_t)) { |
754 | uint64_t addr; |
755 | auto reg = GetGPR(index: 0); |
756 | if (!reg.GetRawData(raw_data&: addr)) |
757 | return {}; |
758 | |
759 | Status error; |
760 | size_t rc = m_process_sp->ReadMemory(vm_addr: addr, buf: m_data_up->GetBytes(), |
761 | size: m_byte_size, error); |
762 | if (rc != m_byte_size) { |
763 | LLDB_LOG(m_log, LOG_PREFIX "Failed to read memory pointed by r3" ); |
764 | return ValueObjectSP(); |
765 | } |
766 | return BuildValueObject(); |
767 | } |
768 | |
769 | // get number of children |
770 | const bool omit_empty_base_classes = true; |
771 | auto n_or_err = m_type.GetNumChildren(omit_empty_base_classes, exe_ctx: nullptr); |
772 | if (!n_or_err) { |
773 | LLDB_LOG_ERROR(m_log, n_or_err.takeError(), LOG_PREFIX "{0}" ); |
774 | return {}; |
775 | } |
776 | uint32_t n = *n_or_err; |
777 | if (!n) { |
778 | LLDB_LOG(m_log, LOG_PREFIX "No children found in struct" ); |
779 | return {}; |
780 | } |
781 | |
782 | // case 2: homogeneous double or float aggregate |
783 | CompilerType elem_type; |
784 | if (m_type.IsHomogeneousAggregate(base_type_ptr: &elem_type)) { |
785 | uint32_t type_flags = elem_type.GetTypeInfo(); |
786 | std::optional<uint64_t> elem_size = |
787 | elem_type.GetByteSize(exe_scope: m_process_sp.get()); |
788 | if (!elem_size) |
789 | return {}; |
790 | if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) { |
791 | LLDB_LOG(m_log, |
792 | LOG_PREFIX "Unexpected type found in homogeneous aggregate" ); |
793 | return {}; |
794 | } |
795 | |
796 | for (uint32_t i = 0; i < n; i++) { |
797 | ValueSP val_sp = GetFloatValue(type&: elem_type, reg_index: i); |
798 | if (!val_sp) |
799 | return {}; |
800 | |
801 | // copy to buffer |
802 | Status error; |
803 | size_t rc = val_sp->GetScalar().GetAsMemoryData( |
804 | dst: m_data_up->GetBytes() + m_dst_offs, dst_len: *elem_size, dst_byte_order: m_byte_order, |
805 | error); |
806 | if (rc != *elem_size) { |
807 | LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data" ); |
808 | return {}; |
809 | } |
810 | m_dst_offs += *elem_size; |
811 | } |
812 | return BuildValueObject(); |
813 | } |
814 | |
815 | // case 3: get from GPRs |
816 | |
817 | // first, check if this is a packed struct or not |
818 | auto ast = m_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>(); |
819 | if (ast) { |
820 | clang::RecordDecl *record_decl = TypeSystemClang::GetAsRecordDecl(type: m_type); |
821 | |
822 | if (record_decl) { |
823 | auto attrs = record_decl->attrs(); |
824 | for (const auto &attr : attrs) { |
825 | if (attr->getKind() == clang::attr::Packed) { |
826 | m_packed = true; |
827 | break; |
828 | } |
829 | } |
830 | } |
831 | } |
832 | |
833 | LLDB_LOG(m_log, LOG_PREFIX "{0} struct" , |
834 | m_packed ? "packed" : "not packed" ); |
835 | |
836 | for (uint32_t i = 0; i < n; i++) { |
837 | std::string name; |
838 | uint32_t size; |
839 | GetChildType(i, name, size); |
840 | // NOTE: the offset returned by GetChildCompilerTypeAtIndex() |
841 | // can't be used because it never considers alignment bytes |
842 | // between struct fields. |
843 | LLDB_LOG(m_log, LOG_PREFIX "field={0}, size={1}" , name, size); |
844 | if (!ExtractField(size)) |
845 | return ValueObjectSP(); |
846 | } |
847 | |
848 | return BuildValueObject(); |
849 | } |
850 | |
851 | // extract 'size' bytes at 'offs' from GPRs |
852 | bool (int32_t offs, uint32_t size, void *buf) { |
853 | while (size) { |
854 | auto reg = GetGPRByOffs(offs); |
855 | if (!reg.IsValid()) |
856 | return false; |
857 | |
858 | uint32_t n = std::min(a: reg.Avail(), b: size); |
859 | uint64_t raw_data; |
860 | |
861 | if (!reg.GetRawData(raw_data)) |
862 | return false; |
863 | |
864 | memcpy(dest: buf, src: (char *)&raw_data + reg.Offs(), n: n); |
865 | offs += n; |
866 | size -= n; |
867 | buf = (char *)buf + n; |
868 | } |
869 | return true; |
870 | } |
871 | |
872 | // extract one field from GPRs and put it in our buffer |
873 | bool (uint32_t size) { |
874 | auto reg = GetGPRByOffs(offs: m_src_offs); |
875 | if (!reg.IsValid()) |
876 | return false; |
877 | |
878 | // handle padding |
879 | if (!m_packed) { |
880 | uint32_t n = m_src_offs % size; |
881 | |
882 | // not 'size' bytes aligned |
883 | if (n) { |
884 | LLDB_LOG(m_log, |
885 | LOG_PREFIX "Extracting {0} alignment bytes at offset {1}" , n, |
886 | m_src_offs); |
887 | // get alignment bytes |
888 | if (!ExtractFromRegs(offs: m_src_offs, size: n, buf: m_data_up->GetBytes() + m_dst_offs)) |
889 | return false; |
890 | m_src_offs += n; |
891 | m_dst_offs += n; |
892 | } |
893 | } |
894 | |
895 | // get field |
896 | LLDB_LOG(m_log, LOG_PREFIX "Extracting {0} field bytes at offset {1}" , size, |
897 | m_src_offs); |
898 | if (!ExtractFromRegs(offs: m_src_offs, size, buf: m_data_up->GetBytes() + m_dst_offs)) |
899 | return false; |
900 | m_src_offs += size; |
901 | m_dst_offs += size; |
902 | return true; |
903 | } |
904 | |
905 | // get child |
906 | CompilerType (uint32_t i, std::string &name, uint32_t &size) { |
907 | // GetChild constant inputs |
908 | const bool transparent_pointers = false; |
909 | const bool omit_empty_base_classes = true; |
910 | const bool ignore_array_bounds = false; |
911 | // GetChild output params |
912 | int32_t child_offs; |
913 | uint32_t child_bitfield_bit_size; |
914 | uint32_t child_bitfield_bit_offset; |
915 | bool child_is_base_class; |
916 | bool child_is_deref_of_parent; |
917 | ValueObject *valobj = nullptr; |
918 | uint64_t language_flags; |
919 | ExecutionContext exe_ctx; |
920 | m_thread.CalculateExecutionContext(exe_ctx); |
921 | |
922 | return m_type.GetChildCompilerTypeAtIndex( |
923 | exe_ctx: &exe_ctx, idx: i, transparent_pointers, omit_empty_base_classes, |
924 | ignore_array_bounds, child_name&: name, child_byte_size&: size, child_byte_offset&: child_offs, child_bitfield_bit_size, |
925 | child_bitfield_bit_offset, child_is_base_class, |
926 | child_is_deref_of_parent, valobj, language_flags); |
927 | } |
928 | }; |
929 | |
930 | #undef LOG_PREFIX |
931 | |
932 | } // anonymous namespace |
933 | |
934 | ValueObjectSP |
935 | ABISysV_ppc64::GetReturnValueObjectSimple(Thread &thread, |
936 | CompilerType &type) const { |
937 | if (!type) |
938 | return ValueObjectSP(); |
939 | |
940 | auto = ReturnValueExtractor::Create(thread, type); |
941 | if (!exp_extractor) { |
942 | Log *log = GetLog(mask: LLDBLog::Expressions); |
943 | LLDB_LOG_ERROR(log, exp_extractor.takeError(), |
944 | "Extracting return value failed: {0}" ); |
945 | return ValueObjectSP(); |
946 | } |
947 | |
948 | return exp_extractor.get().GetValue(); |
949 | } |
950 | |
951 | ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl( |
952 | Thread &thread, CompilerType &return_compiler_type) const { |
953 | return GetReturnValueObjectSimple(thread, type&: return_compiler_type); |
954 | } |
955 | |
956 | bool ABISysV_ppc64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { |
957 | unwind_plan.Clear(); |
958 | unwind_plan.SetRegisterKind(eRegisterKindDWARF); |
959 | |
960 | uint32_t lr_reg_num; |
961 | uint32_t sp_reg_num; |
962 | uint32_t pc_reg_num; |
963 | |
964 | if (GetByteOrder() == lldb::eByteOrderLittle) { |
965 | lr_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le; |
966 | sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le; |
967 | pc_reg_num = ppc64le_dwarf::dwarf_pc_ppc64le; |
968 | } else { |
969 | lr_reg_num = ppc64_dwarf::dwarf_lr_ppc64; |
970 | sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64; |
971 | pc_reg_num = ppc64_dwarf::dwarf_pc_ppc64; |
972 | } |
973 | |
974 | UnwindPlan::RowSP row(new UnwindPlan::Row); |
975 | |
976 | // Our Call Frame Address is the stack pointer value |
977 | row->GetCFAValue().SetIsRegisterPlusOffset(reg_num: sp_reg_num, offset: 0); |
978 | |
979 | // The previous PC is in the LR |
980 | row->SetRegisterLocationToRegister(reg_num: pc_reg_num, other_reg_num: lr_reg_num, can_replace: true); |
981 | unwind_plan.AppendRow(row_sp: row); |
982 | |
983 | // All other registers are the same. |
984 | |
985 | unwind_plan.SetSourceName("ppc64 at-func-entry default" ); |
986 | unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); |
987 | |
988 | return true; |
989 | } |
990 | |
991 | bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { |
992 | unwind_plan.Clear(); |
993 | unwind_plan.SetRegisterKind(eRegisterKindDWARF); |
994 | |
995 | uint32_t sp_reg_num; |
996 | uint32_t pc_reg_num; |
997 | uint32_t cr_reg_num; |
998 | |
999 | if (GetByteOrder() == lldb::eByteOrderLittle) { |
1000 | sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le; |
1001 | pc_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le; |
1002 | cr_reg_num = ppc64le_dwarf::dwarf_cr_ppc64le; |
1003 | } else { |
1004 | sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64; |
1005 | pc_reg_num = ppc64_dwarf::dwarf_lr_ppc64; |
1006 | cr_reg_num = ppc64_dwarf::dwarf_cr_ppc64; |
1007 | } |
1008 | |
1009 | UnwindPlan::RowSP row(new UnwindPlan::Row); |
1010 | const int32_t ptr_size = 8; |
1011 | row->SetUnspecifiedRegistersAreUndefined(true); |
1012 | row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num); |
1013 | |
1014 | row->SetRegisterLocationToAtCFAPlusOffset(reg_num: pc_reg_num, offset: ptr_size * 2, can_replace: true); |
1015 | row->SetRegisterLocationToIsCFAPlusOffset(reg_num: sp_reg_num, offset: 0, can_replace: true); |
1016 | row->SetRegisterLocationToAtCFAPlusOffset(reg_num: cr_reg_num, offset: ptr_size, can_replace: true); |
1017 | |
1018 | unwind_plan.AppendRow(row_sp: row); |
1019 | unwind_plan.SetSourceName("ppc64 default unwind plan" ); |
1020 | unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); |
1021 | unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); |
1022 | unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); |
1023 | unwind_plan.SetReturnAddressRegister(pc_reg_num); |
1024 | return true; |
1025 | } |
1026 | |
1027 | bool ABISysV_ppc64::RegisterIsVolatile(const RegisterInfo *reg_info) { |
1028 | return !RegisterIsCalleeSaved(reg_info); |
1029 | } |
1030 | |
1031 | // See "Register Usage" in the |
1032 | // "System V Application Binary Interface" |
1033 | // "64-bit PowerPC ELF Application Binary Interface Supplement" current version |
1034 | // is 2 released 2015 at |
1035 | // https://members.openpowerfoundation.org/document/dl/576 |
1036 | bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { |
1037 | if (reg_info) { |
1038 | // Preserved registers are : |
1039 | // r1,r2,r13-r31 |
1040 | // cr2-cr4 (partially preserved) |
1041 | // f14-f31 (not yet) |
1042 | // v20-v31 (not yet) |
1043 | // vrsave (not yet) |
1044 | |
1045 | const char *name = reg_info->name; |
1046 | if (name[0] == 'r') { |
1047 | if ((name[1] == '1' || name[1] == '2') && name[2] == '\0') |
1048 | return true; |
1049 | if (name[1] == '1' && name[2] > '2') |
1050 | return true; |
1051 | if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') |
1052 | return true; |
1053 | } |
1054 | |
1055 | if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9') { |
1056 | if (name[2] == '\0') |
1057 | return false; |
1058 | if (name[1] == '1' && name[2] >= '4') |
1059 | return true; |
1060 | if ((name[1] == '2' || name[1] == '3') && name[2] != '\0') |
1061 | return true; |
1062 | } |
1063 | |
1064 | if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp |
1065 | return true; |
1066 | if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp |
1067 | return false; |
1068 | if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc |
1069 | return true; |
1070 | } |
1071 | return false; |
1072 | } |
1073 | |
1074 | void ABISysV_ppc64::Initialize() { |
1075 | PluginManager::RegisterPlugin( |
1076 | name: GetPluginNameStatic(), description: "System V ABI for ppc64 targets" , create_callback: CreateInstance); |
1077 | } |
1078 | |
1079 | void ABISysV_ppc64::Terminate() { |
1080 | PluginManager::UnregisterPlugin(create_callback: CreateInstance); |
1081 | } |
1082 | |