LLDB mainline
ABIWindows_x86_64.cpp
Go to the documentation of this file.
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"
17#include "lldb/Core/Value.h"
22#include "lldb/Target/Process.h"
25#include "lldb/Target/Target.h"
26#include "lldb/Target/Thread.h"
30#include "lldb/Utility/Log.h"
32#include "lldb/Utility/Status.h"
33#include <optional>
34
35using namespace lldb;
36using namespace lldb_private;
37
39
103
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
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
126 addr_t func_addr, addr_t return_addr,
127 llvm::ArrayRef<addr_t> args) const {
128 Log *log = GetLog(LLDBLog::Expressions);
129
130 if (log) {
131 StreamString s;
132 s.Printf("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(", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1),
140 args[i]);
141 s.PutCString(")");
142 log->PutString(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(eRegisterKindGeneric,
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, 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
173 const RegisterInfo *pc_reg_info =
175 const RegisterInfo *sp_reg_info =
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(sp, 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(sp_reg_info, 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(pc_reg_info, 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 argument_register_ids[current_argument_register], 0);
217 current_argument_register++;
218 if (is_signed)
219 scalar.SignExtend(bit_width);
220 return true;
221 }
222 uint32_t byte_size = (bit_width + (CHAR_BIT - 1)) / CHAR_BIT;
224 if (thread.GetProcess()->ReadScalarIntegerFromMemory(
225 current_stack_argument, byte_size, is_signed, scalar, error)) {
226 current_stack_argument += byte_size;
227 return true;
228 }
229 return false;
230}
231
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(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] =
259 argument_register_ids[1] =
262 argument_register_ids[2] =
265 argument_register_ids[3] =
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(value_index);
273
274 if (!value)
275 return false;
276
277 CompilerType compiler_type = value->GetCompilerType();
278 std::optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
279 if (!bit_size)
280 return false;
281 bool is_signed;
282
283 if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
284 ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,
285 argument_register_ids, current_argument_register,
286 current_stack_argument);
287 } else if (compiler_type.IsPointerType()) {
288 ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,
289 argument_register_ids, current_argument_register,
290 current_stack_argument);
291 }
292 }
293
294 return true;
295}
296
298 lldb::ValueObjectSP &new_value_sp) {
300 if (!new_value_sp) {
301 error.SetErrorString("Empty value object for return value.");
302 return error;
303 }
304
305 CompilerType compiler_type = new_value_sp->GetCompilerType();
306 if (!compiler_type) {
307 error.SetErrorString("Null clang type for return value.");
308 return error;
309 }
310
311 Thread *thread = frame_sp->GetThread().get();
312
313 bool is_signed;
314 uint32_t count;
315 bool is_complex;
316
317 RegisterContext *reg_ctx = thread->GetRegisterContext().get();
318
319 bool set_it_simple = false;
320 if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
321 compiler_type.IsPointerType()) {
322 const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
323
324 DataExtractor data;
325 Status data_error;
326 size_t num_bytes = new_value_sp->GetData(data, data_error);
327 if (data_error.Fail()) {
328 error.SetErrorStringWithFormat(
329 "Couldn't convert return value to raw data: %s",
330 data_error.AsCString());
331 return error;
332 }
333 lldb::offset_t offset = 0;
334 if (num_bytes <= 8) {
335 uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
336
337 if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value))
338 set_it_simple = true;
339 } else {
340 error.SetErrorString("We don't support returning longer than 64 bit "
341 "integer values at present.");
342 }
343 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
344 if (is_complex)
345 error.SetErrorString(
346 "We don't support returning complex values at present");
347 else {
348 std::optional<uint64_t> bit_width =
349 compiler_type.GetBitSize(frame_sp.get());
350 if (!bit_width) {
351 error.SetErrorString("can't get type size");
352 return error;
353 }
354 if (*bit_width <= 64) {
355 const RegisterInfo *xmm0_info =
356 reg_ctx->GetRegisterInfoByName("xmm0", 0);
357 RegisterValue xmm0_value;
358 DataExtractor data;
359 Status data_error;
360 size_t num_bytes = new_value_sp->GetData(data, data_error);
361 if (data_error.Fail()) {
362 error.SetErrorStringWithFormat(
363 "Couldn't convert return value to raw data: %s",
364 data_error.AsCString());
365 return error;
366 }
367
368 unsigned char buffer[16];
369 ByteOrder byte_order = data.GetByteOrder();
370
371 data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order);
372 xmm0_value.SetBytes(buffer, 16, byte_order);
373 reg_ctx->WriteRegister(xmm0_info, xmm0_value);
374 set_it_simple = true;
375 } else {
376 // Windows doesn't support 80 bit FP
377 error.SetErrorString(
378 "Windows-x86_64 doesn't allow FP larger than 64 bits.");
379 }
380 }
381 }
382
383 if (!set_it_simple) {
384 // Okay we've got a structure or something that doesn't fit in a simple
385 // register.
386 // TODO(wanyi): On Windows, if the return type is a struct:
387 // 1) smaller that 64 bits and return by value -> RAX
388 // 2) bigger than 64 bits, the caller will allocate memory for that struct
389 // and pass the struct pointer in RCX then return the pointer in RAX
390 error.SetErrorString("We only support setting simple integer and float "
391 "return types at present.");
392 }
393
394 return error;
395}
396
398 Thread &thread, CompilerType &return_compiler_type) const {
399 ValueObjectSP return_valobj_sp;
400 Value value;
401
402 if (!return_compiler_type)
403 return return_valobj_sp;
404
405 value.SetCompilerType(return_compiler_type);
406
407 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
408 if (!reg_ctx)
409 return return_valobj_sp;
410
411 const uint32_t type_flags = return_compiler_type.GetTypeInfo();
412 if (type_flags & eTypeIsScalar) {
413 value.SetValueType(Value::ValueType::Scalar);
414
415 bool success = false;
416 if (type_flags & eTypeIsInteger) {
417 // Extract the register context so we can read arguments from registers
418 std::optional<uint64_t> byte_size =
419 return_compiler_type.GetByteSize(&thread);
420 if (!byte_size)
421 return return_valobj_sp;
422 uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
423 reg_ctx->GetRegisterInfoByName("rax", 0), 0);
424 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
425 switch (*byte_size) {
426 default:
427 break;
428
429 case sizeof(uint64_t):
430 if (is_signed)
431 value.GetScalar() = (int64_t)(raw_value);
432 else
433 value.GetScalar() = (uint64_t)(raw_value);
434 success = true;
435 break;
436
437 case sizeof(uint32_t):
438 if (is_signed)
439 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
440 else
441 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
442 success = true;
443 break;
444
445 case sizeof(uint16_t):
446 if (is_signed)
447 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
448 else
449 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
450 success = true;
451 break;
452
453 case sizeof(uint8_t):
454 if (is_signed)
455 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
456 else
457 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
458 success = true;
459 break;
460 }
461 } else if (type_flags & eTypeIsFloat) {
462 if (type_flags & eTypeIsComplex) {
463 // Don't handle complex yet.
464 } else {
465 std::optional<uint64_t> byte_size =
466 return_compiler_type.GetByteSize(&thread);
467 if (byte_size && *byte_size <= sizeof(long double)) {
468 const RegisterInfo *xmm0_info =
469 reg_ctx->GetRegisterInfoByName("xmm0", 0);
470 RegisterValue xmm0_value;
471 if (reg_ctx->ReadRegister(xmm0_info, xmm0_value)) {
472 DataExtractor data;
473 if (xmm0_value.GetData(data)) {
474 lldb::offset_t offset = 0;
475 if (*byte_size == sizeof(float)) {
476 value.GetScalar() = (float)data.GetFloat(&offset);
477 success = true;
478 } else if (*byte_size == sizeof(double)) {
479 // double and long double are the same on windows
480 value.GetScalar() = (double)data.GetDouble(&offset);
481 success = true;
482 }
483 }
484 }
485 }
486 }
487 }
488
489 if (success)
490 return_valobj_sp = ValueObjectConstResult::Create(
491 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
492 } else if ((type_flags & eTypeIsPointer) ||
493 (type_flags & eTypeInstanceIsPointer)) {
494 unsigned rax_id =
495 reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
496 value.GetScalar() =
497 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
498 0);
499 value.SetValueType(Value::ValueType::Scalar);
500 return_valobj_sp = ValueObjectConstResult::Create(
501 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
502 } else if (type_flags & eTypeIsVector) {
503 std::optional<uint64_t> byte_size =
504 return_compiler_type.GetByteSize(&thread);
505 if (byte_size && *byte_size > 0) {
506 const RegisterInfo *xmm_reg =
507 reg_ctx->GetRegisterInfoByName("xmm0", 0);
508 if (xmm_reg == nullptr)
509 xmm_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
510
511 if (xmm_reg) {
512 if (*byte_size <= xmm_reg->byte_size) {
513 ProcessSP process_sp(thread.GetProcess());
514 if (process_sp) {
515 std::unique_ptr<DataBufferHeap> heap_data_up(
516 new DataBufferHeap(*byte_size, 0));
517 const ByteOrder byte_order = process_sp->GetByteOrder();
518 RegisterValue reg_value;
519 if (reg_ctx->ReadRegister(xmm_reg, reg_value)) {
521 if (reg_value.GetAsMemoryData(*xmm_reg, heap_data_up->GetBytes(),
522 heap_data_up->GetByteSize(),
523 byte_order, error)) {
524 DataExtractor data(DataBufferSP(heap_data_up.release()),
525 byte_order,
526 process_sp->GetTarget()
527 .GetArchitecture()
528 .GetAddressByteSize());
529 return_valobj_sp = ValueObjectConstResult::Create(
530 &thread, return_compiler_type, ConstString(""), data);
531 }
532 }
533 }
534 }
535 }
536 }
537 }
538
539 return return_valobj_sp;
540}
541
542// The compiler will flatten the nested aggregate type into single
543// layer and push the value to stack
544// This helper function will flatten an aggregate type
545// and return true if it can be returned in register(s) by value
546// return false if the aggregate is in memory
548 Thread &thread, ExecutionContext &exe_ctx,
549 CompilerType &return_compiler_type,
550 uint32_t data_byte_offset,
551 std::vector<uint32_t> &aggregate_field_offsets,
552 std::vector<CompilerType> &aggregate_compiler_types) {
553
554 const uint32_t num_children = return_compiler_type.GetNumFields();
555 for (uint32_t idx = 0; idx < num_children; ++idx) {
556 std::string name;
557 bool is_signed;
558 uint32_t count;
559 bool is_complex;
560
561 uint64_t field_bit_offset = 0;
562 CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
563 idx, name, &field_bit_offset, nullptr, nullptr);
564 std::optional<uint64_t> field_bit_width =
565 field_compiler_type.GetBitSize(&thread);
566
567 // if we don't know the size of the field (e.g. invalid type), exit
568 if (!field_bit_width || *field_bit_width == 0) {
569 return false;
570 }
571 // If there are any unaligned fields, this is stored in memory.
572 if (field_bit_offset % *field_bit_width != 0) {
573 return false;
574 }
575
576 // add overall offset
577 uint32_t field_byte_offset = field_bit_offset / 8 + data_byte_offset;
578
579 const uint32_t field_type_flags = field_compiler_type.GetTypeInfo();
580 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
581 field_compiler_type.IsPointerType() ||
582 field_compiler_type.IsFloatingPointType(count, is_complex)) {
583 aggregate_field_offsets.push_back(field_byte_offset);
584 aggregate_compiler_types.push_back(field_compiler_type);
585 } else if (field_type_flags & eTypeHasChildren) {
586 if (!FlattenAggregateType(thread, exe_ctx, field_compiler_type,
587 field_byte_offset, aggregate_field_offsets,
588 aggregate_compiler_types)) {
589 return false;
590 }
591 }
592 }
593 return true;
594}
595
597 Thread &thread, CompilerType &return_compiler_type) const {
598 ValueObjectSP return_valobj_sp;
599
600 if (!return_compiler_type) {
601 return return_valobj_sp;
602 }
603
604 // try extract value as if it's a simple type
605 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
606 if (return_valobj_sp) {
607 return return_valobj_sp;
608 }
609
610 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
611 if (!reg_ctx_sp) {
612 return return_valobj_sp;
613 }
614
615 std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
616 if (!bit_width) {
617 return return_valobj_sp;
618 }
619
620 // if it's not simple or aggregate type, then we don't know how to handle it
621 if (!return_compiler_type.IsAggregateType()) {
622 return return_valobj_sp;
623 }
624
625 ExecutionContext exe_ctx(thread.shared_from_this());
626 Target *target = exe_ctx.GetTargetPtr();
627 uint32_t max_register_value_bit_width = 64;
628
629 // The scenario here is to have a struct/class which is POD
630 // if the return struct/class size is larger than 64 bits,
631 // the caller will allocate memory for it and pass the return addr in RCX
632 // then return the address in RAX
633
634 // if the struct is returned by value in register (RAX)
635 // its size has to be: 1, 2, 4, 8, 16, 32, or 64 bits (aligned)
636 // for floating point, the return value will be copied over to RAX
637 bool is_memory = *bit_width > max_register_value_bit_width ||
638 *bit_width & (*bit_width - 1);
639 std::vector<uint32_t> aggregate_field_offsets;
640 std::vector<CompilerType> aggregate_compiler_types;
641 if (!is_memory &&
642 FlattenAggregateType(thread, exe_ctx, return_compiler_type,
643 0, aggregate_field_offsets,
644 aggregate_compiler_types)) {
645 ByteOrder byte_order = target->GetArchitecture().GetByteOrder();
646 WritableDataBufferSP data_sp(
647 new DataBufferHeap(max_register_value_bit_width / 8, 0));
648 DataExtractor return_ext(data_sp, byte_order,
650
651 // The only register used to return struct/class by value
652 const RegisterInfo *rax_info =
653 reg_ctx_sp->GetRegisterInfoByName("rax", 0);
654 RegisterValue rax_value;
655 reg_ctx_sp->ReadRegister(rax_info, rax_value);
656 DataExtractor rax_data;
657 rax_value.GetData(rax_data);
658
659 uint32_t used_bytes =
660 0; // Tracks how much of the rax registers we've consumed so far
661
662 // in case of the returned type is a subclass of non-abstract-base class
663 // it will have a padding to skip the base content
664 if (aggregate_field_offsets.size())
665 used_bytes = aggregate_field_offsets[0];
666
667 const uint32_t num_children = aggregate_compiler_types.size();
668 for (uint32_t idx = 0; idx < num_children; idx++) {
669 bool is_signed;
670 bool is_complex;
671 uint32_t count;
672
673 CompilerType field_compiler_type = aggregate_compiler_types[idx];
674 uint32_t field_byte_width = (uint32_t) (*field_compiler_type.GetByteSize(&thread));
675 uint32_t field_byte_offset = aggregate_field_offsets[idx];
676
677 // this is unlikely w/o the overall size being greater than 8 bytes
678 // For now, return a nullptr return value object.
679 if (used_bytes >= 8 || used_bytes + field_byte_width > 8) {
680 return return_valobj_sp;
681 }
682
683 DataExtractor *copy_from_extractor = nullptr;
684 uint32_t copy_from_offset = 0;
685 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
686 field_compiler_type.IsPointerType() ||
687 field_compiler_type.IsFloatingPointType(count, is_complex)) {
688 copy_from_extractor = &rax_data;
689 copy_from_offset = used_bytes;
690 used_bytes += field_byte_width;
691 }
692 // These two tests are just sanity checks. If I somehow get the type
693 // calculation wrong above it is better to just return nothing than to
694 // assert or crash.
695 if (!copy_from_extractor) {
696 return return_valobj_sp;
697 }
698 if (copy_from_offset + field_byte_width >
699 copy_from_extractor->GetByteSize()) {
700 return return_valobj_sp;
701 }
702 copy_from_extractor->CopyByteOrderedData(copy_from_offset,
703 field_byte_width, data_sp->GetBytes() + field_byte_offset,
704 field_byte_width, byte_order);
705 }
706 if (!is_memory) {
707 // The result is in our data buffer. Let's make a variable object out
708 // of it:
709 return_valobj_sp = ValueObjectConstResult::Create(
710 &thread, return_compiler_type, ConstString(""), return_ext);
711 }
712 }
713
714 // The Windows x86_64 ABI specifies that the return address for MEMORY
715 // objects be placed in rax on exit from the function.
716
717 // FIXME: This is just taking a guess, rax may very well no longer hold the
718 // return storage location.
719 // If we are going to do this right, when we make a new frame we should
720 // check to see if it uses a memory return, and if we are at the first
721 // instruction and if so stash away the return location. Then we would
722 // only return the memory return value if we know it is valid.
723 if (is_memory) {
724 unsigned rax_id =
725 reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
726 lldb::addr_t storage_addr =
727 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
728 0);
729 return_valobj_sp = ValueObjectMemory::Create(
730 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
731 }
732 return return_valobj_sp;
733}
734
735// This defines the CFA as rsp+8
736// the saved pc is at CFA-8 (i.e. rsp+0)
737// The saved rsp is CFA+0
738
740 unwind_plan.Clear();
742
743 uint32_t sp_reg_num = dwarf_rsp;
744 uint32_t pc_reg_num = dwarf_rip;
745
747 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
748 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
749 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
750 unwind_plan.AppendRow(row);
751 unwind_plan.SetSourceName("x86_64 at-func-entry default");
753 return true;
754}
755
756// Windows-x86_64 doesn't use %rbp
757// No available Unwind information for Windows-x86_64 (section .pdata)
758// Let's use SysV-x86_64 one for now
760 unwind_plan.Clear();
762
763 uint32_t fp_reg_num = dwarf_rbp;
764 uint32_t sp_reg_num = dwarf_rsp;
765 uint32_t pc_reg_num = dwarf_rip;
766
768
769 const int32_t ptr_size = 8;
770 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
771 row->SetOffset(0);
772 row->SetUnspecifiedRegistersAreUndefined(true);
773
774 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
775 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
776 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
777
778 unwind_plan.AppendRow(row);
779 unwind_plan.SetSourceName("x86_64 default unwind plan");
782
783 return true;
784}
785
787 return !RegisterIsCalleeSaved(reg_info);
788}
789
791 if (!reg_info)
792 return false;
793 assert(reg_info->name != nullptr && "unnamed register?");
794 std::string Name = std::string(reg_info->name);
795 bool IsCalleeSaved =
796 llvm::StringSwitch<bool>(Name)
797 .Cases("rbx", "ebx", "rbp", "ebp", "rdi", "edi", "rsi", "esi", true)
798 .Cases("rsp", "esp", "r12", "r13", "r14", "r15", "sp", "fp", true)
799 .Cases("xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12",
800 "xmm13", "xmm14", "xmm15", true)
801 .Default(false);
802 return IsCalleeSaved;
803}
804
805uint32_t ABIWindows_x86_64::GetGenericNum(llvm::StringRef reg) {
806 return llvm::StringSwitch<uint32_t>(reg)
807 .Case("rip", LLDB_REGNUM_GENERIC_PC)
808 .Case("rsp", LLDB_REGNUM_GENERIC_SP)
809 .Case("rbp", LLDB_REGNUM_GENERIC_FP)
810 .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS)
811 // gdbserver uses eflags
812 .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS)
813 .Case("rcx", LLDB_REGNUM_GENERIC_ARG1)
814 .Case("rdx", LLDB_REGNUM_GENERIC_ARG2)
815 .Case("r8", LLDB_REGNUM_GENERIC_ARG3)
816 .Case("r9", LLDB_REGNUM_GENERIC_ARG4)
817 .Default(LLDB_INVALID_REGNUM);
818}
819
822 GetPluginNameStatic(), "Windows ABI for x86_64 targets", CreateInstance);
823}
824
827}
dwarf_regnums
static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, bool is_signed, Thread &thread, uint32_t *argument_register_ids, unsigned int &current_argument_register, addr_t &current_stack_argument)
static bool FlattenAggregateType(Thread &thread, ExecutionContext &exe_ctx, CompilerType &return_compiler_type, uint32_t data_byte_offset, std::vector< uint32_t > &aggregate_field_offsets, std::vector< CompilerType > &aggregate_compiler_types)
@ dwarf_rip
@ dwarf_rsp
@ dwarf_rbp
static bool FlattenAggregateType(Thread &thread, ExecutionContext &exe_ctx, CompilerType &return_compiler_type, uint32_t data_byte_offset, std::vector< uint32_t > &aggregate_field_offsets, std::vector< CompilerType > &aggregate_compiler_types)
@ dwarf_ymm3
@ dwarf_rdi
@ dwarf_r12
@ dwarf_ymm13
@ dwarf_xmm11
@ dwarf_stmm0
@ dwarf_xmm0
@ dwarf_xmm10
@ dwarf_ymm4
@ dwarf_r13
@ dwarf_xmm4
@ dwarf_ymm10
@ dwarf_r8
@ dwarf_bnd2
@ dwarf_ymm12
@ dwarf_xmm7
@ dwarf_stmm5
@ dwarf_ymm14
@ dwarf_r11
@ dwarf_ymm7
@ dwarf_stmm3
@ dwarf_r9
@ dwarf_ymm0
@ dwarf_xmm6
@ dwarf_xmm5
@ dwarf_bnd0
@ dwarf_bnd1
@ dwarf_rcx
@ dwarf_rip
@ dwarf_ymm9
@ dwarf_stmm7
@ dwarf_stmm2
@ dwarf_rsi
@ dwarf_xmm9
@ dwarf_r15
@ dwarf_xmm3
@ dwarf_ymm1
@ dwarf_stmm6
@ dwarf_xmm13
@ dwarf_xmm15
@ dwarf_rax
@ dwarf_rsp
@ dwarf_bnd3
@ dwarf_rbp
@ dwarf_r10
@ dwarf_ymm11
@ dwarf_xmm8
@ dwarf_r14
@ dwarf_ymm5
@ dwarf_xmm2
@ dwarf_ymm8
@ dwarf_ymm2
@ dwarf_xmm14
@ dwarf_xmm1
@ dwarf_stmm1
@ dwarf_rdx
@ dwarf_rbx
@ dwarf_ymm6
@ dwarf_stmm4
@ dwarf_xmm12
@ dwarf_ymm15
static bool ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, bool is_signed, Thread &thread, uint32_t *argument_register_ids, unsigned int &current_argument_register, addr_t &current_stack_argument)
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:349
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:31
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
static llvm::StringRef GetPluginNameStatic()
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override
lldb::ValueObjectSP GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const
bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
bool GetPointerReturnRegister(const char *&name) override
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
bool CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override
size_t GetRedZoneSize() const override
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
static void Initialize()
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t functionAddress, lldb::addr_t returnAddress, llvm::ArrayRef< lldb::addr_t > args) const override
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
uint32_t GetGenericNum(llvm::StringRef reg) override
Return the generic number of the given register.
static std::unique_ptr< llvm::MCRegisterInfo > MakeMCRegisterInfo(const ArchSpec &arch)
Utility function to construct a MCRegisterInfo using the ArchSpec triple.
Definition: ABI.cpp:234
A section + offset based address class.
Definition: Address.h:62
An architecture specification class.
Definition: ArchSpec.h:31
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:691
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:738
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
std::optional< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
CompilerType GetFieldAtIndex(size_t idx, std::string &name, uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, bool *is_bitfield_ptr) const
bool IsFloatingPointType(uint32_t &count, bool &is_complex) const
uint32_t GetNumFields() const
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
std::optional< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
bool IsPointerType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition: ConstString.h:40
A subclass of DataBuffer that stores a data buffer on the heap.
An data extractor class.
Definition: DataExtractor.h:48
float GetFloat(lldb::offset_t *offset_ptr) const
Extract a float from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
lldb::offset_t CopyByteOrderedData(lldb::offset_t src_offset, lldb::offset_t src_len, void *dst, lldb::offset_t dst_len, lldb::ByteOrder dst_byte_order) const
Copy dst_len bytes from *offset_ptr and ensure the copied data is treated as a value that can be swap...
double GetDouble(lldb::offset_t *offset_ptr) const
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Target * GetTargetPtr() const
Returns a pointer to the target object.
void PutString(llvm::StringRef str)
Definition: Log.cpp:136
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
uint64_t GetSP(uint64_t fail_value=LLDB_INVALID_ADDRESS)
virtual bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)=0
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
const RegisterInfo * GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx=0)
virtual bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)=0
bool GetData(DataExtractor &data) const
uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
bool SignExtend(uint32_t bit_pos)
Definition: Scalar.cpp:746
An error handling class.
Definition: Status.h:44
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
const ArchSpec & GetArchitecture() const
Definition: Target.h:1014
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:405
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:437
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:362
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:395
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:478
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:564
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:490
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:686
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, llvm::StringRef name, const Address &address, lldb::TypeSP &type_sp)
const Scalar & GetScalar() const
Definition: Value.h:112
void SetCompilerType(const CompilerType &compiler_type)
Definition: Value.cpp:268
void SetValueType(ValueType value_type)
Definition: Value.h:89
const CompilerType & GetCompilerType()
Definition: Value.cpp:239
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:57
#define LLDB_REGNUM_GENERIC_ARG4
Definition: lldb-defines.h:67
#define LLDB_REGNUM_GENERIC_ARG3
Definition: lldb-defines.h:65
#define LLDB_REGNUM_GENERIC_ARG1
Definition: lldb-defines.h:61
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:60
#define UINT32_MAX
Definition: lldb-defines.h:19
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:87
#define LLDB_REGNUM_GENERIC_ARG2
Definition: lldb-defines.h:63
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:56
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:58
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:314
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ABI > ABISP
Definition: lldb-forward.h:310
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:412
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:472
uint64_t offset_t
Definition: lldb-types.h:83
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
Definition: lldb-forward.h:328
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:329
uint64_t addr_t
Definition: lldb-types.h:79
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:386
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
@ eRegisterKindDWARF
the register numbers seen DWARF
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47