1//===-- ABIWindows_x86_64.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 "ABIWindows_x86_64.h"
10
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/StringSwitch.h"
13#include "llvm/TargetParser/Triple.h"
14
15#include "lldb/Core/Module.h"
16#include "lldb/Core/PluginManager.h"
17#include "lldb/Core/Value.h"
18#include "lldb/Symbol/UnwindPlan.h"
19#include "lldb/Target/Process.h"
20#include "lldb/Target/RegisterContext.h"
21#include "lldb/Target/StackFrame.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Target/Thread.h"
24#include "lldb/Utility/ConstString.h"
25#include "lldb/Utility/DataExtractor.h"
26#include "lldb/Utility/LLDBLog.h"
27#include "lldb/Utility/Log.h"
28#include "lldb/Utility/RegisterValue.h"
29#include "lldb/Utility/Status.h"
30#include "lldb/ValueObject/ValueObjectConstResult.h"
31#include "lldb/ValueObject/ValueObjectMemory.h"
32#include "lldb/ValueObject/ValueObjectRegister.h"
33#include <optional>
34
35using namespace lldb;
36using namespace lldb_private;
37
38LLDB_PLUGIN_DEFINE(ABIWindows_x86_64)
39
40enum dwarf_regnums {
41 dwarf_rax = 0,
42 dwarf_rdx,
43 dwarf_rcx,
44 dwarf_rbx,
45 dwarf_rsi,
46 dwarf_rdi,
47 dwarf_rbp,
48 dwarf_rsp,
49 dwarf_r8,
50 dwarf_r9,
51 dwarf_r10,
52 dwarf_r11,
53 dwarf_r12,
54 dwarf_r13,
55 dwarf_r14,
56 dwarf_r15,
57 dwarf_rip,
58 dwarf_xmm0,
59 dwarf_xmm1,
60 dwarf_xmm2,
61 dwarf_xmm3,
62 dwarf_xmm4,
63 dwarf_xmm5,
64 dwarf_xmm6,
65 dwarf_xmm7,
66 dwarf_xmm8,
67 dwarf_xmm9,
68 dwarf_xmm10,
69 dwarf_xmm11,
70 dwarf_xmm12,
71 dwarf_xmm13,
72 dwarf_xmm14,
73 dwarf_xmm15,
74 dwarf_stmm0,
75 dwarf_stmm1,
76 dwarf_stmm2,
77 dwarf_stmm3,
78 dwarf_stmm4,
79 dwarf_stmm5,
80 dwarf_stmm6,
81 dwarf_stmm7,
82 dwarf_ymm0,
83 dwarf_ymm1,
84 dwarf_ymm2,
85 dwarf_ymm3,
86 dwarf_ymm4,
87 dwarf_ymm5,
88 dwarf_ymm6,
89 dwarf_ymm7,
90 dwarf_ymm8,
91 dwarf_ymm9,
92 dwarf_ymm10,
93 dwarf_ymm11,
94 dwarf_ymm12,
95 dwarf_ymm13,
96 dwarf_ymm14,
97 dwarf_ymm15,
98 dwarf_bnd0 = 126,
99 dwarf_bnd1,
100 dwarf_bnd2,
101 dwarf_bnd3
102};
103
104bool ABIWindows_x86_64::GetPointerReturnRegister(const char *&name) {
105 name = "rax";
106 return true;
107}
108
109size_t ABIWindows_x86_64::GetRedZoneSize() const { return 0; }
110
111//------------------------------------------------------------------
112// Static Functions
113//------------------------------------------------------------------
114
115ABISP
116ABIWindows_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
117 if (arch.GetTriple().getArch() == llvm::Triple::x86_64 &&
118 arch.GetTriple().isOSWindows()) {
119 return ABISP(
120 new ABIWindows_x86_64(std::move(process_sp), MakeMCRegisterInfo(arch)));
121 }
122 return ABISP();
123}
124
125bool ABIWindows_x86_64::PrepareTrivialCall(Thread &thread, addr_t sp,
126 addr_t func_addr, addr_t return_addr,
127 llvm::ArrayRef<addr_t> args) const {
128 Log *log = GetLog(mask: LLDBLog::Expressions);
129
130 if (log) {
131 StreamString s;
132 s.Printf(format: "ABIWindows_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64
133 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
134 ", return_addr = 0x%" PRIx64,
135 thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
136 (uint64_t)return_addr);
137
138 for (size_t i = 0; i < args.size(); ++i)
139 s.Printf(format: ", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1),
140 args[i]);
141 s.PutCString(cstr: ")");
142 log->PutString(str: s.GetString());
143 }
144
145 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
146 if (!reg_ctx)
147 return false;
148
149 const RegisterInfo *reg_info = nullptr;
150
151 if (args.size() > 4) // Windows x64 only put first 4 arguments into registers
152 return false;
153
154 for (size_t i = 0; i < args.size(); ++i) {
155 reg_info = reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric,
156 LLDB_REGNUM_GENERIC_ARG1 + i);
157 LLDB_LOGF(log, "About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s",
158 static_cast<uint64_t>(i + 1), args[i], reg_info->name);
159 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, uval: args[i]))
160 return false;
161 }
162
163 // First, align the SP
164
165 LLDB_LOGF(log, "16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64,
166 (uint64_t)sp, (uint64_t)(sp & ~0xfull));
167
168 sp &= ~(0xfull); // 16-byte alignment
169
170 sp -= 8; // return address
171
172 Status error;
173 const RegisterInfo *pc_reg_info =
174 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
175 const RegisterInfo *sp_reg_info =
176 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
177 ProcessSP process_sp(thread.GetProcess());
178
179 RegisterValue reg_value;
180 LLDB_LOGF(log,
181 "Pushing the return address onto the stack: 0x%" PRIx64
182 ": 0x%" PRIx64,
183 (uint64_t)sp, (uint64_t)return_addr);
184
185 // Save return address onto the stack
186 if (!process_sp->WritePointerToMemory(vm_addr: sp, ptr_value: return_addr, error))
187 return false;
188
189 // %rsp is set to the actual stack value.
190
191 LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
192
193 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: sp_reg_info, uval: sp))
194 return false;
195
196 // %rip is set to the address of the called function.
197
198 LLDB_LOGF(log, "Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
199
200 if (!reg_ctx->WriteRegisterFromUnsigned(reg_info: pc_reg_info, uval: func_addr))
201 return false;
202
203 return true;
204}
205
206static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width,
207 bool is_signed, Thread &thread,
208 uint32_t *argument_register_ids,
209 unsigned int &current_argument_register,
210 addr_t &current_stack_argument) {
211 if (bit_width > 64)
212 return false; // Scalar can't hold large integer arguments
213
214 if (current_argument_register < 4) { // Windows pass first 4 arguments to register
215 scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
216 reg: argument_register_ids[current_argument_register], fail_value: 0);
217 current_argument_register++;
218 if (is_signed)
219 scalar.SignExtend(bit_pos: bit_width);
220 return true;
221 }
222 uint32_t byte_size = (bit_width + (CHAR_BIT - 1)) / CHAR_BIT;
223 Status error;
224 if (thread.GetProcess()->ReadScalarIntegerFromMemory(
225 addr: current_stack_argument, byte_size, is_signed, scalar, error)) {
226 current_stack_argument += byte_size;
227 return true;
228 }
229 return false;
230}
231
232bool ABIWindows_x86_64::GetArgumentValues(Thread &thread,
233 ValueList &values) const {
234 unsigned int num_values = values.GetSize();
235 unsigned int value_index;
236
237 // Extract the register context so we can read arguments from registers
238
239 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
240
241 if (!reg_ctx)
242 return false;
243
244 // Get the pointer to the first stack argument so we have a place to start
245 // when reading data
246
247 addr_t sp = reg_ctx->GetSP(fail_value: 0);
248
249 if (!sp)
250 return false;
251
252 addr_t current_stack_argument = sp + 8; // jump over return address
253
254 uint32_t argument_register_ids[4];
255
256 argument_register_ids[0] =
257 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)
258 ->kinds[eRegisterKindLLDB];
259 argument_register_ids[1] =
260 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)
261 ->kinds[eRegisterKindLLDB];
262 argument_register_ids[2] =
263 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)
264 ->kinds[eRegisterKindLLDB];
265 argument_register_ids[3] =
266 reg_ctx->GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)
267 ->kinds[eRegisterKindLLDB];
268
269 unsigned int current_argument_register = 0;
270
271 for (value_index = 0; value_index < num_values; ++value_index) {
272 Value *value = values.GetValueAtIndex(idx: value_index);
273
274 if (!value)
275 return false;
276
277 CompilerType compiler_type = value->GetCompilerType();
278 std::optional<uint64_t> bit_size =
279 llvm::expectedToOptional(E: compiler_type.GetBitSize(exe_scope: &thread));
280 if (!bit_size)
281 return false;
282 bool is_signed;
283
284 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
285 ReadIntegerArgument(scalar&: value->GetScalar(), bit_width: *bit_size, is_signed, thread,
286 argument_register_ids, current_argument_register,
287 current_stack_argument);
288 } else if (compiler_type.IsPointerType()) {
289 ReadIntegerArgument(scalar&: value->GetScalar(), bit_width: *bit_size, is_signed: false, thread,
290 argument_register_ids, current_argument_register,
291 current_stack_argument);
292 }
293 }
294
295 return true;
296}
297
298Status ABIWindows_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
299 lldb::ValueObjectSP &new_value_sp) {
300 Status error;
301 if (!new_value_sp) {
302 error = Status::FromErrorString(str: "Empty value object for return value.");
303 return error;
304 }
305
306 CompilerType compiler_type = new_value_sp->GetCompilerType();
307 if (!compiler_type) {
308 error = Status::FromErrorString(str: "Null clang type for return value.");
309 return error;
310 }
311
312 Thread *thread = frame_sp->GetThread().get();
313
314 bool is_signed;
315 uint32_t count;
316 bool is_complex;
317
318 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
319
320 bool set_it_simple = false;
321 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
322 compiler_type.IsPointerType()) {
323 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name: "rax", start_idx: 0);
324
325 DataExtractor data;
326 Status data_error;
327 size_t num_bytes = new_value_sp->GetData(data, error&: data_error);
328 if (data_error.Fail()) {
329 error = Status::FromErrorStringWithFormat(
330 format: "Couldn't convert return value to raw data: %s",
331 data_error.AsCString());
332 return error;
333 }
334 lldb::offset_t offset = 0;
335 if (num_bytes <= 8) {
336 uint64_t raw_value = data.GetMaxU64(offset_ptr: &offset, byte_size: num_bytes);
337
338 if (reg_ctx->WriteRegisterFromUnsigned(reg_info, uval: raw_value))
339 set_it_simple = true;
340 } else {
341 error = Status::FromErrorString(
342 str: "We don't support returning longer than 64 bit "
343 "integer values at present.");
344 }
345 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
346 if (is_complex)
347 error = Status::FromErrorString(
348 str: "We don't support returning complex values at present");
349 else {
350 std::optional<uint64_t> bit_width =
351 llvm::expectedToOptional(E: compiler_type.GetBitSize(exe_scope: frame_sp.get()));
352 if (!bit_width) {
353 error = Status::FromErrorString(str: "can't get type size");
354 return error;
355 }
356 if (*bit_width <= 64) {
357 const RegisterInfo *xmm0_info =
358 reg_ctx->GetRegisterInfoByName(reg_name: "xmm0", start_idx: 0);
359 RegisterValue xmm0_value;
360 DataExtractor data;
361 Status data_error;
362 size_t num_bytes = new_value_sp->GetData(data, error&: data_error);
363 if (data_error.Fail()) {
364 error = Status::FromErrorStringWithFormat(
365 format: "Couldn't convert return value to raw data: %s",
366 data_error.AsCString());
367 return error;
368 }
369
370 unsigned char buffer[16];
371 ByteOrder byte_order = data.GetByteOrder();
372
373 data.CopyByteOrderedData(src_offset: 0, src_len: num_bytes, dst: buffer, dst_len: 16, dst_byte_order: byte_order);
374 xmm0_value.SetBytes(bytes: buffer, length: 16, byte_order);
375 reg_ctx->WriteRegister(reg_info: xmm0_info, reg_value: xmm0_value);
376 set_it_simple = true;
377 } else {
378 // Windows doesn't support 80 bit FP
379 error = Status::FromErrorString(
380 str: "Windows-x86_64 doesn't allow FP larger than 64 bits.");
381 }
382 }
383 }
384
385 if (!set_it_simple) {
386 // Okay we've got a structure or something that doesn't fit in a simple
387 // register.
388 // TODO(wanyi): On Windows, if the return type is a struct:
389 // 1) smaller that 64 bits and return by value -> RAX
390 // 2) bigger than 64 bits, the caller will allocate memory for that struct
391 // and pass the struct pointer in RCX then return the pointer in RAX
392 error = Status::FromErrorString(
393 str: "We only support setting simple integer and float "
394 "return types at present.");
395 }
396
397 return error;
398}
399
400ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectSimple(
401 Thread &thread, CompilerType &return_compiler_type) const {
402 ValueObjectSP return_valobj_sp;
403 Value value;
404
405 if (!return_compiler_type)
406 return return_valobj_sp;
407
408 value.SetCompilerType(return_compiler_type);
409
410 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
411 if (!reg_ctx)
412 return return_valobj_sp;
413
414 const uint32_t type_flags = return_compiler_type.GetTypeInfo();
415 if (type_flags & eTypeIsScalar) {
416 value.SetValueType(Value::ValueType::Scalar);
417
418 bool success = false;
419 if (type_flags & eTypeIsInteger) {
420 // Extract the register context so we can read arguments from registers
421 std::optional<uint64_t> byte_size =
422 llvm::expectedToOptional(E: return_compiler_type.GetByteSize(exe_scope: &thread));
423 if (!byte_size)
424 return return_valobj_sp;
425 uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
426 reg_info: reg_ctx->GetRegisterInfoByName(reg_name: "rax", start_idx: 0), fail_value: 0);
427 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
428 switch (*byte_size) {
429 default:
430 break;
431
432 case sizeof(uint64_t):
433 if (is_signed)
434 value.GetScalar() = (int64_t)(raw_value);
435 else
436 value.GetScalar() = (uint64_t)(raw_value);
437 success = true;
438 break;
439
440 case sizeof(uint32_t):
441 if (is_signed)
442 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
443 else
444 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
445 success = true;
446 break;
447
448 case sizeof(uint16_t):
449 if (is_signed)
450 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
451 else
452 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
453 success = true;
454 break;
455
456 case sizeof(uint8_t):
457 if (is_signed)
458 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
459 else
460 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
461 success = true;
462 break;
463 }
464 } else if (type_flags & eTypeIsFloat) {
465 if (type_flags & eTypeIsComplex) {
466 // Don't handle complex yet.
467 } else {
468 std::optional<uint64_t> byte_size =
469 llvm::expectedToOptional(E: return_compiler_type.GetByteSize(exe_scope: &thread));
470 if (byte_size && *byte_size <= sizeof(long double)) {
471 const RegisterInfo *xmm0_info =
472 reg_ctx->GetRegisterInfoByName(reg_name: "xmm0", start_idx: 0);
473 RegisterValue xmm0_value;
474 if (reg_ctx->ReadRegister(reg_info: xmm0_info, reg_value&: xmm0_value)) {
475 DataExtractor data;
476 if (xmm0_value.GetData(data)) {
477 lldb::offset_t offset = 0;
478 if (*byte_size == sizeof(float)) {
479 value.GetScalar() = (float)data.GetFloat(offset_ptr: &offset);
480 success = true;
481 } else if (*byte_size == sizeof(double)) {
482 // double and long double are the same on windows
483 value.GetScalar() = (double)data.GetDouble(offset_ptr: &offset);
484 success = true;
485 }
486 }
487 }
488 }
489 }
490 }
491
492 if (success)
493 return_valobj_sp = ValueObjectConstResult::Create(
494 exe_scope: thread.GetStackFrameAtIndex(idx: 0).get(), value, name: ConstString(""));
495 } else if ((type_flags & eTypeIsPointer) ||
496 (type_flags & eTypeInstanceIsPointer)) {
497 unsigned rax_id =
498 reg_ctx->GetRegisterInfoByName(reg_name: "rax", start_idx: 0)->kinds[eRegisterKindLLDB];
499 value.GetScalar() =
500 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg: rax_id,
501 fail_value: 0);
502 value.SetValueType(Value::ValueType::Scalar);
503 return_valobj_sp = ValueObjectConstResult::Create(
504 exe_scope: thread.GetStackFrameAtIndex(idx: 0).get(), value, name: ConstString(""));
505 } else if (type_flags & eTypeIsVector) {
506 std::optional<uint64_t> byte_size =
507 llvm::expectedToOptional(E: return_compiler_type.GetByteSize(exe_scope: &thread));
508 if (byte_size && *byte_size > 0) {
509 const RegisterInfo *xmm_reg =
510 reg_ctx->GetRegisterInfoByName(reg_name: "xmm0", start_idx: 0);
511 if (xmm_reg == nullptr)
512 xmm_reg = reg_ctx->GetRegisterInfoByName(reg_name: "mm0", start_idx: 0);
513
514 if (xmm_reg) {
515 if (*byte_size <= xmm_reg->byte_size) {
516 ProcessSP process_sp(thread.GetProcess());
517 if (process_sp) {
518 std::unique_ptr<DataBufferHeap> heap_data_up(
519 new DataBufferHeap(*byte_size, 0));
520 const ByteOrder byte_order = process_sp->GetByteOrder();
521 RegisterValue reg_value;
522 if (reg_ctx->ReadRegister(reg_info: xmm_reg, reg_value)) {
523 Status error;
524 if (reg_value.GetAsMemoryData(reg_info: *xmm_reg, dst: heap_data_up->GetBytes(),
525 dst_len: heap_data_up->GetByteSize(),
526 dst_byte_order: byte_order, error)) {
527 DataExtractor data(DataBufferSP(heap_data_up.release()),
528 byte_order,
529 process_sp->GetTarget()
530 .GetArchitecture()
531 .GetAddressByteSize());
532 return_valobj_sp = ValueObjectConstResult::Create(
533 exe_scope: &thread, compiler_type: return_compiler_type, name: ConstString(""), data);
534 }
535 }
536 }
537 }
538 }
539 }
540 }
541
542 return return_valobj_sp;
543}
544
545// The compiler will flatten the nested aggregate type into single
546// layer and push the value to stack
547// This helper function will flatten an aggregate type
548// and return true if it can be returned in register(s) by value
549// return false if the aggregate is in memory
550static bool FlattenAggregateType(
551 Thread &thread, ExecutionContext &exe_ctx,
552 CompilerType &return_compiler_type,
553 uint32_t data_byte_offset,
554 std::vector<uint32_t> &aggregate_field_offsets,
555 std::vector<CompilerType> &aggregate_compiler_types) {
556
557 const uint32_t num_children = return_compiler_type.GetNumFields();
558 for (uint32_t idx = 0; idx < num_children; ++idx) {
559 std::string name;
560 bool is_signed;
561 uint32_t count;
562 bool is_complex;
563
564 uint64_t field_bit_offset = 0;
565 CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
566 idx, name, bit_offset_ptr: &field_bit_offset, bitfield_bit_size_ptr: nullptr, is_bitfield_ptr: nullptr);
567 std::optional<uint64_t> field_bit_width =
568 llvm::expectedToOptional(E: field_compiler_type.GetBitSize(exe_scope: &thread));
569
570 // if we don't know the size of the field (e.g. invalid type), exit
571 if (!field_bit_width || *field_bit_width == 0) {
572 return false;
573 }
574 // If there are any unaligned fields, this is stored in memory.
575 if (field_bit_offset % *field_bit_width != 0) {
576 return false;
577 }
578
579 // add overall offset
580 uint32_t field_byte_offset = field_bit_offset / 8 + data_byte_offset;
581
582 const uint32_t field_type_flags = field_compiler_type.GetTypeInfo();
583 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
584 field_compiler_type.IsPointerType() ||
585 field_compiler_type.IsFloatingPointType(count, is_complex)) {
586 aggregate_field_offsets.push_back(x: field_byte_offset);
587 aggregate_compiler_types.push_back(x: field_compiler_type);
588 } else if (field_type_flags & eTypeHasChildren) {
589 if (!FlattenAggregateType(thread, exe_ctx, return_compiler_type&: field_compiler_type,
590 data_byte_offset: field_byte_offset, aggregate_field_offsets,
591 aggregate_compiler_types)) {
592 return false;
593 }
594 }
595 }
596 return true;
597}
598
599ValueObjectSP ABIWindows_x86_64::GetReturnValueObjectImpl(
600 Thread &thread, CompilerType &return_compiler_type) const {
601 ValueObjectSP return_valobj_sp;
602
603 if (!return_compiler_type) {
604 return return_valobj_sp;
605 }
606
607 // try extract value as if it's a simple type
608 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
609 if (return_valobj_sp) {
610 return return_valobj_sp;
611 }
612
613 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
614 if (!reg_ctx_sp) {
615 return return_valobj_sp;
616 }
617
618 std::optional<uint64_t> bit_width =
619 llvm::expectedToOptional(E: return_compiler_type.GetBitSize(exe_scope: &thread));
620 if (!bit_width) {
621 return return_valobj_sp;
622 }
623
624 // if it's not simple or aggregate type, then we don't know how to handle it
625 if (!return_compiler_type.IsAggregateType()) {
626 return return_valobj_sp;
627 }
628
629 ExecutionContext exe_ctx(thread.shared_from_this());
630 Target *target = exe_ctx.GetTargetPtr();
631 uint32_t max_register_value_bit_width = 64;
632
633 // The scenario here is to have a struct/class which is POD
634 // if the return struct/class size is larger than 64 bits,
635 // the caller will allocate memory for it and pass the return addr in RCX
636 // then return the address in RAX
637
638 // if the struct is returned by value in register (RAX)
639 // its size has to be: 1, 2, 4, 8, 16, 32, or 64 bits (aligned)
640 // for floating point, the return value will be copied over to RAX
641 bool is_memory = *bit_width > max_register_value_bit_width ||
642 *bit_width & (*bit_width - 1);
643 std::vector<uint32_t> aggregate_field_offsets;
644 std::vector<CompilerType> aggregate_compiler_types;
645 if (!is_memory &&
646 FlattenAggregateType(thread, exe_ctx, return_compiler_type,
647 data_byte_offset: 0, aggregate_field_offsets,
648 aggregate_compiler_types)) {
649 ByteOrder byte_order = target->GetArchitecture().GetByteOrder();
650 WritableDataBufferSP data_sp(
651 new DataBufferHeap(max_register_value_bit_width / 8, 0));
652 DataExtractor return_ext(data_sp, byte_order,
653 target->GetArchitecture().GetAddressByteSize());
654
655 // The only register used to return struct/class by value
656 const RegisterInfo *rax_info =
657 reg_ctx_sp->GetRegisterInfoByName(reg_name: "rax", start_idx: 0);
658 RegisterValue rax_value;
659 reg_ctx_sp->ReadRegister(reg_info: rax_info, reg_value&: rax_value);
660 DataExtractor rax_data;
661 rax_value.GetData(data&: rax_data);
662
663 uint32_t used_bytes =
664 0; // Tracks how much of the rax registers we've consumed so far
665
666 // in case of the returned type is a subclass of non-abstract-base class
667 // it will have a padding to skip the base content
668 if (aggregate_field_offsets.size())
669 used_bytes = aggregate_field_offsets[0];
670
671 const uint32_t num_children = aggregate_compiler_types.size();
672 for (uint32_t idx = 0; idx < num_children; idx++) {
673 bool is_signed;
674 bool is_complex;
675 uint32_t count;
676
677 CompilerType field_compiler_type = aggregate_compiler_types[idx];
678 uint32_t field_byte_width =
679 (uint32_t)(llvm::expectedToOptional(
680 E: field_compiler_type.GetByteSize(exe_scope: &thread))
681 .value_or(u: 0));
682 uint32_t field_byte_offset = aggregate_field_offsets[idx];
683
684 // this is unlikely w/o the overall size being greater than 8 bytes
685 // For now, return a nullptr return value object.
686 if (used_bytes >= 8 || used_bytes + field_byte_width > 8) {
687 return return_valobj_sp;
688 }
689
690 DataExtractor *copy_from_extractor = nullptr;
691 uint32_t copy_from_offset = 0;
692 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
693 field_compiler_type.IsPointerType() ||
694 field_compiler_type.IsFloatingPointType(count, is_complex)) {
695 copy_from_extractor = &rax_data;
696 copy_from_offset = used_bytes;
697 used_bytes += field_byte_width;
698 }
699 // These two tests are just sanity checks. If I somehow get the type
700 // calculation wrong above it is better to just return nothing than to
701 // assert or crash.
702 if (!copy_from_extractor) {
703 return return_valobj_sp;
704 }
705 if (copy_from_offset + field_byte_width >
706 copy_from_extractor->GetByteSize()) {
707 return return_valobj_sp;
708 }
709 copy_from_extractor->CopyByteOrderedData(src_offset: copy_from_offset,
710 src_len: field_byte_width, dst: data_sp->GetBytes() + field_byte_offset,
711 dst_len: field_byte_width, dst_byte_order: byte_order);
712 }
713 if (!is_memory) {
714 // The result is in our data buffer. Let's make a variable object out
715 // of it:
716 return_valobj_sp = ValueObjectConstResult::Create(
717 exe_scope: &thread, compiler_type: return_compiler_type, name: ConstString(""), data: return_ext);
718 }
719 }
720
721 // The Windows x86_64 ABI specifies that the return address for MEMORY
722 // objects be placed in rax on exit from the function.
723
724 // FIXME: This is just taking a guess, rax may very well no longer hold the
725 // return storage location.
726 // If we are going to do this right, when we make a new frame we should
727 // check to see if it uses a memory return, and if we are at the first
728 // instruction and if so stash away the return location. Then we would
729 // only return the memory return value if we know it is valid.
730 if (is_memory) {
731 unsigned rax_id =
732 reg_ctx_sp->GetRegisterInfoByName(reg_name: "rax", start_idx: 0)->kinds[eRegisterKindLLDB];
733 lldb::addr_t storage_addr =
734 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg: rax_id,
735 fail_value: 0);
736 return_valobj_sp = ValueObjectMemory::Create(
737 exe_scope: &thread, name: "", address: Address(storage_addr, nullptr), ast_type: return_compiler_type);
738 }
739 return return_valobj_sp;
740}
741
742// This defines the CFA as rsp+8
743// the saved pc is at CFA-8 (i.e. rsp+0)
744// The saved rsp is CFA+0
745
746UnwindPlanSP ABIWindows_x86_64::CreateFunctionEntryUnwindPlan() {
747 uint32_t sp_reg_num = dwarf_rsp;
748 uint32_t pc_reg_num = dwarf_rip;
749
750 UnwindPlan::Row row;
751 row.GetCFAValue().SetIsRegisterPlusOffset(reg_num: sp_reg_num, offset: 8);
752 row.SetRegisterLocationToAtCFAPlusOffset(reg_num: pc_reg_num, offset: -8, can_replace: false);
753 row.SetRegisterLocationToIsCFAPlusOffset(reg_num: sp_reg_num, offset: 0, can_replace: true);
754
755 auto plan_sp = std::make_shared<UnwindPlan>(args: eRegisterKindDWARF);
756 plan_sp->AppendRow(row: std::move(row));
757 plan_sp->SetSourceName("x86_64 at-func-entry default");
758 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
759 return plan_sp;
760}
761
762// Windows-x86_64 doesn't use %rbp
763// No available Unwind information for Windows-x86_64 (section .pdata)
764// Let's use SysV-x86_64 one for now
765UnwindPlanSP ABIWindows_x86_64::CreateDefaultUnwindPlan() {
766 uint32_t fp_reg_num = dwarf_rbp;
767 uint32_t sp_reg_num = dwarf_rsp;
768 uint32_t pc_reg_num = dwarf_rip;
769
770 UnwindPlan::Row row;
771
772 const int32_t ptr_size = 8;
773 row.GetCFAValue().SetIsRegisterPlusOffset(reg_num: dwarf_rbp, offset: 2 * ptr_size);
774 row.SetOffset(0);
775 row.SetUnspecifiedRegistersAreUndefined(true);
776
777 row.SetRegisterLocationToAtCFAPlusOffset(reg_num: fp_reg_num, offset: ptr_size * -2, can_replace: true);
778 row.SetRegisterLocationToAtCFAPlusOffset(reg_num: pc_reg_num, offset: ptr_size * -1, can_replace: true);
779 row.SetRegisterLocationToIsCFAPlusOffset(reg_num: sp_reg_num, offset: 0, can_replace: true);
780
781 auto plan_sp = std::make_shared<UnwindPlan>(args: eRegisterKindDWARF);
782 plan_sp->AppendRow(row: std::move(row));
783 plan_sp->SetSourceName("x86_64 default unwind plan");
784 plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
785 plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
786 return plan_sp;
787}
788
789bool ABIWindows_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) {
790 return !RegisterIsCalleeSaved(reg_info);
791}
792
793bool ABIWindows_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
794 if (!reg_info)
795 return false;
796 assert(reg_info->name != nullptr && "unnamed register?");
797 std::string Name = std::string(reg_info->name);
798 bool IsCalleeSaved =
799 llvm::StringSwitch<bool>(Name)
800 .Cases(S0: "rbx", S1: "ebx", S2: "rbp", S3: "ebp", S4: "rdi", S5: "edi", S6: "rsi", S7: "esi", Value: true)
801 .Cases(S0: "rsp", S1: "esp", S2: "r12", S3: "r13", S4: "r14", S5: "r15", S6: "sp", S7: "fp", Value: true)
802 .Cases(S0: "xmm6", S1: "xmm7", S2: "xmm8", S3: "xmm9", S4: "xmm10", S5: "xmm11", S6: "xmm12",
803 S7: "xmm13", S8: "xmm14", S9: "xmm15", Value: true)
804 .Default(Value: false);
805 return IsCalleeSaved;
806}
807
808uint32_t ABIWindows_x86_64::GetGenericNum(llvm::StringRef reg) {
809 return llvm::StringSwitch<uint32_t>(reg)
810 .Case(S: "rip", LLDB_REGNUM_GENERIC_PC)
811 .Case(S: "rsp", LLDB_REGNUM_GENERIC_SP)
812 .Case(S: "rbp", LLDB_REGNUM_GENERIC_FP)
813 .Case(S: "rflags", LLDB_REGNUM_GENERIC_FLAGS)
814 // gdbserver uses eflags
815 .Case(S: "eflags", LLDB_REGNUM_GENERIC_FLAGS)
816 .Case(S: "rcx", LLDB_REGNUM_GENERIC_ARG1)
817 .Case(S: "rdx", LLDB_REGNUM_GENERIC_ARG2)
818 .Case(S: "r8", LLDB_REGNUM_GENERIC_ARG3)
819 .Case(S: "r9", LLDB_REGNUM_GENERIC_ARG4)
820 .Default(LLDB_INVALID_REGNUM);
821}
822
823void ABIWindows_x86_64::Initialize() {
824 PluginManager::RegisterPlugin(
825 name: GetPluginNameStatic(), description: "Windows ABI for x86_64 targets", create_callback: CreateInstance);
826}
827
828void ABIWindows_x86_64::Terminate() {
829 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
830}
831

source code of lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp