diff options
Diffstat (limited to 'lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp')
-rw-r--r-- | lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp | 2160 |
1 files changed, 2160 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp new file mode 100644 index 000000000000..1a93bac564f7 --- /dev/null +++ b/lldb/source/Plugins/ABI/ARM/ABISysV_arm.cpp @@ -0,0 +1,2160 @@ +//===-- ABISysV_arm.cpp ---------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_arm.h" + +#include <vector> + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/Status.h" + +#include "Plugins/Process/Utility/ARMDefines.h" +#include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ABISysV_arm) + +static RegisterInfo g_register_infos[] = { + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME + // DWARF GENERIC PROCESS PLUGIN + // LLDB NATIVE VALUE REGS INVALIDATE REGS + // ========== ======= == === ============= ============ + // ======================= =================== =========================== + // ======================= ====================== ========== + // =============== + {"r0", + "arg1", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r1", + "arg2", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r2", + "arg3", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r3", + "arg4", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r4", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r5", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r6", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r7", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r8", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r9", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r10", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r11", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r12", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"sp", + "r13", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"lr", + "r14", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"pc", + "r15", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"cpsr", + "psr", + 4, + 0, + eEncodingUint, + eFormatHex, + {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s0", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s1", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s2", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s3", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s4", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s5", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s6", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s7", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s8", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s9", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s10", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s11", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s12", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s13", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s14", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s15", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s16", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s17", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s18", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s19", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s20", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s21", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s22", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s23", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s24", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s25", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s26", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s27", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s28", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s29", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s30", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"s31", + nullptr, + 4, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"fpscr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d0", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d1", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d2", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d3", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d4", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d5", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d6", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d7", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d8", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d9", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d10", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d11", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d12", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d13", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d14", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d15", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d16", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d17", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d18", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d19", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d20", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d21", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d22", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d23", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d24", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d25", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d26", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d27", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d28", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d29", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d30", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"d31", + nullptr, + 8, + 0, + eEncodingIEEE754, + eFormatFloat, + {LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r8_usr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r9_usr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r10_usr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r11_usr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r12_usr", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_usr", + "sp_usr", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_usr", + "lr_usr", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r8_fiq", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r9_fiq", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r10_fiq", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r11_fiq", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r12_fiq", + nullptr, + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_fiq", + "sp_fiq", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_fiq", + "lr_fiq", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_irq", + "sp_irq", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_irq", + "lr_irq", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_abt", + "sp_abt", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_abt", + "lr_abt", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_und", + "sp_und", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_und", + "lr_und", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r13_svc", + "sp_svc", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}, + {"r14_svc", + "lr_svc", + 4, + 0, + eEncodingUint, + eFormatHex, + {LLDB_INVALID_REGNUM, dwarf_r14_svc, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + 0}}; + +static const uint32_t k_num_register_infos = + llvm::array_lengthof(g_register_infos); +static bool g_register_info_names_constified = false; + +const lldb_private::RegisterInfo * +ABISysV_arm::GetRegisterInfoArray(uint32_t &count) { + // Make the C-string names and alt_names for the register infos into const + // C-string values by having the ConstString unique the names in the global + // constant C-string pool. + if (!g_register_info_names_constified) { + g_register_info_names_constified = true; + for (uint32_t i = 0; i < k_num_register_infos; ++i) { + if (g_register_infos[i].name) + g_register_infos[i].name = + ConstString(g_register_infos[i].name).GetCString(); + if (g_register_infos[i].alt_name) + g_register_infos[i].alt_name = + ConstString(g_register_infos[i].alt_name).GetCString(); + } + } + count = k_num_register_infos; + return g_register_infos; +} + +size_t ABISysV_arm::GetRedZoneSize() const { return 0; } + +// Static Functions + +ABISP +ABISysV_arm::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) { + const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch(); + const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor(); + + if (vendor_type != llvm::Triple::Apple) { + if ((arch_type == llvm::Triple::arm) || + (arch_type == llvm::Triple::thumb)) { + return ABISP( + new ABISysV_arm(std::move(process_sp), MakeMCRegisterInfo(arch))); + } + } + + return ABISP(); +} + +bool ABISysV_arm::PrepareTrivialCall(Thread &thread, addr_t sp, + addr_t function_addr, addr_t return_addr, + llvm::ArrayRef<addr_t> args) const { + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return false; + + const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + + RegisterValue reg_value; + + const uint8_t reg_names[] = { + LLDB_REGNUM_GENERIC_ARG1, LLDB_REGNUM_GENERIC_ARG2, + LLDB_REGNUM_GENERIC_ARG3, LLDB_REGNUM_GENERIC_ARG4}; + + llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); + + for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { + if (ai == ae) + break; + + reg_value.SetUInt32(*ai); + if (!reg_ctx->WriteRegister( + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, reg_names[i]), + reg_value)) + return false; + + ++ai; + } + + if (ai != ae) { + // Spill onto the stack + size_t num_stack_regs = ae - ai; + + sp -= (num_stack_regs * 4); + // Keep the stack 8 byte aligned, not that we need to + sp &= ~(8ull - 1ull); + + // just using arg1 to get the right size + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + + addr_t arg_pos = sp; + + for (; ai != ae; ++ai) { + reg_value.SetUInt32(*ai); + if (reg_ctx + ->WriteRegisterValueToMemory(reg_info, arg_pos, + reg_info->byte_size, reg_value) + .Fail()) + return false; + arg_pos += reg_info->byte_size; + } + } + + TargetSP target_sp(thread.CalculateTarget()); + Address so_addr; + + // Figure out if our return address is ARM or Thumb by using the + // Address::GetCallableLoadAddress(Target*) which will figure out the ARM + // thumb-ness and set the correct address bits for us. + so_addr.SetLoadAddress(return_addr, target_sp.get()); + return_addr = so_addr.GetCallableLoadAddress(target_sp.get()); + + // Set "lr" to the return address + if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_num, return_addr)) + return false; + + // Set "sp" to the requested value + if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) + return false; + + // If bit zero or 1 is set, this must be a thumb function, no need to figure + // this out from the symbols. + so_addr.SetLoadAddress(function_addr, target_sp.get()); + function_addr = so_addr.GetCallableLoadAddress(target_sp.get()); + + const RegisterInfo *cpsr_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); + const uint32_t curr_cpsr = reg_ctx->ReadRegisterAsUnsigned(cpsr_reg_info, 0); + + // Make a new CPSR and mask out any Thumb IT (if/then) bits + uint32_t new_cpsr = curr_cpsr & ~MASK_CPSR_IT_MASK; + // If bit zero or 1 is set, this must be thumb... + if (function_addr & 1ull) + new_cpsr |= MASK_CPSR_T; // Set T bit in CPSR + else + new_cpsr &= ~MASK_CPSR_T; // Clear T bit in CPSR + + if (new_cpsr != curr_cpsr) { + if (!reg_ctx->WriteRegisterFromUnsigned(cpsr_reg_info, new_cpsr)) + return false; + } + + function_addr &= + ~1ull; // clear bit zero since the CPSR will take care of the mode for us + + // Set "pc" to the address requested + return reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, function_addr); +} + +bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const { + uint32_t num_values = values.GetSize(); + + ExecutionContext exe_ctx(thread.shared_from_this()); + // For now, assume that the types in the AST values come from the Target's + // scratch AST. + + // Extract the register context so we can read arguments from registers + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + + if (!reg_ctx) + return false; + + addr_t sp = 0; + + for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) { + // We currently only support extracting values with Clang QualTypes. Do we + // care about others? + Value *value = values.GetValueAtIndex(value_idx); + + if (!value) + return false; + + CompilerType compiler_type = value->GetCompilerType(); + if (compiler_type) { + bool is_signed = false; + size_t bit_width = 0; + if (compiler_type.IsIntegerOrEnumerationType(is_signed) || + compiler_type.IsPointerOrReferenceType()) { + if (llvm::Optional<uint64_t> size = compiler_type.GetBitSize(&thread)) + bit_width = *size; + } else { + // We only handle integer, pointer and reference types currently... + return false; + } + + if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) { + if (value_idx < 4) { + // Arguments 1-4 are in r0-r3... + const RegisterInfo *arg_reg_info = nullptr; + arg_reg_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); + if (arg_reg_info) { + RegisterValue reg_value; + + if (reg_ctx->ReadRegister(arg_reg_info, reg_value)) { + if (is_signed) + reg_value.SignExtend(bit_width); + if (!reg_value.GetScalarValue(value->GetScalar())) + return false; + continue; + } + } + return false; + } else { + if (sp == 0) { + // Read the stack pointer if it already hasn't been read + sp = reg_ctx->GetSP(0); + if (sp == 0) + return false; + } + + // Arguments 5 on up are on the stack + const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8; + Status error; + if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory( + sp, arg_byte_size, is_signed, value->GetScalar(), error)) + return false; + + sp += arg_byte_size; + } + } + } + } + return true; +} + +static bool GetReturnValuePassedInMemory(Thread &thread, + RegisterContext *reg_ctx, + size_t byte_size, Value &value) { + Status error; + DataBufferHeap buffer(byte_size, 0); + + const RegisterInfo *r0_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + uint32_t address = + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), + buffer.GetByteSize(), error); + + if (error.Fail()) + return false; + + value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); + return true; +} + +bool ABISysV_arm::IsArmHardFloat(Thread &thread) const { + ProcessSP process_sp(thread.GetProcess()); + if (process_sp) { + const ArchSpec &arch(process_sp->GetTarget().GetArchitecture()); + + return (arch.GetFlags() & ArchSpec::eARM_abi_hard_float) != 0; + } + + return false; +} + +ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl( + Thread &thread, lldb_private::CompilerType &compiler_type) const { + Value value; + ValueObjectSP return_valobj_sp; + + if (!compiler_type) + return return_valobj_sp; + + // value.SetContext (Value::eContextTypeClangType, + // compiler_type.GetOpaqueQualType()); + value.SetCompilerType(compiler_type); + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return return_valobj_sp; + + bool is_signed; + bool is_complex; + uint32_t float_count; + bool is_vfp_candidate = false; + uint8_t vfp_count = 0; + uint8_t vfp_byte_size = 0; + + // Get the pointer to the first stack argument so we have a place to start + // when reading data + + const RegisterInfo *r0_reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread); + llvm::Optional<uint64_t> byte_size = compiler_type.GetByteSize(&thread); + if (!bit_width || !byte_size) + return return_valobj_sp; + + if (compiler_type.IsIntegerOrEnumerationType(is_signed)) { + switch (*bit_width) { + default: + return return_valobj_sp; + case 64: { + const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + uint64_t raw_value; + raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & + UINT32_MAX)) + << 32; + if (is_signed) + value.GetScalar() = (int64_t)raw_value; + else + value.GetScalar() = (uint64_t)raw_value; + } break; + case 32: + if (is_signed) + value.GetScalar() = (int32_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); + else + value.GetScalar() = (uint32_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); + break; + case 16: + if (is_signed) + value.GetScalar() = (int16_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); + else + value.GetScalar() = (uint16_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); + break; + case 8: + if (is_signed) + value.GetScalar() = (int8_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); + else + value.GetScalar() = (uint8_t)( + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); + break; + } + } else if (compiler_type.IsPointerType()) { + uint32_t ptr = + thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & + UINT32_MAX; + value.GetScalar() = ptr; + } else if (compiler_type.IsVectorType(nullptr, nullptr)) { + if (IsArmHardFloat(thread) && (*byte_size == 8 || *byte_size == 16)) { + is_vfp_candidate = true; + vfp_byte_size = 8; + vfp_count = (*byte_size == 8 ? 1 : 2); + } else if (*byte_size <= 16) { + DataBufferHeap buffer(16, 0); + uint32_t *buffer_ptr = (uint32_t *)buffer.GetBytes(); + + for (uint32_t i = 0; 4 * i < *byte_size; ++i) { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); + buffer_ptr[i] = + reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX; + } + value.SetBytes(buffer.GetBytes(), *byte_size); + } else { + if (!GetReturnValuePassedInMemory(thread, reg_ctx, *byte_size, value)) + return return_valobj_sp; + } + } else if (compiler_type.IsFloatingPointType(float_count, is_complex)) { + if (float_count == 1 && !is_complex) { + switch (*bit_width) { + default: + return return_valobj_sp; + case 64: { + static_assert(sizeof(double) == sizeof(uint64_t), ""); + + if (IsArmHardFloat(thread)) { + RegisterValue reg_value; + const RegisterInfo *d0_reg_info = + reg_ctx->GetRegisterInfoByName("d0", 0); + reg_ctx->ReadRegister(d0_reg_info, reg_value); + value.GetScalar() = reg_value.GetAsDouble(); + } else { + uint64_t raw_value; + const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + raw_value = + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + raw_value |= + ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & + UINT32_MAX)) + << 32; + value.GetScalar() = *reinterpret_cast<double *>(&raw_value); + } + break; + } + case 16: // Half precision returned after a conversion to single precision + case 32: { + static_assert(sizeof(float) == sizeof(uint32_t), ""); + + if (IsArmHardFloat(thread)) { + RegisterValue reg_value; + const RegisterInfo *s0_reg_info = + reg_ctx->GetRegisterInfoByName("s0", 0); + reg_ctx->ReadRegister(s0_reg_info, reg_value); + value.GetScalar() = reg_value.GetAsFloat(); + } else { + uint32_t raw_value; + raw_value = + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + value.GetScalar() = *reinterpret_cast<float *>(&raw_value); + } + break; + } + } + } else if (is_complex && float_count == 2) { + if (IsArmHardFloat(thread)) { + is_vfp_candidate = true; + vfp_byte_size = *byte_size / 2; + vfp_count = 2; + } else if (!GetReturnValuePassedInMemory(thread, reg_ctx, *bit_width / 8, + value)) + return return_valobj_sp; + } else + // not handled yet + return return_valobj_sp; + } else if (compiler_type.IsAggregateType()) { + if (IsArmHardFloat(thread)) { + CompilerType base_type; + const uint32_t homogeneous_count = + compiler_type.IsHomogeneousAggregate(&base_type); + + if (homogeneous_count > 0 && homogeneous_count <= 4) { + llvm::Optional<uint64_t> base_byte_size = + base_type.GetByteSize(nullptr); + if (base_type.IsVectorType(nullptr, nullptr)) { + if (base_byte_size && + (*base_byte_size == 8 || *base_byte_size == 16)) { + is_vfp_candidate = true; + vfp_byte_size = 8; + vfp_count = (*base_byte_size == 8 ? homogeneous_count + : homogeneous_count * 2); + } + } else if (base_type.IsFloatingPointType(float_count, is_complex)) { + if (float_count == 1 && !is_complex) { + is_vfp_candidate = true; + if (base_byte_size) + vfp_byte_size = *base_byte_size; + vfp_count = homogeneous_count; + } + } + } else if (homogeneous_count == 0) { + const uint32_t num_children = compiler_type.GetNumFields(); + + if (num_children > 0 && num_children <= 2) { + uint32_t index = 0; + for (index = 0; index < num_children; index++) { + std::string name; + base_type = compiler_type.GetFieldAtIndex(index, name, nullptr, + nullptr, nullptr); + + if (base_type.IsFloatingPointType(float_count, is_complex)) { + llvm::Optional<uint64_t> base_byte_size = + base_type.GetByteSize(nullptr); + if (float_count == 2 && is_complex) { + if (index != 0 && base_byte_size && + vfp_byte_size != *base_byte_size) + break; + else if (base_byte_size) + vfp_byte_size = *base_byte_size; + } else + break; + } else + break; + } + + if (index == num_children) { + is_vfp_candidate = true; + vfp_byte_size = (vfp_byte_size >> 1); + vfp_count = (num_children << 1); + } + } + } + } + + if (*byte_size <= 4) { + RegisterValue r0_reg_value; + uint32_t raw_value = + reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + value.SetBytes(&raw_value, *byte_size); + } else if (!is_vfp_candidate) { + if (!GetReturnValuePassedInMemory(thread, reg_ctx, *byte_size, value)) + return return_valobj_sp; + } + } else { + // not handled yet + return return_valobj_sp; + } + + if (is_vfp_candidate) { + ProcessSP process_sp(thread.GetProcess()); + ByteOrder byte_order = process_sp->GetByteOrder(); + + DataBufferSP data_sp(new DataBufferHeap(*byte_size, 0)); + uint32_t data_offset = 0; + + for (uint32_t reg_index = 0; reg_index < vfp_count; reg_index++) { + uint32_t regnum = 0; + + if (vfp_byte_size == 4) + regnum = dwarf_s0 + reg_index; + else if (vfp_byte_size == 8) + regnum = dwarf_d0 + reg_index; + else + break; + + const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfo(eRegisterKindDWARF, regnum); + if (reg_info == nullptr) + break; + + RegisterValue reg_value; + if (!reg_ctx->ReadRegister(reg_info, reg_value)) + break; + + // Make sure we have enough room in "data_sp" + if ((data_offset + vfp_byte_size) <= data_sp->GetByteSize()) { + Status error; + const size_t bytes_copied = reg_value.GetAsMemoryData( + reg_info, data_sp->GetBytes() + data_offset, vfp_byte_size, + byte_order, error); + if (bytes_copied != vfp_byte_size) + break; + + data_offset += bytes_copied; + } + } + + if (data_offset == *byte_size) { + DataExtractor data; + data.SetByteOrder(byte_order); + data.SetAddressByteSize(process_sp->GetAddressByteSize()); + data.SetData(data_sp); + + return ValueObjectConstResult::Create(&thread, compiler_type, + ConstString(""), data); + } else { // Some error occurred while getting values from registers + return return_valobj_sp; + } + } + + // If we get here, we have a valid Value, so make our ValueObject out of it: + + return_valobj_sp = ValueObjectConstResult::Create( + thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); + return return_valobj_sp; +} + +Status ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value_sp) { + Status error; + if (!new_value_sp) { + error.SetErrorString("Empty value object for return value."); + return error; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { + error.SetErrorString("Null clang type for return value."); + return error; + } + + Thread *thread = frame_sp->GetThread().get(); + + bool is_signed; + uint32_t count; + bool is_complex; + + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + + bool set_it_simple = false; + if (compiler_type.IsIntegerOrEnumerationType(is_signed) || + compiler_type.IsPointerType()) { + DataExtractor data; + Status data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) { + error.SetErrorStringWithFormat( + "Couldn't convert return value to raw data: %s", + data_error.AsCString()); + return error; + } + lldb::offset_t offset = 0; + if (num_bytes <= 8) { + const RegisterInfo *r0_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + if (num_bytes <= 4) { + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + + if (reg_ctx->WriteRegisterFromUnsigned(r0_info, raw_value)) + set_it_simple = true; + } else { + uint32_t raw_value = data.GetMaxU32(&offset, 4); + + if (reg_ctx->WriteRegisterFromUnsigned(r0_info, raw_value)) { + const RegisterInfo *r1_info = reg_ctx->GetRegisterInfo( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); + + if (reg_ctx->WriteRegisterFromUnsigned(r1_info, raw_value)) + set_it_simple = true; + } + } + } else { + error.SetErrorString("We don't support returning longer than 64 bit " + "integer values at present."); + } + } else if (compiler_type.IsFloatingPointType(count, is_complex)) { + if (is_complex) + error.SetErrorString( + "We don't support returning complex values at present"); + else + error.SetErrorString( + "We don't support returning float values at present"); + } + + if (!set_it_simple) + error.SetErrorString( + "We only support setting simple integer return types at present."); + + return error; +} + +bool ABISysV_arm::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + uint32_t lr_reg_num = dwarf_lr; + uint32_t sp_reg_num = dwarf_sp; + uint32_t pc_reg_num = dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); + + // The previous PC is in the LR + row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true); + unwind_plan.AppendRow(row); + + // All other registers are the same. + + unwind_plan.SetSourceName("arm at-func-entry default"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + + return true; +} + +bool ABISysV_arm::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + // TODO: Handle thumb + uint32_t fp_reg_num = dwarf_r11; + uint32_t pc_reg_num = dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + const int32_t ptr_size = 4; + + row->GetCFAValue().SetIsRegisterPlusOffset(fp_reg_num, 2 * ptr_size); + row->SetOffset(0); + + row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("arm default unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); + + return true; +} + +// cf. "ARMv6 Function Calling Conventions" + +// ARMv7 on GNU/Linux general purpose reg rules: +// r0-r3 not preserved (used for argument passing) +// r4-r11 preserved (v1-v8) +// r12 not presrved +// r13 preserved (stack pointer) +// r14 preserved (link register) +// r15 preserved (pc) +// cpsr not preserved (different rules for different bits) + +// ARMv7 VFP register rules: +// d0-d7 not preserved (aka s0-s15, q0-q3) +// d8-d15 preserved (aka s16-s31, q4-q7) +// d16-d31 not preserved (aka q8-q15) + +bool ABISysV_arm::RegisterIsVolatile(const RegisterInfo *reg_info) { + if (reg_info) { + // Volatile registers are: r0, r1, r2, r3, r9, r12, r13 (aka sp) + const char *name = reg_info->name; + if (name[0] == 'r') { + switch (name[1]) { + case '0': + return name[2] == '\0'; // r0 + case '1': + switch (name[2]) { + case '\0': + return true; // r1 + case '2': + return name[3] == '\0'; // r12 + default: + break; + } + break; + + case '2': + return name[2] == '\0'; // r2 + case '3': + return name[2] == '\0'; // r3 + default: + break; + } + } else if (name[0] == 'd') { + switch (name[1]) { + case '0': + return name[2] == '\0'; // d0 is volatile + + case '1': + switch (name[2]) { + case '\0': + return true; // d1 is volatile + case '6': + case '7': + case '8': + case '9': + return name[3] == '\0'; // d16 - d19 are volatile + default: + break; + } + break; + + case '2': + switch (name[2]) { + case '\0': + return true; // d2 is volatile + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return name[3] == '\0'; // d20 - d29 are volatile + default: + break; + } + break; + + case '3': + switch (name[2]) { + case '\0': + return true; // d3 is volatile + case '0': + case '1': + return name[3] == '\0'; // d30 - d31 are volatile + default: + break; + } + break; + case '4': + case '5': + case '6': + case '7': + return name[2] == '\0'; // d4 - d7 are volatile + + default: + break; + } + } else if (name[0] == 's') { + switch (name[1]) { + case '0': + return name[2] == '\0'; // s0 is volatile + + case '1': + switch (name[2]) { + case '\0': + return true; // s1 is volatile + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + return name[3] == '\0'; // s10 - s15 are volatile + default: + break; + } + break; + + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return name[2] == '\0'; // s2 - s9 are volatile + + default: + break; + } + } else if (name[0] == 'q') { + switch (name[1]) { + case '1': + switch (name[2]) { + case '\0': + return true; // q1 is volatile + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + return true; // q10-q15 are volatile + default: + return false; + } + break; + + case '0': + case '2': + case '3': + return name[2] == '\0'; // q0-q3 are volatile + case '8': + case '9': + return name[2] == '\0'; // q8-q9 are volatile + default: + break; + } + } else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') + return true; + } + return false; +} + +void ABISysV_arm::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "SysV ABI for arm targets", CreateInstance); +} + +void ABISysV_arm::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString ABISysV_arm::GetPluginNameStatic() { + static ConstString g_name("SysV-arm"); + return g_name; +} + +// PluginInterface protocol + +lldb_private::ConstString ABISysV_arm::GetPluginName() { + return GetPluginNameStatic(); +} + +uint32_t ABISysV_arm::GetPluginVersion() { return 1; } |