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"
19#include "lldb/Target/Process.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Target/Thread.h"
27#include "lldb/Utility/Log.h"
29#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 = Status::FromErrorString("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 = Status::FromErrorString("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()) {
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 {
341 "We don't support returning longer than 64 bit "
342 "integer values at present.");
343 }
344 } else if (compiler_type.IsFloatingPointType(count, is_complex)) {
345 if (is_complex)
347 "We don't support returning complex values at present");
348 else {
349 std::optional<uint64_t> bit_width =
350 compiler_type.GetBitSize(frame_sp.get());
351 if (!bit_width) {
352 error = Status::FromErrorString("can't get type size");
353 return error;
354 }
355 if (*bit_width <= 64) {
356 const RegisterInfo *xmm0_info =
357 reg_ctx->GetRegisterInfoByName("xmm0", 0);
358 RegisterValue xmm0_value;
359 DataExtractor data;
360 Status data_error;
361 size_t num_bytes = new_value_sp->GetData(data, data_error);
362 if (data_error.Fail()) {
364 "Couldn't convert return value to raw data: %s",
365 data_error.AsCString());
366 return error;
367 }
368
369 unsigned char buffer[16];
370 ByteOrder byte_order = data.GetByteOrder();
371
372 data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order);
373 xmm0_value.SetBytes(buffer, 16, byte_order);
374 reg_ctx->WriteRegister(xmm0_info, xmm0_value);
375 set_it_simple = true;
376 } else {
377 // Windows doesn't support 80 bit FP
379 "Windows-x86_64 doesn't allow FP larger than 64 bits.");
380 }
381 }
382 }
383
384 if (!set_it_simple) {
385 // Okay we've got a structure or something that doesn't fit in a simple
386 // register.
387 // TODO(wanyi): On Windows, if the return type is a struct:
388 // 1) smaller that 64 bits and return by value -> RAX
389 // 2) bigger than 64 bits, the caller will allocate memory for that struct
390 // and pass the struct pointer in RCX then return the pointer in RAX
392 "We only support setting simple integer and float "
393 "return types at present.");
394 }
395
396 return error;
397}
398
400 Thread &thread, CompilerType &return_compiler_type) const {
401 ValueObjectSP return_valobj_sp;
402 Value value;
403
404 if (!return_compiler_type)
405 return return_valobj_sp;
406
407 value.SetCompilerType(return_compiler_type);
408
409 RegisterContext *reg_ctx = thread.GetRegisterContext().get();
410 if (!reg_ctx)
411 return return_valobj_sp;
412
413 const uint32_t type_flags = return_compiler_type.GetTypeInfo();
414 if (type_flags & eTypeIsScalar) {
415 value.SetValueType(Value::ValueType::Scalar);
416
417 bool success = false;
418 if (type_flags & eTypeIsInteger) {
419 // Extract the register context so we can read arguments from registers
420 std::optional<uint64_t> byte_size =
421 return_compiler_type.GetByteSize(&thread);
422 if (!byte_size)
423 return return_valobj_sp;
424 uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
425 reg_ctx->GetRegisterInfoByName("rax", 0), 0);
426 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
427 switch (*byte_size) {
428 default:
429 break;
430
431 case sizeof(uint64_t):
432 if (is_signed)
433 value.GetScalar() = (int64_t)(raw_value);
434 else
435 value.GetScalar() = (uint64_t)(raw_value);
436 success = true;
437 break;
438
439 case sizeof(uint32_t):
440 if (is_signed)
441 value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
442 else
443 value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
444 success = true;
445 break;
446
447 case sizeof(uint16_t):
448 if (is_signed)
449 value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
450 else
451 value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
452 success = true;
453 break;
454
455 case sizeof(uint8_t):
456 if (is_signed)
457 value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
458 else
459 value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
460 success = true;
461 break;
462 }
463 } else if (type_flags & eTypeIsFloat) {
464 if (type_flags & eTypeIsComplex) {
465 // Don't handle complex yet.
466 } else {
467 std::optional<uint64_t> byte_size =
468 return_compiler_type.GetByteSize(&thread);
469 if (byte_size && *byte_size <= sizeof(long double)) {
470 const RegisterInfo *xmm0_info =
471 reg_ctx->GetRegisterInfoByName("xmm0", 0);
472 RegisterValue xmm0_value;
473 if (reg_ctx->ReadRegister(xmm0_info, xmm0_value)) {
474 DataExtractor data;
475 if (xmm0_value.GetData(data)) {
476 lldb::offset_t offset = 0;
477 if (*byte_size == sizeof(float)) {
478 value.GetScalar() = (float)data.GetFloat(&offset);
479 success = true;
480 } else if (*byte_size == sizeof(double)) {
481 // double and long double are the same on windows
482 value.GetScalar() = (double)data.GetDouble(&offset);
483 success = true;
484 }
485 }
486 }
487 }
488 }
489 }
490
491 if (success)
492 return_valobj_sp = ValueObjectConstResult::Create(
493 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
494 } else if ((type_flags & eTypeIsPointer) ||
495 (type_flags & eTypeInstanceIsPointer)) {
496 unsigned rax_id =
497 reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
498 value.GetScalar() =
499 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
500 0);
501 value.SetValueType(Value::ValueType::Scalar);
502 return_valobj_sp = ValueObjectConstResult::Create(
503 thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
504 } else if (type_flags & eTypeIsVector) {
505 std::optional<uint64_t> byte_size =
506 return_compiler_type.GetByteSize(&thread);
507 if (byte_size && *byte_size > 0) {
508 const RegisterInfo *xmm_reg =
509 reg_ctx->GetRegisterInfoByName("xmm0", 0);
510 if (xmm_reg == nullptr)
511 xmm_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
512
513 if (xmm_reg) {
514 if (*byte_size <= xmm_reg->byte_size) {
515 ProcessSP process_sp(thread.GetProcess());
516 if (process_sp) {
517 std::unique_ptr<DataBufferHeap> heap_data_up(
518 new DataBufferHeap(*byte_size, 0));
519 const ByteOrder byte_order = process_sp->GetByteOrder();
520 RegisterValue reg_value;
521 if (reg_ctx->ReadRegister(xmm_reg, reg_value)) {
523 if (reg_value.GetAsMemoryData(*xmm_reg, heap_data_up->GetBytes(),
524 heap_data_up->GetByteSize(),
525 byte_order, error)) {
526 DataExtractor data(DataBufferSP(heap_data_up.release()),
527 byte_order,
528 process_sp->GetTarget()
529 .GetArchitecture()
530 .GetAddressByteSize());
531 return_valobj_sp = ValueObjectConstResult::Create(
532 &thread, return_compiler_type, ConstString(""), data);
533 }
534 }
535 }
536 }
537 }
538 }
539 }
540
541 return return_valobj_sp;
542}
543
544// The compiler will flatten the nested aggregate type into single
545// layer and push the value to stack
546// This helper function will flatten an aggregate type
547// and return true if it can be returned in register(s) by value
548// return false if the aggregate is in memory
550 Thread &thread, ExecutionContext &exe_ctx,
551 CompilerType &return_compiler_type,
552 uint32_t data_byte_offset,
553 std::vector<uint32_t> &aggregate_field_offsets,
554 std::vector<CompilerType> &aggregate_compiler_types) {
555
556 const uint32_t num_children = return_compiler_type.GetNumFields();
557 for (uint32_t idx = 0; idx < num_children; ++idx) {
558 std::string name;
559 bool is_signed;
560 uint32_t count;
561 bool is_complex;
562
563 uint64_t field_bit_offset = 0;
564 CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
565 idx, name, &field_bit_offset, nullptr, nullptr);
566 std::optional<uint64_t> field_bit_width =
567 field_compiler_type.GetBitSize(&thread);
568
569 // if we don't know the size of the field (e.g. invalid type), exit
570 if (!field_bit_width || *field_bit_width == 0) {
571 return false;
572 }
573 // If there are any unaligned fields, this is stored in memory.
574 if (field_bit_offset % *field_bit_width != 0) {
575 return false;
576 }
577
578 // add overall offset
579 uint32_t field_byte_offset = field_bit_offset / 8 + data_byte_offset;
580
581 const uint32_t field_type_flags = field_compiler_type.GetTypeInfo();
582 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
583 field_compiler_type.IsPointerType() ||
584 field_compiler_type.IsFloatingPointType(count, is_complex)) {
585 aggregate_field_offsets.push_back(field_byte_offset);
586 aggregate_compiler_types.push_back(field_compiler_type);
587 } else if (field_type_flags & eTypeHasChildren) {
588 if (!FlattenAggregateType(thread, exe_ctx, field_compiler_type,
589 field_byte_offset, aggregate_field_offsets,
590 aggregate_compiler_types)) {
591 return false;
592 }
593 }
594 }
595 return true;
596}
597
599 Thread &thread, CompilerType &return_compiler_type) const {
600 ValueObjectSP return_valobj_sp;
601
602 if (!return_compiler_type) {
603 return return_valobj_sp;
604 }
605
606 // try extract value as if it's a simple type
607 return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
608 if (return_valobj_sp) {
609 return return_valobj_sp;
610 }
611
612 RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
613 if (!reg_ctx_sp) {
614 return return_valobj_sp;
615 }
616
617 std::optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
618 if (!bit_width) {
619 return return_valobj_sp;
620 }
621
622 // if it's not simple or aggregate type, then we don't know how to handle it
623 if (!return_compiler_type.IsAggregateType()) {
624 return return_valobj_sp;
625 }
626
627 ExecutionContext exe_ctx(thread.shared_from_this());
628 Target *target = exe_ctx.GetTargetPtr();
629 uint32_t max_register_value_bit_width = 64;
630
631 // The scenario here is to have a struct/class which is POD
632 // if the return struct/class size is larger than 64 bits,
633 // the caller will allocate memory for it and pass the return addr in RCX
634 // then return the address in RAX
635
636 // if the struct is returned by value in register (RAX)
637 // its size has to be: 1, 2, 4, 8, 16, 32, or 64 bits (aligned)
638 // for floating point, the return value will be copied over to RAX
639 bool is_memory = *bit_width > max_register_value_bit_width ||
640 *bit_width & (*bit_width - 1);
641 std::vector<uint32_t> aggregate_field_offsets;
642 std::vector<CompilerType> aggregate_compiler_types;
643 if (!is_memory &&
644 FlattenAggregateType(thread, exe_ctx, return_compiler_type,
645 0, aggregate_field_offsets,
646 aggregate_compiler_types)) {
647 ByteOrder byte_order = target->GetArchitecture().GetByteOrder();
648 WritableDataBufferSP data_sp(
649 new DataBufferHeap(max_register_value_bit_width / 8, 0));
650 DataExtractor return_ext(data_sp, byte_order,
652
653 // The only register used to return struct/class by value
654 const RegisterInfo *rax_info =
655 reg_ctx_sp->GetRegisterInfoByName("rax", 0);
656 RegisterValue rax_value;
657 reg_ctx_sp->ReadRegister(rax_info, rax_value);
658 DataExtractor rax_data;
659 rax_value.GetData(rax_data);
660
661 uint32_t used_bytes =
662 0; // Tracks how much of the rax registers we've consumed so far
663
664 // in case of the returned type is a subclass of non-abstract-base class
665 // it will have a padding to skip the base content
666 if (aggregate_field_offsets.size())
667 used_bytes = aggregate_field_offsets[0];
668
669 const uint32_t num_children = aggregate_compiler_types.size();
670 for (uint32_t idx = 0; idx < num_children; idx++) {
671 bool is_signed;
672 bool is_complex;
673 uint32_t count;
674
675 CompilerType field_compiler_type = aggregate_compiler_types[idx];
676 uint32_t field_byte_width = (uint32_t) (*field_compiler_type.GetByteSize(&thread));
677 uint32_t field_byte_offset = aggregate_field_offsets[idx];
678
679 // this is unlikely w/o the overall size being greater than 8 bytes
680 // For now, return a nullptr return value object.
681 if (used_bytes >= 8 || used_bytes + field_byte_width > 8) {
682 return return_valobj_sp;
683 }
684
685 DataExtractor *copy_from_extractor = nullptr;
686 uint32_t copy_from_offset = 0;
687 if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
688 field_compiler_type.IsPointerType() ||
689 field_compiler_type.IsFloatingPointType(count, is_complex)) {
690 copy_from_extractor = &rax_data;
691 copy_from_offset = used_bytes;
692 used_bytes += field_byte_width;
693 }
694 // These two tests are just sanity checks. If I somehow get the type
695 // calculation wrong above it is better to just return nothing than to
696 // assert or crash.
697 if (!copy_from_extractor) {
698 return return_valobj_sp;
699 }
700 if (copy_from_offset + field_byte_width >
701 copy_from_extractor->GetByteSize()) {
702 return return_valobj_sp;
703 }
704 copy_from_extractor->CopyByteOrderedData(copy_from_offset,
705 field_byte_width, data_sp->GetBytes() + field_byte_offset,
706 field_byte_width, byte_order);
707 }
708 if (!is_memory) {
709 // The result is in our data buffer. Let's make a variable object out
710 // of it:
711 return_valobj_sp = ValueObjectConstResult::Create(
712 &thread, return_compiler_type, ConstString(""), return_ext);
713 }
714 }
715
716 // The Windows x86_64 ABI specifies that the return address for MEMORY
717 // objects be placed in rax on exit from the function.
718
719 // FIXME: This is just taking a guess, rax may very well no longer hold the
720 // return storage location.
721 // If we are going to do this right, when we make a new frame we should
722 // check to see if it uses a memory return, and if we are at the first
723 // instruction and if so stash away the return location. Then we would
724 // only return the memory return value if we know it is valid.
725 if (is_memory) {
726 unsigned rax_id =
727 reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
728 lldb::addr_t storage_addr =
729 (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id,
730 0);
731 return_valobj_sp = ValueObjectMemory::Create(
732 &thread, "", Address(storage_addr, nullptr), return_compiler_type);
733 }
734 return return_valobj_sp;
735}
736
737// This defines the CFA as rsp+8
738// the saved pc is at CFA-8 (i.e. rsp+0)
739// The saved rsp is CFA+0
740
742 unwind_plan.Clear();
744
745 uint32_t sp_reg_num = dwarf_rsp;
746 uint32_t pc_reg_num = dwarf_rip;
747
749 row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
750 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
751 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
752 unwind_plan.AppendRow(row);
753 unwind_plan.SetSourceName("x86_64 at-func-entry default");
755 return true;
756}
757
758// Windows-x86_64 doesn't use %rbp
759// No available Unwind information for Windows-x86_64 (section .pdata)
760// Let's use SysV-x86_64 one for now
762 unwind_plan.Clear();
764
765 uint32_t fp_reg_num = dwarf_rbp;
766 uint32_t sp_reg_num = dwarf_rsp;
767 uint32_t pc_reg_num = dwarf_rip;
768
770
771 const int32_t ptr_size = 8;
772 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
773 row->SetOffset(0);
774 row->SetUnspecifiedRegistersAreUndefined(true);
775
776 row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
777 row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
778 row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
779
780 unwind_plan.AppendRow(row);
781 unwind_plan.SetSourceName("x86_64 default unwind plan");
784
785 return true;
786}
787
789 return !RegisterIsCalleeSaved(reg_info);
790}
791
793 if (!reg_info)
794 return false;
795 assert(reg_info->name != nullptr && "unnamed register?");
796 std::string Name = std::string(reg_info->name);
797 bool IsCalleeSaved =
798 llvm::StringSwitch<bool>(Name)
799 .Cases("rbx", "ebx", "rbp", "ebp", "rdi", "edi", "rsi", "esi", true)
800 .Cases("rsp", "esp", "r12", "r13", "r14", "r15", "sp", "fp", true)
801 .Cases("xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12",
802 "xmm13", "xmm14", "xmm15", true)
803 .Default(false);
804 return IsCalleeSaved;
805}
806
807uint32_t ABIWindows_x86_64::GetGenericNum(llvm::StringRef reg) {
808 return llvm::StringSwitch<uint32_t>(reg)
809 .Case("rip", LLDB_REGNUM_GENERIC_PC)
810 .Case("rsp", LLDB_REGNUM_GENERIC_SP)
811 .Case("rbp", LLDB_REGNUM_GENERIC_FP)
812 .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS)
813 // gdbserver uses eflags
814 .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS)
815 .Case("rcx", LLDB_REGNUM_GENERIC_ARG1)
816 .Case("rdx", LLDB_REGNUM_GENERIC_ARG2)
817 .Case("r8", LLDB_REGNUM_GENERIC_ARG3)
818 .Case("r9", LLDB_REGNUM_GENERIC_ARG4)
819 .Default(LLDB_INVALID_REGNUM);
820}
821
824 GetPluginNameStatic(), "Windows ABI for x86_64 targets", CreateInstance);
825}
826
829}
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:376
#define LLDB_PLUGIN_DEFINE(PluginName)
Definition: PluginManager.h:32
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:709
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:461
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:756
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:147
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:745
An error handling class.
Definition: Status.h:115
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition: Status.cpp:106
static Status FromErrorString(const char *str)
Definition: Status.h:138
bool Fail() const
Test for error condition.
Definition: Status.cpp:270
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:195
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:1039
virtual lldb::StackFrameSP GetStackFrameAtIndex(uint32_t idx)
Definition: Thread.h:408
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP GetProcess() const
Definition: Thread.h:157
void SetRegisterKind(lldb::RegisterKind kind)
Definition: UnwindPlan.h:471
void AppendRow(const RowSP &row_sp)
Definition: UnwindPlan.cpp:392
std::shared_ptr< Row > RowSP
Definition: UnwindPlan.h:429
void SetSourcedFromCompiler(lldb_private::LazyBool from_compiler)
Definition: UnwindPlan.h:512
void SetSourceName(const char *)
Definition: UnwindPlan.cpp:594
void SetUnwindPlanValidAtAllInstructions(lldb_private::LazyBool valid_at_all_insn)
Definition: UnwindPlan.h:524
Value * GetValueAtIndex(size_t idx)
Definition: Value.cpp:691
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.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::ABI > ABISP
Definition: lldb-forward.h:317
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
Definition: lldb-forward.h:336
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
Definition: lldb-forward.h:337
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:394
@ 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