diff options
Diffstat (limited to 'source/Plugins')
329 files changed, 66037 insertions, 19036 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 700d223fbc6da..3b9b0f3460729 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -17,7 +17,6 @@  #include "lldb/Core/Scalar.h"  #include "lldb/Core/Value.h"  #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@  #include "llvm/ADT/Triple.h"  #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  #include "Plugins/Process/Utility/ARMDefines.h"  #include <vector> @@ -38,90 +37,90 @@ using namespace lldb_private;  static RegisterInfo g_register_infos[] =  { -    //  NAME       ALT       SZ OFF ENCODING         FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE            VALUE REGS    INVALIDATE REGS +    //  NAME       ALT       SZ OFF ENCODING         FORMAT          EH_FRAME                DWARF               GENERIC                     PROCESS PLUGIN          LLDB NATIVE            VALUE REGS    INVALIDATE REGS      //  ========== =======   == === =============    ============    ======================= =================== =========================== ======================= ====================== ==========    =============== -    {   "r0",      "arg1",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r0,               dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   gdb_arm_r0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r1",      "arg2",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r1,               dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   gdb_arm_r1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r2",      "arg3",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r2,               dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   gdb_arm_r2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r3",      "arg4",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r3,               dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   gdb_arm_r3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r4",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r5",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r6",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r7",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r8",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r9",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r10",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r11",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r12",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "sp",      "r13",     4, 0, eEncodingUint    , eFormatHex,   { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "lr",      "r14",     4, 0, eEncodingUint    , eFormatHex,   { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "pc",      "r15",     4, 0, eEncodingUint    , eFormatHex,   { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "cpsr",    "psr",     4, 0, eEncodingUint    , eFormatHex,   { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s0",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s1",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s2",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s3",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s4",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s5",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s6",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s7",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s8",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s9",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s10",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s11",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s12",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s13",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s14",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s15",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s16",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s17",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s18",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s19",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s20",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s21",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s22",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s23",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s24",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s25",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s26",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s27",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s28",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s29",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s30",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s31",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "fpscr",   NULL,      4, 0, eEncodingUint    , eFormatHex  , { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d0",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d0,           LLDB_INVALID_REGNUM,        gdb_arm_d0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d1",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d1,           LLDB_INVALID_REGNUM,        gdb_arm_d1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d2",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d2,           LLDB_INVALID_REGNUM,        gdb_arm_d2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d3",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d3,           LLDB_INVALID_REGNUM,        gdb_arm_d3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d4",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d4,           LLDB_INVALID_REGNUM,        gdb_arm_d4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d5",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d5,           LLDB_INVALID_REGNUM,        gdb_arm_d5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d6",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d6,           LLDB_INVALID_REGNUM,        gdb_arm_d6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d7",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d7,           LLDB_INVALID_REGNUM,        gdb_arm_d7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d8",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d8,           LLDB_INVALID_REGNUM,        gdb_arm_d8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d9",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d9,           LLDB_INVALID_REGNUM,        gdb_arm_d9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d10",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d10,          LLDB_INVALID_REGNUM,        gdb_arm_d10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d11",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d11,          LLDB_INVALID_REGNUM,        gdb_arm_d11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d12",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d12,          LLDB_INVALID_REGNUM,        gdb_arm_d12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d13",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d13,          LLDB_INVALID_REGNUM,        gdb_arm_d13,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d14",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d14,          LLDB_INVALID_REGNUM,        gdb_arm_d14,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d15",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d15,          LLDB_INVALID_REGNUM,        gdb_arm_d15,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d16",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,        gdb_arm_d16,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d17",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,        gdb_arm_d17,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d18",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,        gdb_arm_d18,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d19",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,        gdb_arm_d19,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d20",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,        gdb_arm_d20,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d21",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,        gdb_arm_d21,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d22",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,        gdb_arm_d22,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d23",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,        gdb_arm_d23,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d24",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,        gdb_arm_d24,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d25",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,        gdb_arm_d25,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d26",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,        gdb_arm_d26,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d27",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,        gdb_arm_d27,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d28",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,        gdb_arm_d28,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d29",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,        gdb_arm_d29,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d30",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,        gdb_arm_d30,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d31",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,        gdb_arm_d31,            LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r0",      "arg1",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r0,           dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r1",      "arg2",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r1,           dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r2",      "arg3",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r2,           dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r3",      "arg4",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r3,           dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r4",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r4,           dwarf_r4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r5",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r5,           dwarf_r5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r6",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r6,           dwarf_r6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r7",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r7,           dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r8",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r8,           dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r9",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r9,           dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r10",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r10,          dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r11",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r11,          dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r12",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r12,          dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "sp",      "r13",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_sp,           dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "lr",      "r14",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_lr,           dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "pc",      "r15",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_pc,           dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "cpsr",    "psr",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_cpsr,         dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s0",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s1",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s2",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s3",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s4",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s5",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s6",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s7",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s8",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s9",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s10",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s11",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s12",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s13",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s14",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s15",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s16",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s17",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s18",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s19",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s20",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s21",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s22",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s23",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s24",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s25",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s26",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s27",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s28",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s29",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s30",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s31",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "fpscr",   NULL,      4, 0, eEncodingUint    , eFormatHex  , { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d0",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d1",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d2",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d3",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d4",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d5",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d6",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d7",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d8",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d9",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d10",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d11",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d12",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d13",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d14",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d15",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d16",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d17",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d18",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d19",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d20",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d21",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d22",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d23",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d24",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d25",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d26",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d27",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d28",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d29",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d30",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d31",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r8_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r8_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r9_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r9_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r10_usr", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r10_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, @@ -239,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,          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); +        // Keep the stack 16 byte aligned +        sp &= ~(16ull-1ull);          // just using arg1 to get the right size          const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); @@ -333,18 +332,18 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,          if (!value)              return false; -        ClangASTType clang_type = value->GetClangType(); -        if (clang_type) +        CompilerType compiler_type = value->GetCompilerType(); +        if (compiler_type)          {              bool is_signed = false;              size_t bit_width = 0; -            if (clang_type.IsIntegerType (is_signed)) +            if (compiler_type.IsIntegerType (is_signed))              { -                bit_width = clang_type.GetBitSize(&thread); +                bit_width = compiler_type.GetBitSize(&thread);              } -            else if (clang_type.IsPointerOrReferenceType ()) +            else if (compiler_type.IsPointerOrReferenceType ())              { -                bit_width = clang_type.GetBitSize(&thread); +                bit_width = compiler_type.GetBitSize(&thread);              }              else              { @@ -414,22 +413,37 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,      return true;  } +bool +ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const +{ +    bool is_armv7k = false; +    if (thread) +    { +        ProcessSP process_sp (thread->GetProcess()); +        if (process_sp) +        { +            const ArchSpec &arch (process_sp->GetTarget().GetArchitecture()); +            const ArchSpec::Core system_core = arch.GetCore(); +            if (system_core == ArchSpec::eCore_arm_armv7k) +            { +                is_armv7k = true; +            } +        } +    } +    return is_armv7k; +} +  ValueObjectSP  ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, -                                         lldb_private::ClangASTType &clang_type) const +                                         lldb_private::CompilerType &compiler_type) const  {      Value value;      ValueObjectSP return_valobj_sp; -    if (!clang_type) -        return return_valobj_sp; -     -    clang::ASTContext *ast_context = clang_type.GetASTContext(); -    if (!ast_context) +    if (!compiler_type)          return return_valobj_sp; -    //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); -    value.SetClangType (clang_type); +    value.SetCompilerType (compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx) @@ -441,14 +455,68 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,      // when reading data      const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); -    if (clang_type.IsIntegerType (is_signed)) +    if (compiler_type.IsIntegerType (is_signed))      { -        size_t bit_width = clang_type.GetBitSize(&thread); +        size_t bit_width = compiler_type.GetBitSize(&thread);          switch (bit_width)          {              default:                  return return_valobj_sp; +            case 128: +                if (IsArmv7kProcess (&thread)) +                { +                    // "A composite type not larger than 16 bytes is returned in r0-r3. The format is +                    // as if the result had been stored in memory at a word-aligned address and then +                    // loaded into r0-r3 with an ldm instruction" +                    { +                        const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); +                        const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); +                        const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); +                        if (r1_reg_info && r2_reg_info && r3_reg_info) +                        { +                            const size_t byte_size = compiler_type.GetByteSize(&thread); +                            ProcessSP process_sp (thread.GetProcess()); +                            if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size + r2_reg_info->byte_size + r3_reg_info->byte_size +                                && process_sp) +                            { +                                std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); +                                const ByteOrder byte_order = process_sp->GetByteOrder(); +                                RegisterValue r0_reg_value; +                                RegisterValue r1_reg_value; +                                RegisterValue r2_reg_value; +                                RegisterValue r3_reg_value; +                                if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value) +                                    && reg_ctx->ReadRegister(r1_reg_info, r1_reg_value) +                                    && reg_ctx->ReadRegister(r2_reg_info, r2_reg_value) +                                    && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value)) +                                { +                                    Error error; +                                    if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error) +                                        && r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error) +                                        && r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error) +                                        && r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error)) +                                    { +                                        DataExtractor data (DataBufferSP (heap_data_ap.release()), +                                                            byte_order, +                                                            process_sp->GetAddressByteSize()); +                                         +                                        return_valobj_sp = ValueObjectConstResult::Create (&thread, +                                                                                        compiler_type, +                                                                                        ConstString(""), +                                                                                        data); +                                        return return_valobj_sp; +                                    } +                                } +                            } +                        } +                    } +                } +                else +                { +                    return return_valobj_sp; +                } +                break;              case 64:              {                  const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); @@ -481,7 +549,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,                  break;          }      } -    else if (clang_type.IsPointerType ()) +    else if (compiler_type.IsPointerType ())      {          uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;          value.GetScalar() = ptr; @@ -510,8 +578,8 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -526,7 +594,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          DataExtractor data;          Error data_error; @@ -561,12 +629,45 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj                  }              }          } +        else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get())) +        { +            // "A composite type not larger than 16 bytes is returned in r0-r3. The format is +            // as if the result had been stored in memory at a word-aligned address and then +            // loaded into r0-r3 with an ldm instruction" + +            const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); +            const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); +            const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); +            const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); +            lldb::offset_t offset = 0; +            uint32_t bytes_written = 4; +            uint32_t raw_value = data.GetMaxU64(&offset, 4); +            if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes) +            { +                bytes_written += 4; +                raw_value = data.GetMaxU64(&offset, 4); +                if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value)) +                { +                    bytes_written += 4; +                    raw_value = data.GetMaxU64(&offset, 4); +                    if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) +                    { +                        bytes_written += 4; +                        raw_value = data.GetMaxU64(&offset, 4); +                        if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r3_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 (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index eee43943d73ac..a4e9dead77946 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -20,42 +20,36 @@  class ABIMacOSX_arm : public lldb_private::ABI  {  public: -    ~ABIMacOSX_arm() { } +    ~ABIMacOSX_arm() override = default; -    virtual size_t  -    GetRedZoneSize () const; +    size_t  +    GetRedZoneSize() const override; -    virtual bool -    PrepareTrivialCall (lldb_private::Thread &thread,  -                        lldb::addr_t sp, -                        lldb::addr_t func_addr, -                        lldb::addr_t returnAddress,  -                        llvm::ArrayRef<lldb::addr_t> args) const; +    bool +    PrepareTrivialCall(lldb_private::Thread &thread, +                       lldb::addr_t sp, +                       lldb::addr_t func_addr, +                       lldb::addr_t returnAddress, +                       llvm::ArrayRef<lldb::addr_t> args) const override; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                    lldb_private::ClangASTType &ast_type) const; - -public: -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are are 4 byte aligned          if (cfa & (4ull - 1ull)) @@ -65,8 +59,8 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // Just make sure the address is a valid 32 bit address. Bit zero          // might be set due to Thumb function calls, so don't enforce 2 byte @@ -74,20 +68,24 @@ public:          return pc <= UINT32_MAX;      } -    virtual lldb::addr_t -    FixCodeAddress (lldb::addr_t pc) +    lldb::addr_t +    FixCodeAddress(lldb::addr_t pc) override      {          // ARM uses bit zero to signify a code address is thumb, so we must          // strip bit zero in any code addresses.          return pc & ~(lldb::addr_t)1;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; + +    bool +    IsArmv7kProcess (lldb_private::Thread *thread) const;      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -103,13 +101,18 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); + +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  protected: +    lldb::ValueObjectSP +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &ast_type) const override; +  private:      ABIMacOSX_arm() :           lldb_private::ABI()  @@ -118,4 +121,4 @@ private:      }  }; -#endif  // liblldb_ABIMacOSX_arm_h_ +#endif // liblldb_ABIMacOSX_arm_h_ diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 04b96180deb37..0e6f9d663ae8e 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -19,7 +19,6 @@  #include "lldb/Core/Value.h"  #include "lldb/Core/Value.h"  #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/RegisterContext.h" @@ -37,12 +36,11 @@ using namespace lldb;  using namespace lldb_private;  static const char *pluginDesc = "Mac OS X ABI for arm64 targets"; -static const char *pluginShort = "abi.macosx-arm64";  static RegisterInfo g_register_infos[] =   { -    //  NAME       ALT       SZ OFF ENCODING          FORMAT                   COMPILER             DWARF                  GENERIC                     GDB                     LLDB NATIVE +    //  NAME       ALT       SZ OFF ENCODING          FORMAT                   EH_FRAME             DWARF                  GENERIC                     PROCESS PLUGIN          LLDB NATIVE      //  ========== =======   == === =============     ===================      ===================  ====================== =========================== ======================= ======================      {   "x0",      NULL,      8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x0,       LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "x1",      NULL,      8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x1,       LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -77,7 +75,7 @@ static RegisterInfo g_register_infos[] =      {   "lr",      "x30",     8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x30,      LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "sp",      "x31",     8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x31,      LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "pc",      NULL,      8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::pc,       LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "cpsr",    "psr",     4, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "cpsr",    "psr",     4, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr,     LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "v0",      NULL,     16, 0, eEncodingVector , eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM, arm64_dwarf::v0,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "v1",      NULL,     16, 0, eEncodingVector , eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM, arm64_dwarf::v1,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -115,71 +113,71 @@ static RegisterInfo g_register_infos[] =      {   "fpsr",    NULL,      4, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "fpcr",    NULL,      4, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s0",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s1",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s2",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s3",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s4",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s5",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s6",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s7",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s8",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s9",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s10",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s11",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s12",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s13",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s14",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s15",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s16",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s17",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s18",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s19",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s20",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s21",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s22",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s23",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s24",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s25",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s26",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s27",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s28",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s29",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s30",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "s31",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, - -    {   "d0",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d1",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d2",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d3",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d4",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d5",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d6",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d7",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d8",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d9",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d10",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d11",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d12",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d13",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d14",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d15",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d16",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d17",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d18",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d19",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d20",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d21",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d22",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d23",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d24",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d25",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d26",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d27",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d28",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d29",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d30",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, -    {   "d31",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL } +    {   "s0",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s1",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s2",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s3",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s4",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s5",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s6",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s7",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s8",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s9",      NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s10",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s11",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s12",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s13",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s14",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s15",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s16",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s17",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s18",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s19",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s20",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s21",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s22",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s23",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s24",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s25",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s26",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s27",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s28",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s29",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s30",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "s31",     NULL,     4, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, + +    {   "d0",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d1",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d2",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d3",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d4",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d5",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d6",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d7",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d8",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d9",      NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d10",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d11",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d12",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d13",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d14",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d15",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d16",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d17",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d18",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d19",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d20",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d21",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d22",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d23",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d24",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d25",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d26",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d27",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d28",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d29",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d30",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, +    {   "d31",     NULL,     8, 0, eEncodingIEEE754 , eFormatFloat         , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -322,7 +320,7 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const          if (!value)              return false; -        ClangASTType value_type = value->GetClangType(); +        CompilerType value_type = value->GetCompilerType();          if (value_type)          {              bool is_signed = false; @@ -424,7 +422,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO          return error;      } -    ClangASTType return_value_type = new_value_sp->GetClangType(); +    CompilerType return_value_type = new_value_sp->GetCompilerType();      if (!return_value_type)      {          error.SetErrorString ("Null clang type for return value."); @@ -709,7 +707,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)  static bool  LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,                                        RegisterContext *reg_ctx, -                                      const ClangASTType &value_type, +                                      const CompilerType &value_type,                                        bool is_return_value, // false => parameter, true => return value                                        uint32_t &NGRN,       // NGRN (see ABI documentation)                                        uint32_t &NSRN,       // NSRN (see ABI documentation) @@ -724,18 +722,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,      const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();      Error error; -    ClangASTType base_type; +    CompilerType base_type;      const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);      if (homogeneous_count > 0 && homogeneous_count <= 8)      { -        printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);          // Make sure we have enough registers          if (NSRN < 8 && (8-NSRN) >= homogeneous_count)          {              if (!base_type)                  return false;              const size_t base_byte_size = base_type.GetByteSize(nullptr); -            printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);              uint32_t data_offset = 0;              for (uint32_t i=0; i<homogeneous_count; ++i) @@ -861,7 +857,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,  }  ValueObjectSP -ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; @@ -870,16 +866,16 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_      if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)          return return_valobj_sp; -    //value.SetContext (Value::eContextTypeClangType, return_clang_type); -    value.SetClangType(return_clang_type); +    //value.SetContext (Value::eContextTypeClangType, return_compiler_type); +    value.SetCompilerType(return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const size_t byte_size = return_clang_type.GetByteSize(nullptr); +    const size_t byte_size = return_compiler_type.GetByteSize(nullptr); -    const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);      if (type_flags & eTypeIsScalar ||          type_flags & eTypeIsPointer)      { @@ -926,7 +922,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_                                                                      exe_ctx.GetProcessRef().GetAddressByteSize());                                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                                   return_clang_type, +                                                                                                   return_compiler_type,                                                                                                     ConstString(""),                                                                                                     data);                                                  return return_valobj_sp; @@ -1043,7 +1039,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_                                                  byte_order,                                                  exe_ctx.GetProcessRef().GetAddressByteSize());                              return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                               return_clang_type, +                                                                               return_compiler_type,                                                                                 ConstString(""),                                                                                 data);                          } @@ -1060,10 +1056,10 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_          uint32_t NGRN = 0;  // Search ABI docs for NGRN          uint32_t NSRN = 0;  // Search ABI docs for NSRN          const bool is_return_value = true; -        if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data)) +        if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))          {              return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                               return_clang_type, +                                                               return_compiler_type,                                                                 ConstString(""),                                                                 data);                      } @@ -1095,12 +1091,6 @@ ABIMacOSX_arm64::GetPluginNameStatic()      return g_plugin_name;  } -const char * -ABIMacOSX_arm64::GetShortPluginName() -{ -    return pluginShort; -} -  uint32_t  ABIMacOSX_arm64::GetPluginVersion()  { diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h index 6cce6a6f11741..1bc94f61c2f14 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h @@ -22,30 +22,30 @@ class ABIMacOSX_arm64 :      public lldb_private::ABI  {  public: -    ~ABIMacOSX_arm64() { } +    ~ABIMacOSX_arm64() override = default; -    virtual size_t  -    GetRedZoneSize () const; +    size_t +    GetRedZoneSize() const override; -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The arm64 ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -57,9 +57,8 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. - -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -69,8 +68,8 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          if (pc & (4ull - 1ull))              return false;   // Not 4 byte aligned @@ -79,12 +78,13 @@ public:          return true;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override;      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -97,28 +97,26 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ +      static lldb_private::ConstString      GetPluginNameStatic(); -    virtual lldb_private::ConstString -    GetPluginName() +    lldb_private::ConstString +    GetPluginName() override      {          return GetPluginNameStatic();      } -    virtual const char * -    GetShortPluginName(); -     -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;  protected: -    virtual lldb::ValueObjectSP +    lldb::ValueObjectSP      GetReturnValueObjectImpl (lldb_private::Thread &thread, -                    lldb_private::ClangASTType &ast_type) const; +                    lldb_private::CompilerType &ast_type) const override;  private:      ABIMacOSX_arm64() :  @@ -128,4 +126,4 @@ private:      }   }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_arm64_h_ diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 4204d18769b89..75e5fb1558e62 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -16,13 +16,13 @@  #include "lldb/Core/RegisterValue.h"  #include "lldb/Core/Scalar.h"  #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.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 "llvm/ADT/STLExtras.h"  #include "llvm/ADT/Triple.h"  #include <vector> @@ -32,16 +32,16 @@ using namespace lldb_private;  enum  { -    gcc_eax = 0, -    gcc_ecx, -    gcc_edx, -    gcc_ebx, -    gcc_ebp, -    gcc_esp, -    gcc_esi, -    gcc_edi, -    gcc_eip, -    gcc_eflags +    ehframe_eax = 0, +    ehframe_ecx, +    ehframe_edx, +    ehframe_ebx, +    ehframe_ebp,   // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin +    ehframe_esp,   // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin +    ehframe_esi, +    ehframe_edi, +    ehframe_eip, +    ehframe_eflags  };  enum @@ -82,121 +82,60 @@ enum      dwarf_ymm7 = dwarf_xmm7  }; -enum -{ -    gdb_eax        =  0, -    gdb_ecx        =  1, -    gdb_edx        =  2, -    gdb_ebx        =  3, -    gdb_esp        =  4, -    gdb_ebp        =  5, -    gdb_esi        =  6, -    gdb_edi        =  7, -    gdb_eip        =  8, -    gdb_eflags     =  9, -    gdb_cs         = 10, -    gdb_ss         = 11, -    gdb_ds         = 12, -    gdb_es         = 13, -    gdb_fs         = 14, -    gdb_gs         = 15, -    gdb_stmm0      = 16, -    gdb_stmm1      = 17, -    gdb_stmm2      = 18, -    gdb_stmm3      = 19, -    gdb_stmm4      = 20, -    gdb_stmm5      = 21, -    gdb_stmm6      = 22, -    gdb_stmm7      = 23, -    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl, -    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat, -    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag, -    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg, -    gdb_fioff      = 28,    gdb_ip      = gdb_fioff, -    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg, -    gdb_fooff      = 30,    gdb_dp      = gdb_fooff, -    gdb_fop        = 31, -    gdb_xmm0       = 32, -    gdb_xmm1       = 33, -    gdb_xmm2       = 34, -    gdb_xmm3       = 35, -    gdb_xmm4       = 36, -    gdb_xmm5       = 37, -    gdb_xmm6       = 38, -    gdb_xmm7       = 39, -    gdb_mxcsr      = 40, -    gdb_mm0        = 41, -    gdb_mm1        = 42, -    gdb_mm2        = 43, -    gdb_mm3        = 44, -    gdb_mm4        = 45, -    gdb_mm5        = 46, -    gdb_mm6        = 47, -    gdb_mm7        = 48, -    gdb_ymm0       = gdb_xmm0, -    gdb_ymm1       = gdb_xmm1, -    gdb_ymm2       = gdb_xmm2, -    gdb_ymm3       = gdb_xmm3, -    gdb_ymm4       = gdb_xmm4, -    gdb_ymm5       = gdb_xmm5, -    gdb_ymm6       = gdb_xmm6, -    gdb_ymm7       = gdb_xmm7 -}; -  static RegisterInfo g_register_infos[] =   { -  //  NAME      ALT      SZ OFF ENCODING         FORMAT                COMPILER              DWARF                 GENERIC                      GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS +  //  NAME      ALT      SZ OFF ENCODING         FORMAT                EH_FRAME              DWARF                 GENERIC                      PROCESS PLUGIN        LLDB NATIVE            VALUE REGS    INVALIDATE REGS    //  ======    =======  == === =============    ============          ===================== ===================== ============================ ====================  ====================== ==========    =============== -    { "eax",    NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_eax             , dwarf_eax           , LLDB_INVALID_REGNUM       , gdb_eax            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ebx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebx             , dwarf_ebx           , LLDB_INVALID_REGNUM       , gdb_ebx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ecx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ecx             , dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , gdb_ecx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "edx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edx             , dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , gdb_edx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "esi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_esi             , dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , gdb_esi            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "edi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edi             , dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , gdb_edi            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ebp"   , "fp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebp             , dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "esp"   , "sp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_esp             , dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "eip"   , "pc",    4,  0, eEncodingUint  , eFormatHex          , { gcc_eip             , dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "eflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0         , LLDB_INVALID_REGNUM       , gdb_stmm0          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1         , LLDB_INVALID_REGNUM       , gdb_stmm1          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2         , LLDB_INVALID_REGNUM       , gdb_stmm2          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3         , LLDB_INVALID_REGNUM       , gdb_stmm3          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4         , LLDB_INVALID_REGNUM       , gdb_stmm4          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5         , LLDB_INVALID_REGNUM       , gdb_stmm5          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6         , LLDB_INVALID_REGNUM       , gdb_stmm6          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7         , LLDB_INVALID_REGNUM       , gdb_stmm7          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0          , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1          , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2          , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3          , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4          , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5          , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6          , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7          , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0          , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1          , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2          , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3          , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4          , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5          , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6          , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7          , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      NULL,              NULL} +    { "eax",    NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_eax         , dwarf_eax           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ebx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_ebx         , dwarf_ebx           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ecx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_ecx         , dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "edx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_edx         , dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "esi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_esi         , dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "edi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { ehframe_edi         , dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ebp"   , "fp",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_ebp         , dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "esp"   , "sp",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_esp         , dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "eip"   , "pc",    4,  0, eEncodingUint  , eFormatHex          , { ehframe_eip         , dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "eflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7         , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -237,7 +176,7 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)  {      static ABISP g_abi_sp;       if ((arch.GetTriple().getArch() == llvm::Triple::x86) && -          (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS())) +          (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS()))       {          if (!g_abi_sp)              g_abi_sp.reset (new ABIMacOSX_i386); @@ -316,184 +255,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,      return true;  } -bool -ABIMacOSX_i386::PrepareNormalCall (Thread &thread, -                                   addr_t sp, -                                   addr_t func_addr, -                                   addr_t return_addr, -                                   ValueList &args) const -{ -    ExecutionContext exe_ctx (thread.shared_from_this()); -    RegisterContext *reg_ctx = thread.GetRegisterContext().get(); -    if (!reg_ctx) -        return false; -     -    Process *process = exe_ctx.GetProcessPtr(); -    Error error; -    uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); -    uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); -    uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); -     -    // Do the argument layout -     -    std::vector <uint32_t> argLayout;   // 4-byte chunks, as discussed in the ABI Function Call Guide -     -    size_t numArgs = args.GetSize(); -    size_t index; -     -    for (index = 0; index < numArgs; ++index) -    { -        Value *val = args.GetValueAtIndex(index); -         -        if (!val) -            return false; -         -        switch (val->GetValueType()) -        { -        case Value::eValueTypeScalar: -            { -                Scalar &scalar = val->GetScalar(); -                switch (scalar.GetType()) -                { -                case Scalar::e_void: -                    return false; -                case Scalar::e_sint:  -                case Scalar::e_uint: -                case Scalar::e_slong: -                case Scalar::e_ulong: -                case Scalar::e_slonglong: -                case Scalar::e_ulonglong: -                    { -                        uint64_t data = scalar.ULongLong(); -                         -                        switch (scalar.GetByteSize()) -                        { -                        default: -                            return false; -                        case 1: -                            argLayout.push_back((uint32_t)(data & 0xffull)); -                            break; -                        case 2: -                            argLayout.push_back((uint32_t)(data & 0xffffull)); -                            break; -                        case 4: -                            argLayout.push_back((uint32_t)(data & 0xffffffffull)); -                            break; -                        case 8: -                            argLayout.push_back((uint32_t)(data & 0xffffffffull)); -                            argLayout.push_back((uint32_t)(data >> 32)); -                            break; -                        } -                    } -                    break; -                case Scalar::e_float: -                    { -                        float data = scalar.Float(); -                        uint32_t dataRaw = *((uint32_t*)(&data)); -                        argLayout.push_back(dataRaw); -                    } -                    break; -                case Scalar::e_double: -                    { -                        double data = scalar.Double(); -                        uint32_t *dataRaw = ((uint32_t*)(&data)); -                        argLayout.push_back(dataRaw[0]); -                        argLayout.push_back(dataRaw[1]); -                    } -                    break; -                case Scalar::e_long_double: -                    { -                        long double data = scalar.Double(); -                        uint32_t *dataRaw = ((uint32_t*)(&data)); -                        while ((argLayout.size() * 4) & 0xf) -                            argLayout.push_back(0); -                        argLayout.push_back(dataRaw[0]); -                        argLayout.push_back(dataRaw[1]); -                        argLayout.push_back(dataRaw[2]); -                        argLayout.push_back(dataRaw[3]); -                    } -                    break; -                } -            } -            break; -        case Value::eValueTypeHostAddress: -            { -                ClangASTType clang_type (val->GetClangType()); -                if (clang_type) -                { -                    uint32_t cstr_length = 0; -                    if (clang_type.IsCStringType (cstr_length)) -                    { -                        const char *cstr = (const char*)val->GetScalar().ULongLong(); -                        cstr_length = strlen(cstr); -                         -                        // Push the string onto the stack immediately. -                         -                        sp -= (cstr_length + 1); -                         -                        if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1)) -                            return false; -                         -                        // Put the address of the string into the argument array. -                         -                        argLayout.push_back((uint32_t)(sp & 0xffffffff)); -                    } -                    else -                    { -                        return false; -                    } -                } -                break; -            } -            break; -        case Value::eValueTypeFileAddress: -        case Value::eValueTypeLoadAddress: -        default: -            return false; -        } -    } -     -    // Make room for the arguments on the stack -     -    sp -= 4 * argLayout.size(); -     -    // Align the SP -     -    sp &= ~(16ull-1ull); // 16-byte alignment -     -    // Write the arguments on the stack -     -    size_t numChunks = argLayout.size(); - -    for (index = 0; index < numChunks; ++index) -        if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t)) -            return false; -     -    // The return address is pushed onto the stack. -     -    sp -= 4; -    uint32_t returnAddressU32 = return_addr; -    if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32)) -        return false; -     -    // %esp is set to the actual stack value. -     -    if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) -        return false; -     -    // %ebp is set to a fake value, in our case 0x0x00000000 -     -    if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000)) -        return false; -     -    // %eip is set to the address of the called function. -     -    if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) -        return false; -     -    return true;     -} -  static bool   ReadIntegerArgument (Scalar           &scalar,                       unsigned int     bit_width, @@ -545,23 +306,23 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,          // We currently only support extracting values with Clang QualTypes.          // Do we care about others? -        ClangASTType clang_type (value->GetClangType()); -        if (clang_type) +        CompilerType compiler_type (value->GetCompilerType()); +        if (compiler_type)          {              bool is_signed; -            if (clang_type.IsIntegerType (is_signed)) +            if (compiler_type.IsIntegerType (is_signed))              {                  ReadIntegerArgument(value->GetScalar(), -                                    clang_type.GetBitSize(&thread), +                                    compiler_type.GetBitSize(&thread),                                      is_signed,                                      thread.GetProcess().get(),                                       current_stack_argument);              } -            else if (clang_type.IsPointerType()) +            else if (compiler_type.IsPointerType())              {                  ReadIntegerArgument(value->GetScalar(), -                                    clang_type.GetBitSize(&thread), +                                    compiler_type.GetBitSize(&thread),                                      false,                                      thread.GetProcess().get(),                                      current_stack_argument); @@ -582,8 +343,8 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -598,7 +359,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          DataExtractor data;          Error data_error; @@ -638,7 +399,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb              error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present"); @@ -654,16 +415,16 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb  ValueObjectSP  ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, -                                          ClangASTType &clang_type) const +                                          CompilerType &compiler_type) const  {      Value value;      ValueObjectSP return_valobj_sp; -    if (!clang_type) +    if (!compiler_type)          return return_valobj_sp; -    //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); -    value.SetClangType (clang_type); +    //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); +    value.SetCompilerType (compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();          if (!reg_ctx) @@ -671,9 +432,9 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,      bool is_signed; -    if (clang_type.IsIntegerType (is_signed)) +    if (compiler_type.IsIntegerType (is_signed))      { -        size_t bit_width = clang_type.GetBitSize(&thread); +        size_t bit_width = compiler_type.GetBitSize(&thread);          unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];          unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -713,7 +474,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,                  break;          }      } -    else if (clang_type.IsPointerType ()) +    else if (compiler_type.IsPointerType ())      {          unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];          uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index d81b7a7e684b0..6a82fce35bf76 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -22,48 +22,33 @@ class ABIMacOSX_i386 :      public lldb_private::ABI  {  public: - -    ~ABIMacOSX_i386() { } -     -    virtual size_t  -    GetRedZoneSize () const; +    ~ABIMacOSX_i386() override = default; -    virtual bool -    PrepareTrivialCall (lldb_private::Thread &thread,  -                        lldb::addr_t sp, -                        lldb::addr_t func_addr, -                        lldb::addr_t return_addr,  -                        llvm::ArrayRef<lldb::addr_t> args) const; +    size_t  +    GetRedZoneSize() const override; -    virtual bool -    PrepareNormalCall (lldb_private::Thread &thread, +    bool +    PrepareTrivialCall(lldb_private::Thread &thread,                         lldb::addr_t sp,                         lldb::addr_t func_addr,                         lldb::addr_t return_addr, -                       lldb_private::ValueList &args) const; +                       llvm::ArrayRef<lldb::addr_t> args) const override; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                    lldb_private::ClangASTType &ast_type) const; - -public: - -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The Darwin i386 ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public:      //      // If we were to enforce 16-byte alignment, we also need to relax to 4-byte      // alignment for non-darwin i386 targets. -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are are 4 byte aligned          if (cfa & (4ull - 1ull)) @@ -89,19 +74,20 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // Just make sure the address is a valid 32 bit address.           return pc <= UINT32_MAX;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override;      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -114,22 +100,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ +      static lldb_private::ConstString      GetPluginNameStatic (); -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  protected: +    lldb::ValueObjectSP +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &ast_type) const override; +      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABIMacOSX_i386() :  +        lldb_private::ABI()  +    { +        // Call CreateInstance instead.   +    }   }; - -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_i386_h_ diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index 50a9863d83e74..ef625dece2656 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -17,7 +17,6 @@  #include "lldb/Core/Scalar.h"  #include "lldb/Core/Value.h"  #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@  #include "llvm/ADT/Triple.h"  #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  #include "Plugins/Process/Utility/ARMDefines.h"  #include <vector> @@ -38,90 +37,90 @@ using namespace lldb_private;  static RegisterInfo g_register_infos[] =  { -    //  NAME       ALT       SZ OFF ENCODING         FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE            VALUE REGS    INVALIDATE REGS +    //  NAME       ALT       SZ OFF ENCODING         FORMAT          EH_FRAME                DWARF               GENERIC                     PROCESS PLUGIN          LLDB NATIVE            VALUE REGS    INVALIDATE REGS      //  ========== =======   == === =============    ============    ======================= =================== =========================== ======================= ====================== ==========    =============== -    {   "r0",      "arg1",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r0,               dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   gdb_arm_r0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r1",      "arg2",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r1,               dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   gdb_arm_r1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r2",      "arg3",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r2,               dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   gdb_arm_r2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r3",      "arg4",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r3,               dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   gdb_arm_r3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r4",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r5",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r6",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r7",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r8",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r9",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r10",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r11",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "r12",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "sp",      "r13",     4, 0, eEncodingUint    , eFormatHex,   { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "lr",      "r14",     4, 0, eEncodingUint    , eFormatHex,   { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "pc",      "r15",     4, 0, eEncodingUint    , eFormatHex,   { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "cpsr",    "psr",     4, 0, eEncodingUint    , eFormatHex,   { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s0",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s1",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s2",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s3",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s4",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s5",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s6",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s7",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s8",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s9",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s10",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s11",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s12",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s13",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s14",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s15",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s16",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s17",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s18",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s19",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s20",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s21",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s22",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s23",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s24",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s25",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s26",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s27",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s28",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s29",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s30",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "s31",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "fpscr",   NULL,      4, 0, eEncodingUint    , eFormatHex  , { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d0",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d0,           LLDB_INVALID_REGNUM,        gdb_arm_d0,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d1",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d1,           LLDB_INVALID_REGNUM,        gdb_arm_d1,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d2",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d2,           LLDB_INVALID_REGNUM,        gdb_arm_d2,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d3",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d3,           LLDB_INVALID_REGNUM,        gdb_arm_d3,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d4",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d4,           LLDB_INVALID_REGNUM,        gdb_arm_d4,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d5",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d5,           LLDB_INVALID_REGNUM,        gdb_arm_d5,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d6",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d6,           LLDB_INVALID_REGNUM,        gdb_arm_d6,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d7",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d7,           LLDB_INVALID_REGNUM,        gdb_arm_d7,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d8",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d8,           LLDB_INVALID_REGNUM,        gdb_arm_d8,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d9",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d9,           LLDB_INVALID_REGNUM,        gdb_arm_d9,             LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d10",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d10,          LLDB_INVALID_REGNUM,        gdb_arm_d10,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d11",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d11,          LLDB_INVALID_REGNUM,        gdb_arm_d11,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d12",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d12,          LLDB_INVALID_REGNUM,        gdb_arm_d12,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d13",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d13,          LLDB_INVALID_REGNUM,        gdb_arm_d13,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d14",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d14,          LLDB_INVALID_REGNUM,        gdb_arm_d14,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d15",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d15,          LLDB_INVALID_REGNUM,        gdb_arm_d15,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d16",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,        gdb_arm_d16,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d17",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,        gdb_arm_d17,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d18",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,        gdb_arm_d18,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d19",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,        gdb_arm_d19,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d20",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,        gdb_arm_d20,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d21",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,        gdb_arm_d21,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d22",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,        gdb_arm_d22,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d23",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,        gdb_arm_d23,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d24",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,        gdb_arm_d24,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d25",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,        gdb_arm_d25,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d26",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,        gdb_arm_d26,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d27",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,        gdb_arm_d27,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d28",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,        gdb_arm_d28,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d29",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,        gdb_arm_d29,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d30",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,        gdb_arm_d30,            LLDB_INVALID_REGNUM },      NULL,              NULL}, -    {   "d31",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,        gdb_arm_d31,            LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r0",      "arg1",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r0,           dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r1",      "arg2",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r1,           dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r2",      "arg3",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r2,           dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r3",      "arg4",    4, 0, eEncodingUint    , eFormatHex,   { ehframe_r3,           dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r4",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r4,           dwarf_r4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r5",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r5,           dwarf_r5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r6",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r6,           dwarf_r6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r7",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r7,           dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r8",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r8,           dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r9",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r9,           dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r10",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r10,          dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r11",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r11,          dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "r12",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { ehframe_r12,          dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "sp",      "r13",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_sp,           dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "lr",      "r14",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_lr,           dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "pc",      "r15",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_pc,           dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "cpsr",    "psr",     4, 0, eEncodingUint    , eFormatHex,   { ehframe_cpsr,         dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s0",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s1",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s2",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s3",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s4",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s5",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s6",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s7",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s8",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s9",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s10",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s11",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s12",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s13",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s14",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s15",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s16",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s17",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s18",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s19",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s20",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s21",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s22",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s23",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s24",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s25",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s26",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s27",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s28",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s29",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s30",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "s31",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "fpscr",   NULL,      4, 0, eEncodingUint    , eFormatHex  , { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d0",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d1",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d2",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d3",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d4",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d5",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d6",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d7",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d8",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d9",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d10",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d11",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d12",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d13",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d14",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d15",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d16",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d17",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d18",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d19",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d20",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d21",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d22",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d23",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d24",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d25",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d26",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d27",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d28",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d29",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d30",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, +    {   "d31",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r8_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r8_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r9_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r9_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},      {   "r10_usr", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r10_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}, @@ -333,18 +332,18 @@ ABISysV_arm::GetArgumentValues (Thread &thread,          if (!value)              return false; -        ClangASTType clang_type = value->GetClangType(); -        if (clang_type) +        CompilerType compiler_type = value->GetCompilerType(); +        if (compiler_type)          {              bool is_signed = false;              size_t bit_width = 0; -            if (clang_type.IsIntegerType (is_signed)) +            if (compiler_type.IsIntegerType (is_signed))              { -                bit_width = clang_type.GetBitSize(&thread); +                bit_width = compiler_type.GetBitSize(&thread);              } -            else if (clang_type.IsPointerOrReferenceType ()) +            else if (compiler_type.IsPointerOrReferenceType ())              { -                bit_width = clang_type.GetBitSize(&thread); +                bit_width = compiler_type.GetBitSize(&thread);              }              else              { @@ -398,22 +397,35 @@ ABISysV_arm::GetArgumentValues (Thread &thread,      return true;  } +static bool +GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t byte_size, Value& value) +{ +    Error 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; +} +  ValueObjectSP  ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, -                                       lldb_private::ClangASTType &clang_type) const +                                       lldb_private::CompilerType &compiler_type) const  {      Value value;      ValueObjectSP return_valobj_sp; -    if (!clang_type) +    if (!compiler_type)          return return_valobj_sp; -    clang::ASTContext *ast_context = clang_type.GetASTContext(); -    if (!ast_context) -        return return_valobj_sp; - -    //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); -    value.SetClangType (clang_type); +    //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); +    value.SetCompilerType (compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx) @@ -427,9 +439,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,      // when reading data      const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); -    size_t bit_width = clang_type.GetBitSize(&thread); +    size_t bit_width = compiler_type.GetBitSize(&thread); -    if (clang_type.IsIntegerType (is_signed)) +    if (compiler_type.IsIntegerType (is_signed))      {                 switch (bit_width)          { @@ -467,12 +479,33 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,                  break;          }      } -    else if (clang_type.IsPointerType ()) +    else if (compiler_type.IsPointerType ())      {          uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;          value.GetScalar() = ptr;      } -    else if (clang_type.IsFloatingPointType(float_count, is_complex)) +    else if (compiler_type.IsVectorType(nullptr, nullptr)) +    { +        size_t byte_size = compiler_type.GetByteSize(&thread); +        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)          { @@ -506,9 +539,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,              return return_valobj_sp;          }      } -    else if (clang_type.IsAggregateType()) +    else if (compiler_type.IsAggregateType())      { -        size_t byte_size = clang_type.GetByteSize(&thread); +        size_t byte_size = compiler_type.GetByteSize(&thread);          if (byte_size <= 4)          {              RegisterValue r0_reg_value; @@ -517,16 +550,7 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,          }          else          { -            RegisterValue r0_reg_value; -            uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; - -            Error error; -            DataBufferHeap buffer(byte_size, 0); -            thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error); - -            if (error.Success()) -                value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); -            else +            if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))                  return return_valobj_sp;          }      } @@ -554,8 +578,8 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -570,7 +594,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          DataExtractor data;          Error data_error; @@ -610,7 +634,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec              error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index 69becd6ec0c26..e3b280296a648 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -20,7 +20,7 @@  class ABISysV_arm : public lldb_private::ABI  {  public: -    ~ABISysV_arm() { } +    ~ABISysV_arm() override = default;      size_t      GetRedZoneSize () const override; @@ -39,12 +39,6 @@ public:      lldb_private::Error      SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: -    lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                    lldb_private::ClangASTType &ast_type) const override; - -public:      bool      CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -88,6 +82,7 @@ public:      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -103,6 +98,7 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ +      lldb_private::ConstString      GetPluginName() override; @@ -110,6 +106,10 @@ public:      GetPluginVersion() override;  protected: +    lldb::ValueObjectSP +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &ast_type) const override; +  private:      ABISysV_arm() :           lldb_private::ABI()  @@ -118,4 +118,4 @@ private:      }  }; -#endif  // liblldb_ABISysV_arm_h_ +#endif // liblldb_ABISysV_arm_h_ diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index ed058ff19d992..bc6df235cb1e7 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -18,7 +18,6 @@  #include "lldb/Core/Scalar.h"  #include "lldb/Core/Value.h"  #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/RegisterContext.h" @@ -37,7 +36,7 @@ using namespace lldb_private;  static RegisterInfo g_register_infos[] =  { -    //  NAME       ALT       SZ OFF ENCODING          FORMAT                   COMPILER             DWARF                  GENERIC                     GDB                     LLDB NATIVE +    //  NAME       ALT       SZ OFF ENCODING          FORMAT                   EH_FRAME             DWARF                  GENERIC                     PROCESS PLUGIN          LLDB NATIVE      //  ========== =======   == === =============     ===================      ===================  ====================== =========================== ======================= ======================      {   "x0",      NULL,      8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x0,       LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL },      {   "x1",      NULL,      8, 0, eEncodingUint   , eFormatHex           , { LLDB_INVALID_REGNUM, arm64_dwarf::x1,       LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -313,7 +312,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const          if (!value)              return false; -        ClangASTType value_type = value->GetClangType(); +        CompilerType value_type = value->GetCompilerType();          if (value_type)          {              bool is_signed = false; @@ -397,7 +396,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj          return error;      } -    ClangASTType return_value_type = new_value_sp->GetClangType(); +    CompilerType return_value_type = new_value_sp->GetCompilerType();      if (!return_value_type)      {          error.SetErrorString ("Null clang type for return value."); @@ -686,7 +685,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)  static bool  LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,                                        RegisterContext *reg_ctx, -                                      const ClangASTType &value_type, +                                      const CompilerType &value_type,                                        bool is_return_value, // false => parameter, true => return value                                        uint32_t &NGRN,       // NGRN (see ABI documentation)                                        uint32_t &NSRN,       // NSRN (see ABI documentation) @@ -701,18 +700,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,      const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();      Error error; -    ClangASTType base_type; +    CompilerType base_type;      const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);      if (homogeneous_count > 0 && homogeneous_count <= 8)      { -        printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);          // Make sure we have enough registers          if (NSRN < 8 && (8-NSRN) >= homogeneous_count)          {              if (!base_type)                  return false;              const size_t base_byte_size = base_type.GetByteSize(nullptr); -            printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);              uint32_t data_offset = 0;              for (uint32_t i=0; i<homogeneous_count; ++i) @@ -831,7 +828,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,  }  ValueObjectSP -ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; @@ -840,16 +837,16 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl      if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)          return return_valobj_sp; -    //value.SetContext (Value::eContextTypeClangType, return_clang_type); -    value.SetClangType(return_clang_type); +    //value.SetContext (Value::eContextTypeClangType, return_compiler_type); +    value.SetCompilerType(return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const size_t byte_size = return_clang_type.GetByteSize(nullptr); +    const size_t byte_size = return_compiler_type.GetByteSize(nullptr); -    const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);      if (type_flags & eTypeIsScalar ||          type_flags & eTypeIsPointer)      { @@ -898,7 +895,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                                                                      exe_ctx.GetProcessRef().GetAddressByteSize());                                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                                   return_clang_type, +                                                                                                   return_compiler_type,                                                                                                     ConstString(""),                                                                                                     data);                                                  return return_valobj_sp; @@ -1015,7 +1012,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                                                  byte_order,                                                  exe_ctx.GetProcessRef().GetAddressByteSize());                              return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                               return_clang_type, +                                                                               return_compiler_type,                                                                                 ConstString(""),                                                                                 data);                          } @@ -1032,10 +1029,10 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl          uint32_t NGRN = 0;  // Search ABI docs for NGRN          uint32_t NSRN = 0;  // Search ABI docs for NSRN          const bool is_return_value = true; -        if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data)) +        if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))          {              return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                               return_clang_type, +                                                               return_compiler_type,                                                                 ConstString(""),                                                                 data);                      } diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h index 08c8682d8fa49..e36f87e744f40 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h @@ -20,7 +20,7 @@  class ABISysV_arm64 : public lldb_private::ABI  {  public: -    ~ABISysV_arm64() { } +    ~ABISysV_arm64() override = default;      size_t      GetRedZoneSize () const override; @@ -39,12 +39,6 @@ public:      lldb_private::Error      SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: -    lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                    lldb_private::ClangASTType &ast_type) const override; - -public:      bool      CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -64,7 +58,6 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. -      bool      CallFrameAddressIsValid (lldb::addr_t cfa) override      { @@ -92,6 +85,7 @@ public:      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -107,6 +101,7 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ +      lldb_private::ConstString      GetPluginName() override; @@ -114,6 +109,10 @@ public:      GetPluginVersion() override;  protected: +    lldb::ValueObjectSP +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &ast_type) const override; +  private:      ABISysV_arm64() :           lldb_private::ABI()  @@ -122,4 +121,4 @@ private:      }  }; -#endif  // liblldb_ABISysV_arm64_h_ +#endif // liblldb_ABISysV_arm64_h_ diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp index 69129df1f16b7..e0299b6f0b941 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -30,7 +29,7 @@  #include "llvm/ADT/Triple.h" -#include "llvm/IR/Type.h" +#include "llvm/IR/DerivedTypes.h"  using namespace lldb;  using namespace lldb_private; @@ -227,7 +226,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,  //  . handle 64bit values and their register / stack requirements  */ -#define HEX_ABI_DEBUG 1 +#define HEX_ABI_DEBUG 0  bool  ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,                                         lldb::addr_t  sp  ,  @@ -243,6 +242,23 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,      // grab the process so we have access to the memory for spilling      lldb::ProcessSP proc = thread.GetProcess( ); +    // get the register context for modifying all of the registers +    RegisterContext *reg_ctx = thread.GetRegisterContext().get(); +    if (!reg_ctx) +        return false; +     +    uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); +    if (pc_reg == LLDB_INVALID_REGNUM) +        return false; + +    uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); +    if (ra_reg == LLDB_INVALID_REGNUM) +        return false; + +    uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); +    if (sp_reg == LLDB_INVALID_REGNUM) +        return false; +      // push host data onto target      for ( size_t i = 0; i < args.size( ); i++ )      { @@ -277,11 +293,6 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,      // check if this is a variable argument function      bool isVArg = prototype.isFunctionVarArg(); -    // get the register context for modifying all of the registers -    RegisterContext *reg_ctx = thread.GetRegisterContext().get(); -    if (!reg_ctx) -        return false; -          // number of arguments passed by register      int nRegArgs = nVArgRegParams;      if (! isVArg ) @@ -324,10 +335,9 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,      }      // update registers with current function call state -    reg_ctx->WriteRegisterFromUnsigned ( 41, pc ); -    reg_ctx->WriteRegisterFromUnsigned ( 31, ra ); -    reg_ctx->WriteRegisterFromUnsigned ( 29, sp ); -//  reg_ctx->WriteRegisterFromUnsigned ( FP ??? ); +    reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); +    reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); +    reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);  #if HEX_ABI_DEBUG      // quick and dirty stack dumper for debugging @@ -359,14 +369,14 @@ ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::Valu  }  ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, CompilerType &return_compiler_type ) const  {      ValueObjectSP return_valobj_sp;      return return_valobj_sp;  }  ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, CompilerType &return_compiler_type ) const  {      ValueObjectSP return_valobj_sp;      return return_valobj_sp; diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 1550a38c4f3b2..337e3fdcf7b54 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -21,63 +21,54 @@ class ABISysV_hexagon :      public lldb_private::ABI  {  public: +    ~ABISysV_hexagon() override = default; -    ~ABISysV_hexagon( void ) -    { -    } - -    virtual size_t -    GetRedZoneSize ( void ) const; +    size_t +    GetRedZoneSize() const override; -    virtual 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; +    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;      // special thread plan for GDB style non-jit function calls -    virtual bool -    PrepareTrivialCall ( lldb_private::Thread &thread,  -                         lldb::addr_t sp, -                         lldb::addr_t functionAddress, -                         lldb::addr_t returnAddress, -                         llvm::Type &prototype, -                         llvm::ArrayRef<ABI::CallArgument> args ) const; - -    virtual bool -    GetArgumentValues ( lldb_private::Thread &thread, -                        lldb_private::ValueList &values ) const; +    bool +    PrepareTrivialCall(lldb_private::Thread &thread,  +                       lldb::addr_t sp, +                       lldb::addr_t functionAddress, +                       lldb::addr_t returnAddress, +                       llvm::Type &prototype, +                       llvm::ArrayRef<ABI::CallArgument> args) const override; + +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                       lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject ( lldb::StackFrameSP &frame_sp, -                           lldb::ValueObjectSP &new_value ); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, +                         lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple ( lldb_private::Thread &thread, -                                 lldb_private::ClangASTType &ast_type ) const; -     -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl ( lldb_private::Thread &thread, -                               lldb_private::ClangASTType &type ) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override;      // specialized to work with llvm IR types -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &type ) const; +    lldb::ValueObjectSP +    GetReturnValueObjectImpl(lldb_private::Thread &thread, llvm::Type &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info ); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; -    virtual bool -    CallFrameAddressIsValid ( lldb::addr_t cfa ) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & 0x07) @@ -87,50 +78,60 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid ( lldb::addr_t pc ) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // We have a 64 bit address space, so anything is valid as opcodes          // aren't fixed width...          return true;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray ( uint32_t &count ); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override;      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void -    Initialize ( void ); +    Initialize();      static void -    Terminate ( void ); +    Terminate();      static lldb::ABISP      CreateInstance ( const lldb_private::ArchSpec &arch );      static lldb_private::ConstString -    GetPluginNameStatic ( void ); +    GetPluginNameStatic();      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName ( void ); -    virtual uint32_t -    GetPluginVersion ( void ); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void -    CreateRegisterMapIfNeeded ( void ); +    CreateRegisterMapIfNeeded(); + +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const;      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_hexagon() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABISysV_hexagon_h_ +#endif // liblldb_ABISysV_hexagon_h_ diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 26da9aeb370d0..0a3779a2ce94e 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -19,7 +19,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -59,171 +58,109 @@ using namespace lldb_private;  // Comment: Table 2.14 is followed till 'mm' entries.  // After that, all entries are ignored here. -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_eax = 0, -    gcc_dwarf_ecx, -    gcc_dwarf_edx, -    gcc_dwarf_ebx, -    gcc_dwarf_esp, -    gcc_dwarf_ebp, -    gcc_dwarf_esi, -    gcc_dwarf_edi, -    gcc_dwarf_eip, -    gcc_dwarf_eflags, - -    gcc_dwarf_st0 = 11, -    gcc_dwarf_st1, -    gcc_dwarf_st2, -    gcc_dwarf_st3, -    gcc_dwarf_st4, -    gcc_dwarf_st5, -    gcc_dwarf_st6, -    gcc_dwarf_st7, - -    gcc_dwarf_xmm0 = 21, -    gcc_dwarf_xmm1, -    gcc_dwarf_xmm2, -    gcc_dwarf_xmm3, -    gcc_dwarf_xmm4, -    gcc_dwarf_xmm5, -    gcc_dwarf_xmm6, -    gcc_dwarf_xmm7, -    gcc_dwarf_ymm0 = gcc_dwarf_xmm0, -    gcc_dwarf_ymm1 = gcc_dwarf_xmm1, -    gcc_dwarf_ymm2 = gcc_dwarf_xmm2, -    gcc_dwarf_ymm3 = gcc_dwarf_xmm3, -    gcc_dwarf_ymm4 = gcc_dwarf_xmm4, -    gcc_dwarf_ymm5 = gcc_dwarf_xmm5, -    gcc_dwarf_ymm6 = gcc_dwarf_xmm6, -    gcc_dwarf_ymm7 = gcc_dwarf_xmm7, - -    gcc_dwarf_mm0 = 29, -    gcc_dwarf_mm1, -    gcc_dwarf_mm2, -    gcc_dwarf_mm3, -    gcc_dwarf_mm4, -    gcc_dwarf_mm5, -    gcc_dwarf_mm6, -    gcc_dwarf_mm7 -}; - - -enum gdb_regnums -{ -    gdb_eax        =  0, -    gdb_ecx        =  1, -    gdb_edx        =  2, -    gdb_ebx        =  3, -    gdb_esp        =  4, -    gdb_ebp        =  5, -    gdb_esi        =  6, -    gdb_edi        =  7, -    gdb_eip        =  8, -    gdb_eflags     =  9, -    gdb_cs         = 10, -    gdb_ss         = 11, -    gdb_ds         = 12, -    gdb_es         = 13, -    gdb_fs         = 14, -    gdb_gs         = 15, -    gdb_st0        = 16, -    gdb_st1        = 17, -    gdb_st2        = 18, -    gdb_st3        = 19, -    gdb_st4        = 20, -    gdb_st5        = 21, -    gdb_st6        = 22, -    gdb_st7        = 23, -    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl, -    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat, -    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag, -    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg, -    gdb_fioff      = 28,    gdb_ip      = gdb_fioff, -    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg, -    gdb_fooff      = 30,    gdb_dp      = gdb_fooff, -    gdb_fop        = 31, -    gdb_xmm0       = 32, -    gdb_xmm1       = 33, -    gdb_xmm2       = 34, -    gdb_xmm3       = 35, -    gdb_xmm4       = 36, -    gdb_xmm5       = 37, -    gdb_xmm6       = 38, -    gdb_xmm7       = 39, -    gdb_mxcsr      = 40, -    gdb_mm0        = 41, -    gdb_mm1        = 42, -    gdb_mm2        = 43, -    gdb_mm3        = 44, -    gdb_mm4        = 45, -    gdb_mm5        = 46, -    gdb_mm6        = 47, -    gdb_mm7        = 48, -    gdb_ymm0       = gdb_xmm0, -    gdb_ymm1       = gdb_xmm1, -    gdb_ymm2       = gdb_xmm2, -    gdb_ymm3       = gdb_xmm3, -    gdb_ymm4       = gdb_xmm4, -    gdb_ymm5       = gdb_xmm5, -    gdb_ymm6       = gdb_xmm6, -    gdb_ymm7       = gdb_xmm7 +    dwarf_eax = 0, +    dwarf_ecx, +    dwarf_edx, +    dwarf_ebx, +    dwarf_esp, +    dwarf_ebp, +    dwarf_esi, +    dwarf_edi, +    dwarf_eip, +    dwarf_eflags, + +    dwarf_st0 = 11, +    dwarf_st1, +    dwarf_st2, +    dwarf_st3, +    dwarf_st4, +    dwarf_st5, +    dwarf_st6, +    dwarf_st7, + +    dwarf_xmm0 = 21, +    dwarf_xmm1, +    dwarf_xmm2, +    dwarf_xmm3, +    dwarf_xmm4, +    dwarf_xmm5, +    dwarf_xmm6, +    dwarf_xmm7, +    dwarf_ymm0 = dwarf_xmm0, +    dwarf_ymm1 = dwarf_xmm1, +    dwarf_ymm2 = dwarf_xmm2, +    dwarf_ymm3 = dwarf_xmm3, +    dwarf_ymm4 = dwarf_xmm4, +    dwarf_ymm5 = dwarf_xmm5, +    dwarf_ymm6 = dwarf_xmm6, +    dwarf_ymm7 = dwarf_xmm7, + +    dwarf_mm0 = 29, +    dwarf_mm1, +    dwarf_mm2, +    dwarf_mm3, +    dwarf_mm4, +    dwarf_mm5, +    dwarf_mm6, +    dwarf_mm7  };  static RegisterInfo g_register_infos[] =  { -  //  NAME      ALT         SZ OFF ENCODING         FORMAT                  COMPILER                 DWARF                      GENERIC                  GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS +  //  NAME      ALT         SZ OFF ENCODING         FORMAT                  EH_FRAME                 DWARF                      GENERIC                PROCESS PLUGIN          LLDB NATIVE            VALUE REGS    INVALIDATE REGS    //  ======    =======     == === =============    ============          ===================== =====================    ============================ ====================  ======================    ==========    =============== -    { "eax",    nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_eax       , gcc_dwarf_eax           , LLDB_INVALID_REGNUM       , gdb_eax            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ebx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_ebx       , gcc_dwarf_ebx           , LLDB_INVALID_REGNUM       , gdb_ebx            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ecx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_ecx       , gcc_dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , gdb_ecx            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "edx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_edx       , gcc_dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , gdb_edx            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "esi"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_esi       , gcc_dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , gdb_esi            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "edi"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_edi       , gcc_dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , gdb_edi            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ebp"   , "fp",       4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_ebp       , gcc_dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "esp"   , "sp",       4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_esp       , gcc_dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "eip"   , "pc",       4,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_eip       , gcc_dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "eflags", nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "cs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ss"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ds"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "es"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "gs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st0"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0           , LLDB_INVALID_REGNUM       , gdb_st0            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st1"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1           , LLDB_INVALID_REGNUM       , gdb_st1            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st2"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2           , LLDB_INVALID_REGNUM       , gdb_st2            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st3"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3           , LLDB_INVALID_REGNUM       , gdb_st3            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st4"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4           , LLDB_INVALID_REGNUM       , gdb_st4            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st5"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5           , LLDB_INVALID_REGNUM       , gdb_st5            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st6"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6           , LLDB_INVALID_REGNUM       , gdb_st6            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "st7"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7           , LLDB_INVALID_REGNUM       , gdb_st7            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fctrl" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fstat" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ftag"  , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fiseg" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fioff" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "foseg" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fooff" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "fop"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm0"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0          , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm1"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1          , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm2"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2          , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm3"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3          , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm4"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4          , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm5"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5          , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm6"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6          , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "xmm7"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7          , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "mxcsr" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm0"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0          , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm1"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1          , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm2"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2          , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm3"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3          , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm4"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4          , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm5"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5          , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm6"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6          , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      nullptr,        nullptr}, -    { "ymm7"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7          , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      nullptr,        nullptr} +    { "eax",    nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_eax       ,     dwarf_eax           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ebx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_ebx       ,     dwarf_ebx           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ecx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_ecx       ,     dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "edx"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_edx       ,     dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "esi"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_esi       ,     dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "edi"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , {     dwarf_edi       ,     dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ebp"   , "fp",       4,  0, eEncodingUint  , eFormatHex          , {     dwarf_ebp       ,     dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "esp"   , "sp",       4,  0, eEncodingUint  , eFormatHex          , {     dwarf_esp       ,     dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "eip"   , "pc",       4,  0, eEncodingUint  , eFormatHex          , {     dwarf_eip       ,     dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "eflags", nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "cs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ss"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ds"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "es"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "gs"    , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st0"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st0           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st1"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st1           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st2"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st2           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st3"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st3           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st4"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st4           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st5"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st5           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st6"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st6           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "st7"   , nullptr,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_st7           , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fctrl" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fstat" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ftag"  , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fiseg" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fioff" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "foseg" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fooff" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "fop"   , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm0"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm1"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm2"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm3"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm4"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm5"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm6"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "xmm7"  , nullptr,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_xmm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "mxcsr" , nullptr,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm0"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm0          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm1"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm1          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm2"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm2          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm3"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm3          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm4"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm4          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm5"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm5          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm6"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm6          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}, +    { "ymm7"  , nullptr,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM ,     dwarf_ymm7          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      nullptr,        nullptr}  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -387,22 +324,22 @@ ABISysV_i386::GetArgumentValues (Thread &thread,              return false;          // Currently: Support for extracting values with Clang QualTypes only. -        ClangASTType clang_type (value->GetClangType()); -        if (clang_type) +        CompilerType compiler_type (value->GetCompilerType()); +        if (compiler_type)          {              bool is_signed; -            if (clang_type.IsIntegerType (is_signed)) +            if (compiler_type.IsIntegerType (is_signed))              {                  ReadIntegerArgument(value->GetScalar(), -                                    clang_type.GetBitSize(&thread), +                                    compiler_type.GetBitSize(&thread),                                      is_signed,                                      thread.GetProcess().get(),                                      current_stack_argument);              } -            else if (clang_type.IsPointerType()) +            else if (compiler_type.IsPointerType())              {                  ReadIntegerArgument(value->GetScalar(), -                                    clang_type.GetBitSize(&thread), +                                    compiler_type.GetBitSize(&thread),                                      false,                                      thread.GetProcess().get(),                                      current_stack_argument); @@ -418,29 +355,170 @@ Error  ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)  {      Error error; -    //ToDo: Yet to be implemented -    error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet"); +    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; +    } + +    const uint32_t type_flags = compiler_type.GetTypeInfo (); +    Thread *thread = frame_sp->GetThread().get(); +    RegisterContext *reg_ctx = thread->GetRegisterContext().get(); +    DataExtractor data; +    Error data_error; +    size_t num_bytes = new_value_sp->GetData(data, data_error); +    bool register_write_successful = true; + +    if (data_error.Fail()) +    { +        error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); +        return error; +    } + +    // Following "IF ELSE" block categorizes various 'Fundamental Data Types'. +    // The terminology 'Fundamental Data Types' used here is adopted from +    // Table 2.1 of the reference document (specified on top of this file) + +    if (type_flags & eTypeIsPointer)     // 'Pointer' +    { +        if(num_bytes != sizeof(uint32_t)) +        { +            error.SetErrorString("Pointer to be returned is not 4 bytes wide"); +            return error; +        } +        lldb::offset_t offset = 0; +        const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); +        uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); +        register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); +    } +    else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' +    { +        lldb::offset_t offset = 0; +        const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); + +        if (type_flags & eTypeIsInteger)    // 'Integral' except enum +        { +            switch (num_bytes) +            { +                default: +                    break; +                case 16: +                    // For clang::BuiltinType::UInt128 & Int128 +                    // ToDo: Need to decide how to handle it +                    break; +                case 8: +                { +                    uint32_t raw_value_low = data.GetMaxU32(&offset, 4); +                    const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0); +                    uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset); +                    register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) && +                                                reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high)); +                    break; +                } +                case 4: +                case 2: +                case 1: +                { +                    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); +                    register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); +                    break; +                } +            } +        } +        else if (type_flags & eTypeIsEnumeration)    // handles enum +        { +            uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); +            register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); +        } +        else if (type_flags & eTypeIsFloat)  // 'Floating Point' +        { +            RegisterValue st0_value, fstat_value, ftag_value; +            const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0); +            const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0); +            const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0); + +            /* According to Page 3-12 of document +            System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition +            To return Floating Point values, all st% registers except st0 should be empty after exiting from +            a function. This requires setting fstat and ftag registers to specific values. +            fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific +            value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */ +            uint32_t value_fstat_u32 = 0x00003800; + +            /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set +            7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance +            with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */ +            uint32_t value_ftag_u32 = 0x00000080; + +            if (num_bytes <= 12)      // handles float, double, long double, __float80 +            { +                long double value_long_dbl = 0.0; +                if (num_bytes == 4) +                    value_long_dbl = data.GetFloat(&offset); +                else if (num_bytes == 8) +                    value_long_dbl = data.GetDouble(&offset); +                else if (num_bytes == 12) +                    value_long_dbl = data.GetLongDouble(&offset); +                else +                { +                    error.SetErrorString ("Invalid number of bytes for this return type"); +                    return error; +                } +                st0_value.SetLongDouble(value_long_dbl); +                fstat_value.SetUInt32(value_fstat_u32); +                ftag_value.SetUInt32(value_ftag_u32); +                register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) && +                                            reg_ctx->WriteRegister(fstat_info, fstat_value) && +                                            reg_ctx->WriteRegister(ftag_info, ftag_value); +            } +            else if(num_bytes == 16)   // handles __float128 +            { +                error.SetErrorString ("Implementation is missing for this clang type."); +            } +        } +        else +        { +            // Neither 'Integral' nor 'Floating Point'. If flow reaches here +            // then check type_flags. This type_flags is not a valid type. +            error.SetErrorString ("Invalid clang type"); +        } +    } +    else +    { +        /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types +        are yet to be implemented */ +        error.SetErrorString ("Currently only Integral and Floating Point clang types are supported."); +    } +    if(!register_write_successful) +        error.SetErrorString ("Register writing failed");      return error;  }  ValueObjectSP  ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, -                                          ClangASTType &return_clang_type) const +                                          CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp; -    value.SetClangType (return_clang_type); +    value.SetCompilerType (return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const uint32_t type_flags = return_clang_type.GetTypeInfo (); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo ();      unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];      unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -463,7 +541,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,      else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'      {          value.SetValueType(Value::eValueTypeScalar); -        const size_t byte_size = return_clang_type.GetByteSize(nullptr); +        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);          bool success = false;          if (type_flags & eTypeIsInteger)    // 'Integral' except enum @@ -579,7 +657,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,                  return_valobj_sp = ValueObjectMemory::Create (&thread,                                                                 "",                                                                Address (storage_addr, nullptr), -                                                              return_clang_type); +                                                              return_compiler_type);              }          } @@ -597,16 +675,12 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,      else if (type_flags & eTypeIsVector)    // 'Packed'      { -        const size_t byte_size = return_clang_type.GetByteSize(nullptr); +        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);          if (byte_size > 0)          { -            const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); +            const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);              if (vec_reg == nullptr) -            { -                vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); -                if (vec_reg == nullptr) -                    vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); -            } +                vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);              if (vec_reg)              { @@ -631,13 +705,52 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,                                                      byte_order,                                                      process_sp->GetTarget().GetArchitecture().GetAddressByteSize());                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                   return_clang_type, +                                                                                   return_compiler_type,                                                                                     ConstString(""),                                                                                     data);                              }                          }                      }                  } +                else if (byte_size <= vec_reg->byte_size*2) +                { +                    const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0); +                    if (vec_reg2) +                    { +                        ProcessSP process_sp (thread.GetProcess()); +                        if (process_sp) +                        { +                            std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); +                            const ByteOrder byte_order = process_sp->GetByteOrder(); +                            RegisterValue reg_value; +                            RegisterValue reg_value2; +                            if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2)) +                            { + +                                Error error; +                                if (reg_value.GetAsMemoryData (vec_reg, +                                                               heap_data_ap->GetBytes(), +                                                               vec_reg->byte_size, +                                                               byte_order, +                                                               error) && +                                    reg_value2.GetAsMemoryData (vec_reg2, +                                                                heap_data_ap->GetBytes() + vec_reg->byte_size, +                                                                heap_data_ap->GetByteSize() - vec_reg->byte_size, +                                                                byte_order, +                                                                error)) +                                { +                                    DataExtractor data (DataBufferSP (heap_data_ap.release()), +                                                        byte_order, +                                                        process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); +                                    return_valobj_sp = ValueObjectConstResult::Create (&thread, +                                                                                       return_compiler_type, +                                                                                       ConstString(""), +                                                                                       data); +                                } +                            } +                        } +                    } +                }              }          }      } @@ -651,15 +764,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,  ValueObjectSP -ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      ExecutionContext exe_ctx (thread.shared_from_this()); -    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); +    return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);      if (return_valobj_sp)          return return_valobj_sp; @@ -667,14 +780,14 @@ ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla      if (!reg_ctx_sp)         return return_valobj_sp; -    if (return_clang_type.IsAggregateType()) +    if (return_compiler_type.IsAggregateType())      {          unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];          lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);          return_valobj_sp = ValueObjectMemory::Create (&thread,                                                        "",                                                        Address (storage_addr, nullptr), -                                                      return_clang_type); +                                                      return_compiler_type);      }      return return_valobj_sp; @@ -690,8 +803,8 @@ ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t sp_reg_num = gcc_dwarf_esp; -    uint32_t pc_reg_num = gcc_dwarf_eip; +    uint32_t sp_reg_num = dwarf_esp; +    uint32_t pc_reg_num = dwarf_eip;      UnwindPlan::RowSP row(new UnwindPlan::Row);      row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); @@ -714,9 +827,9 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t fp_reg_num = gcc_dwarf_ebp; -    uint32_t sp_reg_num = gcc_dwarf_esp; -    uint32_t pc_reg_num = gcc_dwarf_eip; +    uint32_t fp_reg_num = dwarf_ebp; +    uint32_t sp_reg_num = dwarf_esp; +    uint32_t pc_reg_num = dwarf_eip;      UnwindPlan::RowSP row(new UnwindPlan::Row);      const int32_t ptr_size = 4; diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h index 9612f900d2cef..2d0f097c328e6 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h @@ -21,10 +21,7 @@ class ABISysV_i386 :      public lldb_private::ABI  {  public: - -    ~ABISysV_i386() -    { -    } +    ~ABISysV_i386() override = default;      size_t      GetRedZoneSize () const override @@ -46,18 +43,9 @@ public:      lldb_private::Error      SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: -    lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; - -    bool -    RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); - -public:      lldb::ValueObjectSP      GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const override; +                          lldb_private::CompilerType &type) const override;      bool      CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -104,9 +92,11 @@ public:      const lldb_private::RegisterInfo *      GetRegisterInfoArray (uint32_t &count) override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -119,6 +109,7 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ +      static lldb_private::ConstString      GetPluginNameStatic(); @@ -126,13 +117,25 @@ public:      GetPluginName() override;      uint32_t -    GetPluginVersion()  override +    GetPluginVersion() override      {          return 1;      } +protected: +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; + +    bool +    RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); +  private: -    ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_i386() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h +#endif // liblldb_ABISysV_i386_h_ diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index e1fc13a691afd..3c7e9495d6ce5 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@  using namespace lldb;  using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_r0 = 0, -    gcc_dwarf_r1, -    gcc_dwarf_r2, -    gcc_dwarf_r3, -    gcc_dwarf_r4, -    gcc_dwarf_r5, -    gcc_dwarf_r6, -    gcc_dwarf_r7, -    gcc_dwarf_r8, -    gcc_dwarf_r9, -    gcc_dwarf_r10, -    gcc_dwarf_r11, -    gcc_dwarf_r12, -    gcc_dwarf_r13, -    gcc_dwarf_r14, -    gcc_dwarf_r15, -    gcc_dwarf_r16, -    gcc_dwarf_r17, -    gcc_dwarf_r18, -    gcc_dwarf_r19, -    gcc_dwarf_r20, -    gcc_dwarf_r21, -    gcc_dwarf_r22, -    gcc_dwarf_r23, -    gcc_dwarf_r24, -    gcc_dwarf_r25, -    gcc_dwarf_r26, -    gcc_dwarf_r27, -    gcc_dwarf_r28, -    gcc_dwarf_r29, -    gcc_dwarf_r30, -    gcc_dwarf_r31, -    gcc_dwarf_sr, -    gcc_dwarf_lo, -    gcc_dwarf_hi, -    gcc_dwarf_bad, -    gcc_dwarf_cause, -    gcc_dwarf_pc -}; - -enum gdb_regnums -{ -    gdb_r0 = 0, -    gdb_r1, -    gdb_r2, -    gdb_r3, -    gdb_r4, -    gdb_r5, -    gdb_r6, -    gdb_r7, -    gdb_r8, -    gdb_r9, -    gdb_r10, -    gdb_r11, -    gdb_r12, -    gdb_r13, -    gdb_r14, -    gdb_r15, -    gdb_r16, -    gdb_r17, -    gdb_r18, -    gdb_r19, -    gdb_r20, -    gdb_r21, -    gdb_r22, -    gdb_r23, -    gdb_r24, -    gdb_r25, -    gdb_r26, -    gdb_r27, -    gdb_r28, -    gdb_r29, -    gdb_r30, -    gdb_r31, -    gdb_sr, -    gdb_lo, -    gdb_hi, -    gdb_bad, -    gdb_cause, -    gdb_pc +    dwarf_r0 = 0, +    dwarf_r1, +    dwarf_r2, +    dwarf_r3, +    dwarf_r4, +    dwarf_r5, +    dwarf_r6, +    dwarf_r7, +    dwarf_r8, +    dwarf_r9, +    dwarf_r10, +    dwarf_r11, +    dwarf_r12, +    dwarf_r13, +    dwarf_r14, +    dwarf_r15, +    dwarf_r16, +    dwarf_r17, +    dwarf_r18, +    dwarf_r19, +    dwarf_r20, +    dwarf_r21, +    dwarf_r22, +    dwarf_r23, +    dwarf_r24, +    dwarf_r25, +    dwarf_r26, +    dwarf_r27, +    dwarf_r28, +    dwarf_r29, +    dwarf_r30, +    dwarf_r31, +    dwarf_sr, +    dwarf_lo, +    dwarf_hi, +    dwarf_bad, +    dwarf_cause, +    dwarf_pc  };  static const RegisterInfo  g_register_infos[] =  { -   //  NAME      ALT    SZ OFF ENCODING        FORMAT        COMPILER                DWARF                 GENERIC                   GDB           LLDB NATIVE       VALUE REGS  INVALIDATE REGS -  //  ========  ======  == === =============  =================== ============ ===================== ==================== =================     ====================== ========== =============== -    { "r0"    , "zero", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r0,      gcc_dwarf_r0,           LLDB_INVALID_REGNUM,        gdb_r0,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r1"    , "AT",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r1,      gcc_dwarf_r1,           LLDB_INVALID_REGNUM,        gdb_r1,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r2"    , "v0",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r2,      gcc_dwarf_r2,           LLDB_INVALID_REGNUM,        gdb_r2,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r3"    , "v1",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r3,      gcc_dwarf_r3,           LLDB_INVALID_REGNUM,        gdb_r3,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r4"    , "arg1", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r4,      gcc_dwarf_r4,           LLDB_REGNUM_GENERIC_ARG1,   gdb_r4,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r5"    , "arg2", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r5,      gcc_dwarf_r5,           LLDB_REGNUM_GENERIC_ARG2,   gdb_r5,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r6"    , "arg3", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r6,      gcc_dwarf_r6,           LLDB_REGNUM_GENERIC_ARG3,   gdb_r6,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r7"    , "arg4", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r7,      gcc_dwarf_r7,           LLDB_REGNUM_GENERIC_ARG4,   gdb_r7,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r8"    , "arg5", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r8,      gcc_dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_r8,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r9"    , "arg6", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r9,      gcc_dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_r9,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r10"   , "arg7", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r10,     gcc_dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_r10,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r11"   , "arg8", 4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r11,     gcc_dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_r11,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r12"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r12,     gcc_dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_r12,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r13"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r13,     gcc_dwarf_r13,          LLDB_INVALID_REGNUM,        gdb_r13,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r14"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r14,     gcc_dwarf_r14,          LLDB_INVALID_REGNUM,        gdb_r14,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r15"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r15,     gcc_dwarf_r15,          LLDB_INVALID_REGNUM,        gdb_r15,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r16"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r16,     gcc_dwarf_r16,          LLDB_INVALID_REGNUM,        gdb_r16,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r17"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r17,     gcc_dwarf_r17,          LLDB_INVALID_REGNUM,        gdb_r17,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r18"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r18,     gcc_dwarf_r18,          LLDB_INVALID_REGNUM,        gdb_r18,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r19"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r19,     gcc_dwarf_r19,          LLDB_INVALID_REGNUM,        gdb_r19,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r20"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r20,     gcc_dwarf_r20,          LLDB_INVALID_REGNUM,        gdb_r20,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r21"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r21,     gcc_dwarf_r21,          LLDB_INVALID_REGNUM,        gdb_r21,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r22"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r22,     gcc_dwarf_r22,          LLDB_INVALID_REGNUM,        gdb_r22,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r23"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r23,     gcc_dwarf_r23,          LLDB_INVALID_REGNUM,        gdb_r23,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r24"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r24,     gcc_dwarf_r24,          LLDB_INVALID_REGNUM,        gdb_r24,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r25"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r25,     gcc_dwarf_r25,          LLDB_INVALID_REGNUM,        gdb_r25,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r26"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r26,     gcc_dwarf_r26,          LLDB_INVALID_REGNUM,        gdb_r26,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r27"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r27,     gcc_dwarf_r27,          LLDB_INVALID_REGNUM,        gdb_r27,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r28"   , "gp",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r28,     gcc_dwarf_r28,          LLDB_INVALID_REGNUM,        gdb_r28,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r29"   , "sp",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r29,     gcc_dwarf_r29,          LLDB_REGNUM_GENERIC_SP,     gdb_r29,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r30"   , "fp",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r30,     gcc_dwarf_r30,          LLDB_REGNUM_GENERIC_FP,     gdb_r30,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r31"   , "ra",   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r31,     gcc_dwarf_r31,          LLDB_REGNUM_GENERIC_RA,     gdb_r31,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "sr"    , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_sr,      gcc_dwarf_sr,           LLDB_REGNUM_GENERIC_FLAGS,  gdb_sr,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "lo"    , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_lo,      gcc_dwarf_lo,           LLDB_INVALID_REGNUM,        gdb_lo,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "hi"    , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_hi,      gcc_dwarf_hi,           LLDB_INVALID_REGNUM,        gdb_hi,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "bad"   , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_bad,     gcc_dwarf_bad,          LLDB_INVALID_REGNUM,        gdb_bad,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "cause" , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_cause,   gcc_dwarf_cause,        LLDB_INVALID_REGNUM,        gdb_cause,  LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "pc"    , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_pc,      gcc_dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_pc,     LLDB_INVALID_REGNUM },  NULL,      NULL}, +   //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME           DWARF                   GENERIC                     PROCESS PLUGINS         LLDB NATIVE            VALUE REGS  INVALIDATE REGS +  //  ========  ======  == === =============  ===========    ============       ==============          ============                =================       ===================     ========== ================= +    { "r0"    , "zero", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r0,          dwarf_r0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r1"    , "AT",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r1,          dwarf_r1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r2"    , "v0",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r2,          dwarf_r2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r3"    , "v1",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r3,          dwarf_r3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r4"    , "arg1", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r4,          dwarf_r4,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r5"    , "arg2", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r5,          dwarf_r5,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r6"    , "arg3", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r6,          dwarf_r6,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r7"    , "arg4", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r7,          dwarf_r7,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r8"    , "arg5", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r8,          dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r9"    , "arg6", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r9,          dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r10"   , "arg7", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r10,         dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r11"   , "arg8", 4,  0, eEncodingUint, eFormatHex,  {     dwarf_r11,         dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r12"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r12,         dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r13"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r13,         dwarf_r13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r14"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r14,         dwarf_r14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r15"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r15,         dwarf_r15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r16"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r16,         dwarf_r16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r17"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r17,         dwarf_r17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r18"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r18,         dwarf_r18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r19"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r19,         dwarf_r19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r20"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r20,         dwarf_r20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r21"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r21,         dwarf_r21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r22"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r22,         dwarf_r22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r23"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r23,         dwarf_r23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r24"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r24,         dwarf_r24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r25"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r25,         dwarf_r25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r26"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r26,         dwarf_r26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r27"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r27,         dwarf_r27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r28"   , "gp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r28,         dwarf_r28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r29"   , "sp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r29,         dwarf_r29,          LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r30"   , "fp",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r30,         dwarf_r30,          LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r31"   , "ra",   4,  0, eEncodingUint, eFormatHex,  {     dwarf_r31,         dwarf_r31,          LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "sr"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_sr,          dwarf_sr,           LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "lo"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_lo,          dwarf_lo,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "hi"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_hi,          dwarf_hi,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "bad"   , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_bad,         dwarf_bad,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "cause" , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_cause,       dwarf_cause,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "pc"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_pc,          dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -284,6 +241,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,      const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);      const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);      const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); +    const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);      if (log)      log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); @@ -305,7 +263,14 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,      // Set pc to the address of the called function.      if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))          return false; - +     +    if (log) +        log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); +     +    // All callers of position independent functions must place the address of the called function in t9 (r25) +    if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr)) +        return false; +        return true;  } @@ -325,8 +290,8 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -341,7 +306,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          DataExtractor data;          Error data_error; @@ -382,7 +347,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje              error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present"); @@ -398,40 +363,41 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje  ValueObjectSP -ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      return return_valobj_sp;  }  ValueObjectSP -ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      ExecutionContext exe_ctx (thread.shared_from_this());      if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)          return return_valobj_sp; -    value.SetClangType(return_clang_type); +    value.SetCompilerType(return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    bool is_signed; +    bool is_signed = false; +    bool is_complex = false; +    uint32_t count = 0;      // In MIPS register "r2" (v0) holds the integer function return values      const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); +    size_t bit_width = return_compiler_type.GetBitSize(&thread); -    if (return_clang_type.IsIntegerType (is_signed)) +    if (return_compiler_type.IsIntegerType (is_signed))      { -        size_t bit_width = return_clang_type.GetBitSize(&thread); -                  switch (bit_width)          {              default: @@ -468,11 +434,57 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla                  break;          }      } -    else if (return_clang_type.IsPointerType ()) +    else if (return_compiler_type.IsPointerType ())      {          uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;          value.GetScalar() = ptr;      } +    else if (return_compiler_type.IsAggregateType ()) +    { +        // Structure/Vector is always passed in memory and pointer to that memory is passed in r2.  +        uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); +        // We have got the address. Create a memory object out of it +        return_valobj_sp = ValueObjectMemory::Create (&thread, +                                                      "", +                                                      Address (mem_address, NULL), +                                                      return_compiler_type); +        return return_valobj_sp; +    } +    else if (return_compiler_type.IsFloatingPointType (count, is_complex)) +    { +        const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); +        const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + +        if (count == 1 && !is_complex) +        { +            switch (bit_width) +            { +                default: +                    return return_valobj_sp; +                case 64: +                { +                    static_assert(sizeof(double) == sizeof(uint64_t), ""); +                    uint64_t raw_value; +                    raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; +                    raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32; +                    value.GetScalar() = *reinterpret_cast<double*>(&raw_value); +                    break; +                } +                case 32: +                { +                    static_assert(sizeof(float) == sizeof(uint32_t), ""); +                    uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; +                    value.GetScalar() = *reinterpret_cast<float*>(&raw_value); +                    break; +                } +            } +        } +        else +        { +            // not handled yet +            return return_valobj_sp; +        } +    }      else      {          // not handled yet @@ -496,17 +508,17 @@ ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      UnwindPlan::RowSP row(new UnwindPlan::Row);      // Our Call Frame Address is the stack pointer value -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);      // The previous PC is in the RA -    row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); +    row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);      unwind_plan.AppendRow (row);      // All other registers are the same.      unwind_plan.SetSourceName ("mips at-func-entry default");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); -    unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); +    unwind_plan.SetReturnAddressRegister(dwarf_r31);      return true;  } @@ -518,9 +530,9 @@ ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      UnwindPlan::RowSP row(new UnwindPlan::Row); -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); -    row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); +    row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);      unwind_plan.AppendRow (row);      unwind_plan.SetSourceName ("mips default unwind plan"); @@ -542,13 +554,36 @@ ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)      {          // Preserved registers are :          // r16-r23, r28, r29, r30, r31 +        const char *name = reg_info->name; -        int reg = ((reg_info->byte_offset) / 4); - -        bool save  = (reg >= 16) && (reg <= 23); -             save |= (reg >= 28) && (reg <= 31); +        if (name[0] == 'r') +        { +            switch (name[1]) +            { +                case '1':  +                    if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19 +                        return name[3] == '\0'; +                break; +                case '2':  +                    if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3'  // r20-r23 +                        || name[2] == '8' || name[2] == '9')                                  // r28 and r29 +                        return name[3] == '\0'; +                break; +                case '3':  +                    if (name[2] == '0' || name[2] == '1')       // r30 and r31 +                        return name[3] == '\0'; +                break; +            } -        return save; +            if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0')   // gp (r28) +                return true; +            if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp (r29) +                return true; +            if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp (r30) +                return true; +            if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0')   // ra (r31) +                return true; +        }      }      return false;  } diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index ad47ac2229329..709c3bfe3adf5 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -21,49 +21,40 @@ class ABISysV_mips :      public lldb_private::ABI  {  public: +    ~ABISysV_mips() override = default; -    ~ABISysV_mips() -    { -    } - -    virtual size_t -    GetRedZoneSize () const; +    size_t +    GetRedZoneSize() const override; -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; -     -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -73,21 +64,21 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc)//must- check +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      { -       if (pc & (4ull - 1ull)) -           return false;   // Not 4 byte aligned -         -        // Anything else if fair game.. -        return true; +        // Just make sure the address is a valid 32 bit address. Bit zero +        // might be set due to MicroMIPS function calls, so don't enforce alignment. +        return (pc <= UINT32_MAX);      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -103,21 +94,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void      CreateRegisterMapIfNeeded (); +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; +      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_mips() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips_h_ diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index c790fa7e7bdd0..bc62c9fe82ee0 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@  using namespace lldb;  using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_r0 = 0, -    gcc_dwarf_r1, -    gcc_dwarf_r2, -    gcc_dwarf_r3, -    gcc_dwarf_r4, -    gcc_dwarf_r5, -    gcc_dwarf_r6, -    gcc_dwarf_r7, -    gcc_dwarf_r8, -    gcc_dwarf_r9, -    gcc_dwarf_r10, -    gcc_dwarf_r11, -    gcc_dwarf_r12, -    gcc_dwarf_r13, -    gcc_dwarf_r14, -    gcc_dwarf_r15, -    gcc_dwarf_r16, -    gcc_dwarf_r17, -    gcc_dwarf_r18, -    gcc_dwarf_r19, -    gcc_dwarf_r20, -    gcc_dwarf_r21, -    gcc_dwarf_r22, -    gcc_dwarf_r23, -    gcc_dwarf_r24, -    gcc_dwarf_r25, -    gcc_dwarf_r26, -    gcc_dwarf_r27, -    gcc_dwarf_r28, -    gcc_dwarf_r29, -    gcc_dwarf_r30, -    gcc_dwarf_r31, -    gcc_dwarf_sr, -    gcc_dwarf_lo, -    gcc_dwarf_hi, -    gcc_dwarf_bad, -    gcc_dwarf_cause, -    gcc_dwarf_pc -}; - -enum gdb_regnums -{ -    gdb_r0 = 0, -    gdb_r1, -    gdb_r2, -    gdb_r3, -    gdb_r4, -    gdb_r5, -    gdb_r6, -    gdb_r7, -    gdb_r8, -    gdb_r9, -    gdb_r10, -    gdb_r11, -    gdb_r12, -    gdb_r13, -    gdb_r14, -    gdb_r15, -    gdb_r16, -    gdb_r17, -    gdb_r18, -    gdb_r19, -    gdb_r20, -    gdb_r21, -    gdb_r22, -    gdb_r23, -    gdb_r24, -    gdb_r25, -    gdb_r26, -    gdb_r27, -    gdb_r28, -    gdb_r29, -    gdb_r30, -    gdb_r31, -    gdb_sr, -    gdb_lo, -    gdb_hi, -    gdb_bad, -    gdb_cause, -    gdb_pc +    dwarf_r0 = 0, +    dwarf_r1, +    dwarf_r2, +    dwarf_r3, +    dwarf_r4, +    dwarf_r5, +    dwarf_r6, +    dwarf_r7, +    dwarf_r8, +    dwarf_r9, +    dwarf_r10, +    dwarf_r11, +    dwarf_r12, +    dwarf_r13, +    dwarf_r14, +    dwarf_r15, +    dwarf_r16, +    dwarf_r17, +    dwarf_r18, +    dwarf_r19, +    dwarf_r20, +    dwarf_r21, +    dwarf_r22, +    dwarf_r23, +    dwarf_r24, +    dwarf_r25, +    dwarf_r26, +    dwarf_r27, +    dwarf_r28, +    dwarf_r29, +    dwarf_r30, +    dwarf_r31, +    dwarf_sr, +    dwarf_lo, +    dwarf_hi, +    dwarf_bad, +    dwarf_cause, +    dwarf_pc  };  static const RegisterInfo  g_register_infos_mips64[] =  { -   //  NAME      ALT    SZ OFF ENCODING        FORMAT        COMPILER                DWARF                 GENERIC                   GDB           LLDB NATIVE       VALUE REGS  INVALIDATE REGS -  //  ========  ======  == === =============  =================== ============ ===================== ==================== =================     ====================== ========== =============== -    { "r0"    , "zero", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r0,      gcc_dwarf_r0,           LLDB_INVALID_REGNUM,        gdb_r0,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r1"    , "AT",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r1,      gcc_dwarf_r1,           LLDB_INVALID_REGNUM,        gdb_r1,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r2"    , "v0",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r2,      gcc_dwarf_r2,           LLDB_INVALID_REGNUM,        gdb_r2,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r3"    , "v1",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r3,      gcc_dwarf_r3,           LLDB_INVALID_REGNUM,        gdb_r3,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r4"    , "arg1", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r4,      gcc_dwarf_r4,           LLDB_REGNUM_GENERIC_ARG1,   gdb_r4,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r5"    , "arg2", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r5,      gcc_dwarf_r5,           LLDB_REGNUM_GENERIC_ARG2,   gdb_r5,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r6"    , "arg3", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r6,      gcc_dwarf_r6,           LLDB_REGNUM_GENERIC_ARG3,   gdb_r6,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r7"    , "arg4", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r7,      gcc_dwarf_r7,           LLDB_REGNUM_GENERIC_ARG4,   gdb_r7,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r8"    , "arg5", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r8,      gcc_dwarf_r8,           LLDB_REGNUM_GENERIC_ARG5,   gdb_r8,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r9"    , "arg6", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r9,      gcc_dwarf_r9,           LLDB_REGNUM_GENERIC_ARG6,   gdb_r9,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r10"   , "arg7", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r10,     gcc_dwarf_r10,          LLDB_REGNUM_GENERIC_ARG7,   gdb_r10,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r11"   , "arg8", 8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r11,     gcc_dwarf_r11,          LLDB_REGNUM_GENERIC_ARG8,   gdb_r11,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r12"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r12,     gcc_dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_r12,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r13"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r13,     gcc_dwarf_r13,          LLDB_INVALID_REGNUM,        gdb_r13,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r14"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r14,     gcc_dwarf_r14,          LLDB_INVALID_REGNUM,        gdb_r14,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r15"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r15,     gcc_dwarf_r15,          LLDB_INVALID_REGNUM,        gdb_r15,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r16"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r16,     gcc_dwarf_r16,          LLDB_INVALID_REGNUM,        gdb_r16,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r17"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r17,     gcc_dwarf_r17,          LLDB_INVALID_REGNUM,        gdb_r17,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r18"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r18,     gcc_dwarf_r18,          LLDB_INVALID_REGNUM,        gdb_r18,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r19"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r19,     gcc_dwarf_r19,          LLDB_INVALID_REGNUM,        gdb_r19,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r20"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r20,     gcc_dwarf_r20,          LLDB_INVALID_REGNUM,        gdb_r20,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r21"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r21,     gcc_dwarf_r21,          LLDB_INVALID_REGNUM,        gdb_r21,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r22"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r22,     gcc_dwarf_r22,          LLDB_INVALID_REGNUM,        gdb_r22,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r23"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r23,     gcc_dwarf_r23,          LLDB_INVALID_REGNUM,        gdb_r23,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r24"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r24,     gcc_dwarf_r24,          LLDB_INVALID_REGNUM,        gdb_r24,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r25"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r25,     gcc_dwarf_r25,          LLDB_INVALID_REGNUM,        gdb_r25,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r26"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r26,     gcc_dwarf_r26,          LLDB_INVALID_REGNUM,        gdb_r26,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r27"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r27,     gcc_dwarf_r27,          LLDB_INVALID_REGNUM,        gdb_r27,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r28"   , "gp",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r28,     gcc_dwarf_r28,          LLDB_INVALID_REGNUM,        gdb_r28,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r29"   , "sp",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r29,     gcc_dwarf_r29,          LLDB_REGNUM_GENERIC_SP,     gdb_r29,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r30"   , "fp",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r30,     gcc_dwarf_r30,          LLDB_REGNUM_GENERIC_FP,     gdb_r30,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "r31"   , "ra",   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_r31,     gcc_dwarf_r31,          LLDB_REGNUM_GENERIC_RA,     gdb_r31,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "sr"    , NULL,   4,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_sr,      gcc_dwarf_sr,           LLDB_REGNUM_GENERIC_FLAGS,  gdb_sr,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "lo"    , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_lo,      gcc_dwarf_lo,           LLDB_INVALID_REGNUM,        gdb_lo,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "hi"    , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_hi,      gcc_dwarf_hi,           LLDB_INVALID_REGNUM,        gdb_hi,     LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "bad"   , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_bad,     gcc_dwarf_bad,          LLDB_INVALID_REGNUM,        gdb_bad,    LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "cause" , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_cause,   gcc_dwarf_cause,        LLDB_INVALID_REGNUM,        gdb_cause,  LLDB_INVALID_REGNUM },  NULL,      NULL}, -    { "pc"    , NULL,   8,  0, eEncodingUint, eFormatHex,  { gcc_dwarf_pc,      gcc_dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_pc,     LLDB_INVALID_REGNUM },  NULL,      NULL}, +   //  NAME      ALT    SZ OFF ENCODING        FORMAT         EH_FRAME           DWARF                   GENERIC                     PROCESS PLUGIN          LLDB NATIVE            VALUE REGS INVALIDATE REGS +  //  ========  ======  == === =============  ==========     =============      =================       ====================        =================       ====================    ========== =============== +    { "r0"    , "zero", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r0,          dwarf_r0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r1"    , "AT",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r1,          dwarf_r1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r2"    , "v0",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r2,          dwarf_r2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r3"    , "v1",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r3,          dwarf_r3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r4"    , "arg1", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r4,          dwarf_r4,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r5"    , "arg2", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r5,          dwarf_r5,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r6"    , "arg3", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r6,          dwarf_r6,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r7"    , "arg4", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r7,          dwarf_r7,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r8"    , "arg5", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r8,          dwarf_r8,           LLDB_REGNUM_GENERIC_ARG5,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r9"    , "arg6", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r9,          dwarf_r9,           LLDB_REGNUM_GENERIC_ARG6,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r10"   , "arg7", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r10,         dwarf_r10,          LLDB_REGNUM_GENERIC_ARG7,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r11"   , "arg8", 8,  0, eEncodingUint, eFormatHex,  {     dwarf_r11,         dwarf_r11,          LLDB_REGNUM_GENERIC_ARG8,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r12"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r12,         dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r13"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r13,         dwarf_r13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r14"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r14,         dwarf_r14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r15"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r15,         dwarf_r15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r16"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r16,         dwarf_r16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r17"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r17,         dwarf_r17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r18"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r18,         dwarf_r18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r19"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r19,         dwarf_r19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r20"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r20,         dwarf_r20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r21"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r21,         dwarf_r21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r22"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r22,         dwarf_r22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r23"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r23,         dwarf_r23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r24"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r24,         dwarf_r24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r25"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r25,         dwarf_r25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r26"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r26,         dwarf_r26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r27"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r27,         dwarf_r27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r28"   , "gp",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r28,         dwarf_r28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r29"   , "sp",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r29,         dwarf_r29,          LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r30"   , "fp",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r30,         dwarf_r30,          LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "r31"   , "ra",   8,  0, eEncodingUint, eFormatHex,  {     dwarf_r31,         dwarf_r31,          LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "sr"    , NULL,   4,  0, eEncodingUint, eFormatHex,  {     dwarf_sr,          dwarf_sr,           LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "lo"    , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_lo,          dwarf_lo,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "hi"    , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_hi,          dwarf_hi,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "bad"   , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_bad,         dwarf_bad,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "cause" , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_cause,       dwarf_cause,        LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL}, +    { "pc"    , NULL,   8,  0, eEncodingUint, eFormatHex,  {     dwarf_pc,          dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },  NULL,      NULL},  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64); @@ -290,8 +247,8 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -313,7 +270,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb          return error;      } -    const uint32_t type_flags = clang_type.GetTypeInfo (NULL); +    const uint32_t type_flags = compiler_type.GetTypeInfo (NULL);      if (type_flags & eTypeIsScalar ||          type_flags & eTypeIsPointer) @@ -368,42 +325,50 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb  ValueObjectSP -ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      return return_valobj_sp;  }  ValueObjectSP -ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; - +    Error error; +          ExecutionContext exe_ctx (thread.shared_from_this());      if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)          return return_valobj_sp; -    value.SetClangType(return_clang_type); +    value.SetCompilerType(return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const size_t byte_size = return_clang_type.GetByteSize(nullptr); -    const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); +    Target *target = exe_ctx.GetTargetPtr(); +    ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); +    const size_t byte_size = return_compiler_type.GetByteSize(nullptr); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); +     +    const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); +    const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); -    if (type_flags & eTypeIsScalar) +    if (type_flags & eTypeIsScalar || +        type_flags & eTypeIsPointer)      {          value.SetValueType(Value::eValueTypeScalar);          bool success = false; -        if (type_flags & eTypeIsInteger) +        if (type_flags & eTypeIsInteger || +            type_flags & eTypeIsPointer)          {              // Extract the register context so we can read arguments from registers              // In MIPS register "r2" (v0) holds the integer function return values -            uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); +            uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);              const bool is_signed = (type_flags & eTypeIsSigned) != 0;              switch (byte_size) @@ -444,25 +409,302 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                      break;              }          } +        else if (type_flags & eTypeIsFloat) +        { +            if (type_flags & eTypeIsComplex) +            { +                // Don't handle complex yet. +            } +            else +            { +                if (byte_size <= sizeof(long double)) +                { +                    const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); +                    const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); +                    RegisterValue f0_value, f2_value; +                    DataExtractor f0_data, f2_data; +                     +                    reg_ctx->ReadRegister (f0_info, f0_value); +                    reg_ctx->ReadRegister (f2_info, f2_value); +                     +                    f0_value.GetData(f0_data); +                    f2_value.GetData(f2_data); + +                    lldb::offset_t offset = 0; +                    if (byte_size == sizeof(float)) +                    { +                        value.GetScalar() = (float) f0_data.GetFloat(&offset); +                        success = true; +                    } +                    else if (byte_size == sizeof(double)) +                    { +                        value.GetScalar() = (double) f0_data.GetDouble(&offset); +                        success = true; +                    } +                    else if (byte_size == sizeof(long double)) +                    { +                        DataExtractor *copy_from_extractor = NULL; +                        DataBufferSP data_sp (new DataBufferHeap(16, 0)); +                        DataExtractor return_ext (data_sp,  +                                                  target_byte_order,  +                                                  target->GetArchitecture().GetAddressByteSize()); + +                        if (target_byte_order == eByteOrderLittle) +                        { +                             f0_data.Append(f2_data); +                             copy_from_extractor = &f0_data; +                        } +                        else +                        { +                            f2_data.Append(f0_data); +                            copy_from_extractor = &f2_data; +                        } + +                        copy_from_extractor->CopyByteOrderedData (0, +                                                                  byte_size,  +                                                                  data_sp->GetBytes(), +                                                                  byte_size,  +                                                                  target_byte_order); + +                        return_valobj_sp = ValueObjectConstResult::Create (&thread,  +                                                                           return_compiler_type, +                                                                           ConstString(""), +                                                                           return_ext); +                        return return_valobj_sp; + +                    } +                } +            } +        }          if (success)          return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),                                                             value,                                                             ConstString(""));      } -    else if (type_flags & eTypeIsPointer) +    else if (type_flags & eTypeIsStructUnion || +             type_flags & eTypeIsClass || +             type_flags & eTypeIsVector)      { -        value.SetValueType(Value::eValueTypeScalar); -        uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); -        value.GetScalar() = (uint64_t)(raw_value); +        // Any structure of up to 16 bytes in size is returned in the registers. +        if (byte_size <= 16) +        { +            DataBufferSP data_sp (new DataBufferHeap(16, 0)); +            DataExtractor return_ext (data_sp,  +                                      target_byte_order,  +                                      target->GetArchitecture().GetAddressByteSize()); + +            RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value; + +            uint32_t integer_bytes = 0;         // Tracks how much bytes of r2 and r3 registers we've consumed so far +            bool use_fp_regs = 0;               // True if return values are in FP return registers. +            bool found_non_fp_field = 0;        // True if we found any non floating point field in structure. +            bool use_r2 = 0;                    // True if return values are in r2 register. +            bool use_r3 = 0;                    // True if return values are in r3 register. +            bool sucess = 0;                    // True if the result is copied into our data buffer +            std::string name; +            bool is_complex; +            uint32_t count; +            const uint32_t num_children = return_compiler_type.GetNumFields (); + +            // A structure consisting of one or two FP values (and nothing else) will be +            // returned in the two FP return-value registers i.e fp0 and fp2. +            if (num_children <= 2) +            { +                uint64_t field_bit_offset = 0; -        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), -                                                           value, -                                                           ConstString("")); -    } -    else if (type_flags & eTypeIsVector) -    { -        // TODO: Handle vector types +                // Check if this structure contains only floating point fields +                for (uint32_t idx = 0; idx < num_children; idx++) +                { +                    CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                     +                    if (field_compiler_type.IsFloatingPointType (count, is_complex)) +                        use_fp_regs = 1; +                    else +                        found_non_fp_field = 1; +                } + +                if (use_fp_regs && !found_non_fp_field) +                { +                    // We have one or two FP-only values in this structure. Get it from f0/f2 registers. +                    DataExtractor f0_data, f1_data, f2_data; +                    const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); +                    const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); +                    const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + +                    reg_ctx->ReadRegister (f0_info, f0_value); +                    reg_ctx->ReadRegister (f2_info, f2_value); + +                    f0_value.GetData(f0_data); +                    f2_value.GetData(f2_data); + +                    for (uint32_t idx = 0; idx < num_children; idx++) +                    { +                        CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                        const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); + +                        DataExtractor *copy_from_extractor = NULL; + +                        if (idx == 0) +                        { +                            if (field_byte_width == 16)                 // This case is for long double type. +                            { +                                // If structure contains long double type, then it is returned in fp0/fp1 registers. +                                reg_ctx->ReadRegister (f1_info, f1_value); +                                f1_value.GetData(f1_data); +                                 +                                if (target_byte_order == eByteOrderLittle) +                                { +                                    f0_data.Append(f1_data); +                                    copy_from_extractor = &f0_data; +                                } +                                else +                                { +                                    f1_data.Append(f0_data); +                                    copy_from_extractor = &f1_data; +                                } +                            } +                            else +                                copy_from_extractor = &f0_data;        // This is in f0, copy from register to our result structure +                        } +                        else +                            copy_from_extractor = &f2_data;        // This is in f2, copy from register to our result structure + +                        // Sanity check to avoid crash +                        if (!copy_from_extractor || field_byte_width > copy_from_extractor->GetByteSize()) +                            return return_valobj_sp; + +                        // copy the register contents into our data buffer +                        copy_from_extractor->CopyByteOrderedData (0, +                                                                  field_byte_width,  +                                                                  data_sp->GetBytes() + (field_bit_offset/8), +                                                                  field_byte_width,  +                                                                  target_byte_order); +                    } + +                    // The result is in our data buffer.  Create a variable object out of it +                    return_valobj_sp = ValueObjectConstResult::Create (&thread,  +                                                                       return_compiler_type, +                                                                       ConstString(""), +                                                                       return_ext); + +                    return return_valobj_sp; +                } +            } + +            // If we reach here, it means this structure either contains more than two fields or  +            // it contains at least one non floating point type. +            // In that case, all fields are returned in GP return registers. +            for (uint32_t idx = 0; idx < num_children; idx++) +            { +                uint64_t field_bit_offset = 0; +                bool is_signed; +                uint32_t padding; + +                CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); + +                // if we don't know the size of the field (e.g. invalid type), just bail out +                if (field_byte_width == 0) +                    break; + +                uint32_t field_byte_offset = field_bit_offset/8; + +                if (field_compiler_type.IsIntegerType (is_signed) +                    || field_compiler_type.IsPointerType () +                    || field_compiler_type.IsFloatingPointType (count, is_complex)) +                { +                    padding = field_byte_offset - integer_bytes; + +                    if (integer_bytes < 8) +                    { +                        // We have not yet consumed r2 completely. +                        if (integer_bytes + field_byte_width + padding <= 8) +                        { +                            // This field fits in r2, copy its value from r2 to our result structure +                            integer_bytes = integer_bytes + field_byte_width + padding;  // Increase the consumed bytes. +                            use_r2 = 1; +                        } +                        else +                        { +                            // There isn't enough space left in r2 for this field, so this will be in r3. +                            integer_bytes = integer_bytes + field_byte_width + padding;  // Increase the consumed bytes. +                            use_r3 = 1; +                        } +                    } +                    // We already have consumed at-least 8 bytes that means r2 is done, and this field will be in r3. +                    // Check if this field can fit in r3. +                    else if (integer_bytes + field_byte_width + padding <= 16) +                    { +                        integer_bytes = integer_bytes + field_byte_width + padding; +                        use_r3 = 1; +                    } +                    else +                    { +                        // There isn't any space left for this field, this should not happen as we have already checked +                        // the overall size is not greater than 16 bytes. For now, return a NULL return value object. +                        return return_valobj_sp; +                    } +                } +            } +            // Vector types upto 16 bytes are returned in GP return registers +            if (type_flags & eTypeIsVector) +            { +                if (byte_size <= 8) +                    use_r2 = 1; +                else +                { +                    use_r2 = 1; +                    use_r3 = 1; +                }     +            } + +            if (use_r2) +            { +                reg_ctx->ReadRegister (r2_info, r2_value); + +                const size_t bytes_copied = r2_value.GetAsMemoryData (r2_info, +                                                                      data_sp->GetBytes(), +                                                                      r2_info->byte_size, +                                                                      target_byte_order, +                                                                      error); +                if (bytes_copied != r2_info->byte_size) +                    return return_valobj_sp; +                sucess = 1; +            } +            if (use_r3) +            { +                reg_ctx->ReadRegister (r3_info, r3_value); +                const size_t bytes_copied = r3_value.GetAsMemoryData (r3_info, +                                                                      data_sp->GetBytes() + r2_info->byte_size, +                                                                      r3_info->byte_size, +                                                                      target_byte_order, +                                                                      error);                                                        +                                                         +                if (bytes_copied != r3_info->byte_size) +                    return return_valobj_sp; +                sucess = 1; +            } +            if (sucess) +            { +                // The result is in our data buffer.  Create a variable object out of it +                return_valobj_sp = ValueObjectConstResult::Create (&thread,  +                                                                   return_compiler_type, +                                                                   ConstString(""), +                                                                   return_ext); +            } +            return return_valobj_sp; +        } + +        // Any structure/vector greater than 16 bytes in size is returned in memory. +        // The pointer to that memory is returned in r2. +        uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + +        // We have got the address. Create a memory object out of it +        return_valobj_sp = ValueObjectMemory::Create (&thread, +                                                      "", +                                                      Address (mem_address, NULL), +                                                      return_compiler_type);      }      return return_valobj_sp;  } @@ -476,17 +718,17 @@ ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      UnwindPlan::RowSP row(new UnwindPlan::Row);      // Our Call Frame Address is the stack pointer value -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);      // The previous PC is in the RA -    row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); +    row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);      unwind_plan.AppendRow (row);      // All other registers are the same.      unwind_plan.SetSourceName ("mips64 at-func-entry default");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); -    unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); +    unwind_plan.SetReturnAddressRegister(dwarf_r31);      return true;  } @@ -498,9 +740,9 @@ ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      UnwindPlan::RowSP row(new UnwindPlan::Row); -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); -    row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); +    row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);      unwind_plan.AppendRow (row);      unwind_plan.SetSourceName ("mips64 default unwind plan"); diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index c37e717e09381..3290331e05a03 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -21,46 +21,37 @@ class ABISysV_mips64 :      public lldb_private::ABI  {  public: +    ~ABISysV_mips64() override = default; -    ~ABISysV_mips64() -    { -    } - -    virtual size_t -    GetRedZoneSize () const; +    size_t +    GetRedZoneSize() const override; -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; - -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The SysV mips ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -83,8 +74,8 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {         if (pc & (4ull - 1ull))             return false;   // Not 4 byte aligned @@ -93,11 +84,13 @@ public:          return true;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -113,21 +106,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void      CreateRegisterMapIfNeeded (); +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; +      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_mips64() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips64_h_ diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index 08416dc25b08f..f0da18637ba81 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -34,123 +33,81 @@  using namespace lldb;  using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_r0 = 0, -    gcc_dwarf_r1, -    gcc_dwarf_r2, -    gcc_dwarf_r3, -    gcc_dwarf_r4, -    gcc_dwarf_r5, -    gcc_dwarf_r6, -    gcc_dwarf_r7, -    gcc_dwarf_r8, -    gcc_dwarf_r9, -    gcc_dwarf_r10, -    gcc_dwarf_r11, -    gcc_dwarf_r12, -    gcc_dwarf_r13, -    gcc_dwarf_r14, -    gcc_dwarf_r15, -    gcc_dwarf_r16, -    gcc_dwarf_r17, -    gcc_dwarf_r18, -    gcc_dwarf_r19, -    gcc_dwarf_r20, -    gcc_dwarf_r21, -    gcc_dwarf_r22, -    gcc_dwarf_r23, -    gcc_dwarf_r24, -    gcc_dwarf_r25, -    gcc_dwarf_r26, -    gcc_dwarf_r27, -    gcc_dwarf_r28, -    gcc_dwarf_r29, -    gcc_dwarf_r30, -    gcc_dwarf_r31, -    gcc_dwarf_f0, -    gcc_dwarf_f1, -    gcc_dwarf_f2, -    gcc_dwarf_f3, -    gcc_dwarf_f4, -    gcc_dwarf_f5, -    gcc_dwarf_f6, -    gcc_dwarf_f7, -    gcc_dwarf_f8, -    gcc_dwarf_f9, -    gcc_dwarf_f10, -    gcc_dwarf_f11, -    gcc_dwarf_f12, -    gcc_dwarf_f13, -    gcc_dwarf_f14, -    gcc_dwarf_f15, -    gcc_dwarf_f16, -    gcc_dwarf_f17, -    gcc_dwarf_f18, -    gcc_dwarf_f19, -    gcc_dwarf_f20, -    gcc_dwarf_f21, -    gcc_dwarf_f22, -    gcc_dwarf_f23, -    gcc_dwarf_f24, -    gcc_dwarf_f25, -    gcc_dwarf_f26, -    gcc_dwarf_f27, -    gcc_dwarf_f28, -    gcc_dwarf_f29, -    gcc_dwarf_f30, -    gcc_dwarf_f31, -    gcc_dwarf_cr, -    gcc_dwarf_fpscr, -    gcc_dwarf_xer = 101, -    gcc_dwarf_lr = 108, -    gcc_dwarf_ctr, -    gcc_dwarf_pc, -    gcc_dwarf_cfa, +    dwarf_r0 = 0, +    dwarf_r1, +    dwarf_r2, +    dwarf_r3, +    dwarf_r4, +    dwarf_r5, +    dwarf_r6, +    dwarf_r7, +    dwarf_r8, +    dwarf_r9, +    dwarf_r10, +    dwarf_r11, +    dwarf_r12, +    dwarf_r13, +    dwarf_r14, +    dwarf_r15, +    dwarf_r16, +    dwarf_r17, +    dwarf_r18, +    dwarf_r19, +    dwarf_r20, +    dwarf_r21, +    dwarf_r22, +    dwarf_r23, +    dwarf_r24, +    dwarf_r25, +    dwarf_r26, +    dwarf_r27, +    dwarf_r28, +    dwarf_r29, +    dwarf_r30, +    dwarf_r31, +    dwarf_f0, +    dwarf_f1, +    dwarf_f2, +    dwarf_f3, +    dwarf_f4, +    dwarf_f5, +    dwarf_f6, +    dwarf_f7, +    dwarf_f8, +    dwarf_f9, +    dwarf_f10, +    dwarf_f11, +    dwarf_f12, +    dwarf_f13, +    dwarf_f14, +    dwarf_f15, +    dwarf_f16, +    dwarf_f17, +    dwarf_f18, +    dwarf_f19, +    dwarf_f20, +    dwarf_f21, +    dwarf_f22, +    dwarf_f23, +    dwarf_f24, +    dwarf_f25, +    dwarf_f26, +    dwarf_f27, +    dwarf_f28, +    dwarf_f29, +    dwarf_f30, +    dwarf_f31, +    dwarf_cr, +    dwarf_fpscr, +    dwarf_xer = 101, +    dwarf_lr = 108, +    dwarf_ctr, +    dwarf_pc, +    dwarf_cfa,  }; -enum gdb_regnums -{ -    gdb_r0 = 0, -    gdb_r1, -    gdb_r2, -    gdb_r3, -    gdb_r4, -    gdb_r5, -    gdb_r6, -    gdb_r7, -    gdb_r8, -    gdb_r9, -    gdb_r10, -    gdb_r11, -    gdb_r12, -    gdb_r13, -    gdb_r14, -    gdb_r15, -    gdb_r16, -    gdb_r17, -    gdb_r18, -    gdb_r19, -    gdb_r20, -    gdb_r21, -    gdb_r22, -    gdb_r23, -    gdb_r24, -    gdb_r25, -    gdb_r26, -    gdb_r27, -    gdb_r28, -    gdb_r29, -    gdb_r30, -    gdb_r31, -    gdb_lr, -    gdb_cr, -    gdb_xer, -    gdb_ctr, -    gdb_pc, -}; - -  // Note that the size and offset will be updated by platform-specific classes.  #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)           \      { #reg, alt, 8, 0, eEncodingUint, \ @@ -158,45 +115,45 @@ enum gdb_regnums  static const RegisterInfo  g_register_infos[] =  { -    // General purpose registers.                 GCC,                  DWARF,              Generic,                GDB -    DEFINE_GPR(r0,       NULL,  gcc_dwarf_r0,    gcc_dwarf_r0,    LLDB_INVALID_REGNUM,    gdb_r0), -    DEFINE_GPR(r1,       "sp",  gcc_dwarf_r1,    gcc_dwarf_r1,    LLDB_REGNUM_GENERIC_SP, gdb_r1), -    DEFINE_GPR(r2,       NULL,  gcc_dwarf_r2,    gcc_dwarf_r2,    LLDB_INVALID_REGNUM,    gdb_r2), -    DEFINE_GPR(r3,       "arg1",gcc_dwarf_r3,    gcc_dwarf_r3,    LLDB_REGNUM_GENERIC_ARG1, gdb_r3), -    DEFINE_GPR(r4,       "arg2",gcc_dwarf_r4,    gcc_dwarf_r4,    LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), -    DEFINE_GPR(r5,       "arg3",gcc_dwarf_r5,    gcc_dwarf_r5,    LLDB_REGNUM_GENERIC_ARG3, gdb_r5), -    DEFINE_GPR(r6,       "arg4",gcc_dwarf_r6,    gcc_dwarf_r6,    LLDB_REGNUM_GENERIC_ARG4, gdb_r6), -    DEFINE_GPR(r7,       "arg5",gcc_dwarf_r7,    gcc_dwarf_r7,    LLDB_REGNUM_GENERIC_ARG5, gdb_r7), -    DEFINE_GPR(r8,       "arg6",gcc_dwarf_r8,    gcc_dwarf_r8,    LLDB_REGNUM_GENERIC_ARG6, gdb_r8), -    DEFINE_GPR(r9,       "arg7",gcc_dwarf_r9,    gcc_dwarf_r9,    LLDB_REGNUM_GENERIC_ARG7, gdb_r9), -    DEFINE_GPR(r10,      "arg8",gcc_dwarf_r10,   gcc_dwarf_r10,   LLDB_REGNUM_GENERIC_ARG8, gdb_r10), -    DEFINE_GPR(r11,      NULL,  gcc_dwarf_r11,   gcc_dwarf_r11,   LLDB_INVALID_REGNUM,    gdb_r11), -    DEFINE_GPR(r12,      NULL,  gcc_dwarf_r12,   gcc_dwarf_r12,   LLDB_INVALID_REGNUM,    gdb_r12), -    DEFINE_GPR(r13,      NULL,  gcc_dwarf_r13,   gcc_dwarf_r13,   LLDB_INVALID_REGNUM,    gdb_r13), -    DEFINE_GPR(r14,      NULL,  gcc_dwarf_r14,   gcc_dwarf_r14,   LLDB_INVALID_REGNUM,    gdb_r14), -    DEFINE_GPR(r15,      NULL,  gcc_dwarf_r15,   gcc_dwarf_r15,   LLDB_INVALID_REGNUM,    gdb_r15), -    DEFINE_GPR(r16,      NULL,  gcc_dwarf_r16,   gcc_dwarf_r16,   LLDB_INVALID_REGNUM,    gdb_r16), -    DEFINE_GPR(r17,      NULL,  gcc_dwarf_r17,   gcc_dwarf_r17,   LLDB_INVALID_REGNUM,    gdb_r17), -    DEFINE_GPR(r18,      NULL,  gcc_dwarf_r18,   gcc_dwarf_r18,   LLDB_INVALID_REGNUM,    gdb_r18), -    DEFINE_GPR(r19,      NULL,  gcc_dwarf_r19,   gcc_dwarf_r19,   LLDB_INVALID_REGNUM,    gdb_r19), -    DEFINE_GPR(r20,      NULL,  gcc_dwarf_r20,   gcc_dwarf_r20,   LLDB_INVALID_REGNUM,    gdb_r20), -    DEFINE_GPR(r21,      NULL,  gcc_dwarf_r21,   gcc_dwarf_r21,   LLDB_INVALID_REGNUM,    gdb_r21), -    DEFINE_GPR(r22,      NULL,  gcc_dwarf_r22,   gcc_dwarf_r22,   LLDB_INVALID_REGNUM,    gdb_r22), -    DEFINE_GPR(r23,      NULL,  gcc_dwarf_r23,   gcc_dwarf_r23,   LLDB_INVALID_REGNUM,    gdb_r23), -    DEFINE_GPR(r24,      NULL,  gcc_dwarf_r24,   gcc_dwarf_r24,   LLDB_INVALID_REGNUM,    gdb_r24), -    DEFINE_GPR(r25,      NULL,  gcc_dwarf_r25,   gcc_dwarf_r25,   LLDB_INVALID_REGNUM,    gdb_r25), -    DEFINE_GPR(r26,      NULL,  gcc_dwarf_r26,   gcc_dwarf_r26,   LLDB_INVALID_REGNUM,    gdb_r26), -    DEFINE_GPR(r27,      NULL,  gcc_dwarf_r27,   gcc_dwarf_r27,   LLDB_INVALID_REGNUM,    gdb_r27), -    DEFINE_GPR(r28,      NULL,  gcc_dwarf_r28,   gcc_dwarf_r28,   LLDB_INVALID_REGNUM,    gdb_r28), -    DEFINE_GPR(r29,      NULL,  gcc_dwarf_r29,   gcc_dwarf_r29,   LLDB_INVALID_REGNUM,    gdb_r29), -    DEFINE_GPR(r30,      NULL,  gcc_dwarf_r30,   gcc_dwarf_r30,   LLDB_INVALID_REGNUM,    gdb_r30), -    DEFINE_GPR(r31,      NULL,  gcc_dwarf_r31,   gcc_dwarf_r31,   LLDB_INVALID_REGNUM,    gdb_r31), -    DEFINE_GPR(lr,       "lr",  gcc_dwarf_lr,    gcc_dwarf_lr,    LLDB_REGNUM_GENERIC_RA, gdb_lr), -    DEFINE_GPR(cr,       "cr",  gcc_dwarf_cr,    gcc_dwarf_cr,    LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), -    DEFINE_GPR(xer,      "xer", gcc_dwarf_xer,   gcc_dwarf_xer,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(ctr,      "ctr", gcc_dwarf_ctr,   gcc_dwarf_ctr,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(pc,       "pc",  gcc_dwarf_pc,    gcc_dwarf_pc,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), -    { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, +    // General purpose registers.             eh_frame,                 DWARF,              Generic,    Process Plugin +    DEFINE_GPR(r0,       NULL,  dwarf_r0,    dwarf_r0,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r1,       "sp",  dwarf_r1,    dwarf_r1,    LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r2,       NULL,  dwarf_r2,    dwarf_r2,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r3,       "arg1",dwarf_r3,    dwarf_r3,    LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r4,       "arg2",dwarf_r4,    dwarf_r4,    LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), +    DEFINE_GPR(r5,       "arg3",dwarf_r5,    dwarf_r5,    LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r6,       "arg4",dwarf_r6,    dwarf_r6,    LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r7,       "arg5",dwarf_r7,    dwarf_r7,    LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r8,       "arg6",dwarf_r8,    dwarf_r8,    LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r9,       "arg7",dwarf_r9,    dwarf_r9,    LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r10,      "arg8",dwarf_r10,   dwarf_r10,   LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r11,      NULL,  dwarf_r11,   dwarf_r11,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r12,      NULL,  dwarf_r12,   dwarf_r12,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r13,      NULL,  dwarf_r13,   dwarf_r13,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r14,      NULL,  dwarf_r14,   dwarf_r14,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r15,      NULL,  dwarf_r15,   dwarf_r15,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r16,      NULL,  dwarf_r16,   dwarf_r16,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r17,      NULL,  dwarf_r17,   dwarf_r17,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r18,      NULL,  dwarf_r18,   dwarf_r18,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r19,      NULL,  dwarf_r19,   dwarf_r19,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r20,      NULL,  dwarf_r20,   dwarf_r20,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r21,      NULL,  dwarf_r21,   dwarf_r21,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r22,      NULL,  dwarf_r22,   dwarf_r22,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r23,      NULL,  dwarf_r23,   dwarf_r23,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r24,      NULL,  dwarf_r24,   dwarf_r24,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r25,      NULL,  dwarf_r25,   dwarf_r25,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r26,      NULL,  dwarf_r26,   dwarf_r26,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r27,      NULL,  dwarf_r27,   dwarf_r27,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r28,      NULL,  dwarf_r28,   dwarf_r28,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r29,      NULL,  dwarf_r29,   dwarf_r29,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r30,      NULL,  dwarf_r30,   dwarf_r30,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r31,      NULL,  dwarf_r31,   dwarf_r31,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(lr,       "lr",  dwarf_lr,    dwarf_lr,    LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), +    DEFINE_GPR(cr,       "cr",  dwarf_cr,    dwarf_cr,    LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), +    DEFINE_GPR(xer,      "xer", dwarf_xer,   dwarf_xer,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(ctr,      "ctr", dwarf_ctr,   dwarf_ctr,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(pc,       "pc",  dwarf_pc,    dwarf_pc,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), +    { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +393,25 @@ ABISysV_ppc::GetArgumentValues (Thread &thread,          // We currently only support extracting values with Clang QualTypes.          // Do we care about others? -        ClangASTType clang_type = value->GetClangType(); -        if (!clang_type) +        CompilerType compiler_type = value->GetCompilerType(); +        if (!compiler_type)              return false;          bool is_signed; -        if (clang_type.IsIntegerType (is_signed)) +        if (compiler_type.IsIntegerType (is_signed))          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  is_signed,                                  thread,                                  argument_register_ids,                                  current_argument_register,                                  current_stack_argument);          } -        else if (clang_type.IsPointerType ()) +        else if (compiler_type.IsPointerType ())          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  false,                                  thread,                                  argument_register_ids, @@ -476,8 +433,8 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -492,7 +449,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +475,13 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present");          else          { -            size_t bit_width = clang_type.GetBitSize(frame_sp.get()); +            size_t bit_width = compiler_type.GetBitSize(frame_sp.get());              if (bit_width <= 64)              {                  DataExtractor data; @@ -563,22 +520,22 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec  ValueObjectSP  ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, -                                            ClangASTType &return_clang_type) const +                                         CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      //value.SetContext (Value::eContextTypeClangType, return_value_type); -    value.SetClangType (return_clang_type); +    value.SetCompilerType (return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const uint32_t type_flags = return_clang_type.GetTypeInfo (); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo ();      if (type_flags & eTypeIsScalar)      {          value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +545,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,          {              // Extract the register context so we can read arguments from registers -            const size_t byte_size = return_clang_type.GetByteSize(nullptr); +            const size_t byte_size = return_compiler_type.GetByteSize(nullptr);              uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);              const bool is_signed = (type_flags & eTypeIsSigned) != 0;              switch (byte_size) @@ -637,7 +594,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,              }              else              { -                const size_t byte_size = return_clang_type.GetByteSize(nullptr); +                const size_t byte_size = return_compiler_type.GetByteSize(nullptr);                  if (byte_size <= sizeof(long double))                  {                      const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +638,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,      }      else if (type_flags & eTypeIsVector)      { -        const size_t byte_size = return_clang_type.GetByteSize(nullptr); +        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);          if (byte_size > 0)          { @@ -709,7 +666,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,                                                      byte_order,                                                      process_sp->GetTarget().GetArchitecture().GetAddressByteSize());                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                   return_clang_type, +                                                                                   return_compiler_type,                                                                                     ConstString(""),                                                                                     data);                              } @@ -724,15 +681,15 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,  }  ValueObjectSP -ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      ExecutionContext exe_ctx (thread.shared_from_this()); -    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); +    return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);      if (return_valobj_sp)          return return_valobj_sp; @@ -740,8 +697,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan      if (!reg_ctx_sp)          return return_valobj_sp; -    const size_t bit_width = return_clang_type.GetBitSize(&thread); -    if (return_clang_type.IsAggregateType()) +    const size_t bit_width = return_compiler_type.GetBitSize(&thread); +    if (return_compiler_type.IsAggregateType())      {          Target *target = exe_ctx.GetTargetPtr();          bool is_memory = true; @@ -768,7 +725,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan              uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far              uint32_t integer_bytes = 0;  // Tracks how much of the r3/rds registers we've consumed so far -            const uint32_t num_children = return_clang_type.GetNumFields (); +            const uint32_t num_children = return_compiler_type.GetNumFields ();              // Since we are in the small struct regime, assume we are not in memory.              is_memory = false; @@ -781,8 +738,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan                  bool is_complex;                  uint32_t count; -                ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); -                const size_t field_bit_width = field_clang_type.GetBitSize(&thread); +                CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);                  // If there are any unaligned fields, this is stored in memory.                  if (field_bit_offset % field_bit_width != 0) @@ -798,7 +755,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan                  DataExtractor *copy_from_extractor = NULL;                  uint32_t       copy_from_offset    = 0; -                if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) +                if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())                  {                      if (integer_bytes < 8)                      { @@ -831,7 +788,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan                          return return_valobj_sp;                      }                  } -                else if (field_clang_type.IsFloatingPointType (count, is_complex)) +                else if (field_compiler_type.IsFloatingPointType (count, is_complex))                  {                      // Structs with long doubles are always passed in memory.                      if (field_bit_width == 128) @@ -858,12 +815,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan                              else                              {                                  uint64_t next_field_bit_offset = 0; -                                ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, +                                CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,                                                                                                          name,                                                                                                          &next_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (next_field_clang_type.IsIntegerType (is_signed)) +                                if (next_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -882,12 +839,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan                              else                              {                                  uint64_t prev_field_bit_offset = 0; -                                ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, +                                CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,                                                                                                          name,                                                                                                          &prev_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (prev_field_clang_type.IsIntegerType (is_signed)) +                                if (prev_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -946,7 +903,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan              {                  // The result is in our data buffer.  Let's make a variable object out of it:                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                   return_clang_type, +                                                                   return_compiler_type,                                                                     ConstString(""),                                                                     return_ext);              } @@ -965,7 +922,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan              return_valobj_sp = ValueObjectMemory::Create (&thread,                                                            "",                                                            Address (storage_addr, NULL), -                                                          return_clang_type); +                                                          return_compiler_type);          }      } @@ -978,9 +935,9 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t lr_reg_num = gcc_dwarf_lr; -    uint32_t sp_reg_num = gcc_dwarf_r1; -    uint32_t pc_reg_num = gcc_dwarf_pc; +    uint32_t lr_reg_num = dwarf_lr; +    uint32_t sp_reg_num = dwarf_r1; +    uint32_t pc_reg_num = dwarf_pc;      UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +962,8 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t sp_reg_num = gcc_dwarf_r1; -    uint32_t pc_reg_num = gcc_dwarf_lr; +    uint32_t sp_reg_num = dwarf_r1; +    uint32_t pc_reg_num = dwarf_lr;      UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1020,7 +977,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.SetSourceName ("ppc default unwind plan");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);      unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); -    unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); +    unwind_plan.SetReturnAddressRegister(dwarf_lr);      return true;  } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h index a7aad300e2979..99ee755631c22 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -21,52 +21,37 @@ class ABISysV_ppc :      public lldb_private::ABI  {  public: +    ~ABISysV_ppc() override = default; -    ~ABISysV_ppc() -    { -    } +    size_t +    GetRedZoneSize() const override; -    virtual size_t -    GetRedZoneSize () const; - -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; -     -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); -     -    virtual bool -    StackUsesFrames () -    { -        return true; -    } +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The SysV ppc ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // We have a 64 bit address space, so anything is valid as opcodes          // aren't fixed width...          return true;      } -    virtual bool -    FunctionCallsChangeCFA () -    { -        return true; -    } +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count);      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -123,21 +104,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void      CreateRegisterMapIfNeeded (); +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; +      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_ppc() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc_h_ diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index eb0d7c00070f4..96c54ce97eec2 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -34,120 +33,79 @@  using namespace lldb;  using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_r0 = 0, -    gcc_dwarf_r1, -    gcc_dwarf_r2, -    gcc_dwarf_r3, -    gcc_dwarf_r4, -    gcc_dwarf_r5, -    gcc_dwarf_r6, -    gcc_dwarf_r7, -    gcc_dwarf_r8, -    gcc_dwarf_r9, -    gcc_dwarf_r10, -    gcc_dwarf_r11, -    gcc_dwarf_r12, -    gcc_dwarf_r13, -    gcc_dwarf_r14, -    gcc_dwarf_r15, -    gcc_dwarf_r16, -    gcc_dwarf_r17, -    gcc_dwarf_r18, -    gcc_dwarf_r19, -    gcc_dwarf_r20, -    gcc_dwarf_r21, -    gcc_dwarf_r22, -    gcc_dwarf_r23, -    gcc_dwarf_r24, -    gcc_dwarf_r25, -    gcc_dwarf_r26, -    gcc_dwarf_r27, -    gcc_dwarf_r28, -    gcc_dwarf_r29, -    gcc_dwarf_r30, -    gcc_dwarf_r31, -    gcc_dwarf_f0, -    gcc_dwarf_f1, -    gcc_dwarf_f2, -    gcc_dwarf_f3, -    gcc_dwarf_f4, -    gcc_dwarf_f5, -    gcc_dwarf_f6, -    gcc_dwarf_f7, -    gcc_dwarf_f8, -    gcc_dwarf_f9, -    gcc_dwarf_f10, -    gcc_dwarf_f11, -    gcc_dwarf_f12, -    gcc_dwarf_f13, -    gcc_dwarf_f14, -    gcc_dwarf_f15, -    gcc_dwarf_f16, -    gcc_dwarf_f17, -    gcc_dwarf_f18, -    gcc_dwarf_f19, -    gcc_dwarf_f20, -    gcc_dwarf_f21, -    gcc_dwarf_f22, -    gcc_dwarf_f23, -    gcc_dwarf_f24, -    gcc_dwarf_f25, -    gcc_dwarf_f26, -    gcc_dwarf_f27, -    gcc_dwarf_f28, -    gcc_dwarf_f29, -    gcc_dwarf_f30, -    gcc_dwarf_f31, -    gcc_dwarf_cr, -    gcc_dwarf_fpscr, -    gcc_dwarf_xer = 101, -    gcc_dwarf_lr = 108, -    gcc_dwarf_ctr, -    gcc_dwarf_pc, -    gcc_dwarf_cfa, -}; - -enum gdb_regnums -{ -    gdb_r0 = 0, -    gdb_r1, -    gdb_r2, -    gdb_r3, -    gdb_r4, -    gdb_r5, -    gdb_r6, -    gdb_r7, -    gdb_r8, -    gdb_r9, -    gdb_r10, -    gdb_r11, -    gdb_r12, -    gdb_r13, -    gdb_r14, -    gdb_r15, -    gdb_r16, -    gdb_r17, -    gdb_r18, -    gdb_r19, -    gdb_r20, -    gdb_r21, -    gdb_r22, -    gdb_r23, -    gdb_r24, -    gdb_r25, -    gdb_r26, -    gdb_r27, -    gdb_r28, -    gdb_r29, -    gdb_r30, -    gdb_r31, -    gdb_lr, -    gdb_cr, -    gdb_xer, -    gdb_ctr, -    gdb_pc, +    dwarf_r0 = 0, +    dwarf_r1, +    dwarf_r2, +    dwarf_r3, +    dwarf_r4, +    dwarf_r5, +    dwarf_r6, +    dwarf_r7, +    dwarf_r8, +    dwarf_r9, +    dwarf_r10, +    dwarf_r11, +    dwarf_r12, +    dwarf_r13, +    dwarf_r14, +    dwarf_r15, +    dwarf_r16, +    dwarf_r17, +    dwarf_r18, +    dwarf_r19, +    dwarf_r20, +    dwarf_r21, +    dwarf_r22, +    dwarf_r23, +    dwarf_r24, +    dwarf_r25, +    dwarf_r26, +    dwarf_r27, +    dwarf_r28, +    dwarf_r29, +    dwarf_r30, +    dwarf_r31, +    dwarf_f0, +    dwarf_f1, +    dwarf_f2, +    dwarf_f3, +    dwarf_f4, +    dwarf_f5, +    dwarf_f6, +    dwarf_f7, +    dwarf_f8, +    dwarf_f9, +    dwarf_f10, +    dwarf_f11, +    dwarf_f12, +    dwarf_f13, +    dwarf_f14, +    dwarf_f15, +    dwarf_f16, +    dwarf_f17, +    dwarf_f18, +    dwarf_f19, +    dwarf_f20, +    dwarf_f21, +    dwarf_f22, +    dwarf_f23, +    dwarf_f24, +    dwarf_f25, +    dwarf_f26, +    dwarf_f27, +    dwarf_f28, +    dwarf_f29, +    dwarf_f30, +    dwarf_f31, +    dwarf_cr, +    dwarf_fpscr, +    dwarf_xer = 101, +    dwarf_lr = 108, +    dwarf_ctr, +    dwarf_pc, +    dwarf_cfa,  }; @@ -158,45 +116,45 @@ enum gdb_regnums  static const RegisterInfo  g_register_infos[] =  { -    // General purpose registers.                 GCC,                  DWARF,              Generic,                GDB -    DEFINE_GPR(r0,       NULL,  gcc_dwarf_r0,    gcc_dwarf_r0,    LLDB_INVALID_REGNUM,    gdb_r0), -    DEFINE_GPR(r1,       "sp",  gcc_dwarf_r1,    gcc_dwarf_r1,    LLDB_REGNUM_GENERIC_SP, gdb_r1), -    DEFINE_GPR(r2,       NULL,  gcc_dwarf_r2,    gcc_dwarf_r2,    LLDB_INVALID_REGNUM,    gdb_r2), -    DEFINE_GPR(r3,       "arg1",gcc_dwarf_r3,    gcc_dwarf_r3,    LLDB_REGNUM_GENERIC_ARG1, gdb_r3), -    DEFINE_GPR(r4,       "arg2",gcc_dwarf_r4,    gcc_dwarf_r4,    LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), -    DEFINE_GPR(r5,       "arg3",gcc_dwarf_r5,    gcc_dwarf_r5,    LLDB_REGNUM_GENERIC_ARG3, gdb_r5), -    DEFINE_GPR(r6,       "arg4",gcc_dwarf_r6,    gcc_dwarf_r6,    LLDB_REGNUM_GENERIC_ARG4, gdb_r6), -    DEFINE_GPR(r7,       "arg5",gcc_dwarf_r7,    gcc_dwarf_r7,    LLDB_REGNUM_GENERIC_ARG5, gdb_r7), -    DEFINE_GPR(r8,       "arg6",gcc_dwarf_r8,    gcc_dwarf_r8,    LLDB_REGNUM_GENERIC_ARG6, gdb_r8), -    DEFINE_GPR(r9,       "arg7",gcc_dwarf_r9,    gcc_dwarf_r9,    LLDB_REGNUM_GENERIC_ARG7, gdb_r9), -    DEFINE_GPR(r10,      "arg8",gcc_dwarf_r10,   gcc_dwarf_r10,   LLDB_REGNUM_GENERIC_ARG8, gdb_r10), -    DEFINE_GPR(r11,      NULL,  gcc_dwarf_r11,   gcc_dwarf_r11,   LLDB_INVALID_REGNUM,    gdb_r11), -    DEFINE_GPR(r12,      NULL,  gcc_dwarf_r12,   gcc_dwarf_r12,   LLDB_INVALID_REGNUM,    gdb_r12), -    DEFINE_GPR(r13,      NULL,  gcc_dwarf_r13,   gcc_dwarf_r13,   LLDB_INVALID_REGNUM,    gdb_r13), -    DEFINE_GPR(r14,      NULL,  gcc_dwarf_r14,   gcc_dwarf_r14,   LLDB_INVALID_REGNUM,    gdb_r14), -    DEFINE_GPR(r15,      NULL,  gcc_dwarf_r15,   gcc_dwarf_r15,   LLDB_INVALID_REGNUM,    gdb_r15), -    DEFINE_GPR(r16,      NULL,  gcc_dwarf_r16,   gcc_dwarf_r16,   LLDB_INVALID_REGNUM,    gdb_r16), -    DEFINE_GPR(r17,      NULL,  gcc_dwarf_r17,   gcc_dwarf_r17,   LLDB_INVALID_REGNUM,    gdb_r17), -    DEFINE_GPR(r18,      NULL,  gcc_dwarf_r18,   gcc_dwarf_r18,   LLDB_INVALID_REGNUM,    gdb_r18), -    DEFINE_GPR(r19,      NULL,  gcc_dwarf_r19,   gcc_dwarf_r19,   LLDB_INVALID_REGNUM,    gdb_r19), -    DEFINE_GPR(r20,      NULL,  gcc_dwarf_r20,   gcc_dwarf_r20,   LLDB_INVALID_REGNUM,    gdb_r20), -    DEFINE_GPR(r21,      NULL,  gcc_dwarf_r21,   gcc_dwarf_r21,   LLDB_INVALID_REGNUM,    gdb_r21), -    DEFINE_GPR(r22,      NULL,  gcc_dwarf_r22,   gcc_dwarf_r22,   LLDB_INVALID_REGNUM,    gdb_r22), -    DEFINE_GPR(r23,      NULL,  gcc_dwarf_r23,   gcc_dwarf_r23,   LLDB_INVALID_REGNUM,    gdb_r23), -    DEFINE_GPR(r24,      NULL,  gcc_dwarf_r24,   gcc_dwarf_r24,   LLDB_INVALID_REGNUM,    gdb_r24), -    DEFINE_GPR(r25,      NULL,  gcc_dwarf_r25,   gcc_dwarf_r25,   LLDB_INVALID_REGNUM,    gdb_r25), -    DEFINE_GPR(r26,      NULL,  gcc_dwarf_r26,   gcc_dwarf_r26,   LLDB_INVALID_REGNUM,    gdb_r26), -    DEFINE_GPR(r27,      NULL,  gcc_dwarf_r27,   gcc_dwarf_r27,   LLDB_INVALID_REGNUM,    gdb_r27), -    DEFINE_GPR(r28,      NULL,  gcc_dwarf_r28,   gcc_dwarf_r28,   LLDB_INVALID_REGNUM,    gdb_r28), -    DEFINE_GPR(r29,      NULL,  gcc_dwarf_r29,   gcc_dwarf_r29,   LLDB_INVALID_REGNUM,    gdb_r29), -    DEFINE_GPR(r30,      NULL,  gcc_dwarf_r30,   gcc_dwarf_r30,   LLDB_INVALID_REGNUM,    gdb_r30), -    DEFINE_GPR(r31,      NULL,  gcc_dwarf_r31,   gcc_dwarf_r31,   LLDB_INVALID_REGNUM,    gdb_r31), -    DEFINE_GPR(lr,       "lr",  gcc_dwarf_lr,    gcc_dwarf_lr,    LLDB_REGNUM_GENERIC_RA, gdb_lr), -    DEFINE_GPR(cr,       "cr",  gcc_dwarf_cr,    gcc_dwarf_cr,    LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), -    DEFINE_GPR(xer,      "xer", gcc_dwarf_xer,   gcc_dwarf_xer,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(ctr,      "ctr", gcc_dwarf_ctr,   gcc_dwarf_ctr,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(pc,       "pc",  gcc_dwarf_pc,    gcc_dwarf_pc,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), -    { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, +    // General purpose registers.            eh_frame,                  DWARF,              Generic,     Process Plugin +    DEFINE_GPR(r0,       NULL,  dwarf_r0,    dwarf_r0,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r1,       "sp",  dwarf_r1,    dwarf_r1,    LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r2,       NULL,  dwarf_r2,    dwarf_r2,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r3,       "arg1",dwarf_r3,    dwarf_r3,    LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r4,       "arg2",dwarf_r4,    dwarf_r4,    LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), +    DEFINE_GPR(r5,       "arg3",dwarf_r5,    dwarf_r5,    LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r6,       "arg4",dwarf_r6,    dwarf_r6,    LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r7,       "arg5",dwarf_r7,    dwarf_r7,    LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r8,       "arg6",dwarf_r8,    dwarf_r8,    LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r9,       "arg7",dwarf_r9,    dwarf_r9,    LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r10,      "arg8",dwarf_r10,   dwarf_r10,   LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r11,      NULL,  dwarf_r11,   dwarf_r11,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r12,      NULL,  dwarf_r12,   dwarf_r12,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r13,      NULL,  dwarf_r13,   dwarf_r13,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r14,      NULL,  dwarf_r14,   dwarf_r14,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r15,      NULL,  dwarf_r15,   dwarf_r15,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r16,      NULL,  dwarf_r16,   dwarf_r16,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r17,      NULL,  dwarf_r17,   dwarf_r17,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r18,      NULL,  dwarf_r18,   dwarf_r18,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r19,      NULL,  dwarf_r19,   dwarf_r19,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r20,      NULL,  dwarf_r20,   dwarf_r20,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r21,      NULL,  dwarf_r21,   dwarf_r21,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r22,      NULL,  dwarf_r22,   dwarf_r22,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r23,      NULL,  dwarf_r23,   dwarf_r23,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r24,      NULL,  dwarf_r24,   dwarf_r24,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r25,      NULL,  dwarf_r25,   dwarf_r25,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r26,      NULL,  dwarf_r26,   dwarf_r26,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r27,      NULL,  dwarf_r27,   dwarf_r27,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r28,      NULL,  dwarf_r28,   dwarf_r28,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r29,      NULL,  dwarf_r29,   dwarf_r29,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r30,      NULL,  dwarf_r30,   dwarf_r30,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r31,      NULL,  dwarf_r31,   dwarf_r31,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(lr,       "lr",  dwarf_lr,    dwarf_lr,    LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), +    DEFINE_GPR(cr,       "cr",  dwarf_cr,    dwarf_cr,    LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), +    DEFINE_GPR(xer,      "xer", dwarf_xer,   dwarf_xer,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(ctr,      "ctr", dwarf_ctr,   dwarf_ctr,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(pc,       "pc",  dwarf_pc,    dwarf_pc,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), +    { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +394,25 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread,          // We currently only support extracting values with Clang QualTypes.          // Do we care about others? -        ClangASTType clang_type = value->GetClangType(); -        if (!clang_type) +        CompilerType compiler_type = value->GetCompilerType(); +        if (!compiler_type)              return false;          bool is_signed; -        if (clang_type.IsIntegerType (is_signed)) +        if (compiler_type.IsIntegerType (is_signed))          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  is_signed,                                  thread,                                  argument_register_ids,                                  current_argument_register,                                  current_stack_argument);          } -        else if (clang_type.IsPointerType ()) +        else if (compiler_type.IsPointerType ())          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  false,                                  thread,                                  argument_register_ids, @@ -476,8 +434,8 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -492,7 +450,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +476,13 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present");          else          { -            size_t bit_width = clang_type.GetBitSize(frame_sp.get()); +            size_t bit_width = compiler_type.GetBitSize(frame_sp.get());              if (bit_width <= 64)              {                  DataExtractor data; @@ -563,22 +521,22 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj  ValueObjectSP  ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, -                                            ClangASTType &return_clang_type) const +                                           CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      //value.SetContext (Value::eContextTypeClangType, return_value_type); -    value.SetClangType (return_clang_type); +    value.SetCompilerType (return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const uint32_t type_flags = return_clang_type.GetTypeInfo (); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo ();      if (type_flags & eTypeIsScalar)      {          value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +546,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,          {              // Extract the register context so we can read arguments from registers -            const size_t byte_size = return_clang_type.GetByteSize(nullptr); +            const size_t byte_size = return_compiler_type.GetByteSize(nullptr);              uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);              const bool is_signed = (type_flags & eTypeIsSigned) != 0;              switch (byte_size) @@ -637,7 +595,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,              }              else              { -                const size_t byte_size = return_clang_type.GetByteSize(nullptr); +                const size_t byte_size = return_compiler_type.GetByteSize(nullptr);                  if (byte_size <= sizeof(long double))                  {                      const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +639,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,      }      else if (type_flags & eTypeIsVector)      { -        const size_t byte_size = return_clang_type.GetByteSize(nullptr); +        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);          if (byte_size > 0)          { @@ -709,7 +667,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,                                                      byte_order,                                                      process_sp->GetTarget().GetArchitecture().GetAddressByteSize());                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                   return_clang_type, +                                                                                   return_compiler_type,                                                                                     ConstString(""),                                                                                     data);                              } @@ -724,15 +682,15 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,  }  ValueObjectSP -ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      ExecutionContext exe_ctx (thread.shared_from_this()); -    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); +    return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);      if (return_valobj_sp)          return return_valobj_sp; @@ -740,8 +698,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl      if (!reg_ctx_sp)          return return_valobj_sp; -    const size_t bit_width = return_clang_type.GetBitSize(&thread); -    if (return_clang_type.IsAggregateType()) +    const size_t bit_width = return_compiler_type.GetBitSize(&thread); +    if (return_compiler_type.IsAggregateType())      {          Target *target = exe_ctx.GetTargetPtr();          bool is_memory = true; @@ -768,7 +726,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl              uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far              uint32_t integer_bytes = 0;  // Tracks how much of the r3/rds registers we've consumed so far -            const uint32_t num_children = return_clang_type.GetNumFields (); +            const uint32_t num_children = return_compiler_type.GetNumFields ();              // Since we are in the small struct regime, assume we are not in memory.              is_memory = false; @@ -781,8 +739,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                  bool is_complex;                  uint32_t count; -                ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); -                const size_t field_bit_width = field_clang_type.GetBitSize(&thread); +                CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);                  // If there are any unaligned fields, this is stored in memory.                  if (field_bit_offset % field_bit_width != 0) @@ -798,7 +756,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                  DataExtractor *copy_from_extractor = NULL;                  uint32_t       copy_from_offset    = 0; -                if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) +                if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())                  {                      if (integer_bytes < 8)                      { @@ -831,7 +789,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                          return return_valobj_sp;                      }                  } -                else if (field_clang_type.IsFloatingPointType (count, is_complex)) +                else if (field_compiler_type.IsFloatingPointType (count, is_complex))                  {                      // Structs with long doubles are always passed in memory.                      if (field_bit_width == 128) @@ -858,12 +816,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                              else                              {                                  uint64_t next_field_bit_offset = 0; -                                ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, +                                CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,                                                                                                          name,                                                                                                          &next_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (next_field_clang_type.IsIntegerType (is_signed)) +                                if (next_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -882,12 +840,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl                              else                              {                                  uint64_t prev_field_bit_offset = 0; -                                ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, +                                CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,                                                                                                          name,                                                                                                          &prev_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (prev_field_clang_type.IsIntegerType (is_signed)) +                                if (prev_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -946,7 +904,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl              {                  // The result is in our data buffer.  Let's make a variable object out of it:                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                   return_clang_type, +                                                                   return_compiler_type,                                                                     ConstString(""),                                                                     return_ext);              } @@ -965,7 +923,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl              return_valobj_sp = ValueObjectMemory::Create (&thread,                                                            "",                                                            Address (storage_addr, NULL), -                                                          return_clang_type); +                                                          return_compiler_type);          }      } @@ -978,9 +936,9 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t lr_reg_num = gcc_dwarf_lr; -    uint32_t sp_reg_num = gcc_dwarf_r1; -    uint32_t pc_reg_num = gcc_dwarf_pc; +    uint32_t lr_reg_num = dwarf_lr; +    uint32_t sp_reg_num = dwarf_r1; +    uint32_t pc_reg_num = dwarf_pc;      UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +963,8 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t sp_reg_num = gcc_dwarf_r1; -    uint32_t pc_reg_num = gcc_dwarf_lr; +    uint32_t sp_reg_num = dwarf_r1; +    uint32_t pc_reg_num = dwarf_lr;      UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1015,13 +973,13 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);      row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); -    row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true); +    row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true);      unwind_plan.AppendRow (row);      unwind_plan.SetSourceName ("ppc64 default unwind plan");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);      unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); -    unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); +    unwind_plan.SetReturnAddressRegister(dwarf_lr);      return true;  } diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h index d77cb9f1efe3b..b87f7938d5449 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -21,52 +21,37 @@ class ABISysV_ppc64 :      public lldb_private::ABI  {  public: +    ~ABISysV_ppc64() override = default; -    ~ABISysV_ppc64() -    { -    } +    size_t +    GetRedZoneSize() const override; -    virtual size_t -    GetRedZoneSize () const; - -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; -     -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); -     -    virtual bool -    StackUsesFrames () -    { -        return true; -    } +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The SysV ppc64 ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // We have a 64 bit address space, so anything is valid as opcodes          // aren't fixed width...          return true;      } -    virtual bool -    FunctionCallsChangeCFA () -    { -        return true; -    } +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count);      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -123,21 +104,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void      CreateRegisterMapIfNeeded (); +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; +          bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_ppc64() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc64_h_ diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 1d63628466c23..11e383d269c3e 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -20,7 +20,6 @@  #include "lldb/Core/ValueObjectConstResult.h"  #include "lldb/Core/ValueObjectRegister.h"  #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h"  #include "lldb/Symbol/UnwindPlan.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/Process.h" @@ -34,222 +33,144 @@  using namespace lldb;  using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums  { -    gcc_dwarf_rax = 0, -    gcc_dwarf_rdx, -    gcc_dwarf_rcx, -    gcc_dwarf_rbx, -    gcc_dwarf_rsi, -    gcc_dwarf_rdi, -    gcc_dwarf_rbp, -    gcc_dwarf_rsp, -    gcc_dwarf_r8, -    gcc_dwarf_r9, -    gcc_dwarf_r10, -    gcc_dwarf_r11, -    gcc_dwarf_r12, -    gcc_dwarf_r13, -    gcc_dwarf_r14, -    gcc_dwarf_r15, -    gcc_dwarf_rip, -    gcc_dwarf_xmm0, -    gcc_dwarf_xmm1, -    gcc_dwarf_xmm2, -    gcc_dwarf_xmm3, -    gcc_dwarf_xmm4, -    gcc_dwarf_xmm5, -    gcc_dwarf_xmm6, -    gcc_dwarf_xmm7, -    gcc_dwarf_xmm8, -    gcc_dwarf_xmm9, -    gcc_dwarf_xmm10, -    gcc_dwarf_xmm11, -    gcc_dwarf_xmm12, -    gcc_dwarf_xmm13, -    gcc_dwarf_xmm14, -    gcc_dwarf_xmm15, -    gcc_dwarf_stmm0, -    gcc_dwarf_stmm1, -    gcc_dwarf_stmm2, -    gcc_dwarf_stmm3, -    gcc_dwarf_stmm4, -    gcc_dwarf_stmm5, -    gcc_dwarf_stmm6, -    gcc_dwarf_stmm7, -    gcc_dwarf_ymm0, -    gcc_dwarf_ymm1, -    gcc_dwarf_ymm2, -    gcc_dwarf_ymm3, -    gcc_dwarf_ymm4, -    gcc_dwarf_ymm5, -    gcc_dwarf_ymm6, -    gcc_dwarf_ymm7, -    gcc_dwarf_ymm8, -    gcc_dwarf_ymm9, -    gcc_dwarf_ymm10, -    gcc_dwarf_ymm11, -    gcc_dwarf_ymm12, -    gcc_dwarf_ymm13, -    gcc_dwarf_ymm14, -    gcc_dwarf_ymm15 +    dwarf_rax = 0, +    dwarf_rdx, +    dwarf_rcx, +    dwarf_rbx, +    dwarf_rsi, +    dwarf_rdi, +    dwarf_rbp, +    dwarf_rsp, +    dwarf_r8, +    dwarf_r9, +    dwarf_r10, +    dwarf_r11, +    dwarf_r12, +    dwarf_r13, +    dwarf_r14, +    dwarf_r15, +    dwarf_rip, +    dwarf_xmm0, +    dwarf_xmm1, +    dwarf_xmm2, +    dwarf_xmm3, +    dwarf_xmm4, +    dwarf_xmm5, +    dwarf_xmm6, +    dwarf_xmm7, +    dwarf_xmm8, +    dwarf_xmm9, +    dwarf_xmm10, +    dwarf_xmm11, +    dwarf_xmm12, +    dwarf_xmm13, +    dwarf_xmm14, +    dwarf_xmm15, +    dwarf_stmm0, +    dwarf_stmm1, +    dwarf_stmm2, +    dwarf_stmm3, +    dwarf_stmm4, +    dwarf_stmm5, +    dwarf_stmm6, +    dwarf_stmm7, +    dwarf_ymm0, +    dwarf_ymm1, +    dwarf_ymm2, +    dwarf_ymm3, +    dwarf_ymm4, +    dwarf_ymm5, +    dwarf_ymm6, +    dwarf_ymm7, +    dwarf_ymm8, +    dwarf_ymm9, +    dwarf_ymm10, +    dwarf_ymm11, +    dwarf_ymm12, +    dwarf_ymm13, +    dwarf_ymm14, +    dwarf_ymm15  }; -enum gdb_regnums -{ -    gdb_rax     =   0, -    gdb_rbx     =   1, -    gdb_rcx     =   2, -    gdb_rdx     =   3, -    gdb_rsi     =   4, -    gdb_rdi     =   5, -    gdb_rbp     =   6, -    gdb_rsp     =   7, -    gdb_r8      =   8, -    gdb_r9      =   9, -    gdb_r10     =  10, -    gdb_r11     =  11, -    gdb_r12     =  12, -    gdb_r13     =  13, -    gdb_r14     =  14, -    gdb_r15     =  15, -    gdb_rip     =  16, -    gdb_rflags  =  17, -    gdb_cs      =  18, -    gdb_ss      =  19, -    gdb_ds      =  20, -    gdb_es      =  21, -    gdb_fs      =  22, -    gdb_gs      =  23, -    gdb_stmm0   =  24, -    gdb_stmm1   =  25, -    gdb_stmm2   =  26, -    gdb_stmm3   =  27, -    gdb_stmm4   =  28, -    gdb_stmm5   =  29, -    gdb_stmm6   =  30, -    gdb_stmm7   =  31, -    gdb_fctrl   =  32,  gdb_fcw = gdb_fctrl, -    gdb_fstat   =  33,  gdb_fsw = gdb_fstat, -    gdb_ftag    =  34,  gdb_ftw = gdb_ftag, -    gdb_fiseg   =  35,  gdb_fpu_cs  = gdb_fiseg, -    gdb_fioff   =  36,  gdb_ip  = gdb_fioff, -    gdb_foseg   =  37,  gdb_fpu_ds  = gdb_foseg, -    gdb_fooff   =  38,  gdb_dp  = gdb_fooff, -    gdb_fop     =  39, -    gdb_xmm0    =  40, -    gdb_xmm1    =  41, -    gdb_xmm2    =  42, -    gdb_xmm3    =  43, -    gdb_xmm4    =  44, -    gdb_xmm5    =  45, -    gdb_xmm6    =  46, -    gdb_xmm7    =  47, -    gdb_xmm8    =  48, -    gdb_xmm9    =  49, -    gdb_xmm10   =  50, -    gdb_xmm11   =  51, -    gdb_xmm12   =  52, -    gdb_xmm13   =  53, -    gdb_xmm14   =  54, -    gdb_xmm15   =  55, -    gdb_mxcsr   =  56, -    gdb_ymm0    =  57, -    gdb_ymm1    =  58, -    gdb_ymm2    =  59, -    gdb_ymm3    =  60, -    gdb_ymm4    =  61, -    gdb_ymm5    =  62, -    gdb_ymm6    =  63, -    gdb_ymm7    =  64, -    gdb_ymm8    =  65, -    gdb_ymm9    =  66, -    gdb_ymm10   =  67, -    gdb_ymm11   =  68, -    gdb_ymm12   =  69, -    gdb_ymm13   =  70, -    gdb_ymm14   =  71, -    gdb_ymm15   =  72 -}; - -  static RegisterInfo g_register_infos[] =   { -  //  NAME      ALT      SZ OFF ENCODING         FORMAT              COMPILER                DWARF                 GENERIC                     GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS +  //  NAME      ALT      SZ OFF ENCODING         FORMAT              EH_FRAME                DWARF                 GENERIC                     PROCESS PLUGIN        LLDB NATIVE            VALUE REGS    INVALIDATE REGS    //  ========  =======  == === =============    =================== ======================= ===================== =========================== ===================== ====================== ==========    =============== -    { "rax"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rax       , gcc_dwarf_rax       , LLDB_INVALID_REGNUM       , gdb_rax            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rbx"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rbx       , gcc_dwarf_rbx       , LLDB_INVALID_REGNUM       , gdb_rbx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rcx"   , "arg4",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rcx       , gcc_dwarf_rcx       , LLDB_REGNUM_GENERIC_ARG4  , gdb_rcx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rdx"   , "arg3",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rdx       , gcc_dwarf_rdx       , LLDB_REGNUM_GENERIC_ARG3  , gdb_rdx            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rsi"   , "arg2",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rsi       , gcc_dwarf_rsi       , LLDB_REGNUM_GENERIC_ARG2  , gdb_rsi            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rdi"   , "arg1",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rdi       , gcc_dwarf_rdi       , LLDB_REGNUM_GENERIC_ARG1  , gdb_rdi            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rbp"   , "fp",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rbp       , gcc_dwarf_rbp       , LLDB_REGNUM_GENERIC_FP    , gdb_rbp            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rsp"   , "sp",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rsp       , gcc_dwarf_rsp       , LLDB_REGNUM_GENERIC_SP    , gdb_rsp            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r8"    , "arg5",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r8        , gcc_dwarf_r8        , LLDB_REGNUM_GENERIC_ARG5  , gdb_r8             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r9"    , "arg6",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r9        , gcc_dwarf_r9        , LLDB_REGNUM_GENERIC_ARG6  , gdb_r9             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r10"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r10       , gcc_dwarf_r10       , LLDB_INVALID_REGNUM       , gdb_r10            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r11"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r11       , gcc_dwarf_r11       , LLDB_INVALID_REGNUM       , gdb_r11            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r12"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r12       , gcc_dwarf_r12       , LLDB_INVALID_REGNUM       , gdb_r12            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r13"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r13       , gcc_dwarf_r13       , LLDB_INVALID_REGNUM       , gdb_r13            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r14"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r14       , gcc_dwarf_r14       , LLDB_INVALID_REGNUM       , gdb_r14            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "r15"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r15       , gcc_dwarf_r15       , LLDB_INVALID_REGNUM       , gdb_r15            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rip"   , "pc",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rip       , gcc_dwarf_rip       , LLDB_REGNUM_GENERIC_PC    , gdb_rip            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "rflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags         , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0     , gcc_dwarf_stmm0     , LLDB_INVALID_REGNUM       , gdb_stmm0          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1     , gcc_dwarf_stmm1     , LLDB_INVALID_REGNUM       , gdb_stmm1          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2     , gcc_dwarf_stmm2     , LLDB_INVALID_REGNUM       , gdb_stmm2          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3     , gcc_dwarf_stmm3     , LLDB_INVALID_REGNUM       , gdb_stmm3          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4     , gcc_dwarf_stmm4     , LLDB_INVALID_REGNUM       , gdb_stmm4          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5     , gcc_dwarf_stmm5     , LLDB_INVALID_REGNUM       , gdb_stmm5          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6     , gcc_dwarf_stmm6     , LLDB_INVALID_REGNUM       , gdb_stmm6          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7     , gcc_dwarf_stmm7     , LLDB_INVALID_REGNUM       , gdb_stmm7          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0      , gcc_dwarf_xmm0      , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1      , gcc_dwarf_xmm1      , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2      , gcc_dwarf_xmm2      , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3      , gcc_dwarf_xmm3      , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4      , gcc_dwarf_xmm4      , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5      , gcc_dwarf_xmm5      , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6      , gcc_dwarf_xmm6      , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7      , gcc_dwarf_xmm7      , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm8"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8      , gcc_dwarf_xmm8      , LLDB_INVALID_REGNUM       , gdb_xmm8           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm9"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9      , gcc_dwarf_xmm9      , LLDB_INVALID_REGNUM       , gdb_xmm9           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm10" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10     , gcc_dwarf_xmm10     , LLDB_INVALID_REGNUM       , gdb_xmm10          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm11" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11     , gcc_dwarf_xmm11     , LLDB_INVALID_REGNUM       , gdb_xmm11          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm12" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12     , gcc_dwarf_xmm12     , LLDB_INVALID_REGNUM       , gdb_xmm12          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm13" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13     , gcc_dwarf_xmm13     , LLDB_INVALID_REGNUM       , gdb_xmm13          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm14" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14     , gcc_dwarf_xmm14     , LLDB_INVALID_REGNUM       , gdb_xmm14          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "xmm15" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15     , gcc_dwarf_xmm15     , LLDB_INVALID_REGNUM       , gdb_xmm15          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0      , gcc_dwarf_ymm0      , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1      , gcc_dwarf_ymm1      , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2      , gcc_dwarf_ymm2      , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3      , gcc_dwarf_ymm3      , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4      , gcc_dwarf_ymm4      , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5      , gcc_dwarf_ymm5      , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6      , gcc_dwarf_ymm6      , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7      , gcc_dwarf_ymm7      , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm8"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8      , gcc_dwarf_ymm8      , LLDB_INVALID_REGNUM       , gdb_ymm8           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm9"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9      , gcc_dwarf_ymm9      , LLDB_INVALID_REGNUM       , gdb_ymm9           , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm10" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10     , gcc_dwarf_ymm10     , LLDB_INVALID_REGNUM       , gdb_ymm10          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm11" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11     , gcc_dwarf_ymm11     , LLDB_INVALID_REGNUM       , gdb_ymm11          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm12" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12     , gcc_dwarf_ymm12     , LLDB_INVALID_REGNUM       , gdb_ymm12          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm13" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13     , gcc_dwarf_ymm13     , LLDB_INVALID_REGNUM       , gdb_ymm13          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm14" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14     , gcc_dwarf_ymm14     , LLDB_INVALID_REGNUM       , gdb_ymm14          , LLDB_INVALID_REGNUM },      NULL,              NULL}, -    { "ymm15" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15     , gcc_dwarf_ymm15     , LLDB_INVALID_REGNUM       , gdb_ymm15          , LLDB_INVALID_REGNUM },      NULL,              NULL} +    { "rax"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rax       ,     dwarf_rax       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rbx"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rbx       ,     dwarf_rbx       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rcx"   , "arg4",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rcx       ,     dwarf_rcx       , LLDB_REGNUM_GENERIC_ARG4  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rdx"   , "arg3",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rdx       ,     dwarf_rdx       , LLDB_REGNUM_GENERIC_ARG3  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rsi"   , "arg2",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rsi       ,     dwarf_rsi       , LLDB_REGNUM_GENERIC_ARG2  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rdi"   , "arg1",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rdi       ,     dwarf_rdi       , LLDB_REGNUM_GENERIC_ARG1  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rbp"   , "fp",    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rbp       ,     dwarf_rbp       , LLDB_REGNUM_GENERIC_FP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rsp"   , "sp",    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rsp       ,     dwarf_rsp       , LLDB_REGNUM_GENERIC_SP    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r8"    , "arg5",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r8        ,     dwarf_r8        , LLDB_REGNUM_GENERIC_ARG5  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r9"    , "arg6",  8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r9        ,     dwarf_r9        , LLDB_REGNUM_GENERIC_ARG6  , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r10"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r10       ,     dwarf_r10       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r11"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r11       ,     dwarf_r11       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r12"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r12       ,     dwarf_r12       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r13"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r13       ,     dwarf_r13       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r14"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r14       ,     dwarf_r14       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "r15"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_r15       ,     dwarf_r15       , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rip"   , "pc",    8,  0, eEncodingUint  , eFormatHex          , {     dwarf_rip       ,     dwarf_rip       , LLDB_REGNUM_GENERIC_PC    , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "rflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm0     ,     dwarf_stmm0     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm1     ,     dwarf_stmm1     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm2     ,     dwarf_stmm2     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm3     ,     dwarf_stmm3     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm4     ,     dwarf_stmm4     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm5     ,     dwarf_stmm5     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm6     ,     dwarf_stmm6     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_stmm7     ,     dwarf_stmm7     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm0      ,     dwarf_xmm0      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm1      ,     dwarf_xmm1      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm2      ,     dwarf_xmm2      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm3      ,     dwarf_xmm3      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm4      ,     dwarf_xmm4      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm5      ,     dwarf_xmm5      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm6      ,     dwarf_xmm6      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm7      ,     dwarf_xmm7      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm8"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm8      ,     dwarf_xmm8      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm9"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm9      ,     dwarf_xmm9      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm10" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm10     ,     dwarf_xmm10     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm11" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm11     ,     dwarf_xmm11     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm12" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm12     ,     dwarf_xmm12     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm13" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm13     ,     dwarf_xmm13     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm14" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm14     ,     dwarf_xmm14     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "xmm15" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_xmm15     ,     dwarf_xmm15     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm0      ,     dwarf_ymm0      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm1      ,     dwarf_ymm1      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm2      ,     dwarf_ymm2      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm3      ,     dwarf_ymm3      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm4      ,     dwarf_ymm4      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm5      ,     dwarf_ymm5      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm6      ,     dwarf_ymm6      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm7      ,     dwarf_ymm7      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm8"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm8      ,     dwarf_ymm8      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm9"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm9      ,     dwarf_ymm9      , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm10" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm10     ,     dwarf_ymm10     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm11" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm11     ,     dwarf_ymm11     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm12" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm12     ,     dwarf_ymm12     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm13" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm13     ,     dwarf_ymm13     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm14" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm14     ,     dwarf_ymm14     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}, +    { "ymm15" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, {     dwarf_ymm15     ,     dwarf_ymm15     , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM },      NULL,              NULL}  };  static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -502,25 +423,25 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,          // We currently only support extracting values with Clang QualTypes.          // Do we care about others? -        ClangASTType clang_type = value->GetClangType(); -        if (!clang_type) +        CompilerType compiler_type = value->GetCompilerType(); +        if (!compiler_type)              return false;          bool is_signed; -        if (clang_type.IsIntegerType (is_signed)) +        if (compiler_type.IsIntegerType (is_signed))          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  is_signed,                                  thread,                                   argument_register_ids,                                   current_argument_register,                                  current_stack_argument);          } -        else if (clang_type.IsPointerType ()) +        else if (compiler_type.IsPointerType ())          {              ReadIntegerArgument(value->GetScalar(), -                                clang_type.GetBitSize(&thread), +                                compiler_type.GetBitSize(&thread),                                  false,                                  thread,                                  argument_register_ids,  @@ -542,8 +463,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb          return error;      } -    ClangASTType clang_type = new_value_sp->GetClangType(); -    if (!clang_type) +    CompilerType compiler_type = new_value_sp->GetCompilerType(); +    if (!compiler_type)      {          error.SetErrorString ("Null clang type for return value.");          return error; @@ -558,7 +479,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb      RegisterContext *reg_ctx = thread->GetRegisterContext().get();      bool set_it_simple = false; -    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) +    if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())      {          const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0); @@ -584,13 +505,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb          }      } -    else if (clang_type.IsFloatingPointType (count, is_complex)) +    else if (compiler_type.IsFloatingPointType (count, is_complex))      {          if (is_complex)              error.SetErrorString ("We don't support returning complex values at present");          else          { -            size_t bit_width = clang_type.GetBitSize(frame_sp.get()); +            size_t bit_width = compiler_type.GetBitSize(frame_sp.get());              if (bit_width <= 64)              {                  const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -633,22 +554,22 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb  ValueObjectSP  ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, -                                            ClangASTType &return_clang_type) const +                                            CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp;      Value value; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      //value.SetContext (Value::eContextTypeClangType, return_value_type); -    value.SetClangType (return_clang_type); +    value.SetCompilerType (return_compiler_type);      RegisterContext *reg_ctx = thread.GetRegisterContext().get();      if (!reg_ctx)          return return_valobj_sp; -    const uint32_t type_flags = return_clang_type.GetTypeInfo (); +    const uint32_t type_flags = return_compiler_type.GetTypeInfo ();      if (type_flags & eTypeIsScalar)      {          value.SetValueType(Value::eValueTypeScalar); @@ -658,7 +579,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,          {              // Extract the register context so we can read arguments from registers -            const size_t byte_size = return_clang_type.GetByteSize(nullptr); +            const size_t byte_size = return_compiler_type.GetByteSize(nullptr);              uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);              const bool is_signed = (type_flags & eTypeIsSigned) != 0;              switch (byte_size) @@ -707,7 +628,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,              }              else              { -                const size_t byte_size = return_clang_type.GetByteSize(nullptr); +                const size_t byte_size = return_compiler_type.GetByteSize(nullptr);                  if (byte_size <= sizeof(long double))                  {                      const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -755,18 +676,13 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,      }      else if (type_flags & eTypeIsVector)      { -        const size_t byte_size = return_clang_type.GetByteSize(nullptr); +        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);          if (byte_size > 0)          { +            const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); +            if (altivec_reg == nullptr) +                altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); -            const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); -            if (altivec_reg == NULL) -            { -                altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); -                if (altivec_reg == NULL) -                    altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); -            } -                          if (altivec_reg)              {                  if (byte_size <= altivec_reg->byte_size) @@ -790,13 +706,52 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,                                                      byte_order,                                                      process_sp->GetTarget().GetArchitecture().GetAddressByteSize());                                  return_valobj_sp = ValueObjectConstResult::Create (&thread, -                                                                                   return_clang_type, +                                                                                   return_compiler_type,                                                                                     ConstString(""),                                                                                     data);                              }                          }                      }                  } +                else if (byte_size <= altivec_reg->byte_size*2) +                { +                    const RegisterInfo *altivec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0); +                    if (altivec_reg2) +                    { +                        ProcessSP process_sp (thread.GetProcess()); +                        if (process_sp) +                        { +                            std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); +                            const ByteOrder byte_order = process_sp->GetByteOrder(); +                            RegisterValue reg_value; +                            RegisterValue reg_value2; +                            if (reg_ctx->ReadRegister(altivec_reg, reg_value) && reg_ctx->ReadRegister(altivec_reg2, reg_value2)) +                            { + +                                Error error; +                                if (reg_value.GetAsMemoryData (altivec_reg, +                                                               heap_data_ap->GetBytes(), +                                                               altivec_reg->byte_size, +                                                               byte_order, +                                                               error) && +                                    reg_value2.GetAsMemoryData (altivec_reg2, +                                                               heap_data_ap->GetBytes() + altivec_reg->byte_size, +                                                               heap_data_ap->GetByteSize() - altivec_reg->byte_size, +                                                               byte_order, +                                                               error)) +                                { +                                    DataExtractor data (DataBufferSP (heap_data_ap.release()), +                                                        byte_order, +                                                        process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); +                                    return_valobj_sp = ValueObjectConstResult::Create (&thread, +                                                                                       return_compiler_type, +                                                                                       ConstString(""), +                                                                                       data); +                                } +                            } +                        } +                    } +                }              }          }      } @@ -805,15 +760,15 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,  }  ValueObjectSP -ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const  {      ValueObjectSP return_valobj_sp; -    if (!return_clang_type) +    if (!return_compiler_type)          return return_valobj_sp;      ExecutionContext exe_ctx (thread.shared_from_this()); -    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); +    return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);      if (return_valobj_sp)          return return_valobj_sp; @@ -821,8 +776,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c      if (!reg_ctx_sp)          return return_valobj_sp; -    const size_t bit_width = return_clang_type.GetBitSize(&thread); -    if (return_clang_type.IsAggregateType()) +    const size_t bit_width = return_compiler_type.GetBitSize(&thread); +    if (return_compiler_type.IsAggregateType())      {          Target *target = exe_ctx.GetTargetPtr();          bool is_memory = true; @@ -855,7 +810,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c              uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far              uint32_t integer_bytes = 0;  // Tracks how much of the rax/rds registers we've consumed so far -            const uint32_t num_children = return_clang_type.GetNumFields (); +            const uint32_t num_children = return_compiler_type.GetNumFields ();              // Since we are in the small struct regime, assume we are not in memory.              is_memory = false; @@ -868,8 +823,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                  bool is_complex;                  uint32_t count; -                ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); -                const size_t field_bit_width = field_clang_type.GetBitSize(&thread); +                CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); +                const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);                  // if we don't know the size of the field (e.g. invalid type), just bail out                  if (field_bit_width == 0) @@ -889,7 +844,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                  DataExtractor *copy_from_extractor = NULL;                  uint32_t       copy_from_offset    = 0; -                if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) +                if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())                  {                      if (integer_bytes < 8)                      { @@ -922,7 +877,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                          return return_valobj_sp;                      }                  } -                else if (field_clang_type.IsFloatingPointType (count, is_complex)) +                else if (field_compiler_type.IsFloatingPointType (count, is_complex))                  {                      // Structs with long doubles are always passed in memory.                      if (field_bit_width == 128) @@ -955,12 +910,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                              else                              {                                  uint64_t next_field_bit_offset = 0; -                                ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, +                                CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,                                                                                                          name,                                                                                                          &next_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (next_field_clang_type.IsIntegerType (is_signed)) +                                if (next_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -979,12 +934,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c                              else                              {                                  uint64_t prev_field_bit_offset = 0; -                                ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, +                                CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,                                                                                                          name,                                                                                                          &prev_field_bit_offset,                                                                                                          NULL,                                                                                                          NULL); -                                if (prev_field_clang_type.IsIntegerType (is_signed)) +                                if (prev_field_compiler_type.IsIntegerType (is_signed))                                      in_gpr = true;                                  else                                  { @@ -1048,7 +1003,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c              {                  // The result is in our data buffer.  Let's make a variable object out of it:                  return_valobj_sp = ValueObjectConstResult::Create (&thread,  -                                                                   return_clang_type, +                                                                   return_compiler_type,                                                                     ConstString(""),                                                                     return_ext);              } @@ -1067,7 +1022,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c              return_valobj_sp = ValueObjectMemory::Create (&thread,                                                            "",                                                            Address (storage_addr, NULL), -                                                          return_clang_type);  +                                                          return_compiler_type);          }      } @@ -1084,8 +1039,8 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t sp_reg_num = gcc_dwarf_rsp; -    uint32_t pc_reg_num = gcc_dwarf_rip; +    uint32_t sp_reg_num = dwarf_rsp; +    uint32_t pc_reg_num = dwarf_rip;      UnwindPlan::RowSP row(new UnwindPlan::Row);      row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8); @@ -1108,14 +1063,14 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)      unwind_plan.Clear();      unwind_plan.SetRegisterKind (eRegisterKindDWARF); -    uint32_t fp_reg_num = gcc_dwarf_rbp; -    uint32_t sp_reg_num = gcc_dwarf_rsp; -    uint32_t pc_reg_num = gcc_dwarf_rip; +    uint32_t fp_reg_num = dwarf_rbp; +    uint32_t sp_reg_num = dwarf_rsp; +    uint32_t pc_reg_num = dwarf_rip;      UnwindPlan::RowSP row(new UnwindPlan::Row);      const int32_t ptr_size = 8; -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);      row->SetOffset (0);      row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index 6fefcc2a9c747..07b57abaf57cd 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -21,46 +21,37 @@ class ABISysV_x86_64 :      public lldb_private::ABI  {  public: +    ~ABISysV_x86_64() override = default; -    ~ABISysV_x86_64() -    { -    } - -    virtual size_t -    GetRedZoneSize () const; +    size_t +    GetRedZoneSize() const override; -    virtual 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; +    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; -    virtual bool -    GetArgumentValues (lldb_private::Thread &thread, -                       lldb_private::ValueList &values) const; +    bool +    GetArgumentValues(lldb_private::Thread &thread, +                      lldb_private::ValueList &values) const override; -    virtual lldb_private::Error -    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); +    lldb_private::Error +    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected:      lldb::ValueObjectSP -    GetReturnValueObjectSimple (lldb_private::Thread &thread, -                                lldb_private::ClangASTType &ast_type) const; -     -public:     -    virtual lldb::ValueObjectSP -    GetReturnValueObjectImpl (lldb_private::Thread &thread, -                          lldb_private::ClangASTType &type) const; +    GetReturnValueObjectImpl(lldb_private::Thread &thread, +                             lldb_private::CompilerType &type) const override; -    virtual bool -    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; -    virtual bool -    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); +    bool +    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;      // The SysV x86_64 ABI requires that stack frames be 16 byte aligned.      // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public:      // Whitelisting the trap handlers for user space would be easy (_sigtramp) but      // in other environments there can be a large number of different functions      // involved in async traps. -    virtual bool -    CallFrameAddressIsValid (lldb::addr_t cfa) +    bool +    CallFrameAddressIsValid(lldb::addr_t cfa) override      {          // Make sure the stack call frame addresses are 8 byte aligned          if (cfa & (8ull - 1ull)) @@ -83,19 +74,21 @@ public:          return true;      } -    virtual bool -    CodeAddressIsValid (lldb::addr_t pc) +    bool +    CodeAddressIsValid(lldb::addr_t pc) override      {          // We have a 64 bit address space, so anything is valid as opcodes          // aren't fixed width...          return true;      } -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoArray (uint32_t &count); +    const lldb_private::RegisterInfo * +    GetRegisterInfoArray(uint32_t &count) override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ +      static void      Initialize(); @@ -111,21 +104,30 @@ public:      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override;  protected:      void      CreateRegisterMapIfNeeded (); +    lldb::ValueObjectSP +    GetReturnValueObjectSimple(lldb_private::Thread &thread, +                               lldb_private::CompilerType &ast_type) const; +      bool      RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);  private: -    ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead. +    ABISysV_x86_64() :  +        lldb_private::ABI()  +    { +         // Call CreateInstance instead. +    }  }; -#endif  // liblldb_ABI_h_ +#endif // liblldb_ABISysV_x86_64_h_ diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index d20219f6d1eb6..6d124b689341f 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -7,8 +7,9 @@  //  //===----------------------------------------------------------------------===// -#include "DisassemblerLLVMC.h" - +// C Includes +// C++ Includes +// Project includes  #include "llvm-c/Disassembler.h"  #include "llvm/MC/MCAsmInfo.h"  #include "llvm/MC/MCContext.h" @@ -25,6 +26,8 @@  #include "llvm/Support/TargetSelect.h"  #include "llvm/ADT/SmallString.h" +// Other libraries and framework includes +#include "DisassemblerLLVMC.h"  #include "lldb/Core/Address.h"  #include "lldb/Core/DataExtractor.h" @@ -52,18 +55,16 @@ public:          Instruction (address, addr_class),          m_disasm_sp (disasm.shared_from_this()),          m_does_branch (eLazyBoolCalculate), +        m_has_delay_slot (eLazyBoolCalculate),          m_is_valid (false),          m_using_file_addr (false)      {      } -    virtual -    ~InstructionLLVMC () -    { -    } +    ~InstructionLLVMC() override = default; -    virtual bool -    DoesBranch () +    bool +    DoesBranch() override      {          if (m_does_branch == eLazyBoolCalculate)          { @@ -99,6 +100,43 @@ public:          return m_does_branch == eLazyBoolYes;      } +    bool +    HasDelaySlot() override +    { +        if (m_has_delay_slot == eLazyBoolCalculate) +        { +            GetDisassemblerLLVMC().Lock(this, NULL); +            DataExtractor data; +            if (m_opcode.GetData(data)) +            { +                bool is_alternate_isa; +                lldb::addr_t pc = m_address.GetFileAddress(); + +                DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); +                const uint8_t *opcode_data = data.GetDataStart(); +                const size_t opcode_data_len = data.GetByteSize(); +                llvm::MCInst inst; +                const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, +                                                                   opcode_data_len, +                                                                   pc, +                                                                   inst); +                // if we didn't understand the instruction, say it doesn't have a delay slot... +                if (inst_size == 0) +                    m_has_delay_slot = eLazyBoolNo; +                else +                { +                    const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); +                    if (has_delay_slot) +                        m_has_delay_slot = eLazyBoolYes; +                    else +                        m_has_delay_slot = eLazyBoolNo; +                } +            } +            GetDisassemblerLLVMC().Unlock(); +        } +        return m_has_delay_slot == eLazyBoolYes; +    } +      DisassemblerLLVMC::LLVMCDisassembler *      GetDisasmToUse (bool &is_alternate_isa)      { @@ -117,10 +155,10 @@ public:          return llvm_disasm.m_disasm_ap.get();      } -    virtual size_t -    Decode (const lldb_private::Disassembler &disassembler, -            const lldb_private::DataExtractor &data, -            lldb::offset_t data_offset) +    size_t +    Decode(const lldb_private::Disassembler &disassembler, +           const lldb_private::DataExtractor &data, +           lldb::offset_t data_offset) override      {          // All we have to do is read the opcode which can be easy for some          // architectures @@ -234,15 +272,16 @@ public:          }      } -    virtual void -    CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) +    void +    CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override      {          DataExtractor data;          const AddressClass address_class = GetAddressClass ();          if (m_opcode.GetData(data))          { -            char out_string[512]; +            std::string out_string; +            std::string comment_string;              DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); @@ -293,7 +332,12 @@ public:              if (inst_size > 0)              {                  mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); -                mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); +                mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); +                 +                if (!comment_string.empty()) +                { +                    AppendComment(comment_string); +                }              }              llvm_disasm.Unlock(); @@ -375,10 +419,10 @@ public:              RegularExpression::Match matches(3); -            if (s_regex.Execute(out_string, &matches)) +            if (s_regex.Execute(out_string.c_str(), &matches))              { -                matches.GetMatchAtIndex(out_string, 1, m_opcode_name); -                matches.GetMatchAtIndex(out_string, 2, m_mnemonics); +                matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); +                matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics);              }          }      } @@ -409,12 +453,11 @@ protected:      DisassemblerSP          m_disasm_sp; // for ownership      LazyBool                m_does_branch; +    LazyBool                m_has_delay_slot;      bool                    m_is_valid;      bool                    m_using_file_addr;  }; - -  DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner):      m_is_valid(true)  { @@ -482,9 +525,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con          m_is_valid = false;  } -DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() -{ -} +DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;  uint64_t  DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, @@ -508,22 +549,25 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,          return 0;  } -uint64_t +void  DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, -                                                   char *dst, -                                                   size_t dst_len) +                                                   std::string &inst_string, +                                                   std::string &comments_string)  { -    llvm::StringRef unused_annotations; -    llvm::SmallString<64> inst_string; -    llvm::raw_svector_ostream inst_stream(inst_string); -    m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations, -                                   *m_subtarget_info_ap); -    inst_stream.flush(); -    const size_t output_size = std::min(dst_len - 1, inst_string.size()); -    std::memcpy(dst, inst_string.data(), output_size); -    dst[output_size] = '\0'; - -    return output_size; +    llvm::raw_string_ostream inst_stream(inst_string); +    llvm::raw_string_ostream comments_stream(comments_string); + +    m_instr_printer_ap->setCommentStream(comments_stream); +    m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap); +    m_instr_printer_ap->setCommentStream(llvm::nulls()); +    comments_stream.flush(); +     +    static std::string g_newlines("\r\n"); +     +    for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/) +    { +        comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' '); +    }  }  void @@ -544,35 +588,9 @@ DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)  }  bool -DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst)  { -    llvm::Triple triple = arch.GetTriple(); -    if (flavor == NULL || strcmp (flavor, "default") == 0) -        return true; - -    if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) -    { -        if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) -            return true; -        else -            return false; -    } -    else -        return false; -} - - -Disassembler * -DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) -{ -    if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) -    { -        std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor)); - -        if (disasm_ap.get() && disasm_ap->IsValid()) -            return disasm_ap.release(); -    } -    return NULL; +    return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();  }  DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) : @@ -586,13 +604,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s          m_flavor.assign("default");      } -    const char *triple = arch.GetTriple().getTriple().c_str();      unsigned flavor = ~0U; +    llvm::Triple triple = arch.GetTriple();      // So far the only supported flavor is "intel" on x86.  The base class will set this      // correctly coming in. -    if (arch.GetTriple().getArch() == llvm::Triple::x86 -        || arch.GetTriple().getArch() == llvm::Triple::x86_64) +    if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)      {          if (m_flavor == "intel")          { @@ -605,7 +622,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s      }      ArchSpec thumb_arch(arch); -    if (arch.GetTriple().getArch() == llvm::Triple::arm) +    if (triple.getArch() == llvm::Triple::arm)      {          std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());          // Replace "arm" with "thumb" so we get all thumb variants correct @@ -621,18 +638,29 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s          thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));      } +    // If no sub architecture specified then use the most recent arm architecture so the +    // disassembler will return all instruction. Without it we will see a lot of unknow opcode +    // in case the code uses instructions which are not available in the oldest arm version +    // (used when no sub architecture is specified) +    if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch) +        triple.setArchName("armv8.1a"); + +    const char *triple_str = triple.getTriple().c_str(); + +    // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization +    //       // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,      // so hardcode the primary disassembler to thumb mode.  Same for Cortex-M4 (armv7em).      //      // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32      // instructions defined in ARMv7-A. -    if (arch.GetTriple().getArch() == llvm::Triple::arm +    if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb)          && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m              || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em              || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))      { -        triple = thumb_arch.GetTriple().getTriple().c_str(); +        triple_str = thumb_arch.GetTriple().getTriple().c_str();      }      const char *cpu = ""; @@ -674,8 +702,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s      }      std::string features_str = ""; -    if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel -        || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) +    if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel +        || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el)      {          uint32_t arch_flags = arch.GetFlags ();          if (arch_flags & ArchSpec::eMIPSAse_msa) @@ -684,13 +712,9 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s              features_str += "+dsp,";          if (arch_flags & ArchSpec::eMIPSAse_dspr2)              features_str += "+dspr2,"; -        if (arch_flags & ArchSpec::eMIPSAse_mips16) -            features_str += "+mips16,"; -        if (arch_flags & ArchSpec::eMIPSAse_micromips) -            features_str += "+micromips,";      } -    m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this)); +    m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this));      if (!m_disasm_ap->IsValid())      {          // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, @@ -698,8 +722,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s          m_disasm_ap.reset();      } +    llvm::Triple::ArchType llvm_arch = triple.getArch(); +      // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler. -    if (arch.GetTriple().getArch() == llvm::Triple::arm) +    if (llvm_arch == llvm::Triple::arm)      {          std::string thumb_triple(thumb_arch.GetTriple().getTriple());          m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); @@ -709,10 +735,40 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s              m_alternate_disasm_ap.reset();          }      } +    else if (llvm_arch == llvm::Triple::mips +            || llvm_arch == llvm::Triple::mipsel +            || llvm_arch == llvm::Triple::mips64 +            || llvm_arch == llvm::Triple::mips64el) +    { +        /* Create alternate disassembler for MIPS16 and microMIPS */ +        uint32_t arch_flags = arch.GetFlags (); +        if (arch_flags & ArchSpec::eMIPSAse_mips16) +            features_str += "+mips16,"; +        else if (arch_flags & ArchSpec::eMIPSAse_micromips) +            features_str += "+micromips,"; + +        m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this)); +        if (!m_alternate_disasm_ap->IsValid()) +        { +            m_disasm_ap.reset(); +            m_alternate_disasm_ap.reset(); +        } +    }  } -DisassemblerLLVMC::~DisassemblerLLVMC() +DisassemblerLLVMC::~DisassemblerLLVMC() = default; + +Disassembler * +DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)  { +    if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) +    { +        std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor)); + +        if (disasm_ap.get() && disasm_ap->IsValid()) +            return disasm_ap.release(); +    } +    return NULL;  }  size_t @@ -817,6 +873,24 @@ const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,                                                                         name);  } +bool +DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +{ +    llvm::Triple triple = arch.GetTriple(); +    if (flavor == NULL || strcmp (flavor, "default") == 0) +        return true; + +    if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) +    { +        if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) +            return true; +        else +            return false; +    } +    else +        return false; +} +  int DisassemblerLLVMC::OpInfo (uint64_t PC,                                 uint64_t Offset,                                 uint64_t Size, diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index 56cec03994ef9..6359146d81d85 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -10,10 +10,20 @@  #ifndef liblldb_DisassemblerLLVMC_h_  #define liblldb_DisassemblerLLVMC_h_ +// C Includes +// C++ Includes +#include <memory>  #include <string> +// Other libraries and framework includes  #include "llvm-c/Disassembler.h" +// Project includes +#include "lldb/Core/Address.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/Mutex.h" +  // Opaque references to C++ Objects in LLVM's MC.  namespace llvm  { @@ -25,12 +35,7 @@ namespace llvm      class MCInstPrinter;      class MCAsmInfo;      class MCSubtargetInfo; -} - -#include "lldb/Core/Address.h" -#include "lldb/Core/Disassembler.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Mutex.h" +} // namespace llvm  class InstructionLLVMC; @@ -46,9 +51,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler          ~LLVMCDisassembler();          uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst); -        uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len); +        void PrintMCInst (llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string);          void     SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);          bool     CanBranch (llvm::MCInst &mc_inst); +        bool     HasDelaySlot (llvm::MCInst &mc_inst);          bool     IsValid()          {              return m_is_valid; @@ -66,6 +72,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler      };  public: +    DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); + +    ~DisassemblerLLVMC() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -81,33 +91,28 @@ public:      static lldb_private::Disassembler *      CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor); -    DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); - -    virtual -    ~DisassemblerLLVMC(); - -    virtual size_t -    DecodeInstructions (const lldb_private::Address &base_addr, -                        const lldb_private::DataExtractor& data, -                        lldb::offset_t data_offset, -                        size_t num_instructions, -                        bool append, -                        bool data_from_file); +    size_t +    DecodeInstructions(const lldb_private::Address &base_addr, +                       const lldb_private::DataExtractor& data, +                       lldb::offset_t data_offset, +                       size_t num_instructions, +                       bool append, +                       bool data_from_file) override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  protected:      friend class InstructionLLVMC; -    virtual bool -    FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor); +    bool +    FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override;      bool      IsValid() @@ -163,4 +168,4 @@ protected:      std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;  }; -#endif  // liblldb_DisassemblerLLVM_h_ +#endif // liblldb_DisassemblerLLVM_h_ diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 2308129b8cab0..28493170ac367 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -104,11 +104,6 @@ DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic()             "loads/unloads in Hexagon processes.";  } -void -DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} -  uint32_t  DynamicLoaderHexagonDYLD::GetPluginVersion()  { @@ -177,7 +172,7 @@ DynamicLoaderHexagonDYLD::DidAttach()      // Map the loaded sections of this executable      if ( load_offset != LLDB_INVALID_ADDRESS ) -        UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); +        UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);      // AD: confirm this?      // Load into LLDB all of the currently loaded executables in the stub @@ -248,18 +243,6 @@ DynamicLoaderHexagonDYLD::GetTargetExecutable()      return executable;  } -Error -DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ -    return Error(); -} - -Log * -DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ -    return NULL; -} -  //AD: Needs to be updated?  Error  DynamicLoaderHexagonDYLD::CanLoadImage() @@ -268,7 +251,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage()  }  void -DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, +                                               addr_t link_map_addr, +                                               addr_t base_addr, +                                               bool base_addr_is_offset)  {      Target &target = m_process->GetTarget();      const SectionList *sections = GetSectionListFromModule(module); @@ -442,7 +428,7 @@ DynamicLoaderHexagonDYLD::RefreshModules()          for (I = m_rendezvous.loaded_begin(); I != E; ++I)          {              FileSpec file(I->path.c_str(), true); -            ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); +            ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);              if (module_sp.get())              {                  loaded_modules.AppendIfNeeded( module_sp ); @@ -571,7 +557,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()      {          const char *module_path = I->path.c_str();          FileSpec file(module_path, false); -        ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); +        ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);          if (module_sp.get())          {              module_list.Append(module_sp); @@ -591,7 +577,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()  /// Helper for the entry breakpoint callback.  Resolves the load addresses  /// of all dependent modules.  ModuleSP -DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, +                                              addr_t link_map_addr, +                                              addr_t base_addr, +                                              bool base_addr_is_offset)  {      Target &target = m_process->GetTarget();      ModuleList &modules = target.GetImages(); @@ -602,12 +591,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_      // check if module is currently loaded      if ((module_sp = modules.FindFirstModule (module_spec)))       { -        UpdateLoadedSections(module_sp, link_map_addr, base_addr); +        UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);      }      // try to load this module from disk      else if ((module_sp = target.GetSharedModule(module_spec)))       { -        UpdateLoadedSections(module_sp, link_map_addr, base_addr); +        UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);      }      return module_sp; diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h index aafa385c0fca2..e10d4ee642091 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h @@ -7,12 +7,13 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderHexagon_H_ -#define liblldb_DynamicLoaderHexagon_H_ +#ifndef liblldb_DynamicLoaderHexagonDYLD_h_ +#define liblldb_DynamicLoaderHexagonDYLD_h_  // C Includes  // C++ Includes  // Other libraries and framework includes +// Project includes  #include "lldb/Breakpoint/StoppointCallbackContext.h"  #include "lldb/Target/DynamicLoader.h" @@ -21,6 +22,9 @@  class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader  {  public: +    DynamicLoaderHexagonDYLD(lldb_private::Process *process); + +    ~DynamicLoaderHexagonDYLD() override;      static void      Initialize(); @@ -37,48 +41,34 @@ public:      static lldb_private::DynamicLoader *      CreateInstance(lldb_private::Process *process, bool force); -    DynamicLoaderHexagonDYLD(lldb_private::Process *process); - -    virtual -    ~DynamicLoaderHexagonDYLD(); -      //------------------------------------------------------------------      // DynamicLoader protocol      //------------------------------------------------------------------ -    virtual void -    DidAttach(); +    void +    DidAttach() override; -    virtual void -    DidLaunch(); +    void +    DidLaunch() override; -    virtual lldb::ThreadPlanSP +    lldb::ThreadPlanSP      GetStepThroughTrampolinePlan(lldb_private::Thread &thread, -                                 bool stop_others); +                                 bool stop_others) override; -    virtual lldb_private::Error -    CanLoadImage(); +    lldb_private::Error +    CanLoadImage() override; -    virtual lldb::addr_t -    GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); +    lldb::addr_t +    GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); - -    virtual void -    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - -    virtual lldb_private::Error -    ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - -    virtual lldb_private::Log * -    EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); +    uint32_t +    GetPluginVersion() override;  protected:      /// Runtime linker rendezvous structure. @@ -124,18 +114,22 @@ protected:      void      UpdateLoadedSections(lldb::ModuleSP module,                           lldb::addr_t link_map_addr, -                         lldb::addr_t base_addr); +                         lldb::addr_t base_addr, +                         bool base_addr_is_offset) override;      /// Removes the loaded sections from the target in @p module.      ///      /// @param module The module to traverse.      void -    UnloadSections(const lldb::ModuleSP module); +    UnloadSections(const lldb::ModuleSP module) override;      /// Locates or creates a module given by @p file and updates/loads the      /// resulting module at the virtual base address @p base_addr.      lldb::ModuleSP -    LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); +    LoadModuleAtAddress(const lldb_private::FileSpec &file, +                        lldb::addr_t link_map_addr, +                        lldb::addr_t base_addr, +                        bool base_addr_is_offset) override;      /// Callback routine invoked when we hit the breakpoint on process entry.      /// @@ -173,10 +167,10 @@ protected:      FindRendezvousBreakpointAddress( );  private: -    DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD); -      const lldb_private::SectionList *      GetSectionListFromModule(const lldb::ModuleSP module) const; + +    DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);  }; -#endif  // liblldb_DynamicLoaderHexagonDYLD_H_ +#endif // liblldb_DynamicLoaderHexagonDYLD_h_ diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 8b1dd283394b6..09e874a011df1 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -17,6 +17,7 @@  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Symbol/Symbol.h"  #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/Target.h" @@ -290,19 +291,13 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)      // FreeBSD and on Android it is the full path to the executable.      auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); -    auto os_type = triple.getOS(); -    auto env_type = triple.getEnvironment(); - -    switch (os_type) { +    switch (triple.getOS()) {          case llvm::Triple::FreeBSD:              return entry.file_spec == m_exe_file_spec;          case llvm::Triple::Linux: -            switch (env_type) { -                case llvm::Triple::Android: -                    return entry.file_spec == m_exe_file_spec; -                default: -                    return !entry.file_spec; -            } +            if (triple.isAndroid()) +                return entry.file_spec == m_exe_file_spec; +            return !entry.file_spec;          default:              return false;      } @@ -372,6 +367,25 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)      return str;  } +// Returns true if the load bias reported by the linker is incorrect for the given entry. This +// function is used to handle cases where we want to work around a bug in the system linker. +static bool +isLoadBiasIncorrect(Target& target, const std::string& file_path) +{ +    // On Android L (API 21, 22) the load address of the "/system/bin/linker" isn't filled in +    // correctly. +    uint32_t os_major = 0, os_minor = 0, os_update = 0; +    if (target.GetArchitecture().GetTriple().isAndroid() && +        target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && +        (os_major == 21 || os_major == 22) && +        (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) +    { +        return true; +    } + +    return false; +} +  bool  DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)  { @@ -413,11 +427,9 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)      std::string file_path = ReadStringFromMemory(entry.path_addr);      entry.file_spec.SetFile(file_path, false); -    // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in -    // correctly. To get the correct load address we fetch the load address of the file from the -    // proc file system. -    if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 && -        (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) +    // If the load bias reported by the linker is incorrect then fetch the load address of the file +    // from the proc file system. +    if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))      {          lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;          bool is_loaded = false; diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 8724fc039cb91..6ba7b470d7435 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -62,11 +62,6 @@ DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()             "loads/unloads in POSIX processes.";  } -void -DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} -  uint32_t  DynamicLoaderPOSIXDYLD::GetPluginVersion()  { @@ -96,7 +91,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)        m_load_offset(LLDB_INVALID_ADDRESS),        m_entry_point(LLDB_INVALID_ADDRESS),        m_auxv(), -      m_dyld_bid(LLDB_INVALID_BREAK_ID) +      m_dyld_bid(LLDB_INVALID_BREAK_ID), +      m_vdso_base(LLDB_INVALID_ADDRESS)  {  } @@ -131,6 +127,8 @@ DynamicLoaderPOSIXDYLD::DidAttach()      if (log)          log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset); +    EvalVdsoStatus(); +      // if we dont have a load address we cant re-base      bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; @@ -165,7 +163,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()                           m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID,                           executable_sp->GetFileSpec().GetPath().c_str ()); -        UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset); +        UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true);          // When attaching to a target, there are two possible states:          // (1) We already crossed the entry point and therefore the rendezvous @@ -218,12 +216,13 @@ DynamicLoaderPOSIXDYLD::DidLaunch()      executable = GetTargetExecutable();      load_offset = ComputeLoadOffset(); +    EvalVdsoStatus();      if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)      {          ModuleList module_list;          module_list.Append(executable); -        UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); +        UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);          if (log)              log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); @@ -234,29 +233,19 @@ DynamicLoaderPOSIXDYLD::DidLaunch()  }  Error -DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ -    return Error(); -} - -Log * -DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ -    return NULL; -} - -Error  DynamicLoaderPOSIXDYLD::CanLoadImage()  {      return Error();  }  void -DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, +                                             addr_t link_map_addr, +                                             addr_t base_addr, +                                             bool base_addr_is_offset)  {      m_loaded_modules[module] = link_map_addr; - -    UpdateLoadedSectionsCommon(module, base_addr); +    UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);  }  void @@ -414,7 +403,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()          E = m_rendezvous.loaded_end();          for (I = m_rendezvous.loaded_begin(); I != E; ++I)          { -            ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); +            ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);              if (module_sp.get())              {                  loaded_modules.AppendIfNeeded(module_sp); @@ -432,8 +421,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()          for (I = m_rendezvous.unloaded_begin(); I != E; ++I)          {              ModuleSpec module_spec{I->file_spec}; -            ModuleSP module_sp = -                loaded_modules.FindFirstModule (module_spec); +            ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec);              if (module_sp.get())              { @@ -519,11 +507,18 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()      // that ourselves here.      ModuleSP executable = GetTargetExecutable();      m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - - +    if (m_vdso_base != LLDB_INVALID_ADDRESS) +    { +        FileSpec file_spec("[vdso]", false); +        ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false); +        if (module_sp.get()) +        { +            module_list.Append(module_sp); +        } +    }      for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)      { -        ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); +        ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);          if (module_sp.get())          {              module_list.Append(module_sp); @@ -568,6 +563,16 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset()      return m_load_offset;  } +void +DynamicLoaderPOSIXDYLD::EvalVdsoStatus() +{ +    AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + +    if (I != m_auxv->end()) +        m_vdso_base = I->value; + +} +  addr_t  DynamicLoaderPOSIXDYLD::GetEntryPoint()  { diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 68d3059cb4bec..cb97bbf43ba92 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// +//===-- DynamicLoaderPOSIXDYLD.h --------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,12 +7,13 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderPOSIX_H_ -#define liblldb_DynamicLoaderPOSIX_H_ +#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_ +#define liblldb_DynamicLoaderPOSIXDYLD_h_  // C Includes  // C++ Includes  // Other libraries and framework includes +// Project includes  #include "lldb/Breakpoint/StoppointCallbackContext.h"  #include "lldb/Target/DynamicLoader.h" @@ -23,6 +24,9 @@ class AuxVector;  class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader  {  public: +    DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + +    ~DynamicLoaderPOSIXDYLD() override;      static void      Initialize(); @@ -39,48 +43,34 @@ public:      static lldb_private::DynamicLoader *      CreateInstance(lldb_private::Process *process, bool force); -    DynamicLoaderPOSIXDYLD(lldb_private::Process *process); - -    virtual -    ~DynamicLoaderPOSIXDYLD(); -      //------------------------------------------------------------------      // DynamicLoader protocol      //------------------------------------------------------------------ -    virtual void -    DidAttach(); +    void +    DidAttach() override; -    virtual void -    DidLaunch(); +    void +    DidLaunch() override; -    virtual lldb::ThreadPlanSP +    lldb::ThreadPlanSP      GetStepThroughTrampolinePlan(lldb_private::Thread &thread, -                                 bool stop_others); +                                 bool stop_others) override; -    virtual lldb_private::Error -    CanLoadImage(); +    lldb_private::Error +    CanLoadImage() override; -    virtual lldb::addr_t -    GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); +    lldb::addr_t +    GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); - -    virtual uint32_t -    GetPluginVersion(); - -    virtual void -    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); +    lldb_private::ConstString +    GetPluginName() override; -    virtual lldb_private::Error -    ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - -    virtual lldb_private::Log * -    EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); +    uint32_t +    GetPluginVersion() override;  protected:      /// Runtime linker rendezvous structure. @@ -98,12 +88,16 @@ protected:      /// Rendezvous breakpoint.      lldb::break_id_t m_dyld_bid; +    /// Contains AT_SYSINFO_EHDR, which means a vDSO has been +    /// mapped to the address space +    lldb::addr_t m_vdso_base; +      /// Loaded module list. (link map for each module)      std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;      /// Enables a breakpoint on a function called by the runtime      /// linker each time a module is loaded or unloaded. -    void +    virtual void      SetRendezvousBreakpoint();      /// Callback routine which updates the current list of loaded modules based @@ -126,16 +120,17 @@ protected:      /// @param link_map_addr The virtual address of the link map for the @p module.      ///      /// @param base_addr The virtual base address @p module is loaded at. -    virtual void +    void      UpdateLoadedSections(lldb::ModuleSP module,                           lldb::addr_t link_map_addr, -                         lldb::addr_t base_addr); +                         lldb::addr_t base_addr, +                         bool base_addr_is_offset) override;      /// Removes the loaded sections from the target in @p module.      ///      /// @param module The module to traverse. -    virtual void -    UnloadSections(const lldb::ModuleSP module); +    void +    UnloadSections(const lldb::ModuleSP module) override;      /// Resolves the entry point for the current inferior process and sets a      /// breakpoint at that address. @@ -155,7 +150,7 @@ protected:      /// Helper for the entry breakpoint callback.  Resolves the load addresses      /// of all dependent modules. -    void +    virtual void      LoadAllCurrentModules();      /// Computes a value for m_load_offset returning the computed address on @@ -168,6 +163,11 @@ protected:      lldb::addr_t      GetEntryPoint(); +    /// Evaluate if Aux vectors contain vDSO information +    /// in case they do, read and assign the address to m_vdso_base +    void +    EvalVdsoStatus(); +      /// Loads Module from inferior process.      void      ResolveExecutableModule(lldb::ModuleSP &module_sp); @@ -176,4 +176,4 @@ private:      DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);  }; -#endif  // liblldb_DynamicLoaderPOSIXDYLD_H_ +#endif // liblldb_DynamicLoaderPOSIXDYLD_h_ diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h index ea33164cf8233..a7fdf4d221656 100644 --- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h +++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h @@ -12,12 +12,8 @@  // C Includes  // C++ Includes -#include <map> -#include <vector> -#include <string> -  // Other libraries and framework includes - +// Project includes  #include "lldb/Target/DynamicLoader.h"  #include "lldb/Host/FileSpec.h"  #include "lldb/Core/UUID.h" @@ -27,6 +23,10 @@  class DynamicLoaderStatic : public lldb_private::DynamicLoader  {  public: +    DynamicLoaderStatic(lldb_private::Process *process); + +    ~DynamicLoaderStatic() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -45,37 +45,33 @@ public:      static lldb_private::DynamicLoader *      CreateInstance (lldb_private::Process *process, bool force); -    DynamicLoaderStatic (lldb_private::Process *process); - -    virtual -    ~DynamicLoaderStatic ();      //------------------------------------------------------------------      /// Called after attaching a process.      ///      /// Allow DynamicLoader plug-ins to execute some code after      /// attaching to a process.      //------------------------------------------------------------------ -    virtual void -    DidAttach (); +    void +    DidAttach() override; -    virtual void -    DidLaunch (); +    void +    DidLaunch() override; -    virtual lldb::ThreadPlanSP -    GetStepThroughTrampolinePlan (lldb_private::Thread &thread, -                                  bool stop_others); +    lldb::ThreadPlanSP +    GetStepThroughTrampolinePlan(lldb_private::Thread &thread, +                                 bool stop_others) override; -    virtual lldb_private::Error -    CanLoadImage (); +    lldb_private::Error +    CanLoadImage() override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  private:      void @@ -84,4 +80,4 @@ private:      DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic);  }; -#endif  // liblldb_DynamicLoaderStatic_h_ +#endif // liblldb_DynamicLoaderStatic_h_ diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index 56b56ab3a1949..dd391b4ca4d2a 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -21,40 +21,39 @@ using namespace lldb_private;  DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)      : DynamicLoader(process)  { -  }  DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD()  { -  } -void DynamicLoaderWindowsDYLD::Initialize() +void +DynamicLoaderWindowsDYLD::Initialize()  { -    PluginManager::RegisterPlugin(GetPluginNameStatic(), -                                  GetPluginDescriptionStatic(), -                                  CreateInstance); +    PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);  } -void DynamicLoaderWindowsDYLD::Terminate() +void +DynamicLoaderWindowsDYLD::Terminate()  { -  } -ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() +ConstString +DynamicLoaderWindowsDYLD::GetPluginNameStatic()  {      static ConstString g_plugin_name("windows-dyld");      return g_plugin_name;  } -const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() +const char * +DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()  {      return "Dynamic loader plug-in that watches for shared library "             "loads/unloads in Windows processes.";  } - -DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force) +DynamicLoader * +DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)  {      bool should_create = force;      if (!should_create) @@ -65,32 +64,35 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool f      }      if (should_create) -        return new DynamicLoaderWindowsDYLD (process); +        return new DynamicLoaderWindowsDYLD(process);      return nullptr;  } -void DynamicLoaderWindowsDYLD::DidAttach() +void +DynamicLoaderWindowsDYLD::DidAttach()  { -  } -void DynamicLoaderWindowsDYLD::DidLaunch() +void +DynamicLoaderWindowsDYLD::DidLaunch()  { -  } -Error DynamicLoaderWindowsDYLD::CanLoadImage() +Error +DynamicLoaderWindowsDYLD::CanLoadImage()  {      return Error();  } -ConstString DynamicLoaderWindowsDYLD::GetPluginName() +ConstString +DynamicLoaderWindowsDYLD::GetPluginName()  {      return GetPluginNameStatic();  } -uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() +uint32_t +DynamicLoaderWindowsDYLD::GetPluginVersion()  {      return 1;  } diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h index d12b999f4627c..8c479819c535b 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===// +//===-- DynamicLoaderWindowsDYLD.h ------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,9 +7,13 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ -#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ +#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ +#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-forward.h"  #include "lldb/Target/DynamicLoader.h" @@ -18,9 +22,10 @@ namespace lldb_private  class DynamicLoaderWindowsDYLD : public DynamicLoader  { -  public: +public:      DynamicLoaderWindowsDYLD(Process *process); -    virtual ~DynamicLoaderWindowsDYLD(); + +    ~DynamicLoaderWindowsDYLD() override;      static void Initialize();      static void Terminate(); @@ -29,15 +34,15 @@ class DynamicLoaderWindowsDYLD : public DynamicLoader      static DynamicLoader *CreateInstance(Process *process, bool force); -    void DidAttach () override; -    void DidLaunch () override; -    Error CanLoadImage () override; +    void DidAttach() override; +    void DidLaunch() override; +    Error CanLoadImage() override;      lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override;      ConstString GetPluginName() override;      uint32_t GetPluginVersion() override;  }; -} +} // namespace lldb_private -#endif +#endif // liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp new file mode 100644 index 0000000000000..976310610f51d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -0,0 +1,134 @@ +//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTDumper.h" + +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace lldb_private; + +ASTDumper::ASTDumper (clang::Decl *decl) +{ +    clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl); +     +    bool has_external_lexical_storage; +    bool has_external_visible_storage; +     +    if (decl_ctx) +    { +        has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); +        has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); +        decl_ctx->setHasExternalLexicalStorage(false); +        decl_ctx->setHasExternalVisibleStorage(false); +    } +     +    llvm::raw_string_ostream os(m_dump); +    decl->print (os); +    os.flush(); +     +    if (decl_ctx) +    { +        decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); +        decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); +    } +} + +ASTDumper::ASTDumper (clang::DeclContext *decl_ctx) +{ +    bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); +    bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); +     +    decl_ctx->setHasExternalLexicalStorage(false); +    decl_ctx->setHasExternalVisibleStorage(false); +     +    if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) +    { +        llvm::raw_string_ostream os(m_dump); +        decl->print (os); +        os.flush(); +    } +    else +    { +        m_dump.assign("<DeclContext is not a Decl>"); +    } +     +    decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); +    decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); +} + +ASTDumper::ASTDumper (const clang::Type *type) +{ +    m_dump = clang::QualType(type, 0).getAsString(); +} + +ASTDumper::ASTDumper (clang::QualType type) +{ +    m_dump = type.getAsString(); +} + +ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type) +{ +    m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); +} + +ASTDumper::ASTDumper (const CompilerType &compiler_type) +{ +    m_dump = ClangASTContext::GetQualType(compiler_type).getAsString(); +} + + +const char * +ASTDumper::GetCString() +{ +    return m_dump.c_str(); +} + +void ASTDumper::ToSTDERR() +{ +    fprintf(stderr, "%s\n", m_dump.c_str()); +} + +void ASTDumper::ToLog(Log *log, const char *prefix) +{ +    size_t len = m_dump.length() + 1; +     +    char *alloc = (char*)malloc(len); +    char *str = alloc; +     +    memcpy(str, m_dump.c_str(), len); +     +    char *end = NULL; +     +    end = strchr(str, '\n'); +     +    while (end) +    { +        *end = '\0'; +         +        log->Printf("%s%s", prefix, str); +         +        *end = '\n'; +         +        str = end + 1; +        end = strchr(str, '\n'); +    } +     +    log->Printf("%s%s", prefix, str); +                     +    free(alloc); +} + +void ASTDumper::ToStream(lldb::StreamSP &stream) +{ +    stream->PutCString(m_dump.c_str()); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/source/Plugins/ExpressionParser/Clang/ASTDumper.h new file mode 100644 index 0000000000000..c8dc6847d6c2d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.h @@ -0,0 +1,42 @@ +//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTDumper_h_ +#define liblldb_ASTDumper_h_ + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/TypeVisitor.h" + +#include "lldb/Core/Stream.h" +#include "llvm/ADT/DenseSet.h" + +namespace lldb_private +{ +     +class ASTDumper +{ +public: +    ASTDumper (clang::Decl *decl); +    ASTDumper (clang::DeclContext *decl_ctx); +    ASTDumper (const clang::Type *type); +    ASTDumper (clang::QualType type); +    ASTDumper (lldb::opaque_compiler_type_t type); +    ASTDumper (const CompilerType &compiler_type); +     +    const char *GetCString(); +    void ToSTDERR(); +    void ToLog(Log *log, const char *prefix); +    void ToStream(lldb::StreamSP &stream); +private: +    std::string m_dump; +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp new file mode 100644 index 0000000000000..02505bde240c2 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -0,0 +1,514 @@ +//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTResultSynthesizer.h" + +#include "ClangPersistentVariables.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Target/Target.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, +                                           Target &target) : +    m_ast_context (NULL), +    m_passthrough (passthrough), +    m_passthrough_sema (NULL), +    m_target (target), +    m_sema (NULL) +{ +    if (!m_passthrough) +        return; + +    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); +} + +ASTResultSynthesizer::~ASTResultSynthesizer() +{ +} + +void +ASTResultSynthesizer::Initialize(ASTContext &Context) +{ +    m_ast_context = &Context; + +    if (m_passthrough) +        m_passthrough->Initialize(Context); +} + +void +ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D)) +    { +        if (log && log->GetVerbose()) +        { +            if (named_decl->getIdentifier()) +                log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart()); +            else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) +                log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str()); +            else +                log->Printf("TransformTopLevelDecl(<complex>)"); +        } + +    } + +    if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D)) +    { +        RecordDecl::decl_iterator decl_iterator; + +        for (decl_iterator = linkage_spec_decl->decls_begin(); +             decl_iterator != linkage_spec_decl->decls_end(); +             ++decl_iterator) +        { +            TransformTopLevelDecl(*decl_iterator); +        } +    } +    else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D)) +    { +        if (m_ast_context && +            !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) +        { +            RecordPersistentTypes(method_decl); +            SynthesizeObjCMethodResult(method_decl); +        } +    } +    else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) +    { +        if (m_ast_context && +            !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) +        { +            RecordPersistentTypes(function_decl); +            SynthesizeFunctionResult(function_decl); +        } +    } +} + +bool +ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) +{ +    DeclGroupRef::iterator decl_iterator; + +    for (decl_iterator = D.begin(); +         decl_iterator != D.end(); +         ++decl_iterator) +    { +        Decl *decl = *decl_iterator; + +        TransformTopLevelDecl(decl); +    } + +    if (m_passthrough) +        return m_passthrough->HandleTopLevelDecl(D); +    return true; +} + +bool +ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (!m_sema) +        return false; + +    FunctionDecl *function_decl = FunDecl; + +    if (!function_decl) +        return false; + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream os(s); + +        function_decl->print(os); + +        os.flush(); + +        log->Printf ("Untransformed function AST:\n%s", s.c_str()); +    } + +    Stmt *function_body = function_decl->getBody(); +    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body); + +    bool ret = SynthesizeBodyResult (compound_stmt, +                                     function_decl); + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream os(s); + +        function_decl->print(os); + +        os.flush(); + +        log->Printf ("Transformed function AST:\n%s", s.c_str()); +    } + +    return ret; +} + +bool +ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (!m_sema) +        return false; + +    if (!MethodDecl) +        return false; + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream os(s); + +        MethodDecl->print(os); + +        os.flush(); + +        log->Printf ("Untransformed method AST:\n%s", s.c_str()); +    } + +    Stmt *method_body = MethodDecl->getBody(); + +    if (!method_body) +        return false; + +    CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body); + +    bool ret = SynthesizeBodyResult (compound_stmt, +                                     MethodDecl); + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream os(s); + +        MethodDecl->print(os); + +        os.flush(); + +        log->Printf("Transformed method AST:\n%s", s.c_str()); +    } + +    return ret; +} + +bool +ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, +                                            DeclContext *DC) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    ASTContext &Ctx(*m_ast_context); + +    if (!Body) +        return false; + +    if (Body->body_empty()) +        return false; + +    Stmt **last_stmt_ptr = Body->body_end() - 1; +    Stmt *last_stmt = *last_stmt_ptr; + +    while (dyn_cast<NullStmt>(last_stmt)) +    { +        if (last_stmt_ptr != Body->body_begin()) +        { +            last_stmt_ptr--; +            last_stmt = *last_stmt_ptr; +        } +        else +        { +            return false; +        } +    } + +    Expr *last_expr = dyn_cast<Expr>(last_stmt); + +    if (!last_expr) +        // No auxiliary variable necessary; expression returns void +        return true; + +    // In C++11, last_expr can be a LValueToRvalue implicit cast.  Strip that off if that's the +    // case. + +    do { +        ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr); + +        if (!implicit_cast) +            break; + +        if (implicit_cast->getCastKind() != CK_LValueToRValue) +            break; + +        last_expr = implicit_cast->getSubExpr(); +    } while (0); + +    // is_lvalue is used to record whether the expression returns an assignable Lvalue or an +    // Rvalue.  This is relevant because they are handled differently. +    // +    // For Lvalues +    // +    //   - In AST result synthesis (here!) the expression E is transformed into an initialization +    //     T *$__lldb_expr_result_ptr = &E. +    // +    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be +    //     passed into the expression. +    // +    //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at +    //     an entry in the struct ($__lldb_arg) passed into the expression.  (Other persistent +    //     variables are treated similarly, having been materialized as references, but in those +    //     cases the value of the reference itself is never modified.) +    // +    //   - During materialization, $0 (the result persistent variable) is ignored. +    // +    //   - During dematerialization, $0 is marked up as a load address with value equal to the +    //     contents of the structure entry. +    // +    // For Rvalues +    // +    //   - In AST result synthesis the expression E is transformed into an initialization +    //     static T $__lldb_expr_result = E. +    // +    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be +    //     passed into the expression. +    // +    //   - In IR transformations, an instruction is inserted at the beginning of the function to +    //     dereference the pointer resident in the slot.  Reads and writes to $__lldb_expr_result +    //     are redirected at that dereferenced version.  Guard variables for the static variable +    //     are excised. +    // +    //   - During materialization, $0 (the result persistent variable) is populated with the location +    //     of a newly-allocated area of memory. +    // +    //   - During dematerialization, $0 is ignored. + +    bool is_lvalue = +        (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) && +        (last_expr->getObjectKind() == OK_Ordinary); + +    QualType expr_qual_type = last_expr->getType(); +    const clang::Type *expr_type = expr_qual_type.getTypePtr(); + +    if (!expr_type) +        return false; + +    if (expr_type->isVoidType()) +        return true; + +    if (log) +    { +        std::string s = expr_qual_type.getAsString(); + +        log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); +    } + +    clang::VarDecl *result_decl = NULL; + +    if (is_lvalue) +    { +        IdentifierInfo *result_ptr_id; + +        if (expr_type->isFunctionType()) +            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers +        else +            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); + +        m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type); + +        QualType ptr_qual_type; + +        if (expr_qual_type->getAs<ObjCObjectType>() != NULL) +            ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); +        else +            ptr_qual_type = Ctx.getPointerType(expr_qual_type); + +        result_decl = VarDecl::Create(Ctx, +                                      DC, +                                      SourceLocation(), +                                      SourceLocation(), +                                      result_ptr_id, +                                      ptr_qual_type, +                                      NULL, +                                      SC_Static); + +        if (!result_decl) +            return false; + +        ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); + +        m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); +    } +    else +    { +        IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); + +        result_decl = VarDecl::Create(Ctx, +                                      DC, +                                      SourceLocation(), +                                      SourceLocation(), +                                      &result_id, +                                      expr_qual_type, +                                      NULL, +                                      SC_Static); + +        if (!result_decl) +            return false; + +        m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); +    } + +    DC->addDecl(result_decl); + +    /////////////////////////////// +    // call AddInitializerToDecl +    // + +    //m_sema->AddInitializerToDecl(result_decl, last_expr); + +    ///////////////////////////////// +    // call ConvertDeclToDeclGroup +    // + +    Sema::DeclGroupPtrTy result_decl_group_ptr; + +    result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); + +    //////////////////////// +    // call ActOnDeclStmt +    // + +    StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr, +                                                                       SourceLocation(), +                                                                       SourceLocation())); + +    //////////////////////////////////////////////// +    // replace the old statement with the new one +    // + +    *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.get()); + +    return true; +} + +void +ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) +{ +    if (m_passthrough) +        m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) +{ +    typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator; + +    for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), +         e = TypeDeclIterator(FunDeclCtx->decls_end()); +         i != e; +         ++i) +    { +        MaybeRecordPersistentType(*i); +    } +} + +void +ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) +{ +    if (!D->getIdentifier()) +        return; + +    StringRef name = D->getName(); + +    if (name.size() == 0 || name[0] != '$') +        return; + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    ConstString name_cs(name.str().c_str()); + +    if (log) +        log->Printf ("Recording persistent type %s\n", name_cs.GetCString()); + +    Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(), +                                                                 m_ast_context, +                                                                 D); + +    if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch)) +        llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch); +} + +void +ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) +{ +    if (m_passthrough) +        m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) +{ +    if (m_passthrough) +        m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) +{ +    if (m_passthrough) +        m_passthrough->HandleVTable(RD); +} + +void +ASTResultSynthesizer::PrintStats() +{ +    if (m_passthrough) +        m_passthrough->PrintStats(); +} + +void +ASTResultSynthesizer::InitializeSema(Sema &S) +{ +    m_sema = &S; + +    if (m_passthrough_sema) +        m_passthrough_sema->InitializeSema(S); +} + +void +ASTResultSynthesizer::ForgetSema() +{ +    m_sema = NULL; + +    if (m_passthrough_sema) +        m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h new file mode 100644 index 0000000000000..9f7bbe05b0822 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -0,0 +1,185 @@ +//===-- ASTResultSynthesizer.h ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTResultSynthesizer_h_ +#define liblldb_ASTResultSynthesizer_h_ + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Target/Target.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" +/// @brief Adds a result variable declaration to the ASTs for an expression. +/// +/// Users expect the expression "i + 3" to return a result, even if a result +/// variable wasn't specifically declared.  To fulfil this requirement, LLDB adds +/// a result variable to the expression, transforming it to  +/// "int $__lldb_expr_result = i + 3."  The IR transformers ensure that the +/// resulting variable is mapped to the right piece of memory. +/// ASTResultSynthesizer's job is to add the variable and its initialization to +/// the ASTs for the expression, and it does so by acting as a SemaConsumer for +/// Clang. +//---------------------------------------------------------------------- +class ASTResultSynthesizer : public clang::SemaConsumer +{ +public: +    //---------------------------------------------------------------------- +    /// Constructor +    /// +    /// @param[in] passthrough +    ///     Since the ASTs must typically go through to the Clang code generator +    ///     in order to produce LLVM IR, this SemaConsumer must allow them to +    ///     pass to the next step in the chain after processing.  Passthrough is +    ///     the next ASTConsumer, or NULL if none is required. +    /// +    /// @param[in] target +    ///     The target, which contains the persistent variable store and the +    ///     AST importer. +    //---------------------------------------------------------------------- +    ASTResultSynthesizer(clang::ASTConsumer *passthrough, +                         Target &target); +     +    //---------------------------------------------------------------------- +    /// Destructor +    //---------------------------------------------------------------------- +    ~ASTResultSynthesizer() override; +     +    //---------------------------------------------------------------------- +    /// Link this consumer with a particular AST context +    /// +    /// @param[in] Context +    ///     This AST context will be used for types and identifiers, and also +    ///     forwarded to the passthrough consumer, if one exists. +    //---------------------------------------------------------------------- +    void Initialize(clang::ASTContext &Context) override; +     +    //---------------------------------------------------------------------- +    /// Examine a list of Decls to find the function $__lldb_expr and  +    /// transform its code +    /// +    /// @param[in] D +    ///     The list of Decls to search.  These may contain LinkageSpecDecls, +    ///     which need to be searched recursively.  That job falls to +    ///     TransformTopLevelDecl. +    //---------------------------------------------------------------------- +    bool HandleTopLevelDecl(clang::DeclGroupRef D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleTranslationUnit(clang::ASTContext &Ctx) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleTagDeclDefinition(clang::TagDecl *D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void CompleteTentativeDefinition(clang::VarDecl *D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleVTable(clang::CXXRecordDecl *RD) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void PrintStats() override; +     +    //---------------------------------------------------------------------- +    /// Set the Sema object to use when performing transforms, and pass it on +    /// +    /// @param[in] S +    ///     The Sema to use.  Because Sema isn't externally visible, this class +    ///     casts it to an Action for actual use. +    //---------------------------------------------------------------------- +    void InitializeSema(clang::Sema &S) override; +     +    //---------------------------------------------------------------------- +    /// Reset the Sema to NULL now that transformations are done +    //---------------------------------------------------------------------- +    void ForgetSema() override; + +private: +    //---------------------------------------------------------------------- +    /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing +    /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on +    /// anything that was found +    /// +    /// @param[in] D +    ///     The Decl to hunt. +    //---------------------------------------------------------------------- +    void TransformTopLevelDecl(clang::Decl *D); +     +    //---------------------------------------------------------------------- +    /// Process an Objective-C method and produce the result variable and +    /// initialization +    /// +    /// @param[in] MethodDecl +    ///     The method to process. +    //---------------------------------------------------------------------- +    bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); +     +    //---------------------------------------------------------------------- +    /// Process a function and produce the result variable and initialization +    /// +    /// @param[in] FunDecl +    ///     The function to process. +    //---------------------------------------------------------------------- +    bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); +     +    //---------------------------------------------------------------------- +    /// Process a function body and produce the result variable and  +    /// initialization +    /// +    /// @param[in] Body +    ///     The body of the function. +    /// +    /// @param[in] DC +    ///     The DeclContext of the function, into which the result variable +    ///     is inserted. +    //---------------------------------------------------------------------- +    bool SynthesizeBodyResult(clang::CompoundStmt *Body, +                              clang::DeclContext *DC); +     +    //---------------------------------------------------------------------- +    /// Given a DeclContext for a function or method, find all types +    /// declared in the context and record any persistent types found. +    /// +    /// @param[in] FunDeclCtx +    ///     The context for the function to process. +    //---------------------------------------------------------------------- +    void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); +     +    //---------------------------------------------------------------------- +    /// Given a TypeDecl, if it declares a type whose name starts with a +    /// dollar sign, register it as a pointer type in the target's scratch +    /// AST context. +    /// +    /// @param[in] Body +    ///     The body of the function. +    //---------------------------------------------------------------------- +    void MaybeRecordPersistentType(clang::TypeDecl *D); +     +    clang::ASTContext *m_ast_context;           ///< The AST context to use for identifiers and types. +    clang::ASTConsumer *m_passthrough;          ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer. +    clang::SemaConsumer *m_passthrough_sema;    ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer. +    Target &m_target;                           ///< The target, which contains the persistent variable store and the +    clang::Sema *m_sema;                        ///< The Sema to use. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTResultSynthesizer_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp new file mode 100644 index 0000000000000..38a2b6b33a8ab --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -0,0 +1,221 @@ +//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTStructExtractor.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, +                                       const char *struct_name, +                                       ClangFunctionCaller &function) : +    m_ast_context (NULL), +    m_passthrough (passthrough), +    m_passthrough_sema (NULL), +    m_sema (NULL), +    m_action (NULL), +    m_function (function), +    m_struct_name (struct_name) +{ +    if (!m_passthrough) +        return; + +    m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); +} + +ASTStructExtractor::~ASTStructExtractor() +{ +} + +void +ASTStructExtractor::Initialize(ASTContext &Context) +{ +    m_ast_context = &Context; + +    if (m_passthrough) +        m_passthrough->Initialize(Context); +} + +void +ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) +{ +    if (!F->hasBody()) +        return; + +    Stmt *body_stmt = F->getBody(); +    CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt); + +    if (!body_compound_stmt) +        return; // do we have to handle this? + +    RecordDecl *struct_decl = NULL; + +    StringRef desired_name(m_struct_name.c_str()); + +    for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); +         bi != be; +         ++bi) +    { +        Stmt *curr_stmt = *bi; +        DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt); +        if (!curr_decl_stmt) +            continue; +        DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); +        for (Decl *candidate_decl : decl_group) +        { +            RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl); +            if (!candidate_record_decl) +                continue; +            if (candidate_record_decl->getName() == desired_name) +            { +                struct_decl = candidate_record_decl; +                break; +            } +        } +        if (struct_decl) +            break; +    } + +    if (!struct_decl) +        return; + +    const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); + +    if (!struct_layout) +        return; + +    m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits +    m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; +    m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; + +    for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); +         field_index < num_fields; +         ++field_index) +    { +        m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); +    } + +    m_function.m_struct_valid = true; +} + +void +ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) +{ +    LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D); + +    if (linkage_spec_decl) +    { +        RecordDecl::decl_iterator decl_iterator; + +        for (decl_iterator = linkage_spec_decl->decls_begin(); +             decl_iterator != linkage_spec_decl->decls_end(); +             ++decl_iterator) +        { +            ExtractFromTopLevelDecl(*decl_iterator); +        } +    } + +    FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); + +    if (m_ast_context && +        function_decl && +        !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) +    { +        ExtractFromFunctionDecl(function_decl); +    } +} + +bool +ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) +{ +    DeclGroupRef::iterator decl_iterator; + +    for (decl_iterator = D.begin(); +         decl_iterator != D.end(); +         ++decl_iterator) +    { +        Decl *decl = *decl_iterator; + +        ExtractFromTopLevelDecl(decl); +    } + +    if (m_passthrough) +        return m_passthrough->HandleTopLevelDecl(D); +    return true; +} + +void +ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) +{ +    if (m_passthrough) +        m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) +{ +    if (m_passthrough) +        m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) +{ +    if (m_passthrough) +        m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) +{ +    if (m_passthrough) +        m_passthrough->HandleVTable(RD); +} + +void +ASTStructExtractor::PrintStats() +{ +    if (m_passthrough) +        m_passthrough->PrintStats(); +} + +void +ASTStructExtractor::InitializeSema(Sema &S) +{ +    m_sema = &S; +    m_action = reinterpret_cast<Action*>(m_sema); + +    if (m_passthrough_sema) +        m_passthrough_sema->InitializeSema(S); +} + +void +ASTStructExtractor::ForgetSema() +{ +    m_sema = NULL; +    m_action = NULL; + +    if (m_passthrough_sema) +        m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h new file mode 100644 index 0000000000000..2152cff911ff4 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -0,0 +1,158 @@ +//===-- ASTStructExtractor.h ------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTStructExtractor_h_ +#define liblldb_ASTStructExtractor_h_ + +#include "ClangExpressionVariable.h" +#include "ClangFunctionCaller.h" + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { +     +//---------------------------------------------------------------------- +/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" +/// @brief Extracts and describes the argument structure for a wrapped function. +/// +/// This pass integrates with ClangFunctionCaller, which calls functions with custom +/// sets of arguments.  To avoid having to implement the full calling convention +/// for the target's architecture, ClangFunctionCaller writes a simple wrapper +/// function that takes a pointer to an argument structure that contains room +/// for the address of the function to be called, the values of all its +/// arguments, and room for the function's return value. +/// +/// The definition of this struct is itself in the body of the wrapper function, +/// so Clang does the structure layout itself.  ASTStructExtractor reads through +/// the AST for the wrapper function and finds the struct. +//---------------------------------------------------------------------- +class ASTStructExtractor : public clang::SemaConsumer +{ +public: +    //---------------------------------------------------------------------- +    /// Constructor +    /// +    /// @param[in] passthrough +    ///     Since the ASTs must typically go through to the Clang code generator +    ///     in order to produce LLVM IR, this SemaConsumer must allow them to +    ///     pass to the next step in the chain after processing.  Passthrough is +    ///     the next ASTConsumer, or NULL if none is required. +    /// +    /// @param[in] struct_name +    ///     The name of the structure to extract from the wrapper function. +    /// +    /// @param[in] function +    ///     The caller object whose members should be populated with information +    ///     about the argument struct.  ClangFunctionCaller friends ASTStructExtractor +    ///     for this purpose. +    //---------------------------------------------------------------------- +    ASTStructExtractor(clang::ASTConsumer *passthrough, +                       const char *struct_name, +                       ClangFunctionCaller &function); +     +    //---------------------------------------------------------------------- +    /// Destructor +    //---------------------------------------------------------------------- +    ~ASTStructExtractor() override; +     +    //---------------------------------------------------------------------- +    /// Link this consumer with a particular AST context +    /// +    /// @param[in] Context +    ///     This AST context will be used for types and identifiers, and also +    ///     forwarded to the passthrough consumer, if one exists. +    //---------------------------------------------------------------------- +    void Initialize(clang::ASTContext &Context) override; +     +    //---------------------------------------------------------------------- +    /// Examine a list of Decls to find the function $__lldb_expr and  +    /// transform its code +    /// +    /// @param[in] D +    ///     The list of Decls to search.  These may contain LinkageSpecDecls, +    ///     which need to be searched recursively.  That job falls to +    ///     TransformTopLevelDecl. +    //---------------------------------------------------------------------- +    bool HandleTopLevelDecl(clang::DeclGroupRef D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleTranslationUnit(clang::ASTContext &Ctx) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleTagDeclDefinition(clang::TagDecl *D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void CompleteTentativeDefinition(clang::VarDecl *D) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void HandleVTable(clang::CXXRecordDecl *RD) override; +     +    //---------------------------------------------------------------------- +    /// Passthrough stub +    //---------------------------------------------------------------------- +    void PrintStats() override; +     +    //---------------------------------------------------------------------- +    /// Set the Sema object to use when performing transforms, and pass it on +    /// +    /// @param[in] S +    ///     The Sema to use.  Because Sema isn't externally visible, this class +    ///     casts it to an Action for actual use. +    //---------------------------------------------------------------------- +    void InitializeSema(clang::Sema &S) override; +     +    //---------------------------------------------------------------------- +    /// Reset the Sema to NULL now that transformations are done +    //---------------------------------------------------------------------- +    void ForgetSema() override; + +private: +    //---------------------------------------------------------------------- +    /// Hunt the given FunctionDecl for the argument struct and place +    /// information about it into m_function +    /// +    /// @param[in] F +    ///     The FunctionDecl to hunt. +    //---------------------------------------------------------------------- +    void +    ExtractFromFunctionDecl(clang::FunctionDecl* F); +     +    //---------------------------------------------------------------------- +    /// Hunt the given Decl for FunctionDecls named the same as the wrapper +    /// function name, recursing as necessary through LinkageSpecDecls, and  +    /// calling ExtractFromFunctionDecl on anything that was found +    /// +    /// @param[in] D +    ///     The Decl to hunt. +    //---------------------------------------------------------------------- +    void +    ExtractFromTopLevelDecl(clang::Decl* D); +     +    clang::ASTContext              *m_ast_context;          ///< The AST context to use for identifiers and types. +    clang::ASTConsumer             *m_passthrough;          ///< The ASTConsumer down the chain, for passthrough.  NULL if it's a SemaConsumer. +    clang::SemaConsumer            *m_passthrough_sema;     ///< The SemaConsumer down the chain, for passthrough.  NULL if it's an ASTConsumer. +    clang::Sema                    *m_sema;                 ///< The Sema to use. +    clang::Action                  *m_action;               ///< The Sema to use, cast to an Action so it's usable. +     +    ClangFunctionCaller            &m_function;             ///< The function to populate with information about the argument structure. +    std::string                     m_struct_name;          ///< The name of the structure to extract. +}; +     +} // namespace lldb_private + +#endif // liblldb_ASTStructExtractor_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp new file mode 100644 index 0000000000000..d2ea4390560a5 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -0,0 +1,2101 @@ +//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangASTSource.h" + +#include "ASTDumper.h" +#include "ClangModulesDeclVendor.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +#include <vector> + +using namespace clang; +using namespace lldb_private; + +//------------------------------------------------------------------ +// Scoped class that will remove an active lexical decl from the set +// when it goes out of scope. +//------------------------------------------------------------------ +namespace { +    class ScopedLexicalDeclEraser +    { +    public: +        ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls, +                                const clang::Decl *decl) +            : m_active_lexical_decls(decls), m_decl(decl) +        { +        } + +        ~ScopedLexicalDeclEraser() +        { +            m_active_lexical_decls.erase(m_decl); +        } + +    private: +        std::set<const clang::Decl *> &m_active_lexical_decls; +        const clang::Decl *m_decl; +    }; +} + +ClangASTSource::~ClangASTSource() +{ +    m_ast_importer_sp->ForgetDestination(m_ast_context); + +    // We are in the process of destruction, don't create clang ast context on demand +    // by passing false to Target::GetScratchClangASTContext(create_on_demand). +    ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); + +    if (!scratch_clang_ast_context) +        return; + +    clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + +    if (!scratch_ast_context) +        return; + +    if (m_ast_context != scratch_ast_context) +        m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); +} + +void +ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) +{ +    if (!m_ast_context) +        return; + +    m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); +    m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); +} + +// The core lookup interface. +bool +ClangASTSource::FindExternalVisibleDeclsByName +( +    const DeclContext *decl_ctx, +    DeclarationName clang_decl_name +) +{ +    if (!m_ast_context) +    { +        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +        return false; +    } + +    if (GetImportInProgress()) +    { +        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +        return false; +    } + +    std::string decl_name (clang_decl_name.getAsString()); + +//    if (m_decl_map.DoingASTImport ()) +//      return DeclContext::lookup_result(); +// +    switch (clang_decl_name.getNameKind()) { +    // Normal identifiers. +    case DeclarationName::Identifier: +        { +            clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo(); + +            if (!identifier_info || +                identifier_info->getBuiltinID() != 0) +            { +                SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +                return false; +            } +        } +        break; + +    // Operator names. +    case DeclarationName::CXXOperatorName: +    case DeclarationName::CXXLiteralOperatorName: +        break; + +    // Using directives found in this context. +    // Tell Sema we didn't find any or we'll end up getting asked a *lot*. +    case DeclarationName::CXXUsingDirective: +      SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +      return false; + +    case DeclarationName::ObjCZeroArgSelector: +    case DeclarationName::ObjCOneArgSelector: +    case DeclarationName::ObjCMultiArgSelector: +    { +      llvm::SmallVector<NamedDecl*, 1> method_decls; + +      NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx); + +      FindObjCMethodDecls(method_search_context); + +      SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls); +      return (method_decls.size() > 0); +    } +    // These aren't possible in the global context. +    case DeclarationName::CXXConstructorName: +    case DeclarationName::CXXDestructorName: +    case DeclarationName::CXXConversionFunctionName: +      SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +      return false; +    } + + +    if (!GetLookupsEnabled()) +    { +        // Wait until we see a '$' at the start of a name before we start doing +        // any lookups so we can avoid lookup up all of the builtin types. +        if (!decl_name.empty() && decl_name[0] == '$') +        { +            SetLookupsEnabled (true); +        } +        else +        { +            SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +            return false; +        } +    } + +    ConstString const_decl_name(decl_name.c_str()); + +    const char *uniqued_const_decl_name = const_decl_name.GetCString(); +    if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end()) +    { +        // We are currently looking up this name... +        SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); +        return false; +    } +    m_active_lookups.insert(uniqued_const_decl_name); +//  static uint32_t g_depth = 0; +//  ++g_depth; +//  printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name); +    llvm::SmallVector<NamedDecl*, 4> name_decls; +    NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx); +    FindExternalVisibleDecls(name_search_context); +    SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls); +//  --g_depth; +    m_active_lookups.erase (uniqued_const_decl_name); +    return (name_decls.size() != 0); +} + +void +ClangASTSource::CompleteType (TagDecl *tag_decl) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    if (log) +    { +        log->Printf("    CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s", +                    current_id, static_cast<void*>(m_ast_context), +                    static_cast<void*>(tag_decl), +                    tag_decl->getName().str().c_str()); + +        log->Printf("      CTD[%u] Before:", current_id); +        ASTDumper dumper((Decl*)tag_decl); +        dumper.ToLog(log, "      [CTD] "); +    } + +    auto iter = m_active_lexical_decls.find(tag_decl); +    if (iter != m_active_lexical_decls.end()) +        return; +    m_active_lexical_decls.insert(tag_decl); +    ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + +    if (!m_ast_importer_sp->CompleteTagDecl (tag_decl)) +    { +        // We couldn't complete the type.  Maybe there's a definition +        // somewhere else that can be completed. + +        if (log) +            log->Printf("      CTD[%u] Type could not be completed in the module in which it was first found.", current_id); + +        bool found = false; + +        DeclContext *decl_ctx = tag_decl->getDeclContext(); + +        if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx)) +        { +            ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + +            if (log && log->GetVerbose()) +                log->Printf("      CTD[%u] Inspecting namespace map %p (%d entries)", +                            current_id, static_cast<void*>(namespace_map.get()), +                            static_cast<int>(namespace_map->size())); + +            if (!namespace_map) +                return; + +            for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); +                 i != e && !found; +                 ++i) +            { +                if (log) +                    log->Printf("      CTD[%u] Searching namespace %s in module %s", +                                current_id, +                                i->second.GetName().AsCString(), +                                i->first->GetFileSpec().GetFilename().GetCString()); + +                TypeList types; + +                SymbolContext null_sc; +                ConstString name(tag_decl->getName().str().c_str()); + +                i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); + +                for (uint32_t ti = 0, te = types.GetSize(); +                     ti != te && !found; +                     ++ti) +                { +                    lldb::TypeSP type = types.GetTypeAtIndex(ti); + +                    if (!type) +                        continue; + +                    CompilerType clang_type (type->GetFullCompilerType ()); + +                    if (!clang_type) +                        continue; + +                    const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>(); + +                    if (!tag_type) +                        continue; + +                    TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl()); + +                    if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) +                        found = true; +                } +            } +        } +        else +        { +            TypeList types; + +            SymbolContext null_sc; +            ConstString name(tag_decl->getName().str().c_str()); +            CompilerDeclContext namespace_decl; + +            const ModuleList &module_list = m_target->GetImages(); + +            bool exact_match = false; +            module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types); + +            for (uint32_t ti = 0, te = types.GetSize(); +                 ti != te && !found; +                 ++ti) +            { +                lldb::TypeSP type = types.GetTypeAtIndex(ti); + +                if (!type) +                    continue; + +                CompilerType clang_type (type->GetFullCompilerType ()); + +                if (!clang_type) +                    continue; + +                const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>(); + +                if (!tag_type) +                    continue; + +                TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl()); + +                // We have found a type by basename and we need to make sure the decl contexts +                // are the same before we can try to complete this type with another +                if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl)) +                    continue; + +                if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) +                    found = true; +            } +        } +    } + +    if (log) +    { +        log->Printf("      [CTD] After:"); +        ASTDumper dumper((Decl*)tag_decl); +        dumper.ToLog(log, "      [CTD] "); +    } +} + +void +ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +    { +        log->Printf("    [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", +                    static_cast<void*>(m_ast_context), +                    interface_decl->getName().str().c_str()); +        log->Printf("      [COID] Before:"); +        ASTDumper dumper((Decl*)interface_decl); +        dumper.ToLog(log, "      [COID] "); +    } + +    Decl *original_decl = NULL; +    ASTContext *original_ctx = NULL; + +    if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) +    { +        if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl)) +        { +            ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + +            if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) +            { +                m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl); +            } +        } +    } + +    m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl); + +    if (interface_decl->getSuperClass() && +        interface_decl->getSuperClass() != interface_decl) +        CompleteType(interface_decl->getSuperClass()); + +    if (log) +    { +        log->Printf("      [COID] After:"); +        ASTDumper dumper((Decl*)interface_decl); +        dumper.ToLog(log, "      [COID] "); +    } +} + +clang::ObjCInterfaceDecl * +ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl) +{ +    lldb::ProcessSP process(m_target->GetProcessSP()); + +    if (!process) +        return NULL; + +    ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + +    if (!language_runtime) +        return NULL; + +    ConstString class_name(interface_decl->getNameAsString().c_str()); + +    lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + +    if (!complete_type_sp) +        return NULL; + +    TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ()); +    lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + +    if (!complete_opaque_type) +        return NULL; + +    const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); +    const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type); + +    if (!complete_interface_type) +        return NULL; + +    ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); + +    return complete_iface_decl; +} + +void +ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, +                                          llvm::function_ref<bool(Decl::Kind)> predicate, +                                          llvm::SmallVectorImpl<Decl*> &decls) +{ +    ClangASTMetrics::RegisterLexicalQuery(); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    const Decl *context_decl = dyn_cast<Decl>(decl_context); + +    if (!context_decl) +        return; + +    auto iter = m_active_lexical_decls.find(context_decl); +    if (iter != m_active_lexical_decls.end()) +        return; +    m_active_lexical_decls.insert(context_decl); +    ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    if (log) +    { +        if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) +            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", +                        current_id, static_cast<void*>(m_ast_context), +                        context_named_decl->getNameAsString().c_str(), +                        context_decl->getDeclKindName(), +                        static_cast<const void*>(context_decl)); +        else if(context_decl) +            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", +                        current_id, static_cast<void*>(m_ast_context), +                        context_decl->getDeclKindName(), +                        static_cast<const void*>(context_decl)); +        else +            log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", +                        current_id, static_cast<const void*>(m_ast_context)); +    } + +    Decl *original_decl = NULL; +    ASTContext *original_ctx = NULL; + +    if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) +        return; + +    if (log) +    { +        log->Printf("  FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", +                    current_id, static_cast<void*>(original_ctx), +                    static_cast<void*>(original_decl)); +        ASTDumper(original_decl).ToLog(log, "    "); +    } + +    if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl)) +    { +        ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + +        if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) +        { +            original_decl = complete_iface_decl; +            original_ctx = &complete_iface_decl->getASTContext(); + +            m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl); +        } +    } + +    if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) +    { +        ExternalASTSource *external_source = original_ctx->getExternalSource(); + +        if (external_source) +            external_source->CompleteType (original_tag_decl); +    } + +    const DeclContext *original_decl_context = dyn_cast<DeclContext>(original_decl); + +    if (!original_decl_context) +        return; + +    for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); +         iter != original_decl_context->decls_end(); +         ++iter) +    { +        Decl *decl = *iter; + +        if (predicate(decl->getKind())) +        { +            if (log) +            { +                ASTDumper ast_dumper(decl); +                if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl)) +                    log->Printf("  FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString()); +                else +                    log->Printf("  FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); +            } +             +            Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + +            if (!copied_decl) +                continue; + +            if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) +            { +                QualType copied_field_type = copied_field->getType(); + +                m_ast_importer_sp->RequireCompleteType(copied_field_type); +            } + +            DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context); + +            if (copied_decl->getDeclContext() != decl_context) +            { +                if (copied_decl->getDeclContext()->containsDecl(copied_decl)) +                    copied_decl->getDeclContext()->removeDecl(copied_decl); +                copied_decl->setDeclContext(decl_context_non_const); +            } + +            if (!decl_context_non_const->containsDecl(copied_decl)) +                decl_context_non_const->addDeclInternal(copied_decl); +        } +    } + +    return; +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) +{ +    assert (m_ast_context); + +    ClangASTMetrics::RegisterVisibleQuery(); + +    const ConstString name(context.m_decl_name.getAsString().c_str()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    if (log) +    { +        if (!context.m_decl_context) +            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", +                        current_id, static_cast<void*>(m_ast_context), +                        name.GetCString()); +        else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) +            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", +                        current_id, static_cast<void*>(m_ast_context), +                        name.GetCString(), +                        context_named_decl->getNameAsString().c_str()); +        else +            log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", +                        current_id, static_cast<void*>(m_ast_context), +                        name.GetCString(), +                        context.m_decl_context->getDeclKindName()); +    } + +    context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); + +    if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) +    { +        ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + +        if (log && log->GetVerbose()) +            log->Printf("  CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", +                        current_id, static_cast<void*>(namespace_map.get()), +                        static_cast<int>(namespace_map->size())); + +        if (!namespace_map) +            return; + +        for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); +             i != e; +             ++i) +        { +            if (log) +                log->Printf("  CAS::FEVD[%u] Searching namespace %s in module %s", +                            current_id, +                            i->second.GetName().AsCString(), +                            i->first->GetFileSpec().GetFilename().GetCString()); + +            FindExternalVisibleDecls(context, +                                     i->first, +                                     i->second, +                                     current_id); +        } +    } +    else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) +    { +        FindObjCPropertyAndIvarDecls(context); +    } +    else if (!isa<TranslationUnitDecl>(context.m_decl_context)) +    { +        // we shouldn't be getting FindExternalVisibleDecls calls for these +        return; +    } +    else +    { +        CompilerDeclContext namespace_decl; + +        if (log) +            log->Printf("  CAS::FEVD[%u] Searching the root namespace", current_id); + +        FindExternalVisibleDecls(context, +                                 lldb::ModuleSP(), +                                 namespace_decl, +                                 current_id); +    } + +    if (!context.m_namespace_map->empty()) +    { +        if (log && log->GetVerbose()) +            log->Printf("  CAS::FEVD[%u] Registering namespace map %p (%d entries)", +                        current_id, +                        static_cast<void*>(context.m_namespace_map.get()), +                        static_cast<int>(context.m_namespace_map->size())); + +        NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); + +        if (clang_namespace_decl) +            clang_namespace_decl->setHasExternalVisibleStorage(); +    } +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, +                                          lldb::ModuleSP module_sp, +                                          CompilerDeclContext &namespace_decl, +                                          unsigned int current_id) +{ +    assert (m_ast_context); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    SymbolContextList sc_list; + +    const ConstString name(context.m_decl_name.getAsString().c_str()); + +    const char *name_unique_cstr = name.GetCString(); + +    static ConstString id_name("id"); +    static ConstString Class_name("Class"); + +    if (name == id_name || name == Class_name) +        return; + +    if (name_unique_cstr == NULL) +        return; + +    // The ClangASTSource is not responsible for finding $-names. +    if (name_unique_cstr[0] == '$') +        return; + +    if (module_sp && namespace_decl) +    { +        CompilerDeclContext found_namespace_decl; + +        SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + +        if (symbol_vendor) +        { +            SymbolContext null_sc; + +            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + +            if (found_namespace_decl) +            { +                context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl)); + +                if (log) +                    log->Printf("  CAS::FEVD[%u] Found namespace %s in module %s", +                                current_id, +                                name.GetCString(), +                                module_sp->GetFileSpec().GetFilename().GetCString()); +            } +        } +    } +    else +    { +        const ModuleList &target_images = m_target->GetImages(); +        Mutex::Locker modules_locker (target_images.GetMutex()); + +        for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) +        { +            lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + +            if (!image) +                continue; + +            CompilerDeclContext found_namespace_decl; + +            SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + +            if (!symbol_vendor) +                continue; + +            SymbolContext null_sc; + +            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + +            if (found_namespace_decl) +            { +                context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl)); + +                if (log) +                    log->Printf("  CAS::FEVD[%u] Found namespace %s in module %s", +                                current_id, +                                name.GetCString(), +                                image->GetFileSpec().GetFilename().GetCString()); +            } +        } +    } + +    do +    { +        TypeList types; +        SymbolContext null_sc; +        const bool exact_match = false; + +        if (module_sp && namespace_decl) +            module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); +        else +            m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); + +        bool found_a_type = false; +         +        if (size_t num_types = types.GetSize()) +        { +            for (size_t ti = 0; ti < num_types; ++ti) +            { +                lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); +                 +                if (log) +                { +                    const char *name_string = type_sp->GetName().GetCString(); +                     +                    log->Printf("  CAS::FEVD[%u] Matching type found for \"%s\": %s", +                                current_id, +                                name.GetCString(), +                                (name_string ? name_string : "<anonymous>")); +                } +                 +                CompilerType full_type = type_sp->GetFullCompilerType(); +                 +                CompilerType copied_clang_type (GuardedCopyType(full_type)); +                 +                if (!copied_clang_type) +                { +                    if (log) +                        log->Printf("  CAS::FEVD[%u] - Couldn't export a type", +                                    current_id); +                     +                    continue; +                } +                 +                context.AddTypeDecl(copied_clang_type); +                 +                found_a_type = true; +                break; +            } +        } + +        if (!found_a_type) +        { +            // Try the modules next. +             +            do +            { +                if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) +                { +                    bool append = false; +                    uint32_t max_matches = 1; +                    std::vector <clang::NamedDecl *> decls; +                     +                    if (!modules_decl_vendor->FindDecls(name, +                                                        append, +                                                        max_matches, +                                                        decls)) +                        break; + +                    if (log) +                    { +                        log->Printf("  CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", +                                    current_id, +                                    name.GetCString()); +                    } +                     +                    clang::NamedDecl *const decl_from_modules = decls[0]; +                     +                    if (llvm::isa<clang::TypeDecl>(decl_from_modules) || +                        llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) || +                        llvm::isa<clang::EnumConstantDecl>(decl_from_modules)) +                    { +                        clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); +                        clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; +                         +                        if (!copied_named_decl) +                        { +                            if (log) +                                log->Printf("  CAS::FEVD[%u] - Couldn't export a type from the modules", +                                            current_id); +                             +                            break; +                        } +                         +                        context.AddNamedDecl(copied_named_decl); +                         +                        found_a_type = true; +                    } +                } +            } while (0); +        } +         +        if (!found_a_type) +        { +            do +            { +                // Couldn't find any types elsewhere.  Try the Objective-C runtime if one exists. + +                lldb::ProcessSP process(m_target->GetProcessSP()); + +                if (!process) +                    break; + +                ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + +                if (!language_runtime) +                    break; + +                DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + +                if (!decl_vendor) +                    break; + +                bool append = false; +                uint32_t max_matches = 1; +                std::vector <clang::NamedDecl *> decls; + +                if (!decl_vendor->FindDecls(name, +                                            append, +                                            max_matches, +                                            decls)) +                    break; + +                if (log) +                { +                    log->Printf("  CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", +                                current_id, +                                name.GetCString()); +                } +                 +                clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); +                clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr; +                 +                if (!copied_named_decl) +                { +                    if (log) +                        log->Printf("  CAS::FEVD[%u] - Couldn't export a type from the runtime", +                                    current_id); + +                    break; +                } + +                context.AddNamedDecl(copied_named_decl); +            } +            while(0); +        } + +    } while(0); +} + +template <class D> class TaggedASTDecl { +public: +    TaggedASTDecl() : decl(NULL) { } +    TaggedASTDecl(D *_decl) : decl(_decl) { } +    bool IsValid() const { return (decl != NULL); } +    bool IsInvalid() const { return !IsValid(); } +    D *operator->() const { return decl; } +    D *decl; +}; + +template <class D2, template <class D> class TD, class D1> +TD<D2> +DynCast(TD<D1> source) +{ +    return TD<D2> (dyn_cast<D2>(source.decl)); +} + +template <class D = Decl> class DeclFromParser; +template <class D = Decl> class DeclFromUser; + +template <class D> class DeclFromParser : public TaggedASTDecl<D> { +public: +    DeclFromParser() : TaggedASTDecl<D>() { } +    DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { } + +    DeclFromUser<D> GetOrigin(ClangASTImporter *importer); +}; + +template <class D> class DeclFromUser : public TaggedASTDecl<D> { +public: +    DeclFromUser() : TaggedASTDecl<D>() { } +    DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { } + +    DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx); +}; + +template <class D> +DeclFromUser<D> +DeclFromParser<D>::GetOrigin(ClangASTImporter *importer) +{ +    DeclFromUser <> origin_decl; +    importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); +    if (origin_decl.IsInvalid()) +        return DeclFromUser<D>(); +    return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl)); +} + +template <class D> +DeclFromParser<D> +DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx) +{ +    DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); +    if (parser_generic_decl.IsInvalid()) +        return DeclFromParser<D>(); +    return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl)); +} + +static bool +FindObjCMethodDeclsWithOrigin (unsigned int current_id, +                               NameSearchContext &context, +                               ObjCInterfaceDecl *original_interface_decl, +                               clang::ASTContext *ast_context, +                               ClangASTImporter *ast_importer, +                               const char *log_info) +{ +    const DeclarationName &decl_name(context.m_decl_name); +    clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); + +    Selector original_selector; + +    if (decl_name.isObjCZeroArgSelector()) +    { +        IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); +        original_selector = original_ctx->Selectors.getSelector(0, &ident); +    } +    else if (decl_name.isObjCOneArgSelector()) +    { +        const std::string &decl_name_string = decl_name.getAsString(); +        std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); +        IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); +        original_selector = original_ctx->Selectors.getSelector(1, &ident); +    } +    else +    { +        SmallVector<IdentifierInfo *, 4> idents; + +        clang::Selector sel = decl_name.getObjCSelector(); + +        unsigned num_args = sel.getNumArgs(); + +        for (unsigned i = 0; +             i != num_args; +             ++i) +        { +            idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); +        } + +        original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); +    } + +    DeclarationName original_decl_name(original_selector); +     +    llvm::SmallVector<NamedDecl *, 1> methods; +     +    ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); +     +    if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) +    { +        methods.push_back(instance_method_decl); +    } +    else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) +    { +        methods.push_back(class_method_decl); +    } +     +    if (methods.empty()) +    { +        return false; +    } +     +    for (NamedDecl *named_decl : methods) +    { +        if (!named_decl) +            continue; +         +        ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl); + +        if (!result_method) +            continue; + +        Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); + +        if (!copied_decl) +            continue; + +        ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + +        if (!copied_method_decl) +            continue; + +        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +        if (log) +        { +            ASTDumper dumper((Decl*)copied_method_decl); +            log->Printf("  CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); +        } + +        context.AddNamedDecl(copied_method_decl); +    } + +    return true; +} + +void +ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    const DeclarationName &decl_name(context.m_decl_name); +    const DeclContext *decl_ctx(context.m_decl_context); + +    const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx); + +    if (!interface_decl) +        return; + +    do +    { +        Decl *original_decl = NULL; +        ASTContext *original_ctx = NULL; + +        m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); + +        if (!original_decl) +            break; + +        ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl); + +        if (FindObjCMethodDeclsWithOrigin(current_id, +                                          context, +                                          original_interface_decl, +                                          m_ast_context, +                                          m_ast_importer_sp.get(), +                                          "at origin")) +            return; // found it, no need to look any further +    } while (0); + +    StreamString ss; + +    if (decl_name.isObjCZeroArgSelector()) +    { +        ss.Printf("%s", decl_name.getAsString().c_str()); +    } +    else if (decl_name.isObjCOneArgSelector()) +    { +        ss.Printf("%s", decl_name.getAsString().c_str()); +    } +    else +    { +        clang::Selector sel = decl_name.getObjCSelector(); + +        for (unsigned i = 0, e = sel.getNumArgs(); +             i != e; +             ++i) +        { +            llvm::StringRef r = sel.getNameForSlot(i); +            ss.Printf("%s:", r.str().c_str()); +        } +    } +    ss.Flush(); + +    if (strstr(ss.GetData(), "$__lldb")) +        return; // we don't need any results + +    ConstString selector_name(ss.GetData()); + +    if (log) +        log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]", +                    current_id, static_cast<void*>(m_ast_context), +                    interface_decl->getNameAsString().c_str(), +                    selector_name.AsCString()); +    SymbolContextList sc_list; + +    const bool include_symbols = false; +    const bool include_inlines = false; +    const bool append = false; + +    std::string interface_name = interface_decl->getNameAsString(); + +    do +    { +        StreamString ms; +        ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); +        ms.Flush(); +        ConstString instance_method_name(ms.GetData()); + +        m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + +        if (sc_list.GetSize()) +            break; + +        ms.Clear(); +        ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); +        ms.Flush(); +        ConstString class_method_name(ms.GetData()); + +        m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + +        if (sc_list.GetSize()) +            break; + +        // Fall back and check for methods in categories.  If we find methods this way, we need to check that they're actually in +        // categories on the desired class. + +        SymbolContextList candidate_sc_list; + +        m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list); + +        for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); +             ci != ce; +             ++ci) +        { +            SymbolContext candidate_sc; + +            if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) +                continue; + +            if (!candidate_sc.function) +                continue; + +            const char *candidate_name = candidate_sc.function->GetName().AsCString(); + +            const char *cursor = candidate_name; + +            if (*cursor != '+' && *cursor != '-') +                continue; + +            ++cursor; + +            if (*cursor != '[') +                continue; + +            ++cursor; + +            size_t interface_len = interface_name.length(); + +            if (strncmp(cursor, interface_name.c_str(), interface_len)) +                continue; + +            cursor += interface_len; + +            if (*cursor == ' ' || *cursor == '(') +                sc_list.Append(candidate_sc); +        } +    } +    while (0); + +    if (sc_list.GetSize()) +    { +        // We found a good function symbol.  Use that. + +        for (uint32_t i = 0, e = sc_list.GetSize(); +             i != e; +             ++i) +        { +            SymbolContext sc; + +            if (!sc_list.GetContextAtIndex(i, sc)) +                continue; + +            if (!sc.function) +                continue; + +            CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext(); +            if (!function_decl_ctx) +                continue; + +            ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + +            if (!method_decl) +                continue; + +            ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); + +            if (!found_interface_decl) +                continue; + +            if (found_interface_decl->getName() == interface_decl->getName()) +            { +                Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + +                if (!copied_decl) +                    continue; + +                ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl); + +                if (!copied_method_decl) +                    continue; + +                if (log) +                { +                    ASTDumper dumper((Decl*)copied_method_decl); +                    log->Printf("  CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); +                } + +                context.AddNamedDecl(copied_method_decl); +            } +        } + +        return; +    } + +    // Try the debug information. + +    do +    { +        ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl)); + +        if (!complete_interface_decl) +            break; + +        // We found the complete interface.  The runtime never needs to be queried in this scenario. + +        DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl); + +        if (complete_interface_decl == interface_decl) +            break; // already checked this one + +        if (log) +            log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", +                        current_id, static_cast<void*>(complete_interface_decl), +                        static_cast<void*>(&complete_iface_decl->getASTContext())); + +        FindObjCMethodDeclsWithOrigin(current_id, +                                      context, +                                      complete_interface_decl, +                                      m_ast_context, +                                      m_ast_importer_sp.get(), +                                      "in debug info"); + +        return; +    } +    while (0); +     +    do +    { +        // Check the modules only if the debug information didn't have a complete interface. +         +        if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) +        { +            ConstString interface_name(interface_decl->getNameAsString().c_str()); +            bool append = false; +            uint32_t max_matches = 1; +            std::vector <clang::NamedDecl *> decls; +             +            if (!modules_decl_vendor->FindDecls(interface_name, +                                                append, +                                                max_matches, +                                                decls)) +                break; + +            ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast<ObjCInterfaceDecl>(decls[0]); +             +            if (!interface_decl_from_modules) +                break; +             +            if (FindObjCMethodDeclsWithOrigin(current_id, +                                              context, +                                              interface_decl_from_modules, +                                              m_ast_context, +                                              m_ast_importer_sp.get(), +                                              "in modules")) +                return; +        } +    } +    while (0); + +    do +    { +        // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. + +        lldb::ProcessSP process(m_target->GetProcessSP()); + +        if (!process) +            break; + +        ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + +        if (!language_runtime) +            break; + +        DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + +        if (!decl_vendor) +            break; + +        ConstString interface_name(interface_decl->getNameAsString().c_str()); +        bool append = false; +        uint32_t max_matches = 1; +        std::vector <clang::NamedDecl *> decls; + +        if (!decl_vendor->FindDecls(interface_name, +                                    append, +                                    max_matches, +                                    decls)) +            break; + +        ObjCInterfaceDecl *runtime_interface_decl = dyn_cast<ObjCInterfaceDecl>(decls[0]); +         +        if (!runtime_interface_decl) +            break; + +        FindObjCMethodDeclsWithOrigin(current_id, +                                      context, +                                      runtime_interface_decl, +                                      m_ast_context, +                                      m_ast_importer_sp.get(), +                                      "in runtime"); +    } +    while(0); +} + +static bool +FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, +                                        NameSearchContext &context, +                                        clang::ASTContext &ast_context, +                                        ClangASTImporter *ast_importer, +                                        DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (origin_iface_decl.IsInvalid()) +        return false; + +    std::string name_str = context.m_decl_name.getAsString(); +    StringRef name(name_str.c_str()); +    IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); + +    DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); + +    bool found = false; + +    if (origin_property_decl.IsValid()) +    { +        DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); +        if (parser_property_decl.IsValid()) +        { +            if (log) +            { +                ASTDumper dumper((Decl*)parser_property_decl.decl); +                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); +            } + +            context.AddNamedDecl(parser_property_decl.decl); +            found = true; +        } +    } + +    DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); + +    if (origin_ivar_decl.IsValid()) +    { +        DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); +        if (parser_ivar_decl.IsValid()) +        { +            if (log) +            { +                ASTDumper dumper((Decl*)parser_ivar_decl.decl); +                log->Printf("  CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); +            } + +            context.AddNamedDecl(parser_ivar_decl.decl); +            found = true; +        } +    } + +    return found; +} + +void +ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context)); +    DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + +    ConstString class_name(parser_iface_decl->getNameAsString().c_str()); + +    if (log) +        log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", +                    current_id, static_cast<void*>(m_ast_context), +                    parser_iface_decl->getNameAsString().c_str(), +                    context.m_decl_name.getAsString().c_str()); + +    if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, +                                               context, +                                               *m_ast_context, +                                               m_ast_importer_sp.get(), +                                               origin_iface_decl)) +        return; + +    if (log) +        log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", +                    current_id, static_cast<const void*>(origin_iface_decl.decl), +                    static_cast<void*>(&origin_iface_decl->getASTContext())); + +    SymbolContext null_sc; +    TypeList type_list; + +    do +    { +        ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl)); + +        if (!complete_interface_decl) +            break; + +        // We found the complete interface.  The runtime never needs to be queried in this scenario. + +        DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl); + +        if (complete_iface_decl.decl == origin_iface_decl.decl) +            break; // already checked this one + +        if (log) +            log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", +                        current_id, +                        static_cast<const void*>(complete_iface_decl.decl), +                        static_cast<void*>(&complete_iface_decl->getASTContext())); + +        FindObjCPropertyAndIvarDeclsWithOrigin(current_id, +                                               context, +                                               *m_ast_context, +                                               m_ast_importer_sp.get(), +                                               complete_iface_decl); + +        return; +    } +    while(0); +     +    do +    { +        // Check the modules only if the debug information didn't have a complete interface. +         +        ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); +         +        if (!modules_decl_vendor) +            break; +         +        bool append = false; +        uint32_t max_matches = 1; +        std::vector <clang::NamedDecl *> decls; +         +        if (!modules_decl_vendor->FindDecls(class_name, +                                            append, +                                            max_matches, +                                            decls)) +            break; +         +        DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules(dyn_cast<ObjCInterfaceDecl>(decls[0])); +         +        if (!interface_decl_from_modules.IsValid()) +            break; +         +        if (log) +            log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", +                        current_id, +                        static_cast<const void*>(interface_decl_from_modules.decl), +                        static_cast<void*>(&interface_decl_from_modules->getASTContext())); +         +        if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, +                                                   context, +                                                   *m_ast_context, +                                                   m_ast_importer_sp.get(), +                                                   interface_decl_from_modules)) +            return; +    } +    while(0); + +    do +    { +        // Check the runtime only if the debug information didn't have a complete interface +        // and nothing was in the modules. + +        lldb::ProcessSP process(m_target->GetProcessSP()); + +        if (!process) +            return; + +        ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + +        if (!language_runtime) +            return; + +        DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + +        if (!decl_vendor) +            break; + +        bool append = false; +        uint32_t max_matches = 1; +        std::vector <clang::NamedDecl *> decls; + +        if (!decl_vendor->FindDecls(class_name, +                                    append, +                                    max_matches, +                                    decls)) +            break; + +        DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime(dyn_cast<ObjCInterfaceDecl>(decls[0])); +         +        if (!interface_decl_from_runtime.IsValid()) +            break; + +        if (log) +            log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", +                        current_id, +                        static_cast<const void*>(interface_decl_from_runtime.decl), +                        static_cast<void*>(&interface_decl_from_runtime->getASTContext())); + +        if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, +                                                   context, +                                                   *m_ast_context, +                                                   m_ast_importer_sp.get(), +                                                   interface_decl_from_runtime)) +            return; +    } +    while(0); +} + +typedef llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsetMap; +typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap; + +template <class D, class O> +static bool +ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map, +                ClangASTImporter *importer, ASTContext &dest_ctx) +{ +    // When importing fields into a new record, clang has a hard requirement that +    // fields be imported in field offset order.  Since they are stored in a DenseMap +    // with a pointer as the key type, this means we cannot simply iterate over the +    // map, as the order will be non-deterministic.  Instead we have to sort by the offset +    // and then insert in sorted order. +    typedef llvm::DenseMap<const D *, O> MapType; +    typedef typename MapType::value_type PairType; +    std::vector<PairType> sorted_items; +    sorted_items.reserve(source_map.size()); +    sorted_items.assign(source_map.begin(), source_map.end()); +    std::sort(sorted_items.begin(), sorted_items.end(), +              [](const PairType &lhs, const PairType &rhs) +              { +                  return lhs.second < rhs.second; +              }); + +    for (const auto &item : sorted_items) +    { +        DeclFromUser<D> user_decl(const_cast<D *>(item.first)); +        DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx)); +        if (parser_decl.IsInvalid()) +            return false; +        destination_map.insert(std::pair<const D *, O>(parser_decl.decl, item.second)); +    } + +    return true; +} + +template <bool IsVirtual> +bool +ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser<const CXXRecordDecl> &record, +                   BaseOffsetMap &base_offsets) +{ +    for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), +                                                  be = (IsVirtual ? record->vbases_end() : record->bases_end()); +         bi != be; ++bi) +    { +        if (!IsVirtual && bi->isVirtual()) +            continue; + +        const clang::Type *origin_base_type = bi->getType().getTypePtr(); +        const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>(); + +        if (!origin_base_record_type) +            return false; + +        DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl()); + +        if (origin_base_record.IsInvalid()) +            return false; + +        DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record)); + +        if (origin_base_cxx_record.IsInvalid()) +            return false; + +        CharUnits base_offset; + +        if (IsVirtual) +            base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); +        else +            base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); + +        base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset)); +    } + +    return true; +} + +bool +ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, +                                 FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, +                                 BaseOffsetMap &virtual_base_offsets) +{ +    ClangASTMetrics::RegisterRecordLayout(); + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +        log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']", +                    current_id, static_cast<void*>(m_ast_context), +                    static_cast<const void*>(record), +                    record->getNameAsString().c_str()); + +    DeclFromParser <const RecordDecl> parser_record(record); +    DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer_sp.get())); + +    if (origin_record.IsInvalid()) +        return false; + +    FieldOffsetMap origin_field_offsets; +    BaseOffsetMap origin_base_offsets; +    BaseOffsetMap origin_virtual_base_offsets; + +    ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl)); + +    clang::RecordDecl* definition = origin_record.decl->getDefinition(); +    if (!definition || !definition->isCompleteDefinition()) +        return false; + +    const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); + +    int field_idx = 0, field_count = record_layout.getFieldCount(); + +    for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) +    { +        if (field_idx >= field_count) +            return false; // Layout didn't go well.  Bail out. + +        uint64_t field_offset = record_layout.getFieldOffset(field_idx); + +        origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset)); + +        field_idx++; +    } + +    ASTContext &parser_ast_context(record->getASTContext()); + +    DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record)); + +    if (origin_cxx_record.IsValid()) +    { +        if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) || +            !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets)) +            return false; +    } + +    if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) || +        !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) || +        !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context)) +        return false; + +    size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); +    alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); + +    if (log) +    { +        log->Printf("LRT[%u] returned:", current_id); +        log->Printf("LRT[%u]   Original = (RecordDecl*)%p", current_id, +                    static_cast<const void*>(origin_record.decl)); +        log->Printf("LRT[%u]   Size = %" PRId64, current_id, size); +        log->Printf("LRT[%u]   Alignment = %" PRId64, current_id, alignment); +        log->Printf("LRT[%u]   Fields:", current_id); +        for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); +             fi != fe; +             ++fi) +        { +            log->Printf("LRT[%u]     (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, +                        static_cast<void *>(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); +        } +        DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record); +        if (parser_cxx_record.IsValid()) +        { +            log->Printf("LRT[%u]   Bases:", current_id); +            for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); +                 bi != be; +                 ++bi) +            { +                bool is_virtual = bi->isVirtual(); + +                QualType base_type = bi->getType(); +                const RecordType *base_record_type = base_type->getAs<RecordType>(); +                DeclFromParser <RecordDecl> base_record(base_record_type->getDecl()); +                DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record); + +                log->Printf("LRT[%u]     %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, +                            (is_virtual ? "Virtual " : ""), static_cast<void *>(base_cxx_record.decl), +                            base_cxx_record.decl->getNameAsString().c_str(), +                            (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() +                                        : base_offsets[base_cxx_record.decl].getQuantity())); +            } +        } +        else +        { +            log->Printf("LRD[%u]   Not a CXXRecord, so no bases", current_id); +        } +    } + +    return true; +} + +void +ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, +                                      const ConstString &name, +                                      ClangASTImporter::NamespaceMapSP &parent_map) const +{ +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +    { +        if (parent_map && parent_map->size()) +            log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s", +                        current_id, static_cast<void*>(m_ast_context), +                        name.GetCString(), +                        parent_map->begin()->second.GetName().AsCString()); +        else +            log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s", +                        current_id, static_cast<void*>(m_ast_context), +                        name.GetCString()); +    } + +    if (parent_map) +    { +        for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end(); +             i != e; +             ++i) +        { +            CompilerDeclContext found_namespace_decl; + +            lldb::ModuleSP module_sp = i->first; +            CompilerDeclContext module_parent_namespace_decl = i->second; + +            SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + +            if (!symbol_vendor) +                continue; + +            SymbolContext null_sc; + +            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl); + +            if (!found_namespace_decl) +                continue; + +            namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl)); + +            if (log) +                log->Printf("  CMN[%u] Found namespace %s in module %s", +                            current_id, +                            name.GetCString(), +                            module_sp->GetFileSpec().GetFilename().GetCString()); +        } +    } +    else +    { +        const ModuleList &target_images = m_target->GetImages(); +        Mutex::Locker modules_locker(target_images.GetMutex()); + +        CompilerDeclContext null_namespace_decl; + +        for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) +        { +            lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + +            if (!image) +                continue; + +            CompilerDeclContext found_namespace_decl; + +            SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + +            if (!symbol_vendor) +                continue; + +            SymbolContext null_sc; + +            found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); + +            if (!found_namespace_decl) +                continue; + +            namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl)); + +            if (log) +                log->Printf("  CMN[%u] Found namespace %s in module %s", +                            current_id, +                            name.GetCString(), +                            image->GetFileSpec().GetFilename().GetCString()); +        } +    } +} + +NamespaceDecl * +ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) +{ +    if (!namespace_decls) +        return nullptr; + +    const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second; + +    clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl); +    if (!src_ast) +        return nullptr; +    clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl); + +    if (!src_namespace_decl) +        return nullptr; + +    Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + +    if (!copied_decl) +        return nullptr; + +    NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl); + +    if (!copied_namespace_decl) +        return nullptr; + +    context.m_decls.push_back(copied_namespace_decl); + +    m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls); + +    return dyn_cast<NamespaceDecl>(copied_decl); +} + +CompilerType +ClangASTSource::GuardedCopyType (const CompilerType &src_type) +{ +    ClangASTContext *src_ast = llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); +    if (src_ast == nullptr) +        return CompilerType(); + +    ClangASTMetrics::RegisterLLDBImport(); + +    SetImportInProgress(true); + +    QualType copied_qual_type = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type)); + +    SetImportInProgress(false); + +    if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) +        // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types +        // on occasion. +        return CompilerType(); + +    return CompilerType(m_ast_context, copied_qual_type); +} + +clang::NamedDecl * +NameSearchContext::AddVarDecl(const CompilerType &type) +{ +    assert (type && "Type for variable must be valid!"); + +    if (!type.IsValid()) +        return NULL; + +    ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); +    if (!lldb_ast) +        return NULL; +     +    IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); + +    clang::ASTContext *ast = lldb_ast->getASTContext(); + +    clang::NamedDecl *Decl = VarDecl::Create(*ast, +                                             const_cast<DeclContext*>(m_decl_context), +                                             SourceLocation(), +                                             SourceLocation(), +                                             ii, +                                             ClangASTContext::GetQualType(type), +                                             0, +                                             SC_Static); +    m_decls.push_back(Decl); + +    return Decl; +} + +clang::NamedDecl * +NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c) +{ +    assert (type && "Type for variable must be valid!"); + +    if (!type.IsValid()) +        return NULL; + +    if (m_function_types.count(type)) +        return NULL; +     +    ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem()); +    if (!lldb_ast) +        return NULL; + +    m_function_types.insert(type); + +    QualType qual_type (ClangASTContext::GetQualType(type)); + +    clang::ASTContext *ast = lldb_ast->getASTContext(); + +    const bool isInlineSpecified = false; +    const bool hasWrittenPrototype = true; +    const bool isConstexprSpecified = false; +     +    clang::DeclContext *context = const_cast<DeclContext*>(m_decl_context); +     +    if (extern_c) { +        context = LinkageSpecDecl::Create(*ast, +                                          context, +                                          SourceLocation(), +                                          SourceLocation(), +                                          clang::LinkageSpecDecl::LanguageIDs::lang_c, +                                          false); +    } + +    // Pass the identifier info for functions the decl_name is needed for operators +    clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name; + +    clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, +                                                           context, +                                                           SourceLocation(), +                                                           SourceLocation(), +                                                           decl_name, +                                                           qual_type, +                                                           NULL, +                                                           SC_Extern, +                                                           isInlineSpecified, +                                                           hasWrittenPrototype, +                                                           isConstexprSpecified); + +    // We have to do more than just synthesize the FunctionDecl.  We have to +    // synthesize ParmVarDecls for all of the FunctionDecl's arguments.  To do +    // this, we raid the function's FunctionProtoType for types. + +    const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>(); + +    if (func_proto_type) +    { +        unsigned NumArgs = func_proto_type->getNumParams(); +        unsigned ArgIndex; + +        SmallVector<ParmVarDecl *, 5> parm_var_decls; + +        for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) +        { +            QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); + +            parm_var_decls.push_back(ParmVarDecl::Create (*ast, +                                                          const_cast<DeclContext*>(context), +                                                          SourceLocation(), +                                                          SourceLocation(), +                                                          NULL, +                                                          arg_qual_type, +                                                          NULL, +                                                          SC_Static, +                                                          NULL)); +        } + +        func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls)); +    } +    else +    { +        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +        if (log) +            log->Printf("Function type wasn't a FunctionProtoType"); +    } + +    m_decls.push_back(func_decl); + +    return func_decl; +} + +clang::NamedDecl * +NameSearchContext::AddGenericFunDecl() +{ +    FunctionProtoType::ExtProtoInfo proto_info; + +    proto_info.Variadic = true; + +    QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy,    // result +                                                                                ArrayRef<QualType>(),                                        // argument types +                                                                                proto_info)); + +    return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true); +} + +clang::NamedDecl * +NameSearchContext::AddTypeDecl(const CompilerType &clang_type) +{ +    if (clang_type) +    { +        QualType qual_type = ClangASTContext::GetQualType(clang_type); + +        if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type)) +        { +            TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); + +            m_decls.push_back(typedef_name_decl); + +            return (NamedDecl*)typedef_name_decl; +        } +        else if (const TagType *tag_type = qual_type->getAs<TagType>()) +        { +            TagDecl *tag_decl = tag_type->getDecl(); + +            m_decls.push_back(tag_decl); + +            return tag_decl; +        } +        else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>()) +        { +            ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); + +            m_decls.push_back((NamedDecl*)interface_decl); + +            return (NamedDecl*)interface_decl; +        } +    } +    return NULL; +} + +void +NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) +{ +    for (clang::NamedDecl *decl : result) +        m_decls.push_back (decl); +} + +void +NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) +{ +    m_decls.push_back (decl); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h new file mode 100644 index 0000000000000..bb6384721f513 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -0,0 +1,526 @@ +//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include <set> + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { +     +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types.  Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource :  +    public ClangExternalASTSourceCommon, +    public ClangASTImporter::MapCompleter +{ +public: +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// Initializes class variables. +    /// +    /// @param[in] declMap +    ///     A reference to the LLDB object that handles entity lookup. +    //------------------------------------------------------------------ +    ClangASTSource (const lldb::TargetSP &target) : +        m_import_in_progress (false), +        m_lookups_enabled (false), +        m_target (target), +        m_ast_context (NULL), +        m_active_lexical_decls (), +        m_active_lookups () +    { +        m_ast_importer_sp = m_target->GetClangASTImporter(); +    } +   +    //------------------------------------------------------------------ +    /// Destructor +    //------------------------------------------------------------------ +    ~ClangASTSource() override; +     +    //------------------------------------------------------------------ +    /// Interface stubs. +    //------------------------------------------------------------------ +    clang::Decl *GetExternalDecl (uint32_t) override {   return NULL;                } +    clang::Stmt *GetExternalDeclStmt (uint64_t) override {   return NULL;                } +    clang::Selector GetExternalSelector (uint32_t) override {   return clang::Selector();   } +    uint32_t GetNumExternalSelectors () override {   return 0;                   } +    clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override +                                                    {   return NULL;                } +    void MaterializeVisibleDecls (const clang::DeclContext *DC) +                                                    {   return;                     } +       +    void InstallASTContext (clang::ASTContext *ast_context) +    { +        m_ast_context = ast_context; +        m_ast_importer_sp->InstallMapCompleter(ast_context, *this); +    } +   +    // +    // APIs for ExternalASTSource +    // + +    //------------------------------------------------------------------ +    /// Look up all Decls that match a particular name.  Only handles +    /// Identifiers and DeclContexts that are either NamespaceDecls or +    /// TranslationUnitDecls.  Calls SetExternalVisibleDeclsForName with +    /// the result. +    /// +    /// The work for this function is done by +    /// void FindExternalVisibleDecls (NameSearchContext &); +    /// +    /// @param[in] DC +    ///     The DeclContext to register the found Decls in. +    /// +    /// @param[in] Name +    ///     The name to find entries for. +    /// +    /// @return +    ///     Whatever SetExternalVisibleDeclsForName returns. +    //------------------------------------------------------------------ +    bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + +    //------------------------------------------------------------------ +    /// Enumerate all Decls in a given lexical context. +    /// +    /// @param[in] DC +    ///     The DeclContext being searched. +    /// +    /// @param[in] isKindWeWant +    ///     A callback function that returns true given the +    ///     DeclKinds of desired Decls, and false otherwise. +    /// +    /// @param[in] Decls +    ///     A vector that is filled in with matching Decls. +    //------------------------------------------------------------------ +    void FindExternalLexicalDecls( +        const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, +        llvm::SmallVectorImpl<clang::Decl *> &Decls) override; + +    //------------------------------------------------------------------ +    /// Specify the layout of the contents of a RecordDecl. +    /// +    /// @param[in] Record +    ///     The record (in the parser's AST context) that needs to be +    ///     laid out. +    /// +    /// @param[out] Size +    ///     The total size of the record in bits. +    /// +    /// @param[out] Alignment +    ///     The alignment of the record in bits. +    /// +    /// @param[in] FieldOffsets +    ///     A map that must be populated with pairs of the record's +    ///     fields (in the parser's AST context) and their offsets +    ///     (measured in bits). +    /// +    /// @param[in] BaseOffsets +    ///     A map that must be populated with pairs of the record's +    ///     C++ concrete base classes (in the parser's AST context,  +    ///     and only if the record is a CXXRecordDecl and has base +    ///     classes) and their offsets (measured in bytes). +    /// +    /// @param[in] VirtualBaseOffsets +    ///     A map that must be populated with pairs of the record's +    ///     C++ virtual base classes (in the parser's AST context,  +    ///     and only if the record is a CXXRecordDecl and has base +    ///     classes) and their offsets (measured in bytes). +    /// +    /// @return +    ///     True <=> the layout is valid. +    //----------------------------------------------------------------- +    bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, +                          llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, +                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, +                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override; + +    //------------------------------------------------------------------ +    /// Complete a TagDecl. +    /// +    /// @param[in] Tag +    ///     The Decl to be completed in place. +    //------------------------------------------------------------------ +    void CompleteType(clang::TagDecl *Tag) override; + +    //------------------------------------------------------------------ +    /// Complete an ObjCInterfaceDecl. +    /// +    /// @param[in] Class +    ///     The Decl to be completed in place. +    //------------------------------------------------------------------ +    void CompleteType(clang::ObjCInterfaceDecl *Class) override; + +    //------------------------------------------------------------------ +    /// Called on entering a translation unit.  Tells Clang by calling +    /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() +    /// that this object has something to say about undefined names. +    /// +    /// @param[in] ASTConsumer +    ///     Unused. +    //------------------------------------------------------------------ +    void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + +    // +    // APIs for NamespaceMapCompleter +    // +     +    //------------------------------------------------------------------ +    /// Look up the modules containing a given namespace and put the  +    /// appropriate entries in the namespace map. +    /// +    /// @param[in] namespace_map +    ///     The map to be completed. +    /// +    /// @param[in] name +    ///     The name of the namespace to be found. +    /// +    /// @param[in] parent_map +    ///     The map for the namespace's parent namespace, if there is +    ///     one. +    //------------------------------------------------------------------ +    void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, +                              ClangASTImporter::NamespaceMapSP &parent_map) const override; + +    // +    // Helper APIs +    // +     +    clang::NamespaceDecl * +    AddNamespace (NameSearchContext &context,  +                  ClangASTImporter::NamespaceMapSP &namespace_decls); +     +    //------------------------------------------------------------------ +    /// The worker function for FindExternalVisibleDeclsByName. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when filing results. +    //------------------------------------------------------------------ +    virtual void FindExternalVisibleDecls (NameSearchContext &context); +     +    void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } +    bool GetImportInProgress () { return m_import_in_progress; } +     +    void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } +    bool GetLookupsEnabled () { return m_lookups_enabled; }  +     +    //---------------------------------------------------------------------- +    /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" +    /// @brief Proxy for ClangASTSource +    /// +    /// Clang AST contexts like to own their AST sources, so this is a +    /// state-free proxy object. +    //---------------------------------------------------------------------- +    class ClangASTSourceProxy : public ClangExternalASTSourceCommon +    { +    public: +        ClangASTSourceProxy (ClangASTSource &original) : +            m_original(original) +        { +        } + +        bool +        FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override +        { +            return m_original.FindExternalVisibleDeclsByName(DC, Name); +        } + +        void +        FindExternalLexicalDecls(const clang::DeclContext *DC, +                                 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, +                                 llvm::SmallVectorImpl<clang::Decl *> &Decls) override +        { +            return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); +        } + +        void +        CompleteType(clang::TagDecl *Tag) override +        { +            return m_original.CompleteType(Tag); +        } + +        void +        CompleteType(clang::ObjCInterfaceDecl *Class) override +        { +            return m_original.CompleteType(Class); +        } + +        bool +        layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, +                         llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, +                         llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, +                         llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override +        { +            return m_original.layoutRecordType(Record, +                                               Size,  +                                               Alignment,  +                                               FieldOffsets,  +                                               BaseOffsets,  +                                               VirtualBaseOffsets); +        } + +        void +        StartTranslationUnit(clang::ASTConsumer *Consumer) override +        { +            return m_original.StartTranslationUnit(Consumer); +        } +         +        ClangASTMetadata * +        GetMetadata(const void * object) +        { +            return m_original.GetMetadata(object); +        } +         +        void +        SetMetadata(const void * object, ClangASTMetadata &metadata) +        { +            return m_original.SetMetadata(object, metadata); +        } +         +        bool +        HasMetadata(const void * object) +        { +            return m_original.HasMetadata(object); +        } +    private: +        ClangASTSource &m_original; +    }; +     +    clang::ExternalASTSource *CreateProxy() +    { +        return new ClangASTSourceProxy(*this); +    } +     +protected: +    //------------------------------------------------------------------ +    /// Look for the complete version of an Objective-C interface, and +    /// return it if found. +    /// +    /// @param[in] interface_decl +    ///     An ObjCInterfaceDecl that may not be the complete one. +    /// +    /// @return +    ///     NULL if the complete interface couldn't be found; +    ///     the complete interface otherwise. +    //------------------------------------------------------------------ +    clang::ObjCInterfaceDecl * +    GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); +     +    //------------------------------------------------------------------ +    /// Find all entities matching a given name in a given module, +    /// using a NameSearchContext to make Decls for them. +    /// +    /// @param[in] context +    ///     The NameSearchContext that can construct Decls for this name. +    /// +    /// @param[in] module +    ///     If non-NULL, the module to query. +    /// +    /// @param[in] namespace_decl +    ///     If valid and module is non-NULL, the parent namespace. +    /// +    /// @param[in] current_id +    ///     The ID for the current FindExternalVisibleDecls invocation, +    ///     for logging purposes. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    void  +    FindExternalVisibleDecls (NameSearchContext &context,  +                              lldb::ModuleSP module, +                              CompilerDeclContext &namespace_decl, +                              unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Find all Objective-C methods matching a given selector. +    /// +    /// @param[in] context +    ///     The NameSearchContext that can construct Decls for this name. +    ///     Its m_decl_name contains the selector and its m_decl_context +    ///     is the containing object. +    //------------------------------------------------------------------ +    void +    FindObjCMethodDecls (NameSearchContext &context); +     +    //------------------------------------------------------------------ +    /// Find all Objective-C properties and ivars with a given name. +    /// +    /// @param[in] context +    ///     The NameSearchContext that can construct Decls for this name. +    ///     Its m_decl_name contains the name and its m_decl_context +    ///     is the containing object. +    //------------------------------------------------------------------ +    void +    FindObjCPropertyAndIvarDecls (NameSearchContext &context); +     +    //------------------------------------------------------------------ +    /// A wrapper for ClangASTContext::CopyType that sets a flag that +    /// indicates that we should not respond to queries during import. +    /// +    /// @param[in] dest_context +    ///     The target AST context, typically the parser's AST context. +    /// +    /// @param[in] source_context +    ///     The source AST context, typically the AST context of whatever +    ///     symbol file the type was found in. +    /// +    /// @param[in] src_type +    ///     The source type. +    /// +    /// @return +    ///     The imported type. +    //------------------------------------------------------------------ +    CompilerType +    GuardedCopyType (const CompilerType &src_type); +     +    friend struct NameSearchContext; +     +    bool                    m_import_in_progress; +    bool                    m_lookups_enabled; + +    const lldb::TargetSP                m_target;           ///< The target to use in finding variables and types. +    clang::ASTContext                  *m_ast_context;      ///< The AST context requests are coming in for. +    lldb::ClangASTImporterSP            m_ast_importer_sp;  ///< The target's AST importer. +    std::set<const clang::Decl *>       m_active_lexical_decls; +    std::set<const char *>              m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +///      +/// LLDB needs to create Decls for entities it finds.  This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { +    ClangASTSource &m_ast_source;                               ///< The AST source making the request +    llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls;          ///< The list of declarations already constructed +    ClangASTImporter::NamespaceMapSP m_namespace_map;           ///< The mapping of all namespaces found for this request back to their modules +    const clang::DeclarationName &m_decl_name;                  ///< The name being looked for +    const clang::DeclContext *m_decl_context;                   ///< The DeclContext to put declarations into +    llvm::SmallSet <CompilerType, 5> m_function_types;    ///< All the types of functions that have been reported, so we don't report conflicts +     +    struct { +        bool variable                   : 1; +        bool function_with_type_info    : 1; +        bool function                   : 1; +    } m_found; +     +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// Initializes class variables. +    /// +    /// @param[in] astSource +    ///     A reference to the AST source making a request. +    /// +    /// @param[in] decls +    ///     A reference to a list into which new Decls will be placed.  This +    ///     list is typically empty when the function is called. +    /// +    /// @param[in] name +    ///     The name being searched for (always an Identifier). +    /// +    /// @param[in] dc +    ///     The DeclContext to register Decls in. +    //------------------------------------------------------------------ +    NameSearchContext (ClangASTSource &astSource, +                       llvm::SmallVectorImpl<clang::NamedDecl*> &decls, +                       clang::DeclarationName &name, +                       const clang::DeclContext *dc) : +        m_ast_source(astSource), +        m_decls(decls), +        m_decl_name(name), +        m_decl_context(dc) +    { +        memset(&m_found, 0, sizeof(m_found)); +    } +     +    //------------------------------------------------------------------ +    /// Create a VarDecl with the name being searched for and the provided +    /// type and register it in the right places. +    /// +    /// @param[in] type +    ///     The opaque QualType for the VarDecl being registered. +    //------------------------------------------------------------------ +    clang::NamedDecl *AddVarDecl(const CompilerType &type); +     +    //------------------------------------------------------------------ +    /// Create a FunDecl with the name being searched for and the provided +    /// type and register it in the right places. +    /// +    /// @param[in] type +    ///     The opaque QualType for the FunDecl being registered. +    /// +    /// @param[in] extern_c +    ///     If true, build an extern "C" linkage specification for this. +    //------------------------------------------------------------------ +    clang::NamedDecl *AddFunDecl(const CompilerType &type, +                                 bool extern_c = false); +     +    //------------------------------------------------------------------ +    /// Create a FunDecl with the name being searched for and generic +    /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the +    /// right places. +    //------------------------------------------------------------------ +    clang::NamedDecl *AddGenericFunDecl(); +     +    //------------------------------------------------------------------ +    /// Create a TypeDecl with the name being searched for and the provided +    /// type and register it in the right places. +    /// +    /// @param[in] compiler_type +    ///     The opaque QualType for the TypeDecl being registered. +    //------------------------------------------------------------------ +    clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); +     +     +    //------------------------------------------------------------------ +    /// Add Decls from the provided DeclContextLookupResult to the list +    /// of results. +    /// +    /// @param[in] result +    ///     The DeclContextLookupResult, usually returned as the result +    ///     of querying a DeclContext. +    //------------------------------------------------------------------ +    void AddLookupResult (clang::DeclContextLookupResult result); +     +    //------------------------------------------------------------------ +    /// Add a NamedDecl to the list of results. +    /// +    /// @param[in] decl +    ///     The NamedDecl, usually returned as the result +    ///     of querying a DeclContext. +    //------------------------------------------------------------------ +    void AddNamedDecl (clang::NamedDecl *decl); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTSource_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp new file mode 100644 index 0000000000000..c9bc4b6487cda --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -0,0 +1,2351 @@ +//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" + +#include "ASTDumper.h" +#include "ClangASTSource.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" + +using namespace lldb; +using namespace lldb_private; +using namespace clang; + +ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, +                                                Materializer::PersistentVariableDelegate *result_delegate, +                                                ExecutionContext &exe_ctx) : +    ClangASTSource (exe_ctx.GetTargetSP()), +    m_found_entities (), +    m_struct_members (), +    m_keep_result_in_memory (keep_result_in_memory), +    m_result_delegate (result_delegate), +    m_parser_vars (), +    m_struct_vars () +{ +    EnableStructVars(); +} + +ClangExpressionDeclMap::~ClangExpressionDeclMap() +{ +    // Note: The model is now that the parser's AST context and all associated +    //   data does not vanish until the expression has been executed.  This means +    //   that valuable lookup data (like namespaces) doesn't vanish, but + +    DidParse(); +    DisableStructVars(); +} + +bool +ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, +                                  Materializer *materializer) +{ +    ClangASTMetrics::ClearLocalCounters(); + +    EnableParserVars(); +    m_parser_vars->m_exe_ctx = exe_ctx; + +    Target *target = exe_ctx.GetTargetPtr(); +    if (exe_ctx.GetFramePtr()) +        m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); +    else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) +        m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); +    else if (exe_ctx.GetProcessPtr()) +    { +        m_parser_vars->m_sym_ctx.Clear(true); +        m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); +    } +    else if (target) +    { +        m_parser_vars->m_sym_ctx.Clear(true); +        m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); +    } + +    if (target) +    { +        m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); + +        if (!target->GetScratchClangASTContext()) +            return false; +    } + +    m_parser_vars->m_target_info = GetTargetInfo(); +    m_parser_vars->m_materializer = materializer; + +    return true; +} + +void +ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen) +{ +    assert(m_parser_vars); +    m_parser_vars->m_code_gen = code_gen; +} + +void +ClangExpressionDeclMap::DidParse() +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +        ClangASTMetrics::DumpCounters(log); + +    if (m_parser_vars.get()) +    { +        for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); +             entity_index < num_entities; +             ++entity_index) +        { +            ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index)); +            if (var_sp) +                llvm::cast<ClangExpressionVariable>(var_sp.get())->DisableParserVars(GetParserID()); +        } + +        for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize(); +             pvar_index < num_pvars; +             ++pvar_index) +        { +            ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); +            if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get())) +                clang_var->DisableParserVars(GetParserID()); +        } + +        DisableParserVars(); +    } +} + +// Interface for IRForTarget + +ClangExpressionDeclMap::TargetInfo +ClangExpressionDeclMap::GetTargetInfo() +{ +    assert (m_parser_vars.get()); + +    TargetInfo ret; + +    ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + +    Process *process = exe_ctx.GetProcessPtr(); +    if (process) +    { +        ret.byte_order = process->GetByteOrder(); +        ret.address_byte_size = process->GetAddressByteSize(); +    } +    else +    { +        Target *target = exe_ctx.GetTargetPtr(); +        if (target) +        { +            ret.byte_order = target->GetArchitecture().GetByteOrder(); +            ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); +        } +    } + +    return ret; +} + +bool +ClangExpressionDeclMap::AddPersistentVariable +( +    const NamedDecl *decl, +    const ConstString &name, +    TypeFromParser parser_type, +    bool is_result, +    bool is_lvalue +) +{ +    assert (m_parser_vars.get()); + +    ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(parser_type.GetTypeSystem()); +    if (ast == nullptr) +        return false; + +    if (m_parser_vars->m_materializer && is_result) +    { +        Error err; + +        ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; +        Target *target = exe_ctx.GetTargetPtr(); +        if (target == nullptr) +            return false; + +        ClangASTContext *context(target->GetScratchClangASTContext()); + +        TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), +                                                             ast->getASTContext(), +                                                             parser_type.GetOpaqueQualType()), +                               context); +         +        uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, +                                                                           is_lvalue, +                                                                           m_keep_result_in_memory, +                                                                           m_result_delegate, +                                                                           err); + +        ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(), +                                                                   name, +                                                                   user_type, +                                                                   m_parser_vars->m_target_info.byte_order, +                                                                   m_parser_vars->m_target_info.address_byte_size); + +        m_found_entities.AddNewlyConstructedVariable(var); +         +        var->EnableParserVars(GetParserID()); + +        ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + +        parser_vars->m_named_decl = decl; +        parser_vars->m_parser_type = parser_type; + +        var->EnableJITVars(GetParserID()); + +        ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID()); + +        jit_vars->m_offset = offset; + +        return true; +    } + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +    ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; +    Target *target = exe_ctx.GetTargetPtr(); +    if (target == NULL) +        return false; + +    ClangASTContext *context(target->GetScratchClangASTContext()); + +    TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), +                                                         ast->getASTContext(), +                                                         parser_type.GetOpaqueQualType()), +                           context); + +    if (!user_type.GetOpaqueQualType()) +    { +        if (log) +            log->Printf("Persistent variable's type wasn't copied successfully"); +        return false; +    } + +    if (!m_parser_vars->m_target_info.IsValid()) +        return false; + +    ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (), +                                                                                                                                   name, +                                                                                                                                   user_type, +                                                                                                                                   m_parser_vars->m_target_info.byte_order, +                                                                                                                                   m_parser_vars->m_target_info.address_byte_size).get()); + +    if (!var) +        return false; + +    var->m_frozen_sp->SetHasCompleteType(); + +    if (is_result) +        var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; +    else +        var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist + +    if (is_lvalue) +    { +        var->m_flags |= ClangExpressionVariable::EVIsProgramReference; +    } +    else +    { +        var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; +        var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; +    } + +    if (m_keep_result_in_memory) +    { +        var->m_flags |= ClangExpressionVariable::EVKeepInTarget; +    } + +    if (log) +        log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + +    var->EnableParserVars(GetParserID()); + +    ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + +    parser_vars->m_named_decl = decl; +    parser_vars->m_parser_type = parser_type; + +    return true; +} + +bool +ClangExpressionDeclMap::AddValueToStruct +( +    const NamedDecl *decl, +    const ConstString &name, +    llvm::Value *value, +    size_t size, +    lldb::offset_t alignment +) +{ +    assert (m_struct_vars.get()); +    assert (m_parser_vars.get()); + +    bool is_persistent_variable = false; + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    m_struct_vars->m_struct_laid_out = false; + +    if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID())) +        return true; + +    ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + +    if (!var) +    { +        var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID()); +        is_persistent_variable = true; +    } + +    if (!var) +        return false; + +    if (log) +        log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", +                    static_cast<const void*>(decl), name.GetCString(), +                    var->GetName().GetCString()); + +    // We know entity->m_parser_vars is valid because we used a parser variable +    // to find it + +    ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID()); + +    parser_vars->m_llvm_value = value; + +    if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID())) +    { +        // We already laid this out; do not touch + +        if (log) +            log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset); +    } + +    llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID()); + +    ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID()); + +    jit_vars->m_alignment = alignment; +    jit_vars->m_size = size; + +    m_struct_members.AddVariable(var->shared_from_this()); + +    if (m_parser_vars->m_materializer) +    { +        uint32_t offset = 0; + +        Error err; + +        if (is_persistent_variable) +        { +            ExpressionVariableSP var_sp(var->shared_from_this()); +            offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err); +        } +        else +        { +            if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) +                offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); +            else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) +                offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); +            else if (parser_vars->m_lldb_var) +                offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err); +        } + +        if (!err.Success()) +            return false; + +        if (log) +            log->Printf("Placed at 0x%llx", (unsigned long long)offset); + +        jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. +    } + +    return true; +} + +bool +ClangExpressionDeclMap::DoStructLayout () +{ +    assert (m_struct_vars.get()); + +    if (m_struct_vars->m_struct_laid_out) +        return true; + +    if (!m_parser_vars->m_materializer) +        return false; + +    m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment(); +    m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize(); +    m_struct_vars->m_struct_laid_out = true; +    return true; +} + +bool ClangExpressionDeclMap::GetStructInfo +( +    uint32_t &num_elements, +    size_t &size, +    lldb::offset_t &alignment +) +{ +    assert (m_struct_vars.get()); + +    if (!m_struct_vars->m_struct_laid_out) +        return false; + +    num_elements = m_struct_members.GetSize(); +    size = m_struct_vars->m_struct_size; +    alignment = m_struct_vars->m_struct_alignment; + +    return true; +} + +bool +ClangExpressionDeclMap::GetStructElement +( +    const NamedDecl *&decl, +    llvm::Value *&value, +    lldb::offset_t &offset, +    ConstString &name, +    uint32_t index +) +{ +    assert (m_struct_vars.get()); + +    if (!m_struct_vars->m_struct_laid_out) +        return false; + +    if (index >= m_struct_members.GetSize()) +        return false; + +    ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); + +    if (!member_sp) +        return false; + +    ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetParserVars(GetParserID()); +    ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetJITVars(GetParserID()); + +    if (!parser_vars || +        !jit_vars || +        !member_sp->GetValueObject()) +        return false; + +    decl = parser_vars->m_named_decl; +    value = parser_vars->m_llvm_value; +    offset = jit_vars->m_offset; +    name = member_sp->GetName(); + +    return true; +} + +bool +ClangExpressionDeclMap::GetFunctionInfo +( +    const NamedDecl *decl, +    uint64_t &ptr +) +{ +    ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + +    if (!entity) +        return false; + +    // We know m_parser_vars is valid since we searched for the variable by +    // its NamedDecl + +    ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + +    ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); + +    return true; +} + +static void +FindCodeSymbolInContext +( +    const ConstString &name, +    SymbolContext &sym_ctx, +    uint32_t name_type_mask, +    SymbolContextList &sc_list +) +{ +    sc_list.Clear(); +    SymbolContextList temp_sc_list; +    if (sym_ctx.module_sp) +        sym_ctx.module_sp->FindFunctions(name, +                                         NULL, +                                         name_type_mask, +                                         true,  // include_symbols +                                         false, // include_inlines +                                         true,  // append +                                         temp_sc_list); +    if (temp_sc_list.GetSize() == 0) +    { +        if (sym_ctx.target_sp) +            sym_ctx.target_sp->GetImages().FindFunctions(name, +                                                         name_type_mask, +                                                         true,  // include_symbols +                                                         false, // include_inlines +                                                         true,  // append +                                                         temp_sc_list); +    } + +    SymbolContextList internal_symbol_sc_list; +    unsigned temp_sc_list_size = temp_sc_list.GetSize(); +    for (unsigned i = 0; i < temp_sc_list_size; i++) +    { +        SymbolContext sc; +        temp_sc_list.GetContextAtIndex(i, sc); +        if (sc.function) +        { +            sc_list.Append(sc); +        } +        else if (sc.symbol) +        { +            if (sc.symbol->IsExternal()) +            { +                sc_list.Append(sc); +            } +            else +            { +                internal_symbol_sc_list.Append(sc); +            } +        } +    } + +    // If we had internal symbols and we didn't find any external symbols or +    // functions in debug info, then fallback to the internal symbols +    if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize()) +    { +        sc_list = internal_symbol_sc_list; +    } +} + +bool +ClangExpressionDeclMap::GetFunctionAddress +( +    const ConstString &name, +    uint64_t &func_addr +) +{ +    assert (m_parser_vars.get()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +    ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; +    Target *target = exe_ctx.GetTargetPtr(); +    // Back out in all cases where we're not fully initialized +    if (target == NULL) +        return false; +    if (!m_parser_vars->m_sym_ctx.target_sp) +        return false; + +    SymbolContextList sc_list; + +    FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); + +    uint32_t sc_list_size = sc_list.GetSize(); + +    if (sc_list_size == 0) +    { +        SymbolContext &sc = m_parser_vars->m_sym_ctx; +        if (sc.comp_unit) +        { +            LanguageType lang_type = sc.comp_unit->GetLanguage(); +            if (Language::LanguageIsCPlusPlus(lang_type) && +                CPlusPlusLanguage::IsCPPMangledName(name.AsCString())) +            { +                // 1. Demangle the name +                Mangled mangled(name, true); +                ConstString demangled = mangled.GetDemangledName(lang_type); + +                if (demangled) +                { +                    FindCodeSymbolInContext( +                        demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list); +                    sc_list_size = sc_list.GetSize(); +                } +            } +        } +    } + +    if (sc_list_size == 0) +    { +        // We occasionally get debug information in which a const function is reported +        // as non-const, so the mangled name is wrong.  This is a hack to compensate. + +        if (!strncmp(name.GetCString(), "_ZN", 3) && +            strncmp(name.GetCString(), "_ZNK", 4)) +        { +            std::string fixed_scratch("_ZNK"); +            fixed_scratch.append(name.GetCString() + 3); +            ConstString fixed_name(fixed_scratch.c_str()); + +            if (log) +                log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString()); + +            FindCodeSymbolInContext( +                fixed_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); +            sc_list_size = sc_list.GetSize(); +        } +    } + +    lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS; + +    for (uint32_t i=0; i<sc_list_size; ++i) +    { +        SymbolContext sym_ctx; +        sc_list.GetContextAtIndex(i, sym_ctx); + + +        lldb::addr_t callable_load_addr = LLDB_INVALID_ADDRESS; + +        if (sym_ctx.function) +        { +            const Address func_so_addr = sym_ctx.function->GetAddressRange().GetBaseAddress(); +            if (func_so_addr.IsValid()) +            { +                callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false); +            } +        } +        else if (sym_ctx.symbol) +        { +            if (sym_ctx.symbol->IsExternal()) +                callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); +            else +            { +                if (intern_callable_load_addr == LLDB_INVALID_ADDRESS) +                    intern_callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target); +            } +        } + +        if (callable_load_addr != LLDB_INVALID_ADDRESS) +        { +            func_addr = callable_load_addr; +            return true; +        } +    } + +    // See if we found an internal symbol +    if (intern_callable_load_addr != LLDB_INVALID_ADDRESS) +    { +        func_addr = intern_callable_load_addr; +        return true; +    } + +    return false; +} + +addr_t +ClangExpressionDeclMap::GetSymbolAddress (Target &target, +                                          Process *process, +                                          const ConstString &name, +                                          lldb::SymbolType symbol_type, +                                          lldb_private::Module *module) +{ +    SymbolContextList sc_list; + +    if (module) +        module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); +    else +        target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); + +    const uint32_t num_matches = sc_list.GetSize(); +    addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + +    for (uint32_t i=0; i<num_matches && (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); i++) +    { +        SymbolContext sym_ctx; +        sc_list.GetContextAtIndex(i, sym_ctx); + +        const Address sym_address = sym_ctx.symbol->GetAddress(); + +        if (!sym_address.IsValid()) +            continue; + +        switch (sym_ctx.symbol->GetType()) +        { +            case eSymbolTypeCode: +            case eSymbolTypeTrampoline: +                symbol_load_addr = sym_address.GetCallableLoadAddress (&target); +                break; + +            case eSymbolTypeResolver: +                symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); +                break; + +            case eSymbolTypeReExported: +                { +                    ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); +                    if (reexport_name) +                    { +                        ModuleSP reexport_module_sp; +                        ModuleSpec reexport_module_spec; +                        reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); +                        if (reexport_module_spec.GetPlatformFileSpec()) +                        { +                            reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); +                            if (!reexport_module_sp) +                            { +                                reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); +                                reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); +                            } +                        } +                        symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); +                    } +                } +                break; + +            case eSymbolTypeData: +            case eSymbolTypeRuntime: +            case eSymbolTypeVariable: +            case eSymbolTypeLocal: +            case eSymbolTypeParam: +            case eSymbolTypeInvalid: +            case eSymbolTypeAbsolute: +            case eSymbolTypeException: +            case eSymbolTypeSourceFile: +            case eSymbolTypeHeaderFile: +            case eSymbolTypeObjectFile: +            case eSymbolTypeCommonBlock: +            case eSymbolTypeBlock: +            case eSymbolTypeVariableType: +            case eSymbolTypeLineEntry: +            case eSymbolTypeLineHeader: +            case eSymbolTypeScopeBegin: +            case eSymbolTypeScopeEnd: +            case eSymbolTypeAdditional: +            case eSymbolTypeCompiler: +            case eSymbolTypeInstrumentation: +            case eSymbolTypeUndefined: +            case eSymbolTypeObjCClass: +            case eSymbolTypeObjCMetaClass: +            case eSymbolTypeObjCIVar: +                symbol_load_addr = sym_address.GetLoadAddress (&target); +                break; +        } +    } + +    if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) +    { +        ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); + +        if (runtime) +        { +            symbol_load_addr = runtime->LookupRuntimeSymbol(name); +        } +    } + +    return symbol_load_addr; +} + +addr_t +ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type) +{ +    assert (m_parser_vars.get()); + +    if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) +        return false; + +    return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type); +} + +const Symbol * +ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, +                                              const ConstString &name, +                                              lldb_private::Module *module) +{ +    SymbolContextList sc_list; + +    if (module) +        module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); +    else +        target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + +    const uint32_t matches = sc_list.GetSize(); +    for (uint32_t i=0; i<matches; ++i) +    { +        SymbolContext sym_ctx; +        sc_list.GetContextAtIndex(i, sym_ctx); +        if (sym_ctx.symbol) +        { +            const Symbol *symbol = sym_ctx.symbol; +            const Address sym_address = symbol->GetAddress(); + +            if (sym_address.IsValid()) +            { +                switch (symbol->GetType()) +                { +                    case eSymbolTypeData: +                    case eSymbolTypeRuntime: +                    case eSymbolTypeAbsolute: +                    case eSymbolTypeObjCClass: +                    case eSymbolTypeObjCMetaClass: +                    case eSymbolTypeObjCIVar: +                        if (symbol->GetDemangledNameIsSynthesized()) +                        { +                            // If the demangled name was synthesized, then don't use it +                            // for expressions. Only let the symbol match if the mangled +                            // named matches for these symbols. +                            if (symbol->GetMangled().GetMangledName() != name) +                                break; +                        } +                        return symbol; + +                    case eSymbolTypeReExported: +                        { +                            ConstString reexport_name = symbol->GetReExportedSymbolName(); +                            if (reexport_name) +                            { +                                ModuleSP reexport_module_sp; +                                ModuleSpec reexport_module_spec; +                                reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary(); +                                if (reexport_module_spec.GetPlatformFileSpec()) +                                { +                                    reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); +                                    if (!reexport_module_sp) +                                    { +                                        reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); +                                        reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); +                                    } +                                } +                                // Don't allow us to try and resolve a re-exported symbol if it is the same +                                // as the current symbol +                                if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get()) +                                    return NULL; + +                                return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get()); +                            } +                        } +                        break; + +                    case eSymbolTypeCode: // We already lookup functions elsewhere +                    case eSymbolTypeVariable: +                    case eSymbolTypeLocal: +                    case eSymbolTypeParam: +                    case eSymbolTypeTrampoline: +                    case eSymbolTypeInvalid: +                    case eSymbolTypeException: +                    case eSymbolTypeSourceFile: +                    case eSymbolTypeHeaderFile: +                    case eSymbolTypeObjectFile: +                    case eSymbolTypeCommonBlock: +                    case eSymbolTypeBlock: +                    case eSymbolTypeVariableType: +                    case eSymbolTypeLineEntry: +                    case eSymbolTypeLineHeader: +                    case eSymbolTypeScopeBegin: +                    case eSymbolTypeScopeEnd: +                    case eSymbolTypeAdditional: +                    case eSymbolTypeCompiler: +                    case eSymbolTypeInstrumentation: +                    case eSymbolTypeUndefined: +                    case eSymbolTypeResolver: +                        break; +                } +            } +        } +    } + +    return NULL; +} + +lldb::VariableSP +ClangExpressionDeclMap::FindGlobalVariable +( +    Target &target, +    ModuleSP &module, +    const ConstString &name, +    CompilerDeclContext *namespace_decl, +    TypeFromUser *type +) +{ +    VariableList vars; + +    if (module && namespace_decl) +        module->FindGlobalVariables (name, namespace_decl, true, -1, vars); +    else +        target.GetImages().FindGlobalVariables(name, true, -1, vars); + +    if (vars.GetSize()) +    { +        if (type) +        { +            for (size_t i = 0; i < vars.GetSize(); ++i) +            { +                VariableSP var_sp = vars.GetVariableAtIndex(i); + +                if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetFullCompilerType ())) +                    return var_sp; +            } +        } +        else +        { +            return vars.GetVariableAtIndex(0); +        } +    } + +    return VariableSP(); +} + +// Interface for ClangASTSource + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) +{ +    assert (m_ast_context); + +    ClangASTMetrics::RegisterVisibleQuery(); + +    const ConstString name(context.m_decl_name.getAsString().c_str()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (GetImportInProgress()) +    { +        if (log && log->GetVerbose()) +            log->Printf("Ignoring a query during an import"); +        return; +    } + +    static unsigned int invocation_id = 0; +    unsigned int current_id = invocation_id++; + +    if (log) +    { +        if (!context.m_decl_context) +            log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString()); +        else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context)) +            log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str()); +        else +            log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName()); +    } + +    if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context)) +    { +        ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + +        if (log && log->GetVerbose()) +            log->Printf("  CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", +                        current_id, static_cast<void*>(namespace_map.get()), +                        (int)namespace_map->size()); + +        if (!namespace_map) +            return; + +        for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); +             i != e; +             ++i) +        { +            if (log) +                log->Printf("  CEDM::FEVD[%u] Searching namespace %s in module %s", +                            current_id, +                            i->second.GetName().AsCString(), +                            i->first->GetFileSpec().GetFilename().GetCString()); + +            FindExternalVisibleDecls(context, +                                     i->first, +                                     i->second, +                                     current_id); +        } +    } +    else if (isa<TranslationUnitDecl>(context.m_decl_context)) +    { +        CompilerDeclContext namespace_decl; + +        if (log) +            log->Printf("  CEDM::FEVD[%u] Searching the root namespace", current_id); + +        FindExternalVisibleDecls(context, +                                 lldb::ModuleSP(), +                                 namespace_decl, +                                 current_id); +    } + +    if (!context.m_found.variable) +        ClangASTSource::FindExternalVisibleDecls(context); +} + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, +                                                  lldb::ModuleSP module_sp, +                                                  CompilerDeclContext &namespace_decl, +                                                  unsigned int current_id) +{ +    assert (m_ast_context); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    SymbolContextList sc_list; + +    const ConstString name(context.m_decl_name.getAsString().c_str()); + +    const char *name_unique_cstr = name.GetCString(); + +    if (name_unique_cstr == NULL) +        return; + +    static ConstString id_name("id"); +    static ConstString Class_name("Class"); + +    if (name == id_name || name == Class_name) +        return; + +    // Only look for functions by name out in our symbols if the function +    // doesn't start with our phony prefix of '$' +    Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); +    StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); +    SymbolContext sym_ctx; +    if (frame != nullptr) +        sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); +    if (name_unique_cstr[0] == '$' && !namespace_decl) +    { +        static ConstString g_lldb_class_name ("$__lldb_class"); + +        if (name == g_lldb_class_name) +        { +            // Clang is looking for the type of "this" + +            if (frame == NULL) +                return; + + +            // Find the block that defines the function represented by "sym_ctx" +            Block *function_block = sym_ctx.GetFunctionBlock(); + +            if (!function_block) +                return; + +            CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + +            if (!function_decl_ctx) +                return; + +            clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); + +            if (method_decl) +            { +                clang::CXXRecordDecl *class_decl = method_decl->getParent(); + +                QualType class_qual_type(class_decl->getTypeForDecl(), 0); + +                TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), +                                              ClangASTContext::GetASTContext(&class_decl->getASTContext())); + +                if (log) +                { +                    ASTDumper ast_dumper(class_qual_type); +                    log->Printf("  CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); +                } + +                AddThisType(context, class_user_type, current_id); + +                if (method_decl->isInstance()) +                { +                    // self is a pointer to the object + +                    QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); + +                    TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), +                                                ClangASTContext::GetASTContext(&method_decl->getASTContext())); + +                    m_struct_vars->m_object_pointer_type = self_user_type; +                } +            } +            else +            { +                // This branch will get hit if we are executing code in the context of a function that +                // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a +                // method of the class.  In that case, just look up the "this" variable in the current +                // scope and use its type. +                // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer +                // for C++ so it hasn't actually been tested. + +                VariableList *vars = frame->GetVariableList(false); + +                lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); + +                if (this_var && +                    this_var->IsInScope(frame) && +                    this_var->LocationIsValidForFrame (frame)) +                { +                    Type *this_type = this_var->GetType(); + +                    if (!this_type) +                        return; + +                    TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType(); + +                    if (pointee_type.IsValid()) +                    { +                        if (log) +                        { +                            ASTDumper ast_dumper(pointee_type); +                            log->Printf("  FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); +                        } +                         +                        AddThisType(context, pointee_type, current_id); +                        TypeFromUser this_user_type(this_type->GetFullCompilerType ()); +                        m_struct_vars->m_object_pointer_type = this_user_type; +                        return; +                    } +                } +            } + +            return; +        } + +        static ConstString g_lldb_objc_class_name ("$__lldb_objc_class"); +        if (name == g_lldb_objc_class_name) +        { +            // Clang is looking for the type of "*self" + +            if (!frame) +                return; + +            SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + +            // Find the block that defines the function represented by "sym_ctx" +            Block *function_block = sym_ctx.GetFunctionBlock(); + +            if (!function_block) +                return; + +            CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + +            if (!function_decl_ctx) +                return; + +            clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + +            if (method_decl) +            { +                ObjCInterfaceDecl* self_interface = method_decl->getClassInterface(); + +                if (!self_interface) +                    return; + +                const clang::Type *interface_type = self_interface->getTypeForDecl(); + +                if (!interface_type) +                    return; // This is unlikely, but we have seen crashes where this occurred + +                TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), +                                             ClangASTContext::GetASTContext(&method_decl->getASTContext())); + +                if (log) +                { +                    ASTDumper ast_dumper(interface_type); +                    log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); +                } + +                AddOneType(context, class_user_type, current_id); + +                if (method_decl->isInstanceMethod()) +                { +                    // self is a pointer to the object + +                    QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); + +                    TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), +                                                ClangASTContext::GetASTContext(&method_decl->getASTContext())); + +                    m_struct_vars->m_object_pointer_type = self_user_type; +                } +                else +                { +                    // self is a Class pointer +                    QualType class_type = method_decl->getASTContext().getObjCClassType(); + +                    TypeFromUser self_user_type(class_type.getAsOpaquePtr(), +                                                ClangASTContext::GetASTContext(&method_decl->getASTContext())); + +                    m_struct_vars->m_object_pointer_type = self_user_type; +                } + +                return; +            } +            else +            { +                // This branch will get hit if we are executing code in the context of a function that +                // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a +                // method of the class.  In that case, just look up the "self" variable in the current +                // scope and use its type. + +                VariableList *vars = frame->GetVariableList(false); + +                lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + +                if (self_var && +                    self_var->IsInScope(frame) && +                    self_var->LocationIsValidForFrame (frame)) +                { +                    Type *self_type = self_var->GetType(); + +                    if (!self_type) +                        return; + +                    CompilerType self_clang_type = self_type->GetFullCompilerType (); + +                    if (ClangASTContext::IsObjCClassType(self_clang_type)) +                    { +                        return; +                    } +                    else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) +                    { +                        self_clang_type = self_clang_type.GetPointeeType(); + +                        if (!self_clang_type) +                            return; + +                        if (log) +                        { +                            ASTDumper ast_dumper(self_type->GetFullCompilerType ()); +                            log->Printf("  FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); +                        } + +                        TypeFromUser class_user_type (self_clang_type); + +                        AddOneType(context, class_user_type, current_id); + +                        TypeFromUser self_user_type(self_type->GetFullCompilerType ()); + +                        m_struct_vars->m_object_pointer_type = self_user_type; +                        return; +                    } +                } +            } + +            return; +        } + +        // any other $__lldb names should be weeded out now +        if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) +            return; + +        do +        { +            if (!target) +                break; + +            ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext(); + +            if (!scratch_clang_ast_context) +                break; + +            ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + +            if (!scratch_ast_context) +                break; + +            TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name); + +            if (!ptype_type_decl) +                break; + +            Decl *parser_ptype_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl); + +            if (!parser_ptype_decl) +                break; + +            TypeDecl *parser_ptype_type_decl = dyn_cast<TypeDecl>(parser_ptype_decl); + +            if (!parser_ptype_type_decl) +                break; + +            if (log) +                log->Printf("  CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString()); + +            context.AddNamedDecl(parser_ptype_type_decl); +        } while (0); + +        ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); + +        if (pvar_sp) +        { +            AddOneVariable(context, pvar_sp, current_id); +            return; +        } + +        const char *reg_name(&name.GetCString()[1]); + +        if (m_parser_vars->m_exe_ctx.GetRegisterContext()) +        { +            const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name)); + +            if (reg_info) +            { +                if (log) +                    log->Printf("  CEDM::FEVD[%u] Found register %s", current_id, reg_info->name); + +                AddOneRegister(context, reg_info, current_id); +            } +        } +    } +    else +    { +        ValueObjectSP valobj; +        VariableSP var; + +        if (frame && !namespace_decl) +        { +            CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + +            if (compiler_decl_context) +            { +                // Make sure that the variables are parsed so that we have the declarations +                VariableListSP vars = frame->GetInScopeVariableList(true); +                for (size_t i = 0; i < vars->GetSize(); i++) +                    vars->GetVariableAtIndex(i)->GetDecl(); + +                // Search for declarations matching the name +                std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name); +                 +                bool variable_found = false; +                for (CompilerDecl decl : found_decls) +                { +                    var = decl.GetAsVariable(); +                    if (var) +                    { +                        variable_found = true; +                        valobj = ValueObjectVariable::Create(frame, var); +                        AddOneVariable(context, var, valobj, current_id); +                        context.m_found.variable = true; +                    } +                } +                if (variable_found) +                    return; +            } +        } +        if (target) +        { +            var = FindGlobalVariable (*target, +                                      module_sp, +                                      name, +                                      &namespace_decl, +                                      NULL); + +            if (var) +            { +                valobj = ValueObjectVariable::Create(target, var); +                AddOneVariable(context, var, valobj, current_id); +                context.m_found.variable = true; +                return; +            } +        } +         +        std::vector<clang::NamedDecl *> decls_from_modules; +         +        if (target) +        { +            if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) +            { +                decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); +            } +        } + +        if (!context.m_found.variable) +        { +            const bool include_inlines = false; +            const bool append = false; + +            if (namespace_decl && module_sp) +            { +                const bool include_symbols = false; + +                module_sp->FindFunctions(name, +                                         &namespace_decl, +                                         eFunctionNameTypeBase, +                                         include_symbols, +                                         include_inlines, +                                         append, +                                         sc_list); +            } +            else if (target && !namespace_decl) +            { +                const bool include_symbols = true; + +                // TODO Fix FindFunctions so that it doesn't return +                //   instance methods for eFunctionNameTypeBase. + +                target->GetImages().FindFunctions(name, +                                                  eFunctionNameTypeFull, +                                                  include_symbols, +                                                  include_inlines, +                                                  append, +                                                  sc_list); +            } + +            // If we found more than one function, see if we can use the +            // frame's decl context to remove functions that are shadowed +            // by other functions which match in type but are nearer in scope. +            // +            // AddOneFunction will not add a function whose type has already been +            // added, so if there's another function in the list with a matching +            // type, check to see if their decl context is a parent of the current +            // frame's or was imported via a and using statement, and pick the +            // best match according to lookup rules. +            if (sc_list.GetSize() > 1) +            { +                // Collect some info about our frame's context. +                StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); +                SymbolContext frame_sym_ctx; +                if (frame != nullptr) +                    frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); +                CompilerDeclContext frame_decl_context = frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + +                // We can't do this without a compiler decl context for our frame. +                if (frame_decl_context) +                { +                    clang::DeclContext *frame_decl_ctx = (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); +                    ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(frame_decl_context.GetTypeSystem()); + +                    // Structure to hold the info needed when comparing function +                    // declarations. +                    struct FuncDeclInfo +                    { +                        ConstString m_name; +                        CompilerType m_copied_type; +                        uint32_t m_decl_lvl; +                        SymbolContext m_sym_ctx; +                    }; + +                    // First, symplify things by looping through the symbol contexts +                    // to remove unwanted functions and separate out the functions we +                    // want to compare and prune into a separate list. +                    // Cache the info needed about the function declarations in a +                    // vector for efficiency. +                    SymbolContextList sc_sym_list; +                    uint32_t num_indices = sc_list.GetSize(); +                    std::vector<FuncDeclInfo> fdi_cache; +                    fdi_cache.reserve(num_indices); +                    for (uint32_t index = 0; index < num_indices; ++index) +                    { +                        FuncDeclInfo fdi; +                        SymbolContext sym_ctx; +                        sc_list.GetContextAtIndex(index, sym_ctx); + +                        // We don't know enough about symbols to compare them, +                        // but we should keep them in the list. +                        Function *function = sym_ctx.function; +                        if (!function) +                        { +                            sc_sym_list.Append(sym_ctx); +                            continue; +                        } +                        // Filter out functions without declaration contexts, as well as +                        // class/instance methods, since they'll be skipped in the +                        // code that follows anyway. +                        CompilerDeclContext func_decl_context = function->GetDeclContext(); +                        if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) +                            continue; +                        // We can only prune functions for which we can copy the type. +                        CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); +                        CompilerType copied_func_type = GuardedCopyType(func_clang_type); +                        if (!copied_func_type) +                        { +                            sc_sym_list.Append(sym_ctx); +                            continue; +                        } + +                        fdi.m_sym_ctx = sym_ctx; +                        fdi.m_name = function->GetName(); +                        fdi.m_copied_type = copied_func_type; +                        fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; +                        if (fdi.m_copied_type && func_decl_context) +                        { +                            // Call CountDeclLevels to get the number of parent scopes we +                            // have to look through before we find the function declaration. +                            // When comparing functions of the same type, the one with a +                            // lower count will be closer to us in the lookup scope and +                            // shadows the other. +                            clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); +                            fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, +                                                                  func_decl_ctx, +                                                                  &fdi.m_name, +                                                                  &fdi.m_copied_type); +                        } +                        fdi_cache.emplace_back(fdi); +                    } + +                    // Loop through the functions in our cache looking for matching types, +                    // then compare their scope levels to see which is closer. +                    std::multimap<CompilerType, const FuncDeclInfo*> matches; +                    for (const FuncDeclInfo &fdi : fdi_cache) +                    { +                        const CompilerType t = fdi.m_copied_type; +                        auto q = matches.find(t); +                        if (q != matches.end()) +                        { +                            if (q->second->m_decl_lvl > fdi.m_decl_lvl) +                                // This function is closer; remove the old set. +                                matches.erase(t); +                            else if (q->second->m_decl_lvl < fdi.m_decl_lvl) +                                // The functions in our set are closer - skip this one. +                                continue; +                        } +                        matches.insert(std::make_pair(t, &fdi)); +                    } + +                    // Loop through our matches and add their symbol contexts to our list. +                    SymbolContextList sc_func_list; +                    for (const auto &q : matches) +                        sc_func_list.Append(q.second->m_sym_ctx); + +                    // Rejoin the lists with the functions in front. +                    sc_list = sc_func_list; +                    sc_list.Append(sc_sym_list); +                } +            } + +            if (sc_list.GetSize()) +            { +                Symbol *extern_symbol = NULL; +                Symbol *non_extern_symbol = NULL; + +                for (uint32_t index = 0, num_indices = sc_list.GetSize(); +                     index < num_indices; +                     ++index) +                { +                    SymbolContext sym_ctx; +                    sc_list.GetContextAtIndex(index, sym_ctx); + +                    if (sym_ctx.function) +                    { +                        CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); + +                        if (!decl_ctx) +                            continue; + +                        // Filter out class/instance methods. +                        if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) +                            continue; + +                        AddOneFunction(context, sym_ctx.function, NULL, current_id); +                        context.m_found.function_with_type_info = true; +                        context.m_found.function = true; +                    } +                    else if (sym_ctx.symbol) +                    { +                        if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) +                        { +                            sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); +                            if (sym_ctx.symbol == NULL) +                                continue; +                        } + +                        if (sym_ctx.symbol->IsExternal()) +                            extern_symbol = sym_ctx.symbol; +                        else +                            non_extern_symbol = sym_ctx.symbol; +                    } +                } +                 +                if (!context.m_found.function_with_type_info) +                { +                    for (clang::NamedDecl *decl : decls_from_modules) +                    { +                        if (llvm::isa<clang::FunctionDecl>(decl)) +                        { +                            clang::NamedDecl *copied_decl = llvm::cast<FunctionDecl>(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); +                            context.AddNamedDecl(copied_decl); +                            context.m_found.function_with_type_info = true; +                        } +                    } +                } + +                if (!context.m_found.function_with_type_info) +                { +                    if (extern_symbol) +                    { +                        AddOneFunction (context, NULL, extern_symbol, current_id); +                        context.m_found.function = true; +                    } +                    else if (non_extern_symbol) +                    { +                        AddOneFunction (context, NULL, non_extern_symbol, current_id); +                        context.m_found.function = true; +                    } +                } +            } +             +            if (!context.m_found.function_with_type_info) +            { +                // Try the modules next. +                 +                do +                { +                    if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) +                    { +                        bool append = false; +                        uint32_t max_matches = 1; +                        std::vector <clang::NamedDecl *> decls; +                         +                        if (!modules_decl_vendor->FindDecls(name, +                                                            append, +                                                            max_matches, +                                                            decls)) +                            break; +                         +                        clang::NamedDecl *const decl_from_modules = decls[0]; +                         +                        if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) +                        { +                            if (log) +                            { +                                log->Printf("  CAS::FEVD[%u] Matching function found for \"%s\" in the modules", +                                            current_id, +                                            name.GetCString()); +                            } +                             +                            clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); +                            clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr; +                             +                            if (!copied_function_decl) +                            { +                                if (log) +                                    log->Printf("  CAS::FEVD[%u] - Couldn't export a function declaration from the modules", +                                                current_id); +                                 +                                break; +                            } +                             +                            if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) +                            { +                                DeclGroupRef decl_group_ref(copied_function_decl); +                                m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); +                            } +                             +                            context.AddNamedDecl(copied_function_decl); +                             +                            context.m_found.function_with_type_info = true; +                            context.m_found.function = true; +                        } +                        else if (llvm::isa<clang::VarDecl>(decl_from_modules)) +                        { +                            if (log) +                            { +                                log->Printf("  CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", +                                            current_id, +                                            name.GetCString()); +                            } +                             +                            clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); +                            clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr; +                             +                            if (!copied_var_decl) +                            { +                                if (log) +                                    log->Printf("  CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", +                                                current_id); +                                 +                                break; +                            } +                             +                            context.AddNamedDecl(copied_var_decl); +                             +                            context.m_found.variable = true; +                        } +                    } +                } while (0); +            } + +            if (target && !context.m_found.variable && !namespace_decl) +            { +                // We couldn't find a non-symbol variable for this.  Now we'll hunt for a generic +                // data symbol, and -- if it is found -- treat it as a variable. + +                const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); + +                if (data_symbol) +                { +                    std::string warning("got name from symbols: "); +                    warning.append(name.AsCString()); +                    const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); +                    m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); +                    AddOneGenericVariable(context, *data_symbol, current_id); +                    context.m_found.variable = true; +                } +            } +        } +    } +} + +//static opaque_compiler_type_t +//MaybePromoteToBlockPointerType +//( +//    ASTContext *ast_context, +//    opaque_compiler_type_t candidate_type +//) +//{ +//    if (!candidate_type) +//        return candidate_type; +// +//    QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); +// +//    const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type); +// +//    if (!candidate_pointer_type) +//        return candidate_type; +// +//    QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); +// +//    const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type); +// +//    if (!pointee_record_type) +//        return candidate_type; +// +//    RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); +// +//    if (!pointee_record_decl->isRecord()) +//        return candidate_type; +// +//    if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) +//        return candidate_type; +// +//    QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); +//    QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type); +// +//    return block_pointer_type.getAsOpaquePtr(); +//} + +bool +ClangExpressionDeclMap::GetVariableValue (VariableSP &var, +                                          lldb_private::Value &var_location, +                                          TypeFromUser *user_type, +                                          TypeFromParser *parser_type) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    Type *var_type = var->GetType(); + +    if (!var_type) +    { +        if (log) +            log->PutCString("Skipped a definition because it has no type"); +        return false; +    } + +    CompilerType var_clang_type = var_type->GetFullCompilerType (); + +    if (!var_clang_type) +    { +        if (log) +            log->PutCString("Skipped a definition because it has no Clang type"); +        return false; +    } + +    ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>(var_type->GetForwardCompilerType().GetTypeSystem()); + +    if (!clang_ast) +    { +        if (log) +            log->PutCString("Skipped a definition because it has no Clang AST"); +        return false; +    } + + +    ASTContext *ast = clang_ast->getASTContext(); + +    if (!ast) +    { +        if (log) +            log->PutCString("There is no AST context for the current execution context"); +        return false; +    } +    //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); + +    DWARFExpression &var_location_expr = var->LocationExpression(); + +    Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); +    Error err; + +    if (var->GetLocationIsConstantValueData()) +    { +        DataExtractor const_value_extractor; + +        if (var_location_expr.GetExpressionData(const_value_extractor)) +        { +            var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); +            var_location.SetValueType(Value::eValueTypeHostAddress); +        } +        else +        { +            if (log) +                log->Printf("Error evaluating constant variable: %s", err.AsCString()); +            return false; +        } +    } + +    CompilerType type_to_use = GuardedCopyType(var_clang_type); + +    if (!type_to_use) +    { +        if (log) +            log->Printf("Couldn't copy a variable's type into the parser's AST context"); + +        return false; +    } + +    if (parser_type) +        *parser_type = TypeFromParser(type_to_use); + +    if (var_location.GetContextType() == Value::eContextTypeInvalid) +        var_location.SetCompilerType(type_to_use); + +    if (var_location.GetValueType() == Value::eValueTypeFileAddress) +    { +        SymbolContext var_sc; +        var->CalculateSymbolContext(&var_sc); + +        if (!var_sc.module_sp) +            return false; + +        Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList()); + +        lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + +        if (load_addr != LLDB_INVALID_ADDRESS) +        { +            var_location.GetScalar() = load_addr; +            var_location.SetValueType(Value::eValueTypeLoadAddress); +        } +    } + +    if (user_type) +        *user_type = TypeFromUser(var_clang_type); + +    return true; +} + +void +ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id) +{ +    assert (m_parser_vars.get()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    TypeFromUser ut; +    TypeFromParser pt; +    Value var_location; + +    if (!GetVariableValue (var, var_location, &ut, &pt)) +        return; + +    clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); + +    if (parser_opaque_type.isNull()) +        return; + +    if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) +    { +        if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) +            CompleteType(tag_type->getDecl()); +        if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type)) +            CompleteType(objc_object_ptr_type->getInterfaceDecl()); +    } + + +    bool is_reference = pt.IsReferenceType(); + +    NamedDecl *var_decl = NULL; +    if (is_reference) +        var_decl = context.AddVarDecl(pt); +    else +        var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); + +    std::string decl_name(context.m_decl_name.getAsString()); +    ConstString entity_name(decl_name.c_str()); +    ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); +    m_found_entities.AddNewlyConstructedVariable(entity); + +    assert (entity); +    entity->EnableParserVars(GetParserID()); +    ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); +    parser_vars->m_parser_type = pt; +    parser_vars->m_named_decl  = var_decl; +    parser_vars->m_llvm_value  = NULL; +    parser_vars->m_lldb_value  = var_location; +    parser_vars->m_lldb_var    = var; + +    if (is_reference) +        entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + +    if (log) +    { +        ASTDumper orig_dumper(ut.GetOpaqueQualType()); +        ASTDumper ast_dumper(var_decl); +        log->Printf("  CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString()); +    } +} + +void +ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, +                                       ExpressionVariableSP &pvar_sp, +                                       unsigned int current_id) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    TypeFromUser user_type (llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser()); + +    TypeFromParser parser_type (GuardedCopyType(user_type)); + +    if (!parser_type.GetOpaqueQualType()) +    { +        if (log) +            log->Printf("  CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString()); +        return; +    } + +    NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); + +    llvm::cast<ClangExpressionVariable>(pvar_sp.get())->EnableParserVars(GetParserID()); +    ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetParserVars(GetParserID()); +    parser_vars->m_parser_type = parser_type; +    parser_vars->m_named_decl = var_decl; +    parser_vars->m_llvm_value = NULL; +    parser_vars->m_lldb_value.Clear(); + +    if (log) +    { +        ASTDumper ast_dumper(var_decl); +        log->Printf("  CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); +    } +} + +void +ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, +                                              const Symbol &symbol, +                                              unsigned int current_id) +{ +    assert(m_parser_vars.get()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + +    if (target == NULL) +        return; + +    ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); + +    TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); +    TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); +    NamedDecl *var_decl = context.AddVarDecl(parser_type); + +    std::string decl_name(context.m_decl_name.getAsString()); +    ConstString entity_name(decl_name.c_str()); +    ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), +                                                                entity_name, +                                                                user_type, +                                                                m_parser_vars->m_target_info.byte_order, +                                                                m_parser_vars->m_target_info.address_byte_size)); +    m_found_entities.AddNewlyConstructedVariable(entity); +     +    entity->EnableParserVars(GetParserID()); +    ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + +    const Address symbol_address = symbol.GetAddress(); +    lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); + +    //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); +    parser_vars->m_lldb_value.SetCompilerType(user_type); +    parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; +    parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + +    parser_vars->m_parser_type = parser_type; +    parser_vars->m_named_decl  = var_decl; +    parser_vars->m_llvm_value  = NULL; +    parser_vars->m_lldb_sym    = &symbol; + +    if (log) +    { +        ASTDumper ast_dumper(var_decl); + +        log->Printf("  CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString()); +    } +} + +bool +ClangExpressionDeclMap::ResolveUnknownTypes() +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +    Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + +    ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + +    for (size_t index = 0, num_entities = m_found_entities.GetSize(); +         index < num_entities; +         ++index) +    { +        ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); + +        ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(entity.get())->GetParserVars(GetParserID()); + +        if (entity->m_flags & ClangExpressionVariable::EVUnknownType) +        { +            const NamedDecl *named_decl = parser_vars->m_named_decl; +            const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl); + +            if (!var_decl) +            { +                if (log) +                    log->Printf("Entity of unknown type does not have a VarDecl"); +                return false; +            } + +            if (log) +            { +                ASTDumper ast_dumper(const_cast<VarDecl*>(var_decl)); +                log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString()); +            } + +            QualType var_type = var_decl->getType(); +            TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); + +            lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr()); + +            if (!copied_type) +            { +                if (log) +                    log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable"); + +                return (bool) lldb::ExpressionVariableSP(); +            } + +            TypeFromUser user_type(copied_type, scratch_ast_context); + +//            parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); +            parser_vars->m_lldb_value.SetCompilerType(user_type); +            parser_vars->m_parser_type = parser_type; + +            entity->SetCompilerType(user_type); + +            entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); +        } +    } + +    return true; +} + +void +ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, +                                        const RegisterInfo *reg_info, +                                        unsigned int current_id) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context, +                                                                                    reg_info->encoding, +                                                                                    reg_info->byte_size * 8); + +    if (!clang_type) +    { +        if (log) +            log->Printf("  Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str()); +        return; +    } + +    TypeFromParser parser_clang_type (clang_type); + +    NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); + +    ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), +                                                                m_parser_vars->m_target_info.byte_order, +                                                                m_parser_vars->m_target_info.address_byte_size)); +    m_found_entities.AddNewlyConstructedVariable(entity); + +    std::string decl_name(context.m_decl_name.getAsString()); +    entity->SetName (ConstString (decl_name.c_str())); +    entity->SetRegisterInfo (reg_info); +    entity->EnableParserVars(GetParserID()); +    ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); +    parser_vars->m_parser_type = parser_clang_type; +    parser_vars->m_named_decl = var_decl; +    parser_vars->m_llvm_value = NULL; +    parser_vars->m_lldb_value.Clear(); +    entity->m_flags |= ClangExpressionVariable::EVBareRegister; + +    if (log) +    { +        ASTDumper ast_dumper(var_decl); +        log->Printf("  CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString()); +    } +} + +void +ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, +                                        Function* function, +                                        Symbol* symbol, +                                        unsigned int current_id) +{ +    assert (m_parser_vars.get()); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    NamedDecl *function_decl = NULL; +    Address fun_address; +    CompilerType function_clang_type; + +    bool is_indirect_function = false; + +    if (function) +    { +        Type *function_type = function->GetType(); + +        if (!function_type) +        { +            if (log) +                log->PutCString("  Skipped a function because it has no type"); +            return; +        } + +        function_clang_type = function_type->GetFullCompilerType (); + +        if (!function_clang_type) +        { +            if (log) +                log->PutCString("  Skipped a function because it has no Clang type"); +            return; +        } + +        fun_address = function->GetAddressRange().GetBaseAddress(); + +        CompilerType copied_function_type = GuardedCopyType(function_clang_type); +        if (copied_function_type) +        { +            function_decl = context.AddFunDecl(copied_function_type); + +            if (!function_decl) +            { +                if (log) +                { +                    log->Printf ("  Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", +                                 function_type->GetName().GetCString(), +                                 function_type->GetID()); +                } + +                return; +            } +        } +        else +        { +            // We failed to copy the type we found +            if (log) +            { +                log->Printf ("  Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt", +                             function_type->GetName().GetCString(), +                             function_type->GetID()); +            } + +            return; +        } +    } +    else if (symbol) +    { +        fun_address = symbol->GetAddress(); +        function_decl = context.AddGenericFunDecl(); +        is_indirect_function = symbol->IsIndirect(); +    } +    else +    { +        if (log) +            log->PutCString("  AddOneFunction called with no function and no symbol"); +        return; +    } + +    Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + +    lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); + +    ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), +                                                                 m_parser_vars->m_target_info.byte_order, +                                                                 m_parser_vars->m_target_info.address_byte_size)); +    m_found_entities.AddNewlyConstructedVariable(entity); + +    std::string decl_name(context.m_decl_name.getAsString()); +    entity->SetName(ConstString(decl_name.c_str())); +    entity->SetCompilerType (function_clang_type); +    entity->EnableParserVars(GetParserID()); + +    ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + +    if (load_addr != LLDB_INVALID_ADDRESS) +    { +        parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); +        parser_vars->m_lldb_value.GetScalar() = load_addr; +    } +    else +    { +        // We have to try finding a file address. + +        lldb::addr_t file_addr = fun_address.GetFileAddress(); + +        parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); +        parser_vars->m_lldb_value.GetScalar() = file_addr; +    } + + +    parser_vars->m_named_decl  = function_decl; +    parser_vars->m_llvm_value  = NULL; + +    if (log) +    { +        ASTDumper ast_dumper(function_decl); + +        StreamString ss; + +        fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); + +        log->Printf("  CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", +                    current_id, +                    (function ? "specific" : "generic"), +                    decl_name.c_str(), +                    ss.GetData(), +                    ast_dumper.GetCString()); +    } +} + +void +ClangExpressionDeclMap::AddThisType(NameSearchContext &context, +                                    TypeFromUser &ut, +                                    unsigned int current_id) +{ +    CompilerType copied_clang_type = GuardedCopyType(ut); + +    if (!copied_clang_type) +    { +        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +        if (log) +            log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type"); + +        return; +    } + +    if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ()) +    { +        CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); +        CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); + +        CompilerType method_type = ClangASTContext::CreateFunctionType (m_ast_context, +                                                                        void_clang_type, +                                                                        &void_ptr_clang_type, +                                                                        1, +                                                                        false, +                                                                        copied_clang_type.GetTypeQualifiers()); + +        const bool is_virtual = false; +        const bool is_static = false; +        const bool is_inline = false; +        const bool is_explicit = false; +        const bool is_attr_used = true; +        const bool is_artificial = false; + +        ClangASTContext::GetASTContext(m_ast_context)-> +            AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), +                                      "$__lldb_expr", +                                      method_type, +                                      lldb::eAccessPublic, +                                      is_virtual, +                                      is_static, +                                      is_inline, +                                      is_explicit, +                                      is_attr_used, +                                      is_artificial); +    } + +    if (!copied_clang_type.IsValid()) +        return; +     +    TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType())); +     +    if (!type_source_info) +        return; +     +    // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries. +    // Using a typedef makes this much more robust. +     +    TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context, +                                                    m_ast_context->getTranslationUnitDecl(), +                                                    SourceLocation(), +                                                    SourceLocation(), +                                                    context.m_decl_name.getAsIdentifierInfo(), +                                                    type_source_info); +     +     +    if (!typedef_decl) +        return; +     +    context.AddNamedDecl(typedef_decl); + +    return; +} + +void +ClangExpressionDeclMap::AddOneType(NameSearchContext &context, +                                   TypeFromUser &ut, +                                   unsigned int current_id) +{ +    CompilerType copied_clang_type = GuardedCopyType(ut); + +    if (!copied_clang_type) +    { +        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +        if (log) +            log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + +        return; +    } + +    context.AddTypeDecl(copied_clang_type); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h new file mode 100644 index 0000000000000..b3f890c7acc71 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -0,0 +1,714 @@ +//===-- ClangExpressionDeclMap.h --------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> + +// C++ Includes +#include <vector> + +#include "ClangExpressionVariable.h" +#include "ClangASTSource.h" + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression.  The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name.  But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which  +/// variables should be placed where and relaying this information back so that  +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap :  +    public ClangASTSource +{ +public: +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// Initializes class variables. +    /// +    /// @param[in] keep_result_in_memory +    ///     If true, inhibits the normal deallocation of the memory for +    ///     the result persistent variable, and instead marks the variable +    ///     as persisting. +    /// +    /// @param[in] delegate +    ///     If non-NULL, use this delegate to report result values.  This +    ///     allows the client ClangUserExpression to report a result. +    /// +    /// @param[in] exe_ctx +    ///     The execution context to use when parsing. +    //------------------------------------------------------------------ +    ClangExpressionDeclMap (bool keep_result_in_memory, +                            Materializer::PersistentVariableDelegate *result_delegate, +                            ExecutionContext &exe_ctx); +     +    //------------------------------------------------------------------ +    /// Destructor +    //------------------------------------------------------------------ +    ~ClangExpressionDeclMap() override; +     +    //------------------------------------------------------------------ +    /// Enable the state needed for parsing and IR transformation. +    /// +    /// @param[in] exe_ctx +    ///     The execution context to use when finding types for variables. +    ///     Also used to find a "scratch" AST context to store result types. +    /// +    /// @param[in] materializer +    ///     If non-NULL, the materializer to populate with information about +    ///     the variables to use +    /// +    /// @return +    ///     True if parsing is possible; false if it is unsafe to continue. +    //------------------------------------------------------------------ +    bool +    WillParse (ExecutionContext &exe_ctx, +               Materializer *materializer); +     +    void +    InstallCodeGenerator (clang::ASTConsumer *code_gen); +     +    //------------------------------------------------------------------ +    /// [Used by ClangExpressionParser] For each variable that had an unknown +    ///     type at the beginning of parsing, determine its final type now. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    ResolveUnknownTypes(); +     +    //------------------------------------------------------------------ +    /// Disable the state needed for parsing and IR transformation. +    //------------------------------------------------------------------ +    void  +    DidParse (); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Add a variable to the list of persistent +    ///     variables for the process. +    /// +    /// @param[in] decl +    ///     The Clang declaration for the persistent variable, used for +    ///     lookup during parsing. +    /// +    /// @param[in] name +    ///     The name of the persistent variable, usually $something. +    /// +    /// @param[in] type +    ///     The type of the variable, in the Clang parser's context. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    AddPersistentVariable (const clang::NamedDecl *decl, +                           const ConstString &name,  +                           TypeFromParser type, +                           bool is_result, +                           bool is_lvalue); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Add a variable to the struct that needs to +    ///     be materialized each time the expression runs. +    /// +    /// @param[in] decl +    ///     The Clang declaration for the variable. +    /// +    /// @param[in] name +    ///     The name of the variable. +    /// +    /// @param[in] value +    ///     The LLVM IR value for this variable. +    /// +    /// @param[in] size +    ///     The size of the variable in bytes. +    /// +    /// @param[in] alignment +    ///     The required alignment of the variable in bytes. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    AddValueToStruct (const clang::NamedDecl *decl, +                      const ConstString &name, +                      llvm::Value *value, +                      size_t size, +                      lldb::offset_t alignment); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Finalize the struct, laying out the position  +    /// of each object in it. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    DoStructLayout (); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Get general information about the laid-out +    /// struct after DoStructLayout() has been called. +    /// +    /// @param[out] num_elements +    ///     The number of elements in the struct. +    /// +    /// @param[out] size +    ///     The size of the struct, in bytes. +    /// +    /// @param[out] alignment +    ///     The alignment of the struct, in bytes. +    /// +    /// @return +    ///     True if the information could be retrieved; false otherwise. +    //------------------------------------------------------------------ +    bool  +    GetStructInfo (uint32_t &num_elements, +                   size_t &size, +                   lldb::offset_t &alignment); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Get specific information about one field +    /// of the laid-out struct after DoStructLayout() has been called. +    /// +    /// @param[out] decl +    ///     The parsed Decl for the field, as generated by ClangASTSource +    ///     on ClangExpressionDeclMap's behalf.  In the case of the result +    ///     value, this will have the name $__lldb_result even if the +    ///     result value ends up having the name $1.  This is an +    ///     implementation detail of IRForTarget. +    /// +    /// @param[out] value +    ///     The IR value for the field (usually a GlobalVariable).  In +    ///     the case of the result value, this will have the correct +    ///     name ($1, for instance).  This is an implementation detail +    ///     of IRForTarget. +    /// +    /// @param[out] offset +    ///     The offset of the field from the beginning of the struct. +    ///     As long as the struct is aligned according to its required +    ///     alignment, this offset will align the field correctly. +    /// +    /// @param[out] name +    ///     The name of the field as used in materialization. +    /// +    /// @param[in] index +    ///     The index of the field about which information is requested. +    /// +    /// @return +    ///     True if the information could be retrieved; false otherwise. +    //------------------------------------------------------------------ +    bool  +    GetStructElement (const clang::NamedDecl *&decl, +                      llvm::Value *&value, +                      lldb::offset_t &offset, +                      ConstString &name, +                      uint32_t index); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Get information about a function given its +    /// Decl. +    /// +    /// @param[in] decl +    ///     The parsed Decl for the Function, as generated by ClangASTSource +    ///     on ClangExpressionDeclMap's behalf. +    /// +    /// @param[out] ptr +    ///     The absolute address of the function in the target. +    /// +    /// @return +    ///     True if the information could be retrieved; false otherwise. +    //------------------------------------------------------------------ +    bool  +    GetFunctionInfo (const clang::NamedDecl *decl,  +                     uint64_t &ptr); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Get the address of a function given nothing +    /// but its name.  Some functions are needed but didn't get Decls made +    /// during parsing -- specifically, sel_registerName is never called +    /// in the generated IR but we need to call it nonetheless. +    /// +    /// @param[in] name +    ///     The name of the function.   +    /// +    /// @param[out] ptr +    ///     The absolute address of the function in the target. +    /// +    /// @return +    ///     True if the address could be retrieved; false otherwise. +    //------------------------------------------------------------------ +    bool  +    GetFunctionAddress (const ConstString &name, +                        uint64_t &ptr); +     +    //------------------------------------------------------------------ +    /// [Used by IRForTarget] Get the address of a symbol given nothing +    /// but its name. +    /// +    /// @param[in] target +    ///     The target to find the symbol in.  If not provided, +    ///     then the current parsing context's Target. +    /// +    /// @param[in] process +    ///     The process to use.  For Objective-C symbols, the process's +    ///     Objective-C language runtime may be queried if the process +    ///     is non-NULL. +    /// +    /// @param[in] name +    ///     The name of the symbol.   +    /// +    /// @param[in] module +    ///     The module to limit the search to. This can be NULL +    /// +    /// @return +    ///     Valid load address for the symbol +    //------------------------------------------------------------------ +    lldb::addr_t  +    GetSymbolAddress (Target &target, +                      Process *process, +                      const ConstString &name, +                      lldb::SymbolType symbol_type, +                      Module *module = NULL); +     +    lldb::addr_t +    GetSymbolAddress (const ConstString &name, +                      lldb::SymbolType symbol_type); +     +    //------------------------------------------------------------------ +    /// [Used by IRInterpreter] Get basic target information. +    /// +    /// @param[out] byte_order +    ///     The byte order of the target. +    /// +    /// @param[out] address_byte_size +    ///     The size of a pointer in bytes. +    /// +    /// @return +    ///     True if the information could be determined; false  +    ///     otherwise. +    //------------------------------------------------------------------ +    struct TargetInfo +    { +        lldb::ByteOrder byte_order; +        size_t address_byte_size; +         +        TargetInfo() : +            byte_order(lldb::eByteOrderInvalid), +            address_byte_size(0) +        { +        } +         +        bool IsValid() +        { +            return (byte_order != lldb::eByteOrderInvalid && +                    address_byte_size != 0); +        } +    }; +    TargetInfo GetTargetInfo(); +     +    //------------------------------------------------------------------ +    /// [Used by ClangASTSource] Find all entities matching a given name, +    /// using a NameSearchContext to make Decls for them. +    /// +    /// @param[in] context +    ///     The NameSearchContext that can construct Decls for this name. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    void  +    FindExternalVisibleDecls(NameSearchContext &context) override; +     +    //------------------------------------------------------------------ +    /// Find all entities matching a given name in a given module/namespace, +    /// using a NameSearchContext to make Decls for them. +    /// +    /// @param[in] context +    ///     The NameSearchContext that can construct Decls for this name. +    /// +    /// @param[in] module +    ///     If non-NULL, the module to query. +    /// +    /// @param[in] namespace_decl +    ///     If valid and module is non-NULL, the parent namespace. +    /// +    /// @param[in] name +    ///     The name as a plain C string.  The NameSearchContext contains  +    ///     a DeclarationName for the name so at first the name may seem +    ///     redundant, but ClangExpressionDeclMap operates in RTTI land so  +    ///     it can't access DeclarationName. +    /// +    /// @param[in] current_id +    ///     The ID for the current FindExternalVisibleDecls invocation, +    ///     for logging purposes. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    void  +    FindExternalVisibleDecls (NameSearchContext &context,  +                              lldb::ModuleSP module, +                              CompilerDeclContext &namespace_decl, +                              unsigned int current_id); +private: +    ExpressionVariableList      m_found_entities;           ///< All entities that were looked up for the parser. +    ExpressionVariableList      m_struct_members;           ///< All entities that need to be placed in the struct. +    bool                        m_keep_result_in_memory;    ///< True if result persistent variables generated by this expression should stay in memory. +    Materializer::PersistentVariableDelegate *m_result_delegate;  ///< If non-NULL, used to report expression results to ClangUserExpression. +     +    //---------------------------------------------------------------------- +    /// The following values should not live beyond parsing +    //---------------------------------------------------------------------- +    class ParserVars  +    { +    public: +        ParserVars(ClangExpressionDeclMap &decl_map) : +            m_decl_map(decl_map) +        { +        } +         +        Target * +        GetTarget() +        { +            if (m_exe_ctx.GetTargetPtr()) +                return m_exe_ctx.GetTargetPtr(); +            else if (m_sym_ctx.target_sp) +                m_sym_ctx.target_sp.get(); +            return NULL; +        } +         +        ExecutionContext            m_exe_ctx;                      ///< The execution context to use when parsing. +        SymbolContext               m_sym_ctx;                      ///< The symbol context to use in finding variables and types. +        ClangPersistentVariables   *m_persistent_vars = nullptr;    ///< The persistent variables for the process. +        bool                        m_enable_lookups = false;       ///< Set to true during parsing if we have found the first "$__lldb" name. +        TargetInfo                  m_target_info;                  ///< Basic information about the target. +        Materializer               *m_materializer = nullptr;       ///< If non-NULL, the materializer to use when reporting used variables. +        clang::ASTConsumer         *m_code_gen = nullptr;           ///< If non-NULL, a code generator that receives new top-level functions. +    private: +        ClangExpressionDeclMap     &m_decl_map; +        DISALLOW_COPY_AND_ASSIGN (ParserVars); +    }; +     +    std::unique_ptr<ParserVars> m_parser_vars; +     +    //---------------------------------------------------------------------- +    /// Activate parser-specific variables +    //---------------------------------------------------------------------- +    void  +    EnableParserVars() +    { +        if (!m_parser_vars.get()) +            m_parser_vars.reset(new ParserVars(*this)); +    } +     +    //---------------------------------------------------------------------- +    /// Deallocate parser-specific variables +    //---------------------------------------------------------------------- +    void  +    DisableParserVars() +    { +        m_parser_vars.reset(); +    } +     +    //---------------------------------------------------------------------- +    /// The following values contain layout information for the materialized +    /// struct, but are not specific to a single materialization +    //---------------------------------------------------------------------- +    struct StructVars { +        StructVars() : +            m_struct_alignment(0), +            m_struct_size(0), +            m_struct_laid_out(false), +            m_result_name(), +            m_object_pointer_type(NULL, NULL) +        { +        } +         +        lldb::offset_t              m_struct_alignment;         ///< The alignment of the struct in bytes. +        size_t                      m_struct_size;              ///< The size of the struct in bytes. +        bool                        m_struct_laid_out;          ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). +        ConstString                 m_result_name;              ///< The name of the result variable ($1, for example) +        TypeFromUser                m_object_pointer_type;      ///< The type of the "this" variable, if one exists +    }; +     +    std::unique_ptr<StructVars> m_struct_vars; +     +    //---------------------------------------------------------------------- +    /// Activate struct variables +    //---------------------------------------------------------------------- +    void  +    EnableStructVars() +    { +        if (!m_struct_vars.get()) +            m_struct_vars.reset(new struct StructVars); +    } +     +    //---------------------------------------------------------------------- +    /// Deallocate struct variables +    //---------------------------------------------------------------------- +    void +    DisableStructVars() +    { +        m_struct_vars.reset(); +    } +     +    //---------------------------------------------------------------------- +    /// Get this parser's ID for use in extracting parser- and JIT-specific +    /// data from persistent variables. +    //---------------------------------------------------------------------- +    uint64_t +    GetParserID() +    { +        return (uint64_t)this; +    } +     +    //------------------------------------------------------------------ +    /// Given a target, find a data symbol that has the given name. +    /// +    /// @param[in] target +    ///     The target to use as the basis for the search. +    /// +    /// @param[in] name +    ///     The name as a plain C string. +    /// +    /// @param[in] module +    ///     The module to limit the search to. This can be NULL +    /// +    /// @return +    ///     The LLDB Symbol found, or NULL if none was found. +    //------------------------------------------------------------------ +    const Symbol * +    FindGlobalDataSymbol (Target &target, +                          const ConstString &name, +                          Module *module = NULL); +     +    //------------------------------------------------------------------ +    /// Given a target, find a variable that matches the given name and  +    /// type. +    /// +    /// @param[in] target +    ///     The target to use as a basis for finding the variable. +    /// +    /// @param[in] module +    ///     If non-NULL, the module to search. +    /// +    /// @param[in] name +    ///     The name as a plain C string. +    /// +    /// @param[in] namespace_decl +    ///     If non-NULL and module is non-NULL, the parent namespace. +    /// +    /// @param[in] type +    ///     The required type for the variable.  This function may be called +    ///     during parsing, in which case we don't know its type; hence the +    ///     default. +    /// +    /// @return +    ///     The LLDB Variable found, or NULL if none was found. +    //------------------------------------------------------------------ +    lldb::VariableSP +    FindGlobalVariable (Target &target, +                        lldb::ModuleSP &module, +                        const ConstString &name, +                        CompilerDeclContext *namespace_decl, +                        TypeFromUser *type = NULL); +     +    //------------------------------------------------------------------ +    /// Get the value of a variable in a given execution context and return +    /// the associated Types if needed. +    /// +    /// @param[in] var +    ///     The variable to evaluate. +    /// +    /// @param[out] var_location +    ///     The variable location value to fill in +    /// +    /// @param[out] found_type +    ///     The type of the found value, as it was found in the user process. +    ///     This is only useful when the variable is being inspected on behalf +    ///     of the parser, hence the default. +    /// +    /// @param[out] parser_type +    ///     The type of the found value, as it was copied into the parser's +    ///     AST context.  This is only useful when the variable is being +    ///     inspected on behalf of the parser, hence the default. +    /// +    /// @param[in] decl +    ///     The Decl to be looked up. +    /// +    /// @return +    ///     Return true if the value was successfully filled in. +    //------------------------------------------------------------------ +    bool +    GetVariableValue (lldb::VariableSP &var, +                      lldb_private::Value &var_location, +                      TypeFromUser *found_type = NULL, +                      TypeFromParser *parser_type = NULL); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given LLDB +    /// Variable, and put it in the Tuple list. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] var +    ///     The LLDB Variable that needs a Decl. +    /// +    /// @param[in] valobj +    ///     The LLDB ValueObject for that variable. +    //------------------------------------------------------------------ +    void  +    AddOneVariable (NameSearchContext &context,  +                    lldb::VariableSP var, +                    lldb::ValueObjectSP valobj, +                    unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given +    /// persistent variable, and put it in the list of found entities. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] pvar +    ///     The persistent variable that needs a Decl. +    /// +    /// @param[in] current_id +    ///     The ID of the current invocation of FindExternalVisibleDecls +    ///     for logging purposes. +    //------------------------------------------------------------------ +    void  +    AddOneVariable (NameSearchContext &context,  +                    lldb::ExpressionVariableSP &pvar_sp, +                    unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given LLDB +    /// symbol (treated as a variable), and put it in the list of found +    /// entities. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] var +    ///     The LLDB Variable that needs a Decl. +    //------------------------------------------------------------------ +    void +    AddOneGenericVariable (NameSearchContext &context, +                           const Symbol &symbol, +                           unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given +    /// function.  (Functions are not placed in the Tuple list.)  Can +    /// handle both fully typed functions and generic functions. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] fun +    ///     The Function that needs to be created.  If non-NULL, this is +    ///     a fully-typed function. +    /// +    /// @param[in] sym +    ///     The Symbol that corresponds to a function that needs to be  +    ///     created with generic type (unitptr_t foo(...)). +    //------------------------------------------------------------------ +    void +    AddOneFunction (NameSearchContext &context,  +                    Function *fun,  +                    Symbol *sym, +                    unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given +    /// register. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] reg_info +    ///     The information corresponding to that register. +    //------------------------------------------------------------------ +    void  +    AddOneRegister (NameSearchContext &context,  +                    const RegisterInfo *reg_info, +                    unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Use the NameSearchContext to generate a Decl for the given +    /// type.  (Types are not placed in the Tuple list.) +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] type +    ///     The type that needs to be created. +    //------------------------------------------------------------------ +    void  +    AddOneType (NameSearchContext &context,  +                TypeFromUser &type, +                unsigned int current_id); +     +    //------------------------------------------------------------------ +    /// Generate a Decl for "*this" and add a member function declaration +    /// to it for the expression, then report it. +    /// +    /// @param[in] context +    ///     The NameSearchContext to use when constructing the Decl. +    /// +    /// @param[in] type +    ///     The type for *this. +    //------------------------------------------------------------------ +    void +    AddThisType(NameSearchContext &context, +                TypeFromUser &type, +                unsigned int current_id); +}; +     +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h new file mode 100644 index 0000000000000..bb620def691f9 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -0,0 +1,79 @@ +//===-- ClangExpression.h ---------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpression_h_ +#define liblldb_ClangExpression_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ExpressionTypeSystemHelper.h" + +namespace lldb_private { + +class RecordingMemoryManager; + +//---------------------------------------------------------------------- +// ClangExpressionHelper +//---------------------------------------------------------------------- +class ClangExpressionHelper : public ExpressionTypeSystemHelper +{ +public: +    static bool classof(const ExpressionTypeSystemHelper *ts) +    { +        return ts->getKind() == eKindClangHelper; +    } + +    ClangExpressionHelper () : +        ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) +    { +    } + +    //------------------------------------------------------------------ +    /// Destructor +    //------------------------------------------------------------------ +    virtual ~ClangExpressionHelper () +    { +    } +     +    //------------------------------------------------------------------ +    /// Return the object that the parser should use when resolving external +    /// values.  May be NULL if everything should be self-contained. +    //------------------------------------------------------------------ +    virtual ClangExpressionDeclMap * +    DeclMap () = 0; +     +    //------------------------------------------------------------------ +    /// Return the object that the parser should allow to access ASTs. +    /// May be NULL if the ASTs do not need to be transformed. +    /// +    /// @param[in] passthrough +    ///     The ASTConsumer that the returned transformer should send +    ///     the ASTs to after transformation. +    //------------------------------------------------------------------ +    virtual clang::ASTConsumer * +    ASTTransformer (clang::ASTConsumer *passthrough) = 0; +     + +protected: + +}; + +} // namespace lldb_private + +#endif  // liblldb_ClangExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp new file mode 100644 index 0000000000000..72c33fec8105c --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -0,0 +1,657 @@ +//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetSelect.h" + +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" + +// Project includes +#include "ClangExpressionParser.h" + +#include "ClangASTSource.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionDeclMap.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" +#include "IRForTarget.h" + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/File.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace clang; +using namespace llvm; +using namespace lldb_private; + +//===----------------------------------------------------------------------===// +// Utility Methods for Clang +//===----------------------------------------------------------------------===// + +std::string GetBuiltinIncludePath(const char *Argv0) { +    SmallString<128> P(llvm::sys::fs::getMainExecutable( +        Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); + +    if (!P.empty()) { +        llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang +        llvm::sys::path::remove_filename(P); // Remove /bin   from foo/bin + +        // Get foo/lib/clang/<version>/include +        llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, +                                "include"); +    } + +    return P.str(); +} + +class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks +{ +    ClangModulesDeclVendor     &m_decl_vendor; +    ClangPersistentVariables   &m_persistent_vars; +    StreamString                m_error_stream; +    bool                        m_has_errors = false; + +public: +    LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, +                              ClangPersistentVariables &persistent_vars) : +        m_decl_vendor(decl_vendor), +        m_persistent_vars(persistent_vars) +    { +    } +     +    void +    moduleImport(SourceLocation import_location, +                 clang::ModuleIdPath path, +                 const clang::Module * /*null*/) override +    { +        std::vector<ConstString> string_path; +         +        for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) +        { +            string_path.push_back(ConstString(component.first->getName())); +        } +      +        StreamString error_stream; +         +        ClangModulesDeclVendor::ModuleVector exported_modules; +         +        if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) +        { +            m_has_errors = true; +        } +         +        for (ClangModulesDeclVendor::ModuleID module : exported_modules) +        { +            m_persistent_vars.AddHandLoadedClangModule(module); +        } +    } +     +    bool hasErrors() +    { +        return m_has_errors; +    } +     +    const std::string &getErrorString() +    { +        return m_error_stream.GetString(); +    } +}; + +//===----------------------------------------------------------------------===// +// Implementation of ClangExpressionParser +//===----------------------------------------------------------------------===// + +ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, +                                              Expression &expr, +                                              bool generate_debug_info) : +    ExpressionParser (exe_scope, expr, generate_debug_info), +    m_compiler (), +    m_code_generator (), +    m_pp_callbacks(nullptr) +{ +    // 1. Create a new compiler instance. +    m_compiler.reset(new CompilerInstance()); + +    // 2. Install the target. + +    lldb::TargetSP target_sp; +    if (exe_scope) +        target_sp = exe_scope->CalculateTarget(); + +    // TODO: figure out what to really do when we don't have a valid target. +    // Sometimes this will be ok to just use the host target triple (when we +    // evaluate say "2+3", but other expressions like breakpoint conditions +    // and other things that _are_ target specific really shouldn't just be +    // using the host triple. This needs to be fixed in a better way. +    if (target_sp && target_sp->GetArchitecture().IsValid()) +    { +        std::string triple = target_sp->GetArchitecture().GetTriple().str(); +        m_compiler->getTargetOpts().Triple = triple; +    } +    else +    { +        m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); +    } + +    if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || +        target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) +    { +        m_compiler->getTargetOpts().Features.push_back("+sse"); +        m_compiler->getTargetOpts().Features.push_back("+sse2"); +    } + +    // Any arm32 iOS environment, but not on arm64 +    if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && +        m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && +        m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) +    { +        m_compiler->getTargetOpts().ABI = "apcs-gnu"; +    } + +    m_compiler->createDiagnostics(); + +    // Create the target instance. +    m_compiler->setTarget(TargetInfo::CreateTargetInfo( +        m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); + +    assert (m_compiler->hasTarget()); + +    // 3. Set options. + +    lldb::LanguageType language = expr.Language(); + +    switch (language) +    { +    case lldb::eLanguageTypeC: +    case lldb::eLanguageTypeC89: +    case lldb::eLanguageTypeC99: +    case lldb::eLanguageTypeC11: +        // FIXME: the following language option is a temporary workaround, +        // to "ask for C, get C++." +        // For now, the expression parser must use C++ anytime the +        // language is a C family language, because the expression parser +        // uses features of C++ to capture values. +        m_compiler->getLangOpts().CPlusPlus = true; +        break; +    case lldb::eLanguageTypeObjC: +        m_compiler->getLangOpts().ObjC1 = true; +        m_compiler->getLangOpts().ObjC2 = true; +        // FIXME: the following language option is a temporary workaround, +        // to "ask for ObjC, get ObjC++" (see comment above). +        m_compiler->getLangOpts().CPlusPlus = true; +        break; +    case lldb::eLanguageTypeC_plus_plus: +    case lldb::eLanguageTypeC_plus_plus_11: +    case lldb::eLanguageTypeC_plus_plus_14: +        m_compiler->getLangOpts().CPlusPlus11 = true; +        m_compiler->getHeaderSearchOpts().UseLibcxx = true; +        // fall thru ... +    case lldb::eLanguageTypeC_plus_plus_03: +        m_compiler->getLangOpts().CPlusPlus = true; +        // FIXME: the following language option is a temporary workaround, +        // to "ask for C++, get ObjC++".  Apple hopes to remove this requirement +        // on non-Apple platforms, but for now it is needed. +        m_compiler->getLangOpts().ObjC1 = true; +        break; +    case lldb::eLanguageTypeObjC_plus_plus: +    case lldb::eLanguageTypeUnknown: +    default: +        m_compiler->getLangOpts().ObjC1 = true; +        m_compiler->getLangOpts().ObjC2 = true; +        m_compiler->getLangOpts().CPlusPlus = true; +        m_compiler->getLangOpts().CPlusPlus11 = true; +        m_compiler->getHeaderSearchOpts().UseLibcxx = true; +        break; +    } + +    m_compiler->getLangOpts().Bool = true; +    m_compiler->getLangOpts().WChar = true; +    m_compiler->getLangOpts().Blocks = true; +    m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients +    if (expr.DesiredResultType() == Expression::eResultTypeId) +        m_compiler->getLangOpts().DebuggerCastResultToId = true; + +    m_compiler->getLangOpts().CharIsSigned = +            ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); + +    // Spell checking is a nice feature, but it ends up completing a +    // lot of types that we didn't strictly speaking need to complete. +    // As a result, we spend a long time parsing and importing debug +    // information. +    m_compiler->getLangOpts().SpellChecking = false; + +    lldb::ProcessSP process_sp; +    if (exe_scope) +        process_sp = exe_scope->CalculateProcess(); + +    if (process_sp && m_compiler->getLangOpts().ObjC1) +    { +        if (process_sp->GetObjCLanguageRuntime()) +        { +            if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) +                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); +            else +                m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); + +            if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) +                m_compiler->getLangOpts().DebuggerObjCLiteral = true; +        } +    } + +    m_compiler->getLangOpts().ThreadsafeStatics = false; +    m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access +    m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name + +    // Set CodeGen options +    m_compiler->getCodeGenOpts().EmitDeclMetadata = true; +    m_compiler->getCodeGenOpts().InstrumentFunctions = false; +    m_compiler->getCodeGenOpts().DisableFPElim = true; +    m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; +    if (generate_debug_info) +        m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); +    else +        m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); + +    // Disable some warnings. +    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, +        "unused-value", clang::diag::Severity::Ignored, SourceLocation()); +    m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, +        "odr", clang::diag::Severity::Ignored, SourceLocation()); + +    // Inform the target of the language options +    // +    // FIXME: We shouldn't need to do this, the target should be immutable once +    // created. This complexity should be lifted elsewhere. +    m_compiler->getTarget().adjust(m_compiler->getLangOpts()); + +    // 4. Set up the diagnostic buffer for reporting errors + +    m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + +    // 5. Set up the source management objects inside the compiler + +    clang::FileSystemOptions file_system_options; +    m_file_manager.reset(new clang::FileManager(file_system_options)); + +    if (!m_compiler->hasSourceManager()) +        m_compiler->createSourceManager(*m_file_manager.get()); + +    m_compiler->createFileManager(); +    m_compiler->createPreprocessor(TU_Complete); +     +    if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) +    { +        ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); +        std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); +        m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get()); +        m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); +    } +         +    // 6. Most of this we get from the CompilerInstance, but we +    // also want to give the context an ExternalASTSource. +    m_selector_table.reset(new SelectorTable()); +    m_builtin_context.reset(new Builtin::Context()); + +    std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(), +                                                                  m_compiler->getSourceManager(), +                                                                  m_compiler->getPreprocessor().getIdentifierTable(), +                                                                  *m_selector_table.get(), +                                                                  *m_builtin_context.get())); +     +    ast_context->InitBuiltinTypes(m_compiler->getTarget()); + +    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); +    ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); + +    if (decl_map) +    { +        llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy()); +        decl_map->InstallASTContext(ast_context.get()); +        ast_context->setExternalSource(ast_source); +    } + +    m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); +    m_ast_context->setASTContext(ast_context.get()); +    m_compiler->setASTContext(ast_context.release()); + +    std::string module_name("$__lldb_module"); + +    m_llvm_context.reset(new LLVMContext()); +    m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), +                                             module_name, +                                             m_compiler->getHeaderSearchOpts(), +                                             m_compiler->getPreprocessorOpts(), +                                             m_compiler->getCodeGenOpts(), +                                             *m_llvm_context)); +} + +ClangExpressionParser::~ClangExpressionParser() +{ +} + +unsigned +ClangExpressionParser::Parse (Stream &stream) +{ +    TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient()); + +    diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); + +    const char *expr_text = m_expr.Text(); + +    clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); +    bool created_main_file = false; +    if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) +    { +        std::string temp_source_path; + +        int temp_fd = -1; +        llvm::SmallString<PATH_MAX> result_path; +        FileSpec tmpdir_file_spec; +        if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) +        { +            tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); +            temp_source_path = tmpdir_file_spec.GetPath(); +            llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); +        } +        else +        { +            llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); +        } +         +        if (temp_fd != -1) +        { +            lldb_private::File file (temp_fd, true); +            const size_t expr_text_len = strlen(expr_text); +            size_t bytes_written = expr_text_len; +            if (file.Write(expr_text, bytes_written).Success()) +            { +                if (bytes_written == expr_text_len) +                { +                    file.Close(); +                    SourceMgr.setMainFileID(SourceMgr.createFileID( +                        m_file_manager->getFile(result_path), +                        SourceLocation(), SrcMgr::C_User)); +                    created_main_file = true; +                } +            } +        } +    } + +    if (!created_main_file) +    { +        std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); +        SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); +    } + +    diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); + +    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + +    ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); + +    if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) +        decl_map->InstallCodeGenerator(m_code_generator.get()); + +    if (ast_transformer) +    { +        ast_transformer->Initialize(m_compiler->getASTContext()); +        ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); +    } +    else +    { +        m_code_generator->Initialize(m_compiler->getASTContext()); +        ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); +    } + +    diag_buf->EndSourceFile(); + +    TextDiagnosticBuffer::const_iterator diag_iterator; + +    int num_errors = 0; +     +    if (m_pp_callbacks && m_pp_callbacks->hasErrors()) +    { +        num_errors++; +         +        stream.PutCString(m_pp_callbacks->getErrorString().c_str()); +    } + +    for (diag_iterator = diag_buf->warn_begin(); +         diag_iterator != diag_buf->warn_end(); +         ++diag_iterator) +        stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); + +    for (diag_iterator = diag_buf->err_begin(); +         diag_iterator != diag_buf->err_end(); +         ++diag_iterator) +    { +        num_errors++; +        stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); +    } + +    for (diag_iterator = diag_buf->note_begin(); +         diag_iterator != diag_buf->note_end(); +         ++diag_iterator) +        stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); + +    if (!num_errors) +    { +        if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) +        { +            stream.Printf("error: Couldn't infer the type of a variable\n"); +            num_errors++; +        } +    } + +    return num_errors; +} + +static bool FindFunctionInModule (ConstString &mangled_name, +                                  llvm::Module *module, +                                  const char *orig_name) +{ +    for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); +         fi != fe; +         ++fi) +    { +        if (fi->getName().str().find(orig_name) != std::string::npos) +        { +            mangled_name.SetCString(fi->getName().str().c_str()); +            return true; +        } +    } + +    return false; +} + +Error +ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, +                                            lldb::addr_t &func_end, +                                            lldb::IRExecutionUnitSP &execution_unit_sp, +                                            ExecutionContext &exe_ctx, +                                            bool &can_interpret, +                                            ExecutionPolicy execution_policy) +{ +	func_addr = LLDB_INVALID_ADDRESS; +	func_end = LLDB_INVALID_ADDRESS; +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    Error err; + +    std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); + +    if (!llvm_module_ap.get()) +    { +        err.SetErrorToGenericError(); +        err.SetErrorString("IR doesn't contain a module"); +        return err; +    } + +    // Find the actual name of the function (it's often mangled somehow) + +    ConstString function_name; + +    if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) +    { +        err.SetErrorToGenericError(); +        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); +        return err; +    } +    else +    { +        if (log) +            log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); +    } + +    execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here +                                                 llvm_module_ap, // handed off here +                                                 function_name, +                                                 exe_ctx.GetTargetSP(), +                                                 m_compiler->getTargetOpts().Features)); + +    ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); +    ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL + +    if (decl_map) +    { +        Stream *error_stream = NULL; +        Target *target = exe_ctx.GetTargetPtr(); +        if (target) +            error_stream = target->GetDebugger().GetErrorFile().get(); + +        IRForTarget ir_for_target(decl_map, +                                  m_expr.NeedsVariableResolution(), +                                  *execution_unit_sp, +                                  error_stream, +                                  function_name.AsCString()); + +        bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); + +        Error interpret_error; +        Process *process = exe_ctx.GetProcessPtr(); + +        bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); +        can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); + + +        if (!ir_can_run) +        { +            err.SetErrorString("The expression could not be prepared to run in the target"); +            return err; +        } + +        if (!can_interpret && execution_policy == eExecutionPolicyNever) +        { +            err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); +            return err; +        } + +        if (!process && execution_policy == eExecutionPolicyAlways) +        { +            err.SetErrorString("Expression needed to run in the target, but the target can't be run"); +            return err; +        } + +        if (execution_policy == eExecutionPolicyAlways || !can_interpret) +        { +            if (m_expr.NeedsValidation() && process) +            { +                if (!process->GetDynamicCheckers()) +                { +                    DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); + +                    StreamString install_errors; + +                    if (!dynamic_checkers->Install(install_errors, exe_ctx)) +                    { +                        if (install_errors.GetString().empty()) +                            err.SetErrorString ("couldn't install checkers, unknown error"); +                        else +                            err.SetErrorString (install_errors.GetString().c_str()); + +                        return err; +                    } + +                    process->SetDynamicCheckers(dynamic_checkers); + +                    if (log) +                        log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); +                } + +                IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); + +                if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) +                { +                    err.SetErrorToGenericError(); +                    err.SetErrorString("Couldn't add dynamic checks to the expression"); +                    return err; +                } +            } + +            execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); +        } +    } +    else +    { +        execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); +    } + +    return err; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h new file mode 100644 index 0000000000000..3c055380b839f --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -0,0 +1,136 @@ +//===-- ClangExpressionParser.h ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionParser_h_ +#define liblldb_ClangExpressionParser_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/ExpressionParser.h" + +#include <string> +#include <vector> + +namespace lldb_private +{ + +class IRExecutionUnit; +     +//---------------------------------------------------------------------- +/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" +/// @brief Encapsulates an instance of Clang that can parse expressions. +/// +/// ClangExpressionParser is responsible for preparing an instance of +/// ClangExpression for execution.  ClangExpressionParser uses ClangExpression +/// as a glorified parameter list, performing the required parsing and +/// conversion to formats (DWARF bytecode, or JIT compiled machine code) +/// that can be executed. +//---------------------------------------------------------------------- +class ClangExpressionParser : public ExpressionParser +{ +public: +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// Initializes class variables. +    /// +    /// @param[in] exe_scope, +    ///     If non-NULL, an execution context scope that can help to  +    ///     correctly create an expression with a valid process for  +    ///     optional tuning Objective-C runtime support. Can be NULL. +    /// +    /// @param[in] expr +    ///     The expression to be parsed. +    //------------------------------------------------------------------ +    ClangExpressionParser (ExecutionContextScope *exe_scope, +                           Expression &expr, +                           bool generate_debug_info); +     +    //------------------------------------------------------------------ +    /// Destructor +    //------------------------------------------------------------------ +    ~ClangExpressionParser () override; +     +    //------------------------------------------------------------------ +    /// Parse a single expression and convert it to IR using Clang.  Don't +    /// wrap the expression in anything at all. +    /// +    /// @param[in] stream +    ///     The stream to print errors to. +    /// +    /// @return +    ///     The number of errors encountered during parsing.  0 means +    ///     success. +    //------------------------------------------------------------------ +    unsigned +    Parse (Stream &stream) override; +     +    //------------------------------------------------------------------ +    /// Ready an already-parsed expression for execution, possibly +    /// evaluating it statically. +    /// +    /// @param[out] func_addr +    ///     The address to which the function has been written. +    /// +    /// @param[out] func_end +    ///     The end of the function's allocated memory region.  (func_addr +    ///     and func_end do not delimit an allocated region; the allocated +    ///     region may begin before func_addr.) +    /// +    /// @param[in] execution_unit_sp +    ///     After parsing, ownership of the execution unit for +    ///     for the expression is handed to this shared pointer. +    /// +    /// @param[in] exe_ctx +    ///     The execution context to write the function into. +    /// +    /// @param[out] evaluated_statically +    ///     Set to true if the expression could be interpreted statically; +    ///     untouched otherwise. +    /// +    /// @param[out] const_result +    ///     If the result of the expression is constant, and the +    ///     expression has no side effects, this is set to the result of the  +    ///     expression. +    /// +    /// @param[in] execution_policy +    ///     Determines whether the expression must be JIT-compiled, must be +    ///     evaluated statically, or whether this decision may be made +    ///     opportunistically. +    /// +    /// @return +    ///     An error code indicating the success or failure of the operation. +    ///     Test with Success(). +    //------------------------------------------------------------------ +    Error +    PrepareForExecution (lldb::addr_t &func_addr, +                         lldb::addr_t &func_end, +                         lldb::IRExecutionUnitSP &execution_unit_sp, +                         ExecutionContext &exe_ctx, +                         bool &can_interpret, +                         lldb_private::ExecutionPolicy execution_policy) override; +         +private: +    std::unique_ptr<llvm::LLVMContext>       m_llvm_context;         ///< The LLVM context to generate IR into +    std::unique_ptr<clang::FileManager>      m_file_manager;         ///< The Clang file manager object used by the compiler +    std::unique_ptr<clang::CompilerInstance> m_compiler;             ///< The Clang compiler used to parse expressions into IR +    std::unique_ptr<clang::Builtin::Context> m_builtin_context;      ///< Context for Clang built-ins +    std::unique_ptr<clang::SelectorTable>    m_selector_table;       ///< Selector table for Objective-C methods +    std::unique_ptr<clang::CodeGenerator>    m_code_generator;       ///< The Clang object that generates IR +     +    class LLDBPreprocessorCallbacks; +    LLDBPreprocessorCallbacks               *m_pp_callbacks;         ///< Called when the preprocessor encounters module imports +    std::unique_ptr<ClangASTContext>         m_ast_context; +}; +     +} + +#endif  // liblldb_ClangExpressionParser_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp new file mode 100644 index 0000000000000..908546b3ecdbd --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp @@ -0,0 +1,76 @@ +//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionVariable.h" + +#include "clang/AST/ASTContext.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" + +using namespace lldb_private; +using namespace clang; + +const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable"; + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) : +    ExpressionVariable(LLVMCastKind::eKindClang), +    m_parser_vars(), +    m_jit_vars () +{ +    m_flags = EVNone; +    m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); +} + +ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, +                                                  Value &value, +                                                  const ConstString &name, +                                                  uint16_t flags) : +    ExpressionVariable(LLVMCastKind::eKindClang), +    m_parser_vars(), +    m_jit_vars () +{ +    m_flags = flags; +    m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name); +} + +ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : +    ExpressionVariable(LLVMCastKind::eKindClang), +    m_parser_vars(), +    m_jit_vars () +{ +    m_flags = EVNone; +    m_frozen_sp = valobj_sp; +} + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, +                                                 const ConstString &name, +                                                 const TypeFromUser& user_type, +                                                 lldb::ByteOrder byte_order, +                                                 uint32_t addr_byte_size) : +    ExpressionVariable(LLVMCastKind::eKindClang), +    m_parser_vars(), +    m_jit_vars() +{ +    m_flags = EVNone; +    m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); +    SetName (name); +    SetCompilerType (user_type); +} + +TypeFromUser +ClangExpressionVariable::GetTypeFromUser() +{ +    TypeFromUser tfu (m_frozen_sp->GetCompilerType()); +    return tfu; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h new file mode 100644 index 0000000000000..a4596148f6c74 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -0,0 +1,265 @@ +//===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionVariable_h_ +#define liblldb_ClangExpressionVariable_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> +#include <string.h> + +// C++ Includes +#include <map> +#include <string> +#include <vector> + +// Other libraries and framework includes +#include "llvm/Support/Casting.h" + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TaggedASTType.h" + +namespace llvm { +    class Value; +} + +namespace lldb_private { + +class ValueObjectConstResult; + +//---------------------------------------------------------------------- +/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @brief Encapsulates one variable for the expression parser. +/// +/// The expression parser uses variables in three different contexts: +/// +/// First, it stores persistent variables along with the process for use +/// in expressions.  These persistent variables contain their own data +/// and are typed. +/// +/// Second, in an interpreted expression, it stores the local variables +/// for the expression along with the expression.  These variables +/// contain their own data and are typed. +/// +/// Third, in a JIT-compiled expression, it stores the variables that +/// the expression needs to have materialized and dematerialized at each +/// execution.  These do not contain their own data but are named and +/// typed. +/// +/// This class supports all of these use cases using simple type +/// polymorphism, and provides necessary support methods.  Its interface +/// is RTTI-neutral. +//---------------------------------------------------------------------- +class ClangExpressionVariable : public ExpressionVariable +{ +public: +    ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); + +    ClangExpressionVariable (ExecutionContextScope *exe_scope, +                             Value &value, +                             const ConstString &name, +                             uint16_t flags = EVNone); +     +    ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); +     +    ClangExpressionVariable(ExecutionContextScope *exe_scope, +                            const ConstString &name, +                            const TypeFromUser& user_type, +                            lldb::ByteOrder byte_order, +                            uint32_t addr_byte_size); +         +    //---------------------------------------------------------------------- +    /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways +    //---------------------------------------------------------------------- +     +    //---------------------------------------------------------------------- +    /// Finds a variable by NamedDecl in the list. +    /// +    /// @param[in] name +    ///     The name of the requested variable. +    /// +    /// @return +    ///     The variable requested, or NULL if that variable is not in the list. +    //---------------------------------------------------------------------- +    static ClangExpressionVariable * +    FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id) +    { +        lldb::ExpressionVariableSP var_sp; +        for (size_t index = 0, size = list.GetSize(); index < size; ++index) +        { +            var_sp = list.GetVariableAtIndex(index); +             +            if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(var_sp.get())) +            { +                ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id); +                 +                if (parser_vars && parser_vars->m_named_decl == decl) +                    return clang_var; +            } +        } +        return nullptr; +    } + +    //---------------------------------------------------------------------- +    /// If the variable contains its own data, make a Value point at it. +    /// If \a exe_ctx in not NULL, the value will be resolved in with +    /// that execution context. +    /// +    /// @param[in] value +    ///     The value to point at the data. +    /// +    /// @param[in] exe_ctx +    ///     The execution context to use to resolve \a value. +    /// +    /// @return +    ///     True on success; false otherwise (in particular, if this variable +    ///     does not contain its own data). +    //---------------------------------------------------------------------- +    bool +    PointValueAtData(Value &value, ExecutionContext *exe_ctx); +     +    //---------------------------------------------------------------------- +    /// The following values should not live beyond parsing +    //---------------------------------------------------------------------- +    class ParserVars  +    { +    public: + +        ParserVars() : +            m_parser_type(), +            m_named_decl (NULL), +            m_llvm_value (NULL), +            m_lldb_value (), +            m_lldb_var   (), +            m_lldb_sym   (NULL) +        { +        } + +        TypeFromParser          m_parser_type;  ///< The type of the variable according to the parser +        const clang::NamedDecl *m_named_decl;   ///< The Decl corresponding to this variable +        llvm::Value            *m_llvm_value;   ///< The IR value corresponding to this variable; usually a GlobalValue +        lldb_private::Value     m_lldb_value;   ///< The value found in LLDB for this variable +        lldb::VariableSP        m_lldb_var;     ///< The original variable for this variable +        const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol +    }; +     +private: +    typedef std::map <uint64_t, ParserVars> ParserVarMap; +    ParserVarMap m_parser_vars; + +public: +    //---------------------------------------------------------------------- +    /// Make this variable usable by the parser by allocating space for +    /// parser-specific variables +    //---------------------------------------------------------------------- +    void  +    EnableParserVars(uint64_t parser_id) +    { +        m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); +    } +     +    //---------------------------------------------------------------------- +    /// Deallocate parser-specific variables +    //---------------------------------------------------------------------- +    void +    DisableParserVars(uint64_t parser_id) +    { +        m_parser_vars.erase(parser_id); +    } +     +    //---------------------------------------------------------------------- +    /// Access parser-specific variables +    //---------------------------------------------------------------------- +    ParserVars * +    GetParserVars(uint64_t parser_id) +    { +        ParserVarMap::iterator i = m_parser_vars.find(parser_id); +         +        if (i == m_parser_vars.end()) +            return NULL; +        else +            return &i->second; +    } +     +    //---------------------------------------------------------------------- +    /// The following values are valid if the variable is used by JIT code +    //---------------------------------------------------------------------- +    struct JITVars { +        JITVars () : +            m_alignment (0), +            m_size (0), +            m_offset (0) +        { +        } + +        lldb::offset_t   m_alignment; ///< The required alignment of the variable, in bytes +        size_t  m_size;               ///< The space required for the variable, in bytes +        lldb::offset_t   m_offset;    ///< The offset of the variable in the struct, in bytes +    }; +     +private: +    typedef std::map <uint64_t, JITVars> JITVarMap; +    JITVarMap m_jit_vars; +     +public: +    //---------------------------------------------------------------------- +    /// Make this variable usable for materializing for the JIT by allocating  +    /// space for JIT-specific variables +    //---------------------------------------------------------------------- +    void  +    EnableJITVars(uint64_t parser_id) +    { +        m_jit_vars.insert(std::make_pair(parser_id, JITVars())); +    } +     +    //---------------------------------------------------------------------- +    /// Deallocate JIT-specific variables +    //---------------------------------------------------------------------- +    void  +    DisableJITVars(uint64_t parser_id) +    { +        m_jit_vars.erase(parser_id); +    } +     +    JITVars *GetJITVars(uint64_t parser_id) +    { +        JITVarMap::iterator i = m_jit_vars.find(parser_id); +         +        if (i == m_jit_vars.end()) +            return NULL; +        else +            return &i->second; +    } +     +    TypeFromUser +    GetTypeFromUser (); +     +    //------------------------------------------------------------------ +    // llvm casting support +    //------------------------------------------------------------------ +    static bool classof(const ExpressionVariable *ev) +    { +        return ev->getKind() == ExpressionVariable::eKindClang; +    } +     +    //---------------------------------------------------------------------- +    /// Members +    //----------------------------------------------------------------------         +    DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); +}; + +} // namespace lldb_private + +#endif  // liblldb_ClangExpressionVariable_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp new file mode 100644 index 0000000000000..0d0d7475a00e2 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -0,0 +1,221 @@ +//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangFunctionCaller.h" + +#include "ASTStructExtractor.h" +#include "ClangExpressionParser.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/Module.h" + +// Project includes +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/State.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb_private; + +//---------------------------------------------------------------------- +// ClangFunctionCaller constructor +//---------------------------------------------------------------------- +ClangFunctionCaller::ClangFunctionCaller  +( +    ExecutionContextScope &exe_scope, +    const CompilerType &return_type,  +    const Address& functionAddress,  +    const ValueList &arg_value_list, +    const char *name +) : +    FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), +    m_type_system_helper (*this) +{ +    m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); +    // Can't make a ClangFunctionCaller without a process. +    assert (m_jit_process_wp.lock()); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangFunctionCaller::~ClangFunctionCaller() +{ +} + +unsigned +ClangFunctionCaller::CompileFunction (Stream &errors) +{ +    if (m_compiled) +        return 0; +     +    // FIXME: How does clang tell us there's no return value?  We need to handle that case. +    unsigned num_errors = 0; +     +    std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); +     +    // Cons up the function we're going to wrap our call in, then compile it... +    // We declare the function "extern "C"" because the compiler might be in C++ +    // mode which would mangle the name and then we couldn't find it again... +    m_wrapper_function_text.clear(); +    m_wrapper_function_text.append ("extern \"C\" void "); +    m_wrapper_function_text.append (m_wrapper_function_name); +    m_wrapper_function_text.append (" (void *input)\n{\n    struct "); +    m_wrapper_function_text.append (m_wrapper_struct_name); +    m_wrapper_function_text.append (" \n  {\n"); +    m_wrapper_function_text.append ("    "); +    m_wrapper_function_text.append (return_type_str); +    m_wrapper_function_text.append (" (*fn_ptr) ("); + +    // Get the number of arguments.  If we have a function type and it is prototyped, +    // trust that, otherwise use the values we were given. + +    // FIXME: This will need to be extended to handle Variadic functions.  We'll need +    // to pull the defined arguments out of the function, then add the types from the +    // arguments list for the variable arguments. + +    uint32_t num_args = UINT32_MAX; +    bool trust_function = false; +    // GetArgumentCount returns -1 for an unprototyped function. +    CompilerType function_clang_type; +    if (m_function_ptr) +    { +        function_clang_type = m_function_ptr->GetCompilerType(); +        if (function_clang_type) +        { +            int num_func_args = function_clang_type.GetFunctionArgumentCount(); +            if (num_func_args >= 0) +            { +                trust_function = true; +                num_args = num_func_args; +            } +        } +    } + +    if (num_args == UINT32_MAX) +        num_args = m_arg_values.GetSize(); + +    std::string args_buffer;  // This one stores the definition of all the args in "struct caller". +    std::string args_list_buffer;  // This one stores the argument list called from the structure. +    for (size_t i = 0; i < num_args; i++) +    { +        std::string type_name; + +        if (trust_function) +        { +            type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); +        } +        else +        { +            CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); +            if (clang_qual_type) +            { +                type_name = clang_qual_type.GetTypeName().AsCString(""); +            } +            else +            {    +                errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); +                return 1; +            } +        } + +        m_wrapper_function_text.append (type_name); +        if (i < num_args - 1) +            m_wrapper_function_text.append (", "); + +        char arg_buf[32]; +        args_buffer.append ("    "); +        args_buffer.append (type_name); +        snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); +        args_buffer.push_back (' '); +        args_buffer.append (arg_buf); +        args_buffer.append (";\n"); + +        args_list_buffer.append ("__lldb_fn_data->"); +        args_list_buffer.append (arg_buf); +        if (i < num_args - 1) +            args_list_buffer.append (", "); + +    } +    m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. + +    m_wrapper_function_text.append (args_buffer); + +    m_wrapper_function_text.append ("    "); +    m_wrapper_function_text.append (return_type_str); +    m_wrapper_function_text.append (" return_value;"); +    m_wrapper_function_text.append ("\n  };\n  struct "); +    m_wrapper_function_text.append (m_wrapper_struct_name); +    m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); +    m_wrapper_function_text.append (m_wrapper_struct_name); +    m_wrapper_function_text.append (" *) input;\n"); + +    m_wrapper_function_text.append ("  __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); +    m_wrapper_function_text.append (args_list_buffer); +    m_wrapper_function_text.append (");\n}\n"); + +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +    if (log) +        log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); +         +    // Okay, now compile this expression +     +    lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); +    if (jit_process_sp) +    { +        const bool generate_debug_info = true; +        m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); +         +        num_errors = m_parser->Parse (errors); +    } +    else +    { +        errors.Printf("no process - unable to inject function"); +        num_errors = 1; +    } +     +    m_compiled = (num_errors == 0); +     +    if (!m_compiled) +        return num_errors; + +    return num_errors; +} + +clang::ASTConsumer * +ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ +    m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); +     +    return m_struct_extractor.get(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h new file mode 100644 index 0000000000000..3e30f818a9328 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -0,0 +1,173 @@ +//===-- ClangFunctionCaller.h -----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangFunctionCaller_h_ +#define liblldb_ClangFunctionCaller_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Process.h" + +namespace lldb_private +{ +     +class ASTStructExtractor; +class ClangExpressionParser; + +//---------------------------------------------------------------------- +/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h" +/// @brief Encapsulates a function that can be called. +/// +/// A given ClangFunctionCaller object can handle a single function signature. +/// Once constructed, it can set up any number of concurrent calls to +/// functions with that signature. +/// +/// It performs the call by synthesizing a structure that contains the pointer +/// to the function and the arguments that should be passed to that function, +/// and producing a special-purpose JIT-compiled function that accepts a void* +/// pointing to this struct as its only argument and calls the function in the  +/// struct with the written arguments.  This method lets Clang handle the +/// vagaries of function calling conventions. +/// +/// The simplest use of the ClangFunctionCaller is to construct it with a +/// function representative of the signature you want to use, then call +/// ExecuteFunction(ExecutionContext &, Stream &, Value &). +/// +/// If you need to reuse the arguments for several calls, you can call +/// InsertFunction() followed by WriteFunctionArguments(), which will return +/// the location of the args struct for the wrapper function in args_addr_ref. +/// +/// If you need to call the function on the thread plan stack, you can also  +/// call InsertFunction() followed by GetThreadPlanToCallFunction(). +/// +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed +/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// and its address returned in that variable. +///  +/// Any of the methods that take arg_addr_ptr can be passed NULL, and the +/// argument space will be managed for you. +//----------------------------------------------------------------------     +class ClangFunctionCaller : public FunctionCaller +{ +    friend class ASTStructExtractor; +     +    class ClangFunctionCallerHelper : public ClangExpressionHelper +    { +    public: +        ClangFunctionCallerHelper (ClangFunctionCaller &owner) : +            m_owner(owner) +        { +        } +         +        ~ClangFunctionCallerHelper() override = default; +         +        //------------------------------------------------------------------ +        /// Return the object that the parser should use when resolving external +        /// values.  May be NULL if everything should be self-contained. +        //------------------------------------------------------------------ +        ClangExpressionDeclMap * +        DeclMap() override +        { +            return NULL; +        } +         +        //------------------------------------------------------------------ +        /// Return the object that the parser should allow to access ASTs. +        /// May be NULL if the ASTs do not need to be transformed. +        /// +        /// @param[in] passthrough +        ///     The ASTConsumer that the returned transformer should send +        ///     the ASTs to after transformation. +        //------------------------------------------------------------------ +        clang::ASTConsumer * +        ASTTransformer(clang::ASTConsumer *passthrough) override; + +    private: +        ClangFunctionCaller                      &m_owner; +        std::unique_ptr<ASTStructExtractor> m_struct_extractor;         ///< The class that generates the argument struct layout. +    }; + +public: +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// @param[in] exe_scope +    ///     An execution context scope that gets us at least a target and  +    ///     process. +    /// +    /// @param[in] ast_context +    ///     The AST context to evaluate argument types in. +    /// +    /// @param[in] return_qualtype +    ///     An opaque Clang QualType for the function result.  Should be +    ///     defined in ast_context. +    /// +    /// @param[in] function_address +    ///     The address of the function to call. +    /// +    /// @param[in] arg_value_list +    ///     The default values to use when calling this function.  Can +    ///     be overridden using WriteFunctionArguments(). +    //------------------------------------------------------------------ +    ClangFunctionCaller (ExecutionContextScope &exe_scope, +                         const CompilerType &return_type, +                         const Address& function_address, +                         const ValueList &arg_value_list, +                         const char *name); +     +    ~ClangFunctionCaller() override; + +    //------------------------------------------------------------------ +    /// Compile the wrapper function +    /// +    /// @param[in] errors +    ///     The stream to print parser errors to. +    /// +    /// @return +    ///     The number of errors. +    //------------------------------------------------------------------ +    unsigned +    CompileFunction (Stream &errors) override; +     +    ExpressionTypeSystemHelper * +    GetTypeSystemHelper () override +    { +        return &m_type_system_helper; +    } + +protected: +    const char *GetWrapperStructName() +    { +        return m_wrapper_struct_name.c_str(); +    } + +private: +    //------------------------------------------------------------------ +    // For ClangFunctionCaller only +    //------------------------------------------------------------------ + +    // Note: the parser needs to be destructed before the execution unit, so +    // declare the execution unit first. +    ClangFunctionCallerHelper   m_type_system_helper; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangFunctionCaller_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp new file mode 100644 index 0000000000000..05d8a320a5a43 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -0,0 +1,731 @@ +//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <mutex> + +// Other libraries and framework includes +#include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Lookup.h" +#include "clang/Serialization/ASTReader.h" + +// Project includes +#include "ClangModulesDeclVendor.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" + +using namespace lldb_private; + +namespace { +    // Any Clang compiler requires a consumer for diagnostics.  This one stores them as strings +    // so we can provide them to the user in case a module failed to load. +    class StoringDiagnosticConsumer : public clang::DiagnosticConsumer +    { +    public: +        StoringDiagnosticConsumer (); + +        void +        HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, +                         const clang::Diagnostic &info) override; +         +        void +        ClearDiagnostics (); +         +        void +        DumpDiagnostics (Stream &error_stream); + +    private: +        typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic; +        std::vector<IDAndDiagnostic> m_diagnostics; +        Log * m_log; +    }; +     +    // The private implementation of our ClangModulesDeclVendor.  Contains all the Clang state required +    // to load modules. +    class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor +    { +    public: +        ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, +                                   llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, +                                   std::unique_ptr<clang::CompilerInstance> &&compiler_instance, +                                   std::unique_ptr<clang::Parser> &&parser); + +        ~ClangModulesDeclVendorImpl() override = default; + +        bool +        AddModule(ModulePath &path, +                  ModuleVector *exported_modules, +                  Stream &error_stream) override; + +        bool +        AddModulesForCompileUnit(CompileUnit &cu, +                                 ModuleVector &exported_modules, +                                 Stream &error_stream) override; + +        uint32_t +        FindDecls(const ConstString &name, +                  bool append, +                  uint32_t max_matches, +                  std::vector <clang::NamedDecl*> &decls) override; +         +        void +        ForEachMacro(const ModuleVector &modules, +                     std::function<bool (const std::string &)> handler) override; +         +    private: +        void +        ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports, +                                   clang::Module *module); + +        void +        ReportModuleExports (ModuleVector &exports, +                             clang::Module *module); + +        clang::ModuleLoadResult +        DoGetModule(clang::ModuleIdPath path, bool make_visible); +         +        bool                                                m_enabled = false; +         +        llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>  m_diagnostics_engine; +        llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation; +        std::unique_ptr<clang::CompilerInstance>            m_compiler_instance; +        std::unique_ptr<clang::Parser>                      m_parser; +        size_t                                              m_source_location_index = 0; // used to give name components fake SourceLocations + +        typedef std::vector<ConstString>                    ImportedModule; +        typedef std::map<ImportedModule, clang::Module *>   ImportedModuleMap; +        typedef std::set<ModuleID>                          ImportedModuleSet; +        ImportedModuleMap                                   m_imported_modules; +        ImportedModuleSet                                   m_user_imported_modules; +    }; +} // anonymous namespace + +StoringDiagnosticConsumer::StoringDiagnosticConsumer () +{ +    m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); +} + +void +StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) +{ +    llvm::SmallVector<char, 256> diagnostic_string; +     +    info.FormatDiagnostic(diagnostic_string); +     +    m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); +} + +void +StoringDiagnosticConsumer::ClearDiagnostics () +{ +    m_diagnostics.clear(); +} + +void +StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) +{ +    for (IDAndDiagnostic &diag : m_diagnostics) +    { +        switch (diag.first) +        { +            default: +                error_stream.PutCString(diag.second.c_str()); +                error_stream.PutChar('\n'); +                break; +            case clang::DiagnosticsEngine::Level::Ignored: +                break; +        } +    } +} + +static FileSpec +GetResourceDir () +{ +    static FileSpec g_cached_resource_dir; +     +    static std::once_flag g_once_flag; +     +    std::call_once(g_once_flag, [](){ +        HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); +    }); +     +    return g_cached_resource_dir; +} + +ClangModulesDeclVendor::ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendor::~ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine, +                                                       llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation, +                                                       std::unique_ptr<clang::CompilerInstance> &&compiler_instance, +                                                       std::unique_ptr<clang::Parser> &&parser) : +    ClangModulesDeclVendor(), +    m_diagnostics_engine(diagnostics_engine), +    m_compiler_invocation(compiler_invocation), +    m_compiler_instance(std::move(compiler_instance)), +    m_parser(std::move(parser)), +    m_imported_modules() +{ +} + +void +ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports, +                                                       clang::Module *module) +{ +    if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module))) +        return; +     +    exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)); +     +    llvm::SmallVector<clang::Module*, 2> sub_exports; +     +    module->getExportedModules(sub_exports); + +    for (clang::Module *module : sub_exports) +    { +        ReportModuleExportsHelper(exports, module); +    } +} + +void +ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports, +                                                 clang::Module *module) +{ +    std::set<ClangModulesDeclVendor::ModuleID> exports_set; +     +    ReportModuleExportsHelper(exports_set, module); +     +    for (ModuleID module : exports_set) +    { +        exports.push_back(module); +    } +} + +bool +ClangModulesDeclVendorImpl::AddModule(ModulePath &path, +                                      ModuleVector *exported_modules, +                                      Stream &error_stream) +{ +    // Fail early. +     +    if (m_compiler_instance->hadModuleLoaderFatalFailure()) +    { +        error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); +        return false; +    } +     +    // Check if we've already imported this module. +     +    std::vector<ConstString> imported_module; +     +    for (ConstString path_component : path) +    { +        imported_module.push_back(path_component); +    } +     +    { +        ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); +         +        if (mi != m_imported_modules.end()) +        { +            if (exported_modules) +            { +                ReportModuleExports(*exported_modules, mi->second); +            } +            return true; +        } +    } +     +    if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef())) +    { +        error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString()); +        return false; +    } +     +    llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path; +     +    { +        clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); +         +        for (ConstString path_component : path) +        { +            clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()), +                                                source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++))); +        } +    } +     +    StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient()); +     +    diagnostic_consumer->ClearDiagnostics(); +     +    clang::Module *top_level_module = DoGetModule(clang_path.front(), false); +     +    if (!top_level_module) +    { +        diagnostic_consumer->DumpDiagnostics(error_stream); +        error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString()); +        return false; +    } +     +    clang::Module *submodule = top_level_module; +     +    for (size_t ci = 1; ci < path.size(); ++ci) +    { +        llvm::StringRef component = path[ci].GetStringRef(); +        submodule = submodule->findSubmodule(component.str()); +        if (!submodule) +        { +            diagnostic_consumer->DumpDiagnostics(error_stream); +            error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); +            return false; +        } +    } +     +    clang::Module *requested_module = DoGetModule(clang_path, true); +     +    if (requested_module != nullptr) +    { +        if (exported_modules) +        { +            ReportModuleExports(*exported_modules, requested_module); +        } + +        m_imported_modules[imported_module] = requested_module; +         +        m_enabled = true; +         +        return true; +    } +     +    return false; +} + +bool +ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language) +{ +    switch (language) +    { +    default: +        return false; +    // C++ and friends to be added +    case lldb::LanguageType::eLanguageTypeC: +    case lldb::LanguageType::eLanguageTypeC11: +    case lldb::LanguageType::eLanguageTypeC89: +    case lldb::LanguageType::eLanguageTypeC99: +    case lldb::LanguageType::eLanguageTypeObjC: +        return true; +    } +} + +bool +ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu, +                                                     ClangModulesDeclVendor::ModuleVector &exported_modules, +                                                     Stream &error_stream) +{ +    if (LanguageSupportsClangModules(cu.GetLanguage())) +    { +        std::vector<ConstString> imported_modules = cu.GetImportedModules(); +         +        for (ConstString imported_module : imported_modules) +        { +            std::vector<ConstString> path; +             +            path.push_back(imported_module); +             +            if (!AddModule(path, &exported_modules, error_stream)) +            { +                return false; +            } +        } +         +        return true; +    } + +    return true; +} + +// ClangImporter::lookupValue + +uint32_t +ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, +                                       bool append, +                                       uint32_t max_matches, +                                       std::vector <clang::NamedDecl*> &decls) +{ +    if (!m_enabled) +    { +        return 0; +    } + +    if (!append) +        decls.clear(); +     +    clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); +     +    clang::LookupResult lookup_result(m_compiler_instance->getSema(), +                                      clang::DeclarationName(&ident), +                                      clang::SourceLocation(), +                                      clang::Sema::LookupOrdinaryName); +     +    m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); +     +    uint32_t num_matches = 0; +     +    for (clang::NamedDecl *named_decl : lookup_result) +    { +        if (num_matches >= max_matches) +            return num_matches; +         +        decls.push_back(named_decl); +        ++num_matches; +    } +     +    return num_matches; +} + +void +ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules, +                                         std::function<bool (const std::string &)> handler) +{ +    if (!m_enabled) +    { +        return; +    } +     +    typedef std::map<ModuleID, ssize_t> ModulePriorityMap; +    ModulePriorityMap module_priorities; +     +    ssize_t priority = 0; +     +    for (ModuleID module : modules) +    { +        module_priorities[module] = priority++; +    } +     +    if (m_compiler_instance->getPreprocessor().getExternalSource()) +    { +        m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros(); +    } +     +    for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(), +                                             me = m_compiler_instance->getPreprocessor().macro_end(); +         mi != me; +         ++mi) +    { +        const clang::IdentifierInfo *ii = nullptr; +         +        { +            if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup()) +            { +                lookup->get(mi->first->getName()); +            } +            if (!ii) +            { +                ii = mi->first; +            } +        } +         +        ssize_t found_priority = -1; +        clang::MacroInfo *macro_info = nullptr; +         +        for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) +        { +            clang::Module *module = module_macro->getOwningModule(); +             +            { +                ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module)); +                 +                if (pi != module_priorities.end() && pi->second > found_priority) +                { +                    macro_info = module_macro->getMacroInfo(); +                    found_priority = pi->second; +                } +            } +             +            clang::Module *top_level_module = module->getTopLevelModule(); +             +            if (top_level_module != module) +            { +                ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module)); +                 +                if ((pi != module_priorities.end()) && pi->second > found_priority) +                { +                    macro_info = module_macro->getMacroInfo(); +                    found_priority = pi->second; +                } +            } +        } +         +        if (macro_info) +        { +            std::string macro_expansion = "#define "; +            macro_expansion.append(mi->first->getName().str().c_str()); +             +            { +                if (macro_info->isFunctionLike()) +                { +                    macro_expansion.append("("); +                     +                    bool first_arg = true; +                     +                    for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), +                                                        ae = macro_info->arg_end(); +                         ai != ae; +                         ++ai) +                    { +                        if (!first_arg) +                        { +                            macro_expansion.append(", "); +                        } +                        else +                        { +                            first_arg = false; +                        } +                         +                        macro_expansion.append((*ai)->getName().str()); +                    } +                     +                    if (macro_info->isC99Varargs()) +                    { +                        if (first_arg) +                        { +                            macro_expansion.append("..."); +                        } +                        else +                        { +                            macro_expansion.append(", ..."); +                        } +                    } +                    else if (macro_info->isGNUVarargs()) +                    { +                        macro_expansion.append("..."); +                    } +                     +                    macro_expansion.append(")"); +                } +                 +                macro_expansion.append(" "); + +                bool first_token = true; +                 +                for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), +                     te = macro_info->tokens_end(); +                     ti != te; +                     ++ti) +                { +                    if (!first_token) +                    { +                        macro_expansion.append(" "); +                    } +                    else +                    { +                        first_token = false; +                    } +                     +                    if (ti->isLiteral()) +                    { +                        if (const char *literal_data = ti->getLiteralData()) +                        { +                            std::string token_str(literal_data, ti->getLength()); +                            macro_expansion.append(token_str); +                        } +                        else +                        { +                            bool invalid = false; +                            const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid); +                             +                            if (invalid) +                            { +                                lldbassert(!"Unhandled token kind"); +                                macro_expansion.append("<unknown literal value>"); +                            } +                            else +                            { +                                macro_expansion.append(std::string(literal_source, ti->getLength())); +                            } +                        } +                    } +                    else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind())) +                    { +                        macro_expansion.append(punctuator_spelling); +                    } +                    else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind())) +                    { +                        macro_expansion.append(keyword_spelling); +                    } +                    else +                    { +                        switch (ti->getKind()) +                        { +                            case clang::tok::TokenKind::identifier: +                                macro_expansion.append(ti->getIdentifierInfo()->getName().str()); +                                break; +                            case clang::tok::TokenKind::raw_identifier: +                                macro_expansion.append(ti->getRawIdentifier().str()); +                            default: +                                macro_expansion.append(ti->getName()); +                                break; +                        } +                    } +                } +                 +                if (handler(macro_expansion)) +                { +                    return; +                } +            } +        } +    } +} + +clang::ModuleLoadResult +ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, +                                        bool make_visible) +{ +    clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; +     +    const bool is_inclusion_directive = false; +     +    return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); +} + +static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; + +lldb_private::ClangModulesDeclVendor * +ClangModulesDeclVendor::Create(Target &target) +{ +    // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's +    // compiler are both initialized in the same way – preferably by the same code. +     +    if (!target.GetPlatform()->SupportsModules()) +        return nullptr; +     +    const ArchSpec &arch = target.GetArchitecture(); +     +    std::vector<std::string> compiler_invocation_arguments = +    { +        "-fmodules", +        "-fcxx-modules", +        "-fsyntax-only", +        "-femit-all-decls", +        "-target", arch.GetTriple().str(), +        "-fmodules-validate-system-headers", +        "-Werror=non-modular-include-in-framework-module" +    }; +     +    target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); + +    compiler_invocation_arguments.push_back(ModuleImportBufferName); + +    // Add additional search paths with { "-I", path } or { "-F", path } here. +    +    { +        llvm::SmallString<128> DefaultModuleCache; +        const bool erased_on_reboot = false; +        llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); +        llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); +        llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); +        std::string module_cache_argument("-fmodules-cache-path="); +        module_cache_argument.append(DefaultModuleCache.str().str()); +        compiler_invocation_arguments.push_back(module_cache_argument); +    } +     +    FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); +     +    for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) +    { +        const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); +         +        std::string search_path_argument = "-I"; +        search_path_argument.append(search_path.GetPath()); +         +        compiler_invocation_arguments.push_back(search_path_argument); +    } +     +    { +        FileSpec clang_resource_dir = GetResourceDir(); +         +        if (clang_resource_dir.IsDirectory()) +        { +            compiler_invocation_arguments.push_back("-resource-dir"); +            compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); +        } +    } +     +    llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, +                                                                                                                       new StoringDiagnosticConsumer); +     +    std::vector<const char *> compiler_invocation_argument_cstrs; +     +    for (const std::string &arg : compiler_invocation_arguments) { +        compiler_invocation_argument_cstrs.push_back(arg.c_str()); +    } +     +    llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); +     +    if (!invocation) +        return nullptr; +     +    std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", +                                                                                         ModuleImportBufferName); +     +    invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); +     +    std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance); +     +    instance->setDiagnostics(diagnostics_engine.get()); +    instance->setInvocation(invocation.get()); +     +    std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction); +     +    instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); +     +    if (!instance->hasTarget()) +        return nullptr; +     +    instance->getTarget().adjust(instance->getLangOpts()); +     +    if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) +        return nullptr; +     +    instance->getPreprocessor().enableIncrementalProcessing(); +     +    instance->createModuleManager(); +     +    instance->createSema(action->getTranslationUnitKind(), nullptr); +     +    const bool skipFunctionBodies = false; +    std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); +     +    instance->getPreprocessor().EnterMainSourceFile(); +    parser->Initialize(); +     +    clang::Parser::DeclGroupPtrTy parsed; +     +    while (!parser->ParseTopLevelDecl(parsed)); +     +    return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h new file mode 100644 index 0000000000000..df3b20550f9a0 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -0,0 +1,128 @@ +//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangModulesDeclVendor_h +#define liblldb_ClangModulesDeclVendor_h + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" +#include "lldb/Target/Platform.h" + +#include <set> +#include <vector> + +namespace lldb_private +{ +     +class ClangModulesDeclVendor : public DeclVendor +{ +public: +    //------------------------------------------------------------------ +    // Constructors and Destructors +    //------------------------------------------------------------------ +    ClangModulesDeclVendor(); +     +    ~ClangModulesDeclVendor() override; +     +    static ClangModulesDeclVendor * +    Create(Target &target); +     +    typedef std::vector<ConstString> ModulePath; +    typedef uintptr_t                ModuleID; +    typedef std::vector<ModuleID>    ModuleVector; +     +    //------------------------------------------------------------------ +    /// Add a module to the list of modules to search. +    /// +    /// @param[in] path +    ///     The path to the exact module to be loaded.  E.g., if the desired +    ///     module is std.io, then this should be { "std", "io" }. +    /// +    /// @param[in] exported_modules +    ///     If non-NULL, a pointer to a vector to populate with the ID of every +    ///     module that is re-exported by the specified module. +    /// +    /// @param[in] error_stream +    ///     A stream to populate with the output of the Clang parser when +    ///     it tries to load the module. +    /// +    /// @return +    ///     True if the module could be loaded; false if not.  If the +    ///     compiler encountered a fatal error during a previous module +    ///     load, then this will always return false for this ModuleImporter. +    //------------------------------------------------------------------ +    virtual bool +    AddModule(ModulePath &path, +              ModuleVector *exported_modules, +              Stream &error_stream) = 0; +     +    //------------------------------------------------------------------ +    /// Add all modules referred to in a given compilation unit to the list +    /// of modules to search. +    /// +    /// @param[in] cu +    ///     The compilation unit to scan for imported modules. +    /// +    /// @param[in] exported_modules +    ///     A vector to populate with the ID of each module loaded (directly +    ///     and via re-exports) in this way. +    /// +    /// @param[in] error_stream +    ///     A stream to populate with the output of the Clang parser when +    ///     it tries to load the modules. +    /// +    /// @return +    ///     True if all modules referred to by the compilation unit could be +    ///     loaded; false if one could not be loaded.  If the compiler +    ///     encountered a fatal error during a previous module +    ///     load, then this will always return false for this ModuleImporter. +    //------------------------------------------------------------------ +    virtual bool +    AddModulesForCompileUnit(CompileUnit &cu, +                             ModuleVector &exported_modules, +                             Stream &error_stream) = 0; + +    //------------------------------------------------------------------ +    /// Enumerate all the macros that are defined by a given set of modules +    /// that are already imported. +    /// +    /// @param[in] modules +    ///     The unique IDs for all modules to query.  Later modules have higher +    ///     priority, just as if you @imported them in that order.  This matters +    ///     if module A #defines a macro and module B #undefs it. +    /// +    /// @param[in] handler +    ///     A function to call with the text of each #define (including the +    ///     #define directive).  #undef directives are not included; we simply +    ///     elide any corresponding #define.  If this function returns true, +    ///     we stop the iteration immediately. +    //------------------------------------------------------------------ +    virtual void +    ForEachMacro(const ModuleVector &modules, +                 std::function<bool (const std::string &)> handler) = 0; +     +    //------------------------------------------------------------------ +    /// Query whether Clang supports modules for a particular language. +    /// LLDB uses this to decide whether to try to find the modules loaded +    /// by a gaiven compile unit. +    /// +    /// @param[in] language +    ///     The language to query for. +    /// +    /// @return +    ///     True if Clang has modules for the given language. +    //------------------------------------------------------------------ +    static bool +    LanguageSupportsClangModules (lldb::LanguageType language); +}; +     +} // namespace lldb_private + +#endif // liblldb_ClangModulesDeclVendor_h diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp new file mode 100644 index 0000000000000..9bf9d435d7ead --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -0,0 +1,84 @@ +//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangPersistentVariables.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Value.h" + +#include "llvm/ADT/StringMap.h" + +using namespace lldb; +using namespace lldb_private; + +ClangPersistentVariables::ClangPersistentVariables () : +    lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), +    m_next_persistent_variable_id (0) +{ +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) +{ +    return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp)); +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope,  +                                                    const ConstString &name,  +                                                    const CompilerType& compiler_type, +                                                    lldb::ByteOrder byte_order,  +                                                    uint32_t addr_byte_size) +{ +    return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size)); +} + +void +ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable) +{ +    RemoveVariable(variable); +     +    const char *name = variable->GetName().AsCString(); +     +    if (*name != '$') +        return; +    name++; +     +    if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) +        m_next_persistent_variable_id--; +} + +ConstString +ClangPersistentVariables::GetNextPersistentVariableName () +{ +    char name_cstr[256]; +    ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++); +    ConstString name(name_cstr); +    return name; +} + +void +ClangPersistentVariables::RegisterPersistentType (const ConstString &name, +                                                  clang::TypeDecl *type_decl) +{ +    m_persistent_types.insert(std::pair<const char*, clang::TypeDecl*>(name.GetCString(), type_decl)); +} + +clang::TypeDecl * +ClangPersistentVariables::GetPersistentType (const ConstString &name) +{ +    PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString()); +     +    if (i == m_persistent_types.end()) +        return NULL; +    else +        return i->second; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h new file mode 100644 index 0000000000000..0e03d013d0490 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -0,0 +1,106 @@ +//===-- ClangPersistentVariables.h ------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangPersistentVariables_h_ +#define liblldb_ClangPersistentVariables_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" + +// Project includes +#include "ClangExpressionVariable.h" +#include "ClangModulesDeclVendor.h" + +#include "lldb/Expression/ExpressionVariable.h" + +namespace lldb_private +{ +     +//---------------------------------------------------------------------- +/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between expression invocations. +/// +/// A list of variables that can be accessed and updated by any expression.  See +/// ClangPersistentVariable for more discussion.  Also provides an increasing, +/// 0-based counter for naming result variables. +//---------------------------------------------------------------------- +class ClangPersistentVariables : public PersistentExpressionState +{ +public: +    ClangPersistentVariables(); + +    ~ClangPersistentVariables() override = default; + +    //------------------------------------------------------------------ +    // llvm casting support +    //------------------------------------------------------------------ +    static bool classof(const PersistentExpressionState *pv) +    { +        return pv->getKind() == PersistentExpressionState::eKindClang; +    } + +    lldb::ExpressionVariableSP +    CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override; + +    lldb::ExpressionVariableSP +    CreatePersistentVariable (ExecutionContextScope *exe_scope, +                              const ConstString &name,  +                              const CompilerType& compiler_type,  +                              lldb::ByteOrder byte_order,  +                              uint32_t addr_byte_size) override; + +    //---------------------------------------------------------------------- +    /// Return the next entry in the sequence of strings "$0", "$1", ... for +    /// use naming persistent expression convenience variables. +    /// +    /// @return +    ///     A string that contains the next persistent variable name. +    //---------------------------------------------------------------------- +    ConstString +    GetNextPersistentVariableName () override; +     +    void +    RemovePersistentVariable (lldb::ExpressionVariableSP variable) override; +     +    lldb::addr_t +    LookupSymbol (const ConstString &name) override { return LLDB_INVALID_ADDRESS; } + +    void +    RegisterPersistentType (const ConstString &name, +                            clang::TypeDecl *tag_decl); +     +    clang::TypeDecl * +    GetPersistentType (const ConstString &name); +     +    void +    AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) +    { +        m_hand_loaded_clang_modules.push_back(module); +    } +     +    const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() +    { +        return m_hand_loaded_clang_modules; +    } +     +private: +    uint32_t                                                m_next_persistent_variable_id;  ///< The counter used by GetNextResultName(). +     +    typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap; +    PersistentTypeMap                                       m_persistent_types;             ///< The persistent types declared by the user. +     +    ClangModulesDeclVendor::ModuleVector                    m_hand_loaded_clang_modules;    ///< These are Clang modules we hand-loaded; these are the highest- +                                                                                            ///< priority source for macros. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangPersistentVariables_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp new file mode 100644 index 0000000000000..11f7f84ff5f17 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -0,0 +1,673 @@ +//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#if HAVE_SYS_TYPES_H +#  include <sys/types.h> +#endif + +#include <cstdlib> +#include <string> +#include <map> + +#include "ClangUserExpression.h" + +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +using namespace lldb_private; + +ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope, +                                          const char *expr, +                                          const char *expr_prefix, +                                          lldb::LanguageType language, +                                          ResultType desired_type, +                                          const EvaluateExpressionOptions &options) : +    LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options), +    m_type_system_helper(*m_target_wp.lock().get()) +{ +    switch (m_language) +    { +    case lldb::eLanguageTypeC_plus_plus: +        m_allow_cxx = true; +        break; +    case lldb::eLanguageTypeObjC: +        m_allow_objc = true; +        break; +    case lldb::eLanguageTypeObjC_plus_plus: +    default: +        m_allow_cxx = true; +        m_allow_objc = true; +        break; +    } +} + +ClangUserExpression::~ClangUserExpression () +{ +} + +void +ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +        log->Printf("ClangUserExpression::ScanContext()"); + +    m_target = exe_ctx.GetTargetPtr(); + +    if (!(m_allow_cxx || m_allow_objc)) +    { +        if (log) +            log->Printf("  [CUE::SC] Settings inhibit C++ and Objective-C"); +        return; +    } + +    StackFrame *frame = exe_ctx.GetFramePtr(); +    if (frame == NULL) +    { +        if (log) +            log->Printf("  [CUE::SC] Null stack frame"); +        return; +    } + +    SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + +    if (!sym_ctx.function) +    { +        if (log) +            log->Printf("  [CUE::SC] Null function"); +        return; +    } + +    // Find the block that defines the function represented by "sym_ctx" +    Block *function_block = sym_ctx.GetFunctionBlock(); + +    if (!function_block) +    { +        if (log) +            log->Printf("  [CUE::SC] Null function block"); +        return; +    } + +    CompilerDeclContext decl_context = function_block->GetDeclContext(); + +    if (!decl_context) +    { +        if (log) +            log->Printf("  [CUE::SC] Null decl context"); +        return; +    } + +    if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) +    { +        if (m_allow_cxx && method_decl->isInstance()) +        { +            if (m_enforce_valid_object) +            { +                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + +                const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; + +                if (!variable_list_sp) +                { +                    err.SetErrorString(thisErrorString); +                    return; +                } + +                lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + +                if (!this_var_sp || +                    !this_var_sp->IsInScope(frame) || +                    !this_var_sp->LocationIsValidForFrame (frame)) +                { +                    err.SetErrorString(thisErrorString); +                    return; +                } +            } + +            m_in_cplusplus_method = true; +            m_needs_object_ptr = true; +        } +    } +    else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context)) +    { +        if (m_allow_objc) +        { +            if (m_enforce_valid_object) +            { +                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + +                const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; + +                if (!variable_list_sp) +                { +                    err.SetErrorString(selfErrorString); +                    return; +                } + +                lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + +                if (!self_variable_sp || +                    !self_variable_sp->IsInScope(frame) || +                    !self_variable_sp->LocationIsValidForFrame (frame)) +                { +                    err.SetErrorString(selfErrorString); +                    return; +                } +            } + +            m_in_objectivec_method = true; +            m_needs_object_ptr = true; + +            if (!method_decl->isInstanceMethod()) +                m_in_static_method = true; +        } +    } +    else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) +    { +        // We might also have a function that said in the debug information that it captured an +        // object pointer.  The best way to deal with getting to the ivars at present is by pretending +        // that this is a method of a class in whatever runtime the debug info says the object pointer +        // belongs to.  Do that here. + +        ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl); +        if (metadata && metadata->HasObjectPtr()) +        { +            lldb::LanguageType language = metadata->GetObjectPtrLanguage(); +            if (language == lldb::eLanguageTypeC_plus_plus) +            { +                if (m_enforce_valid_object) +                { +                    lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + +                    const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; + +                    if (!variable_list_sp) +                    { +                        err.SetErrorString(thisErrorString); +                        return; +                    } + +                    lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + +                    if (!this_var_sp || +                        !this_var_sp->IsInScope(frame) || +                        !this_var_sp->LocationIsValidForFrame (frame)) +                    { +                        err.SetErrorString(thisErrorString); +                        return; +                    } +                } + +                m_in_cplusplus_method = true; +                m_needs_object_ptr = true; +            } +            else if (language == lldb::eLanguageTypeObjC) +            { +                if (m_enforce_valid_object) +                { +                    lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + +                    const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; + +                    if (!variable_list_sp) +                    { +                        err.SetErrorString(selfErrorString); +                        return; +                    } + +                    lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + +                    if (!self_variable_sp || +                        !self_variable_sp->IsInScope(frame) || +                        !self_variable_sp->LocationIsValidForFrame (frame)) +                    { +                        err.SetErrorString(selfErrorString); +                        return; +                    } + +                    Type *self_type = self_variable_sp->GetType(); + +                    if (!self_type) +                    { +                        err.SetErrorString(selfErrorString); +                        return; +                    } + +                    CompilerType self_clang_type = self_type->GetForwardCompilerType (); + +                    if (!self_clang_type) +                    { +                        err.SetErrorString(selfErrorString); +                        return; +                    } + +                    if (ClangASTContext::IsObjCClassType(self_clang_type)) +                    { +                        return; +                    } +                    else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) +                    { +                        m_in_objectivec_method = true; +                        m_needs_object_ptr = true; +                    } +                    else +                    { +                        err.SetErrorString(selfErrorString); +                        return; +                    } +                } +                else +                { +                    m_in_objectivec_method = true; +                    m_needs_object_ptr = true; +                } +            } +        } +    } +} + +// This is a really nasty hack, meant to fix Objective-C expressions of the form +// (int)[myArray count].  Right now, because the type information for count is +// not available, [myArray count] returns id, which can't be directly cast to +// int without causing a clang error. +static void +ApplyObjcCastHack(std::string &expr) +{ +#define OBJC_CAST_HACK_FROM "(int)[" +#define OBJC_CAST_HACK_TO   "(int)(long long)[" + +    size_t from_offset; + +    while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) +        expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); + +#undef OBJC_CAST_HACK_TO +#undef OBJC_CAST_HACK_FROM +} + +bool +ClangUserExpression::Parse (Stream &error_stream, +                            ExecutionContext &exe_ctx, +                            lldb_private::ExecutionPolicy execution_policy, +                            bool keep_result_in_memory, +                            bool generate_debug_info) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    Error err; + +    InstallContext(exe_ctx); +     +    if (Target *target = exe_ctx.GetTargetPtr()) +    { +        if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) +        { +            m_result_delegate.RegisterPersistentState(persistent_state); +        } +        else +        { +            error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); +            return false; +        } +    } +    else +    { +        error_stream.PutCString ("error: couldn't start parsing (no target)"); +        return false; +    } + +    ScanContext(exe_ctx, err); + +    if (!err.Success()) +    { +        error_stream.Printf("warning: %s\n", err.AsCString()); +    } + +    StreamString m_transformed_stream; + +    //////////////////////////////////// +    // Generate the expression +    // + +    ApplyObjcCastHack(m_expr_text); +    //ApplyUnicharHack(m_expr_text); + +    std::string prefix = m_expr_prefix; +     +    if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) +    { +        const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules(); +        ClangModulesDeclVendor::ModuleVector modules_for_macros; +         +        for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) +        { +            modules_for_macros.push_back(module); +        } + +        if (m_target->GetEnableAutoImportClangModules()) +        { +            if (StackFrame *frame = exe_ctx.GetFramePtr()) +            { +                if (Block *block = frame->GetFrameBlock()) +                { +                    SymbolContext sc; +                     +                    block->CalculateSymbolContext(&sc); +                     +                    if (sc.comp_unit) +                    { +                        StreamString error_stream; +                         +                        decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); +                    } +                } +            } +        } +    } +     +    std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); +     +    lldb::LanguageType lang_type; + +    if (m_in_cplusplus_method) +        lang_type = lldb::eLanguageTypeC_plus_plus; +    else if (m_in_objectivec_method) +        lang_type = lldb::eLanguageTypeObjC; +    else +        lang_type = lldb::eLanguageTypeC; + +    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) +    { +        error_stream.PutCString ("error: couldn't construct expression body"); +        return false; +    } + +    if (log) +        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + +    //////////////////////////////////// +    // Set up the target and compiler +    // + +    Target *target = exe_ctx.GetTargetPtr(); + +    if (!target) +    { +        error_stream.PutCString ("error: invalid target\n"); +        return false; +    } + +    ////////////////////////// +    // Parse the expression +    // + +    m_materializer_ap.reset(new Materializer()); + +    ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); + +    class OnExit +    { +    public: +        typedef std::function <void (void)> Callback; + +        OnExit (Callback const &callback) : +            m_callback(callback) +        { +        } + +        ~OnExit () +        { +            m_callback(); +        } +    private: +        Callback m_callback; +    }; + +    OnExit on_exit([this]() { ResetDeclMap(); }); + +    if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) +    { +        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + +        ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + +        return false; +    } + +    Process *process = exe_ctx.GetProcessPtr(); +    ExecutionContextScope *exe_scope = process; + +    if (!exe_scope) +        exe_scope = exe_ctx.GetTargetPtr(); + +    ClangExpressionParser parser(exe_scope, *this, generate_debug_info); + +    unsigned num_errors = parser.Parse (error_stream); + +    if (num_errors) +    { +        error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + +        ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + +        return false; +    } + +    ////////////////////////////////////////////////////////////////////////////////////////// +    // Prepare the output of the parser for execution, evaluating it statically if possible +    // + +    Error jit_error = parser.PrepareForExecution (m_jit_start_addr, +                                                  m_jit_end_addr, +                                                  m_execution_unit_sp, +                                                  exe_ctx, +                                                  m_can_interpret, +                                                  execution_policy); + +    if (generate_debug_info) +    { +        lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + +        if (jit_module_sp) +        { +            ConstString const_func_name(FunctionName()); +            FileSpec jit_file; +            jit_file.GetFilename() = const_func_name; +            jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); +            m_jit_module_wp = jit_module_sp; +            target->GetImages().Append(jit_module_sp); +        } +//        lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); +//        StreamFile strm (stdout, false); +//        if (jit_obj_file) +//        { +//            jit_obj_file->GetSectionList(); +//            jit_obj_file->GetSymtab(); +//            jit_obj_file->Dump(&strm); +//        } +//        lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); +//        if (jit_sym_vendor) +//        { +//            lldb_private::SymbolContextList sc_list; +//            jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); +//            sc_list.Dump(&strm, target); +//            jit_sym_vendor->Dump(&strm); +//        } +    } + +    ResetDeclMap(); // Make this go away since we don't need any of its state after parsing.  This also gets rid of any ClangASTImporter::Minions. + +    if (jit_error.Success()) +    { +        if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) +            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); +        return true; +    } +    else +    { +        const char *error_cstr = jit_error.AsCString(); +        if (error_cstr && error_cstr[0]) +            error_stream.Printf ("error: %s\n", error_cstr); +        else +            error_stream.Printf ("error: expression can't be interpreted or run\n"); +        return false; +    } +} + +bool +ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, +                                   std::vector<lldb::addr_t> &args, +                                   lldb::addr_t struct_address, +                                   Stream &error_stream) +{ +    lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; +    lldb::addr_t cmd_ptr    = LLDB_INVALID_ADDRESS; +     +    if (m_needs_object_ptr) +    { +        lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); +        if (!frame_sp) +            return true; +         +        ConstString object_name; + +        if (m_in_cplusplus_method) +        { +            object_name.SetCString("this"); +        } +        else if (m_in_objectivec_method) +        { +            object_name.SetCString("self"); +        } +        else +        { +            error_stream.Printf("Need object pointer but don't know the language\n"); +            return false; +        } + +        Error object_ptr_error; + +        object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + +        if (!object_ptr_error.Success()) +        { +            error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); +            object_ptr = 0; +        } + +        if (m_in_objectivec_method) +        { +            ConstString cmd_name("_cmd"); + +            cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); + +            if (!object_ptr_error.Success()) +            { +                error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); +                cmd_ptr = 0; +            } +        } +        if (object_ptr) +            args.push_back(object_ptr); + +        if (m_in_objectivec_method) +            args.push_back(cmd_ptr); + +        args.push_back(struct_address); +    } +    else +    { +        args.push_back(struct_address); +    } +    return true; +} + +lldb::ExpressionVariableSP +ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope) +{ +    return m_result_delegate.GetVariable(); +} + +void +ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory) +{ +    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx)); +} + +clang::ASTConsumer * +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ +    m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, +                                                           m_target)); + +    return m_result_synthesizer_up.get(); +} + +ClangUserExpression::ResultDelegate::ResultDelegate() +{ +} + +ConstString +ClangUserExpression::ResultDelegate::GetName() +{ +    return m_persistent_state->GetNextPersistentVariableName(); +} + +void +ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable) +{ +    m_variable = variable; +} + +void +ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state) +{ +    m_persistent_state = persistent_state; +} + +lldb::ExpressionVariableSP & +ClangUserExpression::ResultDelegate::GetVariable() +{ +    return m_variable; +} + diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h new file mode 100644 index 0000000000000..f2bfe31dce09d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -0,0 +1,218 @@ +//===-- ClangUserExpression.h -----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangUserExpression_h_ +#define liblldb_ClangUserExpression_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "ASTStructExtractor.h" +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionVariable.h" +#include "IRForTarget.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/LLVMUserExpression.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command.  ClangUserExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression.  It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangUserExpression : public LLVMUserExpression +{ +public: +    enum { kDefaultTimeout = 500000u }; + +    class ClangUserExpressionHelper : public ClangExpressionHelper +    { +    public: +        ClangUserExpressionHelper (Target &target) : +            m_target(target) +        { +        } +         +        ~ClangUserExpressionHelper() override = default; +         +        //------------------------------------------------------------------ +        /// Return the object that the parser should use when resolving external +        /// values.  May be NULL if everything should be self-contained. +        //------------------------------------------------------------------ +        ClangExpressionDeclMap * +        DeclMap() override +        { +            return m_expr_decl_map_up.get(); +        } +         +        void +        ResetDeclMap() +        { +            m_expr_decl_map_up.reset(); +        } +         +        void +        ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory); +         +        //------------------------------------------------------------------ +        /// Return the object that the parser should allow to access ASTs. +        /// May be NULL if the ASTs do not need to be transformed. +        /// +        /// @param[in] passthrough +        ///     The ASTConsumer that the returned transformer should send +        ///     the ASTs to after transformation. +        //------------------------------------------------------------------ +        clang::ASTConsumer * +        ASTTransformer(clang::ASTConsumer *passthrough) override; + +    private: +        Target                                  &m_target; +        std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; +        std::unique_ptr<ASTStructExtractor> m_struct_extractor_up;         ///< The class that generates the argument struct layout. +        std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; +    }; + +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// @param[in] expr +    ///     The expression to parse. +    /// +    /// @param[in] expr_prefix +    ///     If non-NULL, a C string containing translation-unit level +    ///     definitions to be included when the expression is parsed. +    /// +    /// @param[in] language +    ///     If not eLanguageTypeUnknown, a language to use when parsing +    ///     the expression.  Currently restricted to those languages +    ///     supported by Clang. +    /// +    /// @param[in] desired_type +    ///     If not eResultTypeAny, the type to use for the expression +    ///     result. +    //------------------------------------------------------------------ +    ClangUserExpression (ExecutionContextScope &exe_scope, +                         const char *expr, +                         const char *expr_prefix, +                         lldb::LanguageType language, +                         ResultType desired_type, +                         const EvaluateExpressionOptions &options); + +    ~ClangUserExpression() override; + +    //------------------------------------------------------------------ +    /// Parse the expression +    /// +    /// @param[in] error_stream +    ///     A stream to print parse errors and warnings to. +    /// +    /// @param[in] exe_ctx +    ///     The execution context to use when looking up entities that +    ///     are needed for parsing (locations of functions, types of +    ///     variables, persistent variables, etc.) +    /// +    /// @param[in] execution_policy +    ///     Determines whether interpretation is possible or mandatory. +    /// +    /// @param[in] keep_result_in_memory +    ///     True if the resulting persistent variable should reside in +    ///     target memory, if applicable. +    /// +    /// @return +    ///     True on success (no errors); false otherwise. +    //------------------------------------------------------------------ +    bool +    Parse (Stream &error_stream, +           ExecutionContext &exe_ctx, +           lldb_private::ExecutionPolicy execution_policy, +           bool keep_result_in_memory, +           bool generate_debug_info) override; + +    ExpressionTypeSystemHelper * +    GetTypeSystemHelper () override +    { +        return &m_type_system_helper; +    } +     +    ClangExpressionDeclMap * +    DeclMap () +    { +        return m_type_system_helper.DeclMap(); +    } +     +    void +    ResetDeclMap () +    { +        m_type_system_helper.ResetDeclMap(); +    } +     +    void +    ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) +    { +        m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory); +    } + +    lldb::ExpressionVariableSP +    GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; +     +private: +    //------------------------------------------------------------------ +    /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. +    //------------------------------------------------------------------ + +    void +    ScanContext (ExecutionContext &exe_ctx, +                 lldb_private::Error &err) override; + +    bool +    AddArguments (ExecutionContext &exe_ctx, +                  std::vector<lldb::addr_t> &args, +                  lldb::addr_t struct_address, +                  Stream &error_stream) override; +     +    ClangUserExpressionHelper   m_type_system_helper; +     +    class ResultDelegate : public Materializer::PersistentVariableDelegate +    { +    public: +        ResultDelegate(); +        ConstString GetName() override; +        void DidDematerialize(lldb::ExpressionVariableSP &variable) override; +         +        void RegisterPersistentState(PersistentExpressionState *persistent_state); +        lldb::ExpressionVariableSP &GetVariable(); + +    private: +        PersistentExpressionState *m_persistent_state; +        lldb::ExpressionVariableSP m_variable; +    }; +     +    ResultDelegate                                          m_result_delegate; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUserExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp new file mode 100644 index 0000000000000..fe044c17ac788 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -0,0 +1,189 @@ +//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangUtilityFunction.h" + +// C Includes +#include <stdio.h> +#if HAVE_SYS_TYPES_H +#  include <sys/types.h> +#endif + +// C++ Includes + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +//------------------------------------------------------------------ +/// Constructor +/// +/// @param[in] text +///     The text of the function.  Must be a full translation unit. +/// +/// @param[in] name +///     The name of the function, as used in the text. +//------------------------------------------------------------------ +ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope, +                                            const char *text, +                                            const char *name) : +    UtilityFunction (exe_scope, text, name) +{ +} + +ClangUtilityFunction::~ClangUtilityFunction () +{ +} + +//------------------------------------------------------------------ +/// Install the utility function into a process +/// +/// @param[in] error_stream +///     A stream to print parse errors and warnings to. +/// +/// @param[in] exe_ctx +///     The execution context to install the utility function to. +/// +/// @return +///     True on success (no errors); false otherwise. +//------------------------------------------------------------------ +bool +ClangUtilityFunction::Install (Stream &error_stream, +                               ExecutionContext &exe_ctx) +{ +    if (m_jit_start_addr != LLDB_INVALID_ADDRESS) +    { +        error_stream.PutCString("error: already installed\n"); +        return false; +    } +     +    //////////////////////////////////// +    // Set up the target and compiler +    // +     +    Target *target = exe_ctx.GetTargetPtr(); +     +    if (!target) +    { +        error_stream.PutCString ("error: invalid target\n"); +        return false; +    } +     +    Process *process = exe_ctx.GetProcessPtr(); +     +    if (!process) +    { +        error_stream.PutCString ("error: invalid process\n"); +        return false; +    } +         +    ////////////////////////// +    // Parse the expression +    // +     +    bool keep_result_in_memory = false; +     +    ResetDeclMap(exe_ctx, keep_result_in_memory); +     +    if (!DeclMap()->WillParse(exe_ctx, NULL)) +    { +        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); +        return false; +    } +     +    const bool generate_debug_info = true; +    ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); +     +    unsigned num_errors = parser.Parse (error_stream); +     +    if (num_errors) +    { +        error_stream.Printf ("error: %d errors parsing expression\n", num_errors); +         +        ResetDeclMap(); +         +        return false; +    } +     +    ////////////////////////////////// +    // JIT the output of the parser +    // +         +    bool can_interpret = false; // should stay that way +     +    Error jit_error = parser.PrepareForExecution (m_jit_start_addr,  +                                                  m_jit_end_addr, +                                                  m_execution_unit_sp, +                                                  exe_ctx, +                                                  can_interpret, +                                                  eExecutionPolicyAlways); +     +    if (m_jit_start_addr != LLDB_INVALID_ADDRESS) +    { +        m_jit_process_wp = process->shared_from_this(); +        if (parser.GetGenerateDebugInfo()) +        { +            lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); +             +            if (jit_module_sp) +            { +                ConstString const_func_name(FunctionName()); +                FileSpec jit_file; +                jit_file.GetFilename() = const_func_name; +                jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); +                m_jit_module_wp = jit_module_sp; +                target->GetImages().Append(jit_module_sp); +            } +        } +    } +     +#if 0 +	// jingham: look here +    StreamFile logfile ("/tmp/exprs.txt", "a"); +    logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", +                    m_jit_start_addr,  +                    m_function_name.c_str(),  +                    m_function_text.c_str()); +#endif + +    DeclMap()->DidParse(); +     +    ResetDeclMap(); +     +    if (jit_error.Success()) +    { +        return true; +    } +    else +    { +        const char *error_cstr = jit_error.AsCString(); +        if (error_cstr && error_cstr[0]) +            error_stream.Printf ("error: %s\n", error_cstr); +        else +            error_stream.Printf ("error: expression can't be interpreted or run\n"); +        return false; +    } +} + +void +ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) +{ +    m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h new file mode 100644 index 0000000000000..74839717946bc --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -0,0 +1,137 @@ +//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangUtilityFunction_h_ +#define liblldb_ClangUtilityFunction_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/UtilityFunction.h" + +namespace lldb_private  +{ + +//---------------------------------------------------------------------- +/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command.  ClangUtilityFunction encapsulates +/// a self-contained function meant to be used from other code.  Utility +/// functions can perform error-checking for ClangUserExpressions, or can +/// simply provide a way to push a function into the target for the debugger to +/// call later on. +//---------------------------------------------------------------------- +class ClangUtilityFunction : public UtilityFunction +{ +public: +    class ClangUtilityFunctionHelper : public ClangExpressionHelper +    { +    public: +        ClangUtilityFunctionHelper () +        { +        } +         +        ~ClangUtilityFunctionHelper() override {} +         +        //------------------------------------------------------------------ +        /// Return the object that the parser should use when resolving external +        /// values.  May be NULL if everything should be self-contained. +        //------------------------------------------------------------------ +        ClangExpressionDeclMap * +        DeclMap() override +        { +            return m_expr_decl_map_up.get(); +        } +         +        void +        ResetDeclMap() +        { +            m_expr_decl_map_up.reset(); +        } +         +        void +        ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); + +        //------------------------------------------------------------------ +        /// Return the object that the parser should allow to access ASTs. +        /// May be NULL if the ASTs do not need to be transformed. +        /// +        /// @param[in] passthrough +        ///     The ASTConsumer that the returned transformer should send +        ///     the ASTs to after transformation. +        //------------------------------------------------------------------ +        clang::ASTConsumer * +        ASTTransformer(clang::ASTConsumer *passthrough) override +        { +            return nullptr; +        } +    private: +        std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; +    }; +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// @param[in] text +    ///     The text of the function.  Must be a full translation unit. +    /// +    /// @param[in] name +    ///     The name of the function, as used in the text. +    //------------------------------------------------------------------ +    ClangUtilityFunction (ExecutionContextScope &exe_scope, +                          const char *text, +                          const char *name); +     +    ~ClangUtilityFunction() override; +     +    ExpressionTypeSystemHelper * +    GetTypeSystemHelper () override +    { +        return &m_type_system_helper; +    } + +    ClangExpressionDeclMap * +    DeclMap() +    { +        return m_type_system_helper.DeclMap(); +    } + +    void +    ResetDeclMap () +    { +        m_type_system_helper.ResetDeclMap(); +    } +     +    void +    ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) +    { +        m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); +    } +     +    bool +    Install (Stream &error_stream, ExecutionContext &exe_ctx) override; +     +private: +    ClangUtilityFunctionHelper  m_type_system_helper;    ///< The map to use when parsing and materializing the expression. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUtilityFunction_h_ diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp new file mode 100644 index 0000000000000..37b7bd1d2c84e --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -0,0 +1,2820 @@ +//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IRForTarget.h" + +#include "ClangExpressionDeclMap.h" + +#include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueSymbolTable.h" + +#include "clang/AST/ASTContext.h" + +#include "lldb/Core/dwarf.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/CPPLanguageRuntime.h" + +#include <map> + +using namespace llvm; + +static char ID; + +IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) : +    m_execution_unit(execution_unit), +    m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()), +    m_allocation(LLDB_INVALID_ADDRESS) +{ +} + +IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : +    m_maker(maker), +    m_values() +{ +} + +IRForTarget::FunctionValueCache::~FunctionValueCache() +{ +} + +llvm::Value * +IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) +{ +    if (!m_values.count(function)) +    { +        llvm::Value *ret = m_maker(function); +        m_values[function] = ret; +        return ret; +    } +    return m_values[function]; +} + +lldb::addr_t +IRForTarget::StaticDataAllocator::Allocate() +{ +    lldb_private::Error err; + +    if (m_allocation != LLDB_INVALID_ADDRESS) +    { +        m_execution_unit.FreeNow(m_allocation); +        m_allocation = LLDB_INVALID_ADDRESS; +    } + +    m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err); + +    return m_allocation; +} + +lldb::TargetSP +IRForTarget::StaticDataAllocator::GetTarget() +{ +    return m_execution_unit.GetTarget(); +} + +static llvm::Value * +FindEntryInstruction (llvm::Function *function) +{ +    if (function->empty()) +        return NULL; + +    return function->getEntryBlock().getFirstNonPHIOrDbg(); +} + +IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, +                          bool resolve_vars, +                          lldb_private::IRExecutionUnit &execution_unit, +                          lldb_private::Stream *error_stream, +                          const char *func_name) : +    ModulePass(ID), +    m_resolve_vars(resolve_vars), +    m_func_name(func_name), +    m_module(NULL), +    m_decl_map(decl_map), +    m_data_allocator(execution_unit), +    m_CFStringCreateWithBytes(NULL), +    m_sel_registerName(NULL), +    m_intptr_ty(NULL), +    m_error_stream(error_stream), +    m_result_store(NULL), +    m_result_is_pointer(false), +    m_reloc_placeholder(NULL), +    m_entry_instruction_finder (FindEntryInstruction) +{ +} + +/* Handy utility functions used at several places in the code */ + +static std::string +PrintValue(const Value *value, bool truncate = false) +{ +    std::string s; +    if (value) +    { +        raw_string_ostream rso(s); +        value->print(rso); +        rso.flush(); +        if (truncate) +            s.resize(s.length() - 1); +    } +    return s; +} + +static std::string +PrintType(const llvm::Type *type, bool truncate = false) +{ +    std::string s; +    raw_string_ostream rso(s); +    type->print(rso); +    rso.flush(); +    if (truncate) +        s.resize(s.length() - 1); +    return s; +} + +IRForTarget::~IRForTarget() +{ +} + +bool +IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) +{ +    llvm_function.setLinkage(GlobalValue::ExternalLinkage); + +    std::string name = llvm_function.getName().str(); + +    return true; +} + +IRForTarget::LookupResult +IRForTarget::GetFunctionAddress (llvm::Function *fun, +                                 uint64_t &fun_addr, +                                 lldb_private::ConstString &name, +                                 Constant **&value_ptr) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    fun_addr = LLDB_INVALID_ADDRESS; +    name.Clear(); +    value_ptr = NULL; + +    if (fun->isIntrinsic()) +    { +        Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID(); + +        switch (intrinsic_id) +        { +        default: +            if (log) +                log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str()); + +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str()); + +            return LookupResult::Fail; +        case Intrinsic::memcpy: +            { +                static lldb_private::ConstString g_memcpy_str ("memcpy"); +                name = g_memcpy_str; +            } +            break; +        case Intrinsic::memset: +            { +                static lldb_private::ConstString g_memset_str ("memset"); +                name = g_memset_str; +            } +            break; +        case Intrinsic::dbg_declare: +        case Intrinsic::dbg_value: +            return LookupResult::Ignore; +        } + +        if (log && name) +            log->Printf("Resolved intrinsic name \"%s\"", name.GetCString()); +    } +    else +    { +        name.SetCStringWithLength (fun->getName().data(), fun->getName().size()); +    } + +    // Find the address of the function. + +    clang::NamedDecl *fun_decl = DeclForGlobal (fun); + +    if (fun_decl) +    { +        if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) +        { +            std::vector<lldb_private::ConstString> alternates; +            bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); +            if (!found_it) +            { +                if (log) +                    log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); +                // Check for an alternate mangling for names from the standard library. +                // For example, "std::basic_string<...>" has an alternate mangling scheme per +                // the Itanium C++ ABI. +                lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); +                if (process_sp) +                { +                    lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); +                    if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) +                    { +                        for (size_t i = 0; i < alternates.size(); ++i) +                        { +                            const lldb_private::ConstString &alternate_name = alternates[i]; +                            if (log) +                                log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", +                                            name.GetCString(), alternate_name.GetCString()); +                            if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) +                            { +                                if (log) +                                    log->Printf("Found address of function \"%s\" with alternate name \"%s\"", +                                                name.GetCString(), alternate_name.GetCString()); +                                break; +                            } +                        } +                    } +                } +            } + +            if (!found_it) +            { +                lldb_private::Mangled mangled_name(name); +                if (m_error_stream) +                { +                    if (mangled_name.GetMangledName()) +                        m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", +                                               mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), +                                               mangled_name.GetMangledName().GetCString()); +                    else +                        m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", +                                               mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); +                } +                return LookupResult::Fail; +            } +        } +    } +    else +    { +        if (!m_decl_map->GetFunctionAddress (name, fun_addr)) +        { +            if (log) +                log->Printf ("Metadataless function \"%s\" had no address", name.GetCString()); + +            if (m_error_stream) +                m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString()); + +            return LookupResult::Fail; +        } +    } + +    if (log) +        log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); + +    return LookupResult::Success; +} + +llvm::Constant * +IRForTarget::BuildFunctionPointer (llvm::Type *type, +                                   uint64_t ptr) +{ +    PointerType *fun_ptr_ty = PointerType::getUnqual(type); +    Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false); +    return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); +} + +void +IRForTarget::RegisterFunctionMetadata(LLVMContext &context, +                                      llvm::Value *function_ptr, +                                      const char *name) +{ +    for (llvm::User *user : function_ptr->users()) +    { +        if (Instruction *user_inst = dyn_cast<Instruction>(user)) +        { +            MDString* md_name = MDString::get(context, StringRef(name)); + +            MDNode *metadata = MDNode::get(context, md_name); + +            user_inst->setMetadata("lldb.call.realName", metadata); +        } +        else +        { +            RegisterFunctionMetadata (context, user, name); +        } +    } +} + +bool +IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    for (llvm::Module::iterator fi = llvm_module.begin(); +         fi != llvm_module.end(); +         ++fi) +    { +        Function *fun = &*fi; + +        bool is_decl = fun->isDeclaration(); + +        if (log) +            log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str()); + +        if (!is_decl) +            continue; + +        if (fun->use_empty()) +            continue; // ignore + +        uint64_t addr = LLDB_INVALID_ADDRESS; +        lldb_private::ConstString name; +        Constant **value_ptr = NULL; + +        LookupResult result = GetFunctionAddress(fun, +                                                 addr, +                                                 name, +                                                 value_ptr); + +        switch (result) +        { +        case LookupResult::Fail: +            return false; // GetFunctionAddress reports its own errors + +        case LookupResult::Ignore: +            break; // Nothing to do + +        case LookupResult::Success: +            { +                Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr); + +                RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString()); + +                if (value_ptr) +                    *value_ptr = value; + +                // If we are replacing a function with the nobuiltin attribute, it may +                // be called with the builtin attribute on call sites. Remove any such +                // attributes since it's illegal to have a builtin call to something +                // other than a nobuiltin function. +                if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) { +                    llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin); + +                    for (auto u : fun->users()) { +                        if (auto call = dyn_cast<CallInst>(u)) { +                            call->removeAttribute(AttributeSet::FunctionIndex, builtin); +                        } +                    } +                } + +                fun->replaceAllUsesWith(value); +            } +            break; +        } +    } + +    return true; +} + + +clang::NamedDecl * +IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) +{ +    NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); + +    if (!named_metadata) +        return NULL; + +    unsigned num_nodes = named_metadata->getNumOperands(); +    unsigned node_index; + +    for (node_index = 0; +         node_index < num_nodes; +         ++node_index) +    { +        llvm::MDNode *metadata_node = dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index)); +        if (!metadata_node) +            return NULL; + +        if (metadata_node->getNumOperands() != 2) +            continue; + +        if (mdconst::dyn_extract_or_null<GlobalValue>(metadata_node->getOperand(0)) != global_val) +            continue; + +        ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1)); + +        if (!constant_int) +            return NULL; + +        uintptr_t ptr = constant_int->getZExtValue(); + +        return reinterpret_cast<clang::NamedDecl *>(ptr); +    } + +    return NULL; +} + +clang::NamedDecl * +IRForTarget::DeclForGlobal (GlobalValue *global_val) +{ +    return DeclForGlobal(global_val, m_module); +} + +bool +IRForTarget::CreateResultVariable (llvm::Function &llvm_function) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (!m_resolve_vars) +        return true; + +    // Find the result variable.  If it doesn't exist, we can give up right here. + +    ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + +    std::string result_name_str; +    const char *result_name = NULL; + +    for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); +         vi != ve; +         ++vi) +    { +        result_name_str = vi->first().str(); +        const char *value_name = result_name_str.c_str(); + +        if (strstr(value_name, "$__lldb_expr_result_ptr") && +            strncmp(value_name, "_ZGV", 4)) +        { +            result_name = value_name; +            m_result_is_pointer = true; +            break; +        } + +        if (strstr(value_name, "$__lldb_expr_result") && +            strncmp(value_name, "_ZGV", 4)) +        { +            result_name = value_name; +            m_result_is_pointer = false; +            break; +        } +    } + +    if (!result_name) +    { +        if (log) +            log->PutCString("Couldn't find result variable"); + +        return true; +    } + +    if (log) +        log->Printf("Result name: \"%s\"", result_name); + +    Value *result_value = m_module->getNamedValue(result_name); + +    if (!result_value) +    { +        if (log) +            log->PutCString("Result variable had no data"); + +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); + +        return false; +    } + +    if (log) +        log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); + +    GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); + +    if (!result_global) +    { +        if (log) +            log->PutCString("Result variable isn't a GlobalVariable"); + +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); + +        return false; +    } + +    clang::NamedDecl *result_decl = DeclForGlobal (result_global); +    if (!result_decl) +    { +        if (log) +            log->PutCString("Result variable doesn't have a corresponding Decl"); + +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); + +        return false; +    } + +    if (log) +    { +        std::string decl_desc_str; +        raw_string_ostream decl_desc_stream(decl_desc_str); +        result_decl->print(decl_desc_stream); +        decl_desc_stream.flush(); + +        log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); +    } + +    clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl); +    if (!result_var) +    { +        if (log) +            log->PutCString("Result variable Decl isn't a VarDecl"); + +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); + +        return false; +    } + +    // Get the next available result name from m_decl_map and create the persistent +    // variable for it + +    // If the result is an Lvalue, it is emitted as a pointer; see +    // ASTResultSynthesizer::SynthesizeBodyResult. +    if (m_result_is_pointer) +    { +        clang::QualType pointer_qual_type = result_var->getType(); +        const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); + +        const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>(); +        const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>(); + +        if (pointer_pointertype) +        { +            clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); + +            m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), +                                                         lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); +        } +        else if (pointer_objcobjpointertype) +        { +            clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); + +            m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), +                                                         lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); +        } +        else +        { +            if (log) +                log->PutCString("Expected result to have pointer type, but it did not"); + +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); + +            return false; +        } +    } +    else +    { +        m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), +                                                     lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); +    } + + +    lldb::TargetSP target_sp (m_data_allocator.GetTarget()); +    lldb_private::ExecutionContext exe_ctx (target_sp, true); +    if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) +    { +        lldb_private::StreamString type_desc_stream; +        m_result_type.DumpTypeDescription(&type_desc_stream); + +        if (log) +            log->Printf("Result type has size 0"); + +        if (m_error_stream) +            m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", +                                   type_desc_stream.GetData()); +        return false; +    } + +    if (log) +    { +        lldb_private::StreamString type_desc_stream; +        m_result_type.DumpTypeDescription(&type_desc_stream); + +        log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); +    } + +    m_result_name = lldb_private::ConstString("$RESULT_NAME"); + +    if (log) +        log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, +                    m_result_name.GetCString(), +                    m_result_type.GetByteSize(nullptr)); + +    // Construct a new result global and set up its metadata + +    GlobalVariable *new_result_global = new GlobalVariable((*m_module), +                                                           result_global->getType()->getElementType(), +                                                           false, /* not constant */ +                                                           GlobalValue::ExternalLinkage, +                                                           NULL, /* no initializer */ +                                                           m_result_name.GetCString ()); + +    // It's too late in compilation to create a new VarDecl for this, but we don't +    // need to.  We point the metadata at the old VarDecl.  This creates an odd +    // anomaly: a variable with a Value whose name is something like $0 and a +    // Decl whose name is $__lldb_expr_result.  This condition is handled in +    // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is +    // fixed up. + +    ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), +                                                     reinterpret_cast<uint64_t>(result_decl), +                                                     false); + +    llvm::Metadata *values[2]; +    values[0] = ConstantAsMetadata::get(new_result_global); +    values[1] = ConstantAsMetadata::get(new_constant_int); + +    ArrayRef<Metadata *> value_ref(values, 2); + +    MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); +    NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); +    named_metadata->addOperand(persistent_global_md); + +    if (log) +        log->Printf("Replacing \"%s\" with \"%s\"", +                    PrintValue(result_global).c_str(), +                    PrintValue(new_result_global).c_str()); + +    if (result_global->use_empty()) +    { +        // We need to synthesize a store for this variable, because otherwise +        // there's nothing to put into its equivalent persistent variable. + +        BasicBlock &entry_block(llvm_function.getEntryBlock()); +        Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); + +        if (!first_entry_instruction) +            return false; + +        if (!result_global->hasInitializer()) +        { +            if (log) +                log->Printf("Couldn't find initializer for unused variable"); + +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); + +            return false; +        } + +        Constant *initializer = result_global->getInitializer(); + +        StoreInst *synthesized_store = new StoreInst(initializer, +                                                     new_result_global, +                                                     first_entry_instruction); + +        if (log) +            log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); +    } +    else +    { +        result_global->replaceAllUsesWith(new_result_global); +    } + +    if (!m_decl_map->AddPersistentVariable(result_decl, +                                           m_result_name, +                                           m_result_type, +                                           true, +                                           m_result_is_pointer)) +        return false; + +    result_global->eraseFromParent(); + +    return true; +} + +bool +IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, +                                     llvm::GlobalVariable *cstr) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    Type *ns_str_ty = ns_str->getType(); + +    Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); +    Type *i32_ty = Type::getInt32Ty(m_module->getContext()); +    Type *i8_ty = Type::getInt8Ty(m_module->getContext()); + +    if (!m_CFStringCreateWithBytes) +    { +        lldb::addr_t CFStringCreateWithBytes_addr; + +        static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); + +        if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) +        { +            if (log) +                log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); + +            if (m_error_stream) +                m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); + +            return false; +        } + +        if (log) +            log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); + +        // Build the function type: +        // +        // CFStringRef CFStringCreateWithBytes ( +        //   CFAllocatorRef alloc, +        //   const UInt8 *bytes, +        //   CFIndex numBytes, +        //   CFStringEncoding encoding, +        //   Boolean isExternalRepresentation +        // ); +        // +        // We make the following substitutions: +        // +        // CFStringRef -> i8* +        // CFAllocatorRef -> i8* +        // UInt8 * -> i8* +        // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) +        // CFStringEncoding -> i32 +        // Boolean -> i8 + +        Type *arg_type_array[5]; + +        arg_type_array[0] = i8_ptr_ty; +        arg_type_array[1] = i8_ptr_ty; +        arg_type_array[2] = m_intptr_ty; +        arg_type_array[3] = i32_ty; +        arg_type_array[4] = i8_ty; + +        ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5); + +        llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); + +        // Build the constant containing the pointer to the function +        PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); +        Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); +        m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); +    } + +    ConstantDataSequential *string_array = NULL; + +    if (cstr) +        string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer()); + +    Constant *alloc_arg         = Constant::getNullValue(i8_ptr_ty); +    Constant *bytes_arg         = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); +    Constant *numBytes_arg      = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); +    Constant *encoding_arg      = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ +    Constant *isExternal_arg    = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ + +    Value *argument_array[5]; + +    argument_array[0] = alloc_arg; +    argument_array[1] = bytes_arg; +    argument_array[2] = numBytes_arg; +    argument_array[3] = encoding_arg; +    argument_array[4] = isExternal_arg; + +    ArrayRef <Value *> CFSCWB_arguments(argument_array, 5); + +    FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { +        return CallInst::Create(m_CFStringCreateWithBytes, +                                CFSCWB_arguments, +                                "CFStringCreateWithBytes", +                                llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function))); +    }); + +    if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder)) +    { +        if (log) +            log->PutCString("Couldn't replace the NSString with the result of the call"); + +        if (m_error_stream) +            m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n"); + +        return false; +    } + +    ns_str->eraseFromParent(); + +    return true; +} + +bool +IRForTarget::RewriteObjCConstStrings() +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + +    for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); +         vi != ve; +         ++vi) +    { +        std::string value_name = vi->first().str(); +        const char *value_name_cstr = value_name.c_str(); + +        if (strstr(value_name_cstr, "_unnamed_cfstring_")) +        { +            Value *nsstring_value = vi->second; + +            GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value); + +            if (!nsstring_global) +            { +                if (log) +                    log->PutCString("NSString variable is not a GlobalVariable"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); + +                return false; +            } + +            if (!nsstring_global->hasInitializer()) +            { +                if (log) +                    log->PutCString("NSString variable does not have an initializer"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); + +                return false; +            } + +            ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer()); + +            if (!nsstring_struct) +            { +                if (log) +                    log->PutCString("NSString variable's initializer is not a ConstantStruct"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); + +                return false; +            } + +            // We expect the following structure: +            // +            // struct { +            //   int *isa; +            //   int flags; +            //   char *str; +            //   long length; +            // }; + +            if (nsstring_struct->getNumOperands() != 4) +            { +                if (log) +                    log->Printf("NSString variable's initializer structure has an unexpected number of members.  Should be 4, is %d", nsstring_struct->getNumOperands()); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); + +                return false; +            } + +            Constant *nsstring_member = nsstring_struct->getOperand(2); + +            if (!nsstring_member) +            { +                if (log) +                    log->PutCString("NSString initializer's str element was empty"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); + +                return false; +            } + +            ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member); + +            if (!nsstring_expr) +            { +                if (log) +                    log->PutCString("NSString initializer's str element is not a ConstantExpr"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); + +                return false; +            } + +            if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) +            { +                if (log) +                    log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); + +                return false; +            } + +            Constant *nsstring_cstr = nsstring_expr->getOperand(0); + +            GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr); + +            if (!cstr_global) +            { +                if (log) +                    log->PutCString("NSString initializer's str element is not a GlobalVariable"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); + +                return false; +            } + +            if (!cstr_global->hasInitializer()) +            { +                if (log) +                    log->PutCString("NSString initializer's str element does not have an initializer"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); + +                return false; +            } + +            /* +            if (!cstr_array) +            { +                if (log) +                    log->PutCString("NSString initializer's str element is not a ConstantArray"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); + +                return false; +            } + +            if (!cstr_array->isCString()) +            { +                if (log) +                    log->PutCString("NSString initializer's str element is not a C string array"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); + +                return false; +            } +            */ + +            ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer()); + +            if (log) +            { +                if (cstr_array) +                    log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); +                else +                    log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); +            } + +            if (!cstr_array) +                cstr_global = NULL; + +            if (!RewriteObjCConstString(nsstring_global, cstr_global)) +            { +                if (log) +                    log->PutCString("Error rewriting the constant string"); + +                // We don't print an error message here because RewriteObjCConstString has done so for us. + +                return false; +            } +        } +    } + +    for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); +         vi != ve; +         ++vi) +    { +        std::string value_name = vi->first().str(); +        const char *value_name_cstr = value_name.c_str(); + +        if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) +        { +            GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second); + +            if (!gv) +            { +                if (log) +                    log->PutCString("__CFConstantStringClassReference is not a global variable"); + +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); + +                return false; +            } + +            gv->eraseFromParent(); + +            break; +        } +    } + +    return true; +} + +static bool IsObjCSelectorRef (Value *value) +{ +    GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value); + +    if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) +        return false; + +    return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewriteObjCSelector (Instruction* selector_load) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    LoadInst *load = dyn_cast<LoadInst>(selector_load); + +    if (!load) +        return false; + +    // Unpack the message name from the selector.  In LLVM IR, an objc_msgSend gets represented as +    // +    // %tmp     = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> +    // %call    = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*> +    // +    // where %obj is the object pointer and %tmp is the selector. +    // +    // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". +    // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. + +    // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target + +    GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand()); + +    if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) +        return false; + +    Constant *osr_initializer = _objc_selector_references_->getInitializer(); + +    ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer); + +    if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) +        return false; + +    Value *osr_initializer_base = osr_initializer_expr->getOperand(0); + +    if (!osr_initializer_base) +        return false; + +    // Find the string's initializer (a ConstantArray) and get the string from it + +    GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base); + +    if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) +        return false; + +    Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); + +    ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer); + +    if (!omvn_initializer_array->isString()) +        return false; + +    std::string omvn_initializer_string = omvn_initializer_array->getAsString(); + +    if (log) +        log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); + +    // Construct a call to sel_registerName + +    if (!m_sel_registerName) +    { +        lldb::addr_t sel_registerName_addr; + +        static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); +        if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr)) +            return false; + +        if (log) +            log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); + +        // Build the function type: struct objc_selector *sel_registerName(uint8_t*) + +        // The below code would be "more correct," but in actuality what's required is uint8_t* +        //Type *sel_type = StructType::get(m_module->getContext()); +        //Type *sel_ptr_type = PointerType::getUnqual(sel_type); +        Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); + +        Type *type_array[1]; + +        type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); + +        ArrayRef<Type *> srN_arg_types(type_array, 1); + +        llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); + +        // Build the constant containing the pointer to the function +        PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); +        Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); +        m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); +    } + +    Value *argument_array[1]; + +    Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); + +    argument_array[0] = omvn_pointer; + +    ArrayRef<Value *> srN_arguments(argument_array, 1); + +    CallInst *srN_call = CallInst::Create(m_sel_registerName, +                                          srN_arguments, +                                          "sel_registerName", +                                          selector_load); + +    // Replace the load with the call in all users + +    selector_load->replaceAllUsesWith(srN_call); + +    selector_load->eraseFromParent(); + +    return true; +} + +bool +IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    BasicBlock::iterator ii; + +    typedef SmallVector <Instruction*, 2> InstrList; +    typedef InstrList::iterator InstrIterator; + +    InstrList selector_loads; + +    for (ii = basic_block.begin(); +         ii != basic_block.end(); +         ++ii) +    { +        Instruction &inst = *ii; + +        if (LoadInst *load = dyn_cast<LoadInst>(&inst)) +            if (IsObjCSelectorRef(load->getPointerOperand())) +                selector_loads.push_back(&inst); +    } + +    InstrIterator iter; + +    for (iter = selector_loads.begin(); +         iter != selector_loads.end(); +         ++iter) +    { +        if (!RewriteObjCSelector(*iter)) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); + +            if (log) +                log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); + +            return false; +        } +    } + +    return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc); + +    MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); + +    if (!alloc_md || !alloc_md->getNumOperands()) +        return false; + +    ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0)); + +    if (!constant_int) +        return false; + +    // We attempt to register this as a new persistent variable with the DeclMap. + +    uintptr_t ptr = constant_int->getZExtValue(); + +    clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); + +    lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), +                                                   lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); + +    StringRef decl_name (decl->getName()); +    lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); +    if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) +        return false; + +    GlobalVariable *persistent_global = new GlobalVariable((*m_module), +                                                           alloc->getType(), +                                                           false, /* not constant */ +                                                           GlobalValue::ExternalLinkage, +                                                           NULL, /* no initializer */ +                                                           alloc->getName().str().c_str()); + +    // What we're going to do here is make believe this was a regular old external +    // variable.  That means we need to make the metadata valid. + +    NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); + +    llvm::Metadata *values[2]; +    values[0] = ConstantAsMetadata::get(persistent_global); +    values[1] = ConstantAsMetadata::get(constant_int); + +    ArrayRef<llvm::Metadata *> value_ref(values, 2); + +    MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); +    named_metadata->addOperand(persistent_global_md); + +    // Now, since the variable is a pointer variable, we will drop in a load of that +    // pointer variable. + +    LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); + +    if (log) +        log->Printf("Replacing \"%s\" with \"%s\"", +                    PrintValue(alloc).c_str(), +                    PrintValue(persistent_load).c_str()); + +    alloc->replaceAllUsesWith(persistent_load); +    alloc->eraseFromParent(); + +    return true; +} + +bool +IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) +{ +    if (!m_resolve_vars) +        return true; + +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    BasicBlock::iterator ii; + +    typedef SmallVector <Instruction*, 2> InstrList; +    typedef InstrList::iterator InstrIterator; + +    InstrList pvar_allocs; + +    for (ii = basic_block.begin(); +         ii != basic_block.end(); +         ++ii) +    { +        Instruction &inst = *ii; + +        if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst)) +        { +            llvm::StringRef alloc_name = alloc->getName(); + +            if (alloc_name.startswith("$") && +                !alloc_name.startswith("$__lldb")) +            { +                if (alloc_name.find_first_of("0123456789") == 1) +                { +                    if (log) +                        log->Printf("Rejecting a numeric persistent variable."); + +                    if (m_error_stream) +                        m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); + +                    return false; +                } + +                pvar_allocs.push_back(alloc); +            } +        } +    } + +    InstrIterator iter; + +    for (iter = pvar_allocs.begin(); +         iter != pvar_allocs.end(); +         ++iter) +    { +        if (!RewritePersistentAlloc(*iter)) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); + +            if (log) +                log->PutCString("Couldn't rewrite the creation of a persistent variable"); + +            return false; +        } +    } + +    return true; +} + +bool +IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) +{ +    if (!initializer) +        return true; + +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log && log->GetVerbose()) +        log->Printf("  MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); + +    Type *initializer_type = initializer->getType(); + +    if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer)) +    { +        memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); +        return true; +    } +    else if (ConstantDataArray *array_initializer = dyn_cast<ConstantDataArray>(initializer)) +    { +        if (array_initializer->isString()) +        { +            std::string array_initializer_string = array_initializer->getAsString(); +            memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); +        } +        else +        { +            ArrayType *array_initializer_type = array_initializer->getType(); +            Type *array_element_type = array_initializer_type->getElementType(); + +            size_t element_size = m_target_data->getTypeAllocSize(array_element_type); + +            for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) +            { +                Value *operand_value = array_initializer->getOperand(i); +                Constant *operand_constant = dyn_cast<Constant>(operand_value); + +                if (!operand_constant) +                    return false; + +                if (!MaterializeInitializer(data + (i * element_size), operand_constant)) +                    return false; +            } +        } +        return true; +    } +    else if (ConstantStruct *struct_initializer = dyn_cast<ConstantStruct>(initializer)) +    { +        StructType *struct_initializer_type = struct_initializer->getType(); +        const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); + +        for (unsigned i = 0; +             i < struct_initializer->getNumOperands(); +             ++i) +        { +            if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) +                return false; +        } +        return true; +    } +    else if (isa<ConstantAggregateZero>(initializer)) +    { +        memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); +        return true; +    } +    return false; +} + +bool +IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable) +{ +    if (GlobalVariable::isExternalLinkage(global_variable->getLinkage())) +        return false; + +    if (global_variable == m_reloc_placeholder) +        return true; + +    uint64_t offset = m_data_allocator.GetStream().GetSize(); + +    llvm::Type *variable_type = global_variable->getType(); + +    Constant *initializer = global_variable->getInitializer(); + +    llvm::Type *initializer_type = initializer->getType(); + +    size_t size = m_target_data->getTypeAllocSize(initializer_type); +    size_t align = m_target_data->getPrefTypeAlignment(initializer_type); + +    const size_t mask = (align - 1); +    uint64_t aligned_offset = (offset + mask) & ~mask; +    m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); +    offset = aligned_offset; + +    lldb_private::DataBufferHeap data(size, '\0'); + +    if (initializer) +        if (!MaterializeInitializer(data.GetBytes(), initializer)) +            return false; + +    m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize()); + +    Constant *new_pointer = BuildRelocation(variable_type, offset); + +    global_variable->replaceAllUsesWith(new_pointer); + +    global_variable->eraseFromParent(); + +    return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +        log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + +    if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr)) +    { +        switch (constant_expr->getOpcode()) +        { +        default: +            break; +        case Instruction::GetElementPtr: +        case Instruction::BitCast: +            Value *s = constant_expr->getOperand(0); +            if (!MaybeHandleVariable(s)) +                return false; +        } +    } +    else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr)) +    { +        if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) +            return MaterializeInternalVariable(global_variable); + +        clang::NamedDecl *named_decl = DeclForGlobal(global_variable); + +        if (!named_decl) +        { +            if (IsObjCSelectorRef(llvm_value_ptr)) +                return true; + +            if (!global_variable->hasExternalLinkage()) +                return true; + +            if (log) +                log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); + +            return false; +        } + +        std::string name (named_decl->getName().str()); + +        clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl); +        if (value_decl == NULL) +            return false; + +        lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType()); + +        const Type *value_type = NULL; + +        if (name[0] == '$') +        { +            // The $__lldb_expr_result name indicates the return value has allocated as +            // a static variable.  Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, +            // accesses to this static variable need to be redirected to the result of dereferencing +            // a pointer that is passed in as one of the arguments. +            // +            // Consequently, when reporting the size of the type, we report a pointer type pointing +            // to the type of $__lldb_expr_result, not the type itself. +            // +            // We also do this for any user-declared persistent variables. +            compiler_type = compiler_type.GetPointerType(); +            value_type = PointerType::get(global_variable->getType(), 0); +        } +        else +        { +            value_type = global_variable->getType(); +        } + +        const uint64_t value_size = compiler_type.GetByteSize(nullptr); +        lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; + +        if (log) +        { +            log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", +                        name.c_str(), +                        lldb_private::ClangASTContext::GetQualType(compiler_type).getAsString().c_str(), +                        PrintType(value_type).c_str(), +                        value_size, +                        value_alignment); +        } + + +        if (named_decl && !m_decl_map->AddValueToStruct(named_decl, +                                                        lldb_private::ConstString (name.c_str()), +                                                        llvm_value_ptr, +                                                        value_size, +                                                        value_alignment)) +        { +            if (!global_variable->hasExternalLinkage()) +                return true; +            else if (HandleSymbol (global_variable)) +                return true; +            else +                return false; +        } +    } +    else if (dyn_cast<llvm::Function>(llvm_value_ptr)) +    { +        if (log) +            log->Printf("Function pointers aren't handled right now"); + +        return false; +    } + +    return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::HandleSymbol (Value *symbol) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    lldb_private::ConstString name(symbol->getName().str().c_str()); + +    lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); + +    if (symbol_addr == LLDB_INVALID_ADDRESS) +    { +        if (log) +            log->Printf ("Symbol \"%s\" had no address", name.GetCString()); + +        return false; +    } + +    if (log) +        log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + +    Type *symbol_type = symbol->getType(); + +    Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); + +    Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); + +    if (log) +        log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); + +    symbol->replaceAllUsesWith(symbol_addr_ptr); + +    return true; +} + +bool +IRForTarget::MaybeHandleCallArguments (CallInst *Old) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (log) +        log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + +    for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); +         op_index < num_ops; +         ++op_index) +        if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); + +            return false; +        } + +    return true; +} + +bool +IRForTarget::HandleObjCClass(Value *classlist_reference) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference); + +    if (!global_variable) +        return false; + +    Constant *initializer = global_variable->getInitializer(); + +    if (!initializer) +        return false; + +    if (!initializer->hasName()) +        return false; + +    StringRef name(initializer->getName()); +    lldb_private::ConstString name_cstr(name.str().c_str()); +    lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); + +    if (log) +        log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); + +    if (class_ptr == LLDB_INVALID_ADDRESS) +        return false; + +    if (global_variable->use_empty()) +        return false; + +    SmallVector<LoadInst *, 2> load_instructions; + +    for (llvm::User *u : global_variable->users()) +    { +        if (LoadInst *load_instruction = dyn_cast<LoadInst>(u)) +            load_instructions.push_back(load_instruction); +    } + +    if (load_instructions.empty()) +        return false; + +    Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); + +    for (LoadInst *load_instruction : load_instructions) +    { +        Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); + +        load_instruction->replaceAllUsesWith(class_bitcast); + +        load_instruction->eraseFromParent(); +    } + +    return true; +} + +bool +IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) +{ +    BasicBlock::iterator ii; + +    std::vector<CallInst *> calls_to_remove; + +    for (ii = basic_block.begin(); +         ii != basic_block.end(); +         ++ii) +    { +        Instruction &inst = *ii; + +        CallInst *call = dyn_cast<CallInst>(&inst); + +        // MaybeHandleCallArguments handles error reporting; we are silent here +        if (!call) +            continue; + +        bool remove = false; + +        llvm::Function *func = call->getCalledFunction(); + +        if (func && func->getName() == "__cxa_atexit") +            remove = true; + +        llvm::Value *val = call->getCalledValue(); + +        if (val && val->getName() == "__cxa_atexit") +            remove = true; + +        if (remove) +            calls_to_remove.push_back(call); +    } + +    for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); +         ci != ce; +         ++ci) +    { +        (*ci)->eraseFromParent(); +    } + +    return true; +} + +bool +IRForTarget::ResolveCalls(BasicBlock &basic_block) +{ +    ///////////////////////////////////////////////////////////////////////// +    // Prepare the current basic block for execution in the remote process +    // + +    BasicBlock::iterator ii; + +    for (ii = basic_block.begin(); +         ii != basic_block.end(); +         ++ii) +    { +        Instruction &inst = *ii; + +        CallInst *call = dyn_cast<CallInst>(&inst); + +        // MaybeHandleCallArguments handles error reporting; we are silent here +        if (call && !MaybeHandleCallArguments(call)) +            return false; +    } + +    return true; +} + +bool +IRForTarget::ResolveExternals (Function &llvm_function) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    for (GlobalVariable &global_var : m_module->globals()) +    { +        std::string global_name = global_var.getName().str(); + +        if (log) +            log->Printf("Examining %s, DeclForGlobalValue returns %p", +                        global_name.c_str(), +                        static_cast<void*>(DeclForGlobal(&global_var))); + +        if (global_name.find("OBJC_IVAR") == 0) +        { +            if (!HandleSymbol(&global_var)) +            { +                if (m_error_stream) +                    m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); + +                return false; +            } +        } +        else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) +        { +            if (!HandleObjCClass(&global_var)) +            { +                if (m_error_stream) +                    m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + +                return false; +            } +        } +        else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) +        { +            if (!HandleObjCClass(&global_var)) +            { +                if (m_error_stream) +                    m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + +                return false; +            } +        } +        else if (DeclForGlobal(&global_var)) +        { +            if (!MaybeHandleVariable (&global_var)) +            { +                if (m_error_stream) +                    m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); + +                return false; +            } +        } +    } + +    return true; +} + +bool +IRForTarget::ReplaceStrings () +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    typedef std::map <GlobalVariable *, size_t> OffsetsTy; + +    OffsetsTy offsets; + +    for (GlobalVariable &gv : m_module->globals()) +    { +        if (!gv.hasInitializer()) +            continue; + +        Constant *gc = gv.getInitializer(); + +        std::string str; + +        if (gc->isNullValue()) +        { +            Type *gc_type = gc->getType(); + +            ArrayType *gc_array_type = dyn_cast<ArrayType>(gc_type); + +            if (!gc_array_type) +                continue; + +            Type *gc_element_type = gc_array_type->getElementType(); + +            IntegerType *gc_integer_type = dyn_cast<IntegerType>(gc_element_type); + +            if (gc_integer_type->getBitWidth() != 8) +                continue; + +            str = ""; +        } +        else +        { +            ConstantDataArray *gc_array = dyn_cast<ConstantDataArray>(gc); + +            if (!gc_array) +                continue; + +            if (!gc_array->isCString()) +                continue; + +            if (log) +                log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str()); + +            str = gc_array->getAsString(); +        } + +        offsets[&gv] = m_data_allocator.GetStream().GetSize(); + +        m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1); +    } + +    Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + +    for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end(); +         oi != oe; +         ++oi) +    { +        GlobalVariable *gv = oi->first; +        size_t offset = oi->second; + +        Constant *new_initializer = BuildRelocation(char_ptr_ty, offset); + +        if (log) +            log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str()); + +        for (llvm::User *u : gv->users()) +        { +            if (log) +                log->Printf("Found use %s", PrintValue(u).c_str()); + +            ConstantExpr *const_expr = dyn_cast<ConstantExpr>(u); +            StoreInst *store_inst = dyn_cast<StoreInst>(u); + +            if (const_expr) +            { +                if (const_expr->getOpcode() != Instruction::GetElementPtr) +                { +                    if (log) +                        log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str()); + +                    return false; +                } + +                Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType()); +                Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast); + +                const_expr->replaceAllUsesWith(new_gep); +            } +            else if (store_inst) +            { +                Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType()); + +                store_inst->setOperand(0, bit_cast); +            } +            else +            { +                if (log) +                    log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str()); + +                return false; +            } +        } + +        gv->eraseFromParent(); +    } + +    return true; +} + +bool +IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    typedef SmallVector <Value*, 2> ConstantList; +    typedef SmallVector <llvm::Instruction*, 2> UserList; +    typedef ConstantList::iterator ConstantIterator; +    typedef UserList::iterator UserIterator; + +    ConstantList static_constants; +    UserList static_users; + +    for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end(); +         ii != ie; +         ++ii) +    { +        llvm::Instruction &inst = *ii; + +        for (Value *operand_val : inst.operand_values()) +        { +            ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val); + +            if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/) +            { +                static_constants.push_back(operand_val); +                static_users.push_back(&*ii); +            } +        } +    } + +    ConstantIterator constant_iter; +    UserIterator user_iter; + +    for (constant_iter = static_constants.begin(), user_iter = static_users.begin(); +         constant_iter != static_constants.end(); +         ++constant_iter, ++user_iter) +    { +        Value *operand_val = *constant_iter; +        llvm::Instruction *inst = *user_iter; + +        ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val); + +        if (operand_constant_fp) +        { +            Type *operand_type = operand_constant_fp->getType(); + +            APFloat operand_apfloat = operand_constant_fp->getValueAPF(); +            APInt operand_apint = operand_apfloat.bitcastToAPInt(); + +            const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData(); +            size_t operand_data_size = operand_apint.getBitWidth() / 8; + +            if (log) +            { +                std::string s; +                raw_string_ostream ss(s); +                for (size_t index = 0; +                     index < operand_data_size; +                     ++index) +                { +                    ss << (uint32_t)operand_raw_data[index]; +                    ss << " "; +                } +                ss.flush(); + +                log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str()); +            } + +            lldb_private::DataBufferHeap data(operand_data_size, 0); + +            if (lldb_private::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder()) +            { +                uint8_t *data_bytes = data.GetBytes(); + +                for (size_t index = 0; +                     index < operand_data_size; +                     ++index) +                { +                    data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)]; +                } +            } +            else +            { +                memcpy(data.GetBytes(), operand_raw_data, operand_data_size); +            } + +            uint64_t offset = m_data_allocator.GetStream().GetSize(); + +            size_t align = m_target_data->getPrefTypeAlignment(operand_type); + +            const size_t mask = (align - 1); +            uint64_t aligned_offset = (offset + mask) & ~mask; +            m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); + +            m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size); + +            llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo(); + +            Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset); + +            llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst); + +            operand_constant_fp->replaceAllUsesWith(fp_load); +        } +    } + +    return true; +} + +static bool isGuardVariableRef(Value *V) +{ +    Constant *Old = NULL; + +    if (!(Old = dyn_cast<Constant>(V))) +        return false; + +    ConstantExpr *CE = NULL; + +    if ((CE = dyn_cast<ConstantExpr>(V))) +    { +        if (CE->getOpcode() != Instruction::BitCast) +            return false; + +        Old = CE->getOperand(0); +    } + +    GlobalVariable *GV = dyn_cast<GlobalVariable>(Old); + +    if (!GV || !GV->hasName() || +        (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable +         !GV->getName().endswith("@4IA")))    // Microsoft ABI guard variable +    { +        return false; +    } + +    return true; +} + +void +IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) +{ +    Constant *zero(Constant::getNullValue(guard_load->getType())); +    guard_load->replaceAllUsesWith(zero); +    guard_load->eraseFromParent(); +} + +static void ExciseGuardStore(Instruction* guard_store) +{ +    guard_store->eraseFromParent(); +} + +bool +IRForTarget::RemoveGuards(BasicBlock &basic_block) +{ +    /////////////////////////////////////////////////////// +    // Eliminate any reference to guard variables found. +    // + +    BasicBlock::iterator ii; + +    typedef SmallVector <Instruction*, 2> InstrList; +    typedef InstrList::iterator InstrIterator; + +    InstrList guard_loads; +    InstrList guard_stores; + +    for (ii = basic_block.begin(); +         ii != basic_block.end(); +         ++ii) +    { +        Instruction &inst = *ii; + +        if (LoadInst *load = dyn_cast<LoadInst>(&inst)) +            if (isGuardVariableRef(load->getPointerOperand())) +                guard_loads.push_back(&inst); + +        if (StoreInst *store = dyn_cast<StoreInst>(&inst)) +            if (isGuardVariableRef(store->getPointerOperand())) +                guard_stores.push_back(&inst); +    } + +    InstrIterator iter; + +    for (iter = guard_loads.begin(); +         iter != guard_loads.end(); +         ++iter) +        TurnGuardLoadIntoZero(*iter); + +    for (iter = guard_stores.begin(); +         iter != guard_stores.end(); +         ++iter) +        ExciseGuardStore(*iter); + +    return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::UnfoldConstant(Constant *old_constant, +                            FunctionValueCache &value_maker, +                            FunctionValueCache &entry_instruction_finder) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    SmallVector<User*, 16> users; + +    // We do this because the use list might change, invalidating our iterator. +    // Much better to keep a work list ourselves. +    for (llvm::User *u : old_constant->users()) +        users.push_back(u); + +    for (size_t i = 0; +         i < users.size(); +         ++i) +    { +        User *user = users[i]; + +        if (Constant *constant = dyn_cast<Constant>(user)) +        { +            // synthesize a new non-constant equivalent of the constant + +            if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant)) +            { +                switch (constant_expr->getOpcode()) +                { +                default: +                    if (log) +                        log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); +                    return false; +                case Instruction::BitCast: +                    { +                        FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { +                            // UnaryExpr +                            //   OperandList[0] is value + +                            if (constant_expr->getOperand(0) != old_constant) +                                return constant_expr; + +                            return new BitCastInst(value_maker.GetValue(function), +                                                   constant_expr->getType(), +                                                   "", +                                                   llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); +                        }); + +                        if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder)) +                            return false; +                    } +                    break; +                case Instruction::GetElementPtr: +                    { +                        // GetElementPtrConstantExpr +                        //   OperandList[0] is base +                        //   OperandList[1]... are indices + +                        FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { +                            Value *ptr = constant_expr->getOperand(0); + +                            if (ptr == old_constant) +                                ptr = value_maker.GetValue(function); + +                            std::vector<Value*> index_vector; + +                            unsigned operand_index; +                            unsigned num_operands = constant_expr->getNumOperands(); + +                            for (operand_index = 1; +                                 operand_index < num_operands; +                                 ++operand_index) +                            { +                                Value *operand = constant_expr->getOperand(operand_index); + +                                if (operand == old_constant) +                                    operand = value_maker.GetValue(function); + +                                index_vector.push_back(operand); +                            } + +                            ArrayRef <Value*> indices(index_vector); + +                            return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function))); +                        }); + +                        if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) +                            return false; +                    } +                    break; +                } +            } +            else +            { +                if (log) +                    log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); +                return false; +            } +        } +        else +        { +            if (Instruction *inst = llvm::dyn_cast<Instruction>(user)) +            { +                inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); +            } +            else +            { +                if (log) +                    log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); +                return false; +            } +        } +    } + +    if (!isa<GlobalValue>(old_constant)) +    { +        old_constant->destroyConstant(); +    } + +    return true; +} + +bool +IRForTarget::ReplaceVariables (Function &llvm_function) +{ +    if (!m_resolve_vars) +        return true; + +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    m_decl_map->DoStructLayout(); + +    if (log) +        log->Printf("Element arrangement:"); + +    uint32_t num_elements; +    uint32_t element_index; + +    size_t size; +    lldb::offset_t alignment; + +    if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) +        return false; + +    Function::arg_iterator iter(llvm_function.getArgumentList().begin()); + +    if (iter == llvm_function.getArgumentList().end()) +    { +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); + +        return false; +    } + +    Argument *argument = &*iter; + +    if (argument->getName().equals("this")) +    { +        ++iter; + +        if (iter == llvm_function.getArgumentList().end()) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); + +            return false; +        } + +        argument = &*iter; +    } +    else if (argument->getName().equals("self")) +    { +        ++iter; + +        if (iter == llvm_function.getArgumentList().end()) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); + +            return false; +        } + +        if (!iter->getName().equals("_cmd")) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); + +            return false; +        } + +        ++iter; + +        if (iter == llvm_function.getArgumentList().end()) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); + +            return false; +        } + +        argument = &*iter; +    } + +    if (!argument->getName().equals("$__lldb_arg")) +    { +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); + +        return false; +    } + +    if (log) +        log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + +    BasicBlock &entry_block(llvm_function.getEntryBlock()); +    Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); + +    if (!FirstEntryInstruction) +    { +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); + +        return false; +    } + +    LLVMContext &context(m_module->getContext()); +    IntegerType *offset_type(Type::getInt32Ty(context)); + +    if (!offset_type) +    { +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); + +        return false; +    } + +    for (element_index = 0; element_index < num_elements; ++element_index) +    { +        const clang::NamedDecl *decl = NULL; +        Value *value = NULL; +        lldb::offset_t offset; +        lldb_private::ConstString name; + +        if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) +        { +            if (m_error_stream) +                m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete"); + +            return false; +        } + +        if (log) +            log->Printf("  \"%s\" (\"%s\") placed at %" PRIu64, +                        name.GetCString(), +                        decl->getNameAsString().c_str(), +                        offset); + +        if (value) +        { +            if (log) +                log->Printf("    Replacing [%s]", PrintValue(value).c_str()); + +            FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { +                // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result +                // variable is an rvalue, we have to synthesize a dereference of the appropriate structure +                // entry in order to produce the static variable that the AST thinks it is accessing. + +                llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)); + +                ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); +                GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, +                                                                               argument, +                                                                               offset_int, +                                                                               "", +                                                                               entry_instruction); + +                if (name == m_result_name && !m_result_is_pointer) +                { +                    BitCastInst *bit_cast = new BitCastInst(get_element_ptr, +                                                            value->getType()->getPointerTo(), +                                                            "", +                                                            entry_instruction); + +                    LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); + +                    return load; +                } +                else +                { +                    BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); + +                    return bit_cast; +                } +            }); + +            if (Constant *constant = dyn_cast<Constant>(value)) +            { +                UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder); +            } +            else if (Instruction *instruction = dyn_cast<Instruction>(value)) +            { +                value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); +            } +            else +            { +                if (log) +                    log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); +                return false; +            } + +            if (GlobalVariable *var = dyn_cast<GlobalVariable>(value)) +                var->eraseFromParent(); +        } +    } + +    if (log) +        log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); + +    return true; +} + +llvm::Constant * +IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) +{ +    llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); + +    llvm::Constant *offset_array[1]; + +    offset_array[0] = offset_int; + +    llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1); +    llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); +    llvm::Type *char_pointer_type = char_type->getPointerTo(); + +    llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); +    llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); +    llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); + +    return reloc_bitcast; +} + +bool +IRForTarget::CompleteDataAllocation () +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    if (!m_data_allocator.GetStream().GetSize()) +        return true; + +    lldb::addr_t allocation = m_data_allocator.Allocate(); + +    if (log) +    { +        if (allocation) +            log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation); +        else +            log->Printf("Failed to allocate static data"); +    } + +    if (!allocation || allocation == LLDB_INVALID_ADDRESS) +        return false; + +    Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation); +    Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext())); + +    m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast); + +    m_reloc_placeholder->eraseFromParent(); + +    return true; +} + +bool +IRForTarget::StripAllGVs (Module &llvm_module) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); +    std::vector<GlobalVariable *> global_vars; +    std::set<GlobalVariable *>erased_vars; + +    bool erased = true; + +    while (erased) +    { +        erased = false; + +        for (GlobalVariable &global_var : llvm_module.globals()) +        { +            global_var.removeDeadConstantUsers(); + +            if (global_var.use_empty()) +            { +                if (log) +                    log->Printf("Did remove %s", +                                PrintValue(&global_var).c_str()); +                global_var.eraseFromParent(); +                erased = true; +                break; +            } +        } +    } + +    for (GlobalVariable &global_var : llvm_module.globals()) +    { +        GlobalValue::user_iterator ui = global_var.user_begin(); + +        if (log) +            log->Printf("Couldn't remove %s because of %s", +                        PrintValue(&global_var).c_str(), +                        PrintValue(*ui).c_str()); +    } + +    return true; +} + +bool +IRForTarget::runOnModule (Module &llvm_module) +{ +    lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + +    m_module = &llvm_module; +    m_target_data.reset(new DataLayout(m_module)); +    m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); + +    if (log) +    { +        std::string s; +        raw_string_ostream oss(s); + +        m_module->print(oss, NULL); + +        oss.flush(); + +        log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); +    } + +    Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str())); + +    if (!main_function) +    { +        if (log) +            log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); + +        if (m_error_stream) +            m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); + +        return false; +    } + +    if (!FixFunctionLinkage (*main_function)) +    { +        if (log) +            log->Printf("Couldn't fix the linkage for the function"); + +        return false; +    } + +    llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); + +    m_reloc_placeholder = new llvm::GlobalVariable((*m_module), +                                                   int8_ty, +                                                   false /* IsConstant */, +                                                   GlobalVariable::InternalLinkage, +                                                   Constant::getNullValue(int8_ty), +                                                   "reloc_placeholder", +                                                   NULL /* InsertBefore */, +                                                   GlobalVariable::NotThreadLocal /* ThreadLocal */, +                                                   0 /* AddressSpace */); + +    //////////////////////////////////////////////////////////// +    // Replace $__lldb_expr_result with a persistent variable +    // + +    if (!CreateResultVariable(*main_function)) +    { +        if (log) +            log->Printf("CreateResultVariable() failed"); + +        // CreateResultVariable() reports its own errors, so we don't do so here + +        return false; +    } + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream oss(s); + +        m_module->print(oss, NULL); + +        oss.flush(); + +        log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); +    } + +    for (Module::iterator fi = m_module->begin(), fe = m_module->end(); +         fi != fe; +         ++fi) +    { +        llvm::Function *function = &*fi; + +        if (function->begin() == function->end()) +            continue; + +        Function::iterator bbi; + +        for (bbi = function->begin(); +             bbi != function->end(); +             ++bbi) +        { +            if (!RemoveGuards(*bbi)) +            { +                if (log) +                    log->Printf("RemoveGuards() failed"); + +                // RemoveGuards() reports its own errors, so we don't do so here + +                return false; +            } + +            if (!RewritePersistentAllocs(*bbi)) +            { +                if (log) +                    log->Printf("RewritePersistentAllocs() failed"); + +                // RewritePersistentAllocs() reports its own errors, so we don't do so here + +                return false; +            } + +            if (!RemoveCXAAtExit(*bbi)) +            { +                if (log) +                    log->Printf("RemoveCXAAtExit() failed"); + +                // RemoveCXAAtExit() reports its own errors, so we don't do so here + +                return false; +            } +        } +    } + +    /////////////////////////////////////////////////////////////////////////////// +    // Fix all Objective-C constant strings to use NSStringWithCString:encoding: +    // + +    if (!RewriteObjCConstStrings()) +    { +        if (log) +            log->Printf("RewriteObjCConstStrings() failed"); + +        // RewriteObjCConstStrings() reports its own errors, so we don't do so here + +        return false; +    } + +    /////////////////////////////// +    // Resolve function pointers +    // + +    if (!ResolveFunctionPointers(llvm_module)) +    { +        if (log) +            log->Printf("ResolveFunctionPointers() failed"); + +        // ResolveFunctionPointers() reports its own errors, so we don't do so here + +        return false; +    } + +    for (Module::iterator fi = m_module->begin(), fe = m_module->end(); +         fi != fe; +         ++fi) +    { +        llvm::Function *function = &*fi; + +        for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); +             bbi != bbe; +             ++bbi) +        { +            if (!RewriteObjCSelectors(*bbi)) +            { +                if (log) +                    log->Printf("RewriteObjCSelectors() failed"); + +                // RewriteObjCSelectors() reports its own errors, so we don't do so here + +                return false; +            } +        } +    } + +    for (Module::iterator fi = m_module->begin(), fe = m_module->end(); +         fi != fe; +         ++fi) +    { +        llvm::Function *function = &*fi; + +        for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); +             bbi != bbe; +             ++bbi) +        { +            if (!ResolveCalls(*bbi)) +            { +                if (log) +                    log->Printf("ResolveCalls() failed"); + +                // ResolveCalls() reports its own errors, so we don't do so here + +                return false; +            } + +            if (!ReplaceStaticLiterals(*bbi)) +            { +                if (log) +                    log->Printf("ReplaceStaticLiterals() failed"); + +                return false; +            } +        } +    } + +    //////////////////////////////////////////////////////////////////////// +    // Run function-level passes that only make sense on the main function +    // + +    if (!ResolveExternals(*main_function)) +    { +        if (log) +            log->Printf("ResolveExternals() failed"); + +        // ResolveExternals() reports its own errors, so we don't do so here + +        return false; +    } + +    if (!ReplaceVariables(*main_function)) +    { +        if (log) +            log->Printf("ReplaceVariables() failed"); + +        // ReplaceVariables() reports its own errors, so we don't do so here + +        return false; +    } + +    if (!ReplaceStrings()) +    { +        if (log) +            log->Printf("ReplaceStrings() failed"); + +        return false; +    } + +    if (!CompleteDataAllocation()) +    { +        if (log) +            log->Printf("CompleteDataAllocation() failed"); + +        return false; +    } + +    if (!StripAllGVs(llvm_module)) +    { +        if (log) +            log->Printf("StripAllGVs() failed"); +    } + +    if (log && log->GetVerbose()) +    { +        std::string s; +        raw_string_ostream oss(s); + +        m_module->print(oss, NULL); + +        oss.flush(); + +        log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); +    } + +    return true; +} + +void +IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) +{ +} + +PassManagerType +IRForTarget::getPotentialPassManagerType() const +{ +    return PMT_ModulePassManager; +} diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h new file mode 100644 index 0000000000000..fb4abcc103ded --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -0,0 +1,745 @@ +//===-- IRForTarget.h ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_IRForTarget_h_ +#define liblldb_IRForTarget_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/Pass.h" + +#include <map> +#include <functional> + +namespace llvm { +    class BasicBlock; +    class CallInst; +    class Constant; +    class ConstantInt; +    class Function; +    class GlobalValue; +    class GlobalVariable; +    class Instruction; +    class IntegerType; +    class Module; +    class StoreInst; +    class DataLayout; +    class Type; +    class Value; +} + +namespace lldb_private { +    class ClangExpressionDeclMap; +    class IRExecutionUnit; +    class IRMemoryMap; +} + +//---------------------------------------------------------------------- +/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" +/// @brief Transforms the IR for a function to run in the target +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRForTarget makes the second possible, by applying a series of +/// transformations to the IR which make it relocatable.  These +/// transformations are discussed in more detail next to their relevant +/// functions. +//---------------------------------------------------------------------- +class IRForTarget : public llvm::ModulePass +{ +public: +    enum class LookupResult { +        Success, +        Fail, +        Ignore +    }; +     +    //------------------------------------------------------------------ +    /// Constructor +    /// +    /// @param[in] decl_map +    ///     The list of externally-referenced variables for the expression, +    ///     for use in looking up globals and allocating the argument +    ///     struct.  See the documentation for ClangExpressionDeclMap. +    /// +    /// @param[in] resolve_vars +    ///     True if the external variable references (including persistent +    ///     variables) should be resolved.  If not, only external functions +    ///     are resolved. +    /// +    /// @param[in] execution_policy +    ///     Determines whether an IR interpreter can be used to statically +    ///     evaluate the expression. +    /// +    /// @param[in] const_result +    ///     This variable is populated with the statically-computed result +    ///     of the function, if it has no side-effects and the result can +    ///     be computed statically. +    /// +    /// @param[in] execution_unit +    ///     The holder for raw data associated with the expression. +    /// +    /// @param[in] error_stream +    ///     If non-NULL, a stream on which errors can be printed. +    /// +    /// @param[in] func_name +    ///     The name of the function to prepare for execution in the target. +    //------------------------------------------------------------------ +    IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, +                bool resolve_vars, +                lldb_private::IRExecutionUnit &execution_unit, +                lldb_private::Stream *error_stream, +                const char* func_name = "$__lldb_expr"); +     +    //------------------------------------------------------------------ +    /// Destructor +    //------------------------------------------------------------------ +    ~IRForTarget() override; +     +    //------------------------------------------------------------------ +    /// Run this IR transformer on a single module +    /// +    /// Implementation of the llvm::ModulePass::runOnModule() function. +    /// +    /// @param[in] llvm_module +    ///     The module to run on.  This module is searched for the function +    ///     $__lldb_expr, and that function is passed to the passes one by  +    ///     one. +    /// +    /// @param[in] interpreter_error +    ///     An error.  If the expression fails to be interpreted, this error +    ///     is set to a reason why. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    runOnModule(llvm::Module &llvm_module) override; +     +    //------------------------------------------------------------------ +    /// Interface stub +    /// +    /// Implementation of the llvm::ModulePass::assignPassManager()  +    /// function. +    //------------------------------------------------------------------ +    void +    assignPassManager(llvm::PMStack &pass_mgr_stack, +		      llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override; +     +    //------------------------------------------------------------------ +    /// Returns PMT_ModulePassManager +    /// +    /// Implementation of the llvm::ModulePass::getPotentialPassManagerType()  +    /// function. +    //------------------------------------------------------------------ +    llvm::PassManagerType +    getPotentialPassManagerType() const override; + +private: +    //------------------------------------------------------------------ +    /// Ensures that the current function's linkage is set to external. +    /// Otherwise the JIT may not return an address for it. +    /// +    /// @param[in] llvm_function +    ///     The function whose linkage is to be fixed. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    FixFunctionLinkage (llvm::Function &llvm_function); +     +    //------------------------------------------------------------------ +    /// A module-level pass to replace all function pointers with their +    /// integer equivalents. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] llvm_module +    ///     The module currently being processed. +    /// +    /// @param[in] llvm_function +    ///     The function currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise. +    //------------------------------------------------------------------ +    bool  +    HasSideEffects (llvm::Function &llvm_function); +     +    //------------------------------------------------------------------ +    /// A function-level pass to check whether the function has side +    /// effects. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// Get the address of a function, and a location to put the complete +    /// Value of the function if one is available. +    /// +    /// @param[in] function +    ///     The function to find the location of. +    /// +    /// @param[out] ptr +    ///     The location of the function in the target. +    /// +    /// @param[out] name +    ///     The resolved name of the function (matters for intrinsics). +    /// +    /// @param[out] value_ptr +    ///     A variable to put the function's completed Value* in, or NULL +    ///     if the Value* shouldn't be stored anywhere. +    /// +    /// @return +    ///     The pointer. +    //------------------------------------------------------------------  +    LookupResult +    GetFunctionAddress (llvm::Function *function, +                        uint64_t &ptr, +                        lldb_private::ConstString &name, +                        llvm::Constant **&value_ptr); +     +    //------------------------------------------------------------------ +    /// Build a function pointer given a type and a raw pointer. +    /// +    /// @param[in] type +    ///     The type of the function pointer to be built. +    /// +    /// @param[in] ptr +    ///     The value of the pointer. +    /// +    /// @return +    ///     The pointer. +    //------------------------------------------------------------------  +    llvm::Constant * +    BuildFunctionPointer (llvm::Type *type, +                          uint64_t ptr); +     +    void +    RegisterFunctionMetadata (llvm::LLVMContext &context, +                              llvm::Value *function_ptr, +                              const char *name); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] llvm_function +    ///     The function currently being processed. +    /// +    /// @return +    ///     True if the function has side effects (or if this cannot +    ///     be determined); false otherwise. +    //------------------------------------------------------------------ +    bool  +    ResolveFunctionPointers (llvm::Module &llvm_module); +     +    //------------------------------------------------------------------ +    /// A function-level pass to take the generated global value +    /// $__lldb_expr_result and make it into a persistent variable. +    /// Also see ASTResultSynthesizer. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// Find the NamedDecl corresponding to a Value.  This interface is +    /// exposed for the IR interpreter. +    /// +    /// @param[in] module +    ///     The module containing metadata to search +    /// +    /// @param[in] global +    ///     The global entity to search for +    /// +    /// @return +    ///     The corresponding variable declaration +    //------------------------------------------------------------------ +public: +    static clang::NamedDecl * +    DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); +private: +    clang::NamedDecl * +    DeclForGlobal (llvm::GlobalValue *global); +     +    //------------------------------------------------------------------ +    /// Set the constant result variable m_const_result to the provided +    /// constant, assuming it can be evaluated.  The result variable +    /// will be reset to NULL later if the expression has side effects. +    /// +    /// @param[in] initializer +    ///     The constant initializer for the variable. +    /// +    /// @param[in] name +    ///     The name of the result variable. +    /// +    /// @param[in] type +    ///     The Clang type of the result variable. +    //------------------------------------------------------------------     +    void  +    MaybeSetConstantResult (llvm::Constant *initializer, +                            const lldb_private::ConstString &name, +                            lldb_private::TypeFromParser type); +     +    //------------------------------------------------------------------ +    /// If the IR represents a cast of a variable, set m_const_result +    /// to the result of the cast.  The result variable will be reset to +    /// NULL latger if the expression has side effects. +    /// +    /// @param[in] type +    ///     The Clang type of the result variable. +    //------------------------------------------------------------------   +    void +    MaybeSetCastResult (lldb_private::TypeFromParser type); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] llvm_function +    ///     The function currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    CreateResultVariable (llvm::Function &llvm_function); +     +    //------------------------------------------------------------------ +    /// A module-level pass to find Objective-C constant strings and +    /// transform them to calls to CFStringCreateWithBytes. +    //------------------------------------------------------------------ + +    //------------------------------------------------------------------ +    /// Rewrite a single Objective-C constant string. +    /// +    /// @param[in] NSStr +    ///     The constant NSString to be transformed +    /// +    /// @param[in] CStr +    ///     The constant C string inside the NSString.  This will be +    ///     passed as the bytes argument to CFStringCreateWithBytes. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RewriteObjCConstString (llvm::GlobalVariable *NSStr, +                            llvm::GlobalVariable *CStr);     +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RewriteObjCConstStrings (); + +    //------------------------------------------------------------------ +    /// A basic block-level pass to find all Objective-C method calls and +    /// rewrite them to use sel_registerName instead of statically allocated +    /// selectors.  The reason is that the selectors are created on the +    /// assumption that the Objective-C runtime will scan the appropriate +    /// section and prepare them.  This doesn't happen when code is copied +    /// into the target, though, and there's no easy way to induce the +    /// runtime to scan them.  So instead we get our selectors from +    /// sel_registerName. +    //------------------------------------------------------------------ + +    //------------------------------------------------------------------ +    /// Replace a single selector reference +    /// +    /// @param[in] selector_load +    ///     The load of the statically-allocated selector. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RewriteObjCSelector (llvm::Instruction* selector_load); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] basic_block +    ///     The basic block currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RewriteObjCSelectors (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// A basic block-level pass to find all newly-declared persistent +    /// variables and register them with the ClangExprDeclMap.  This  +    /// allows them to be materialized and dematerialized like normal +    /// external variables.  Before transformation, these persistent +    /// variables look like normal locals, so they have an allocation. +    /// This pass excises these allocations and makes references look +    /// like external references where they will be resolved -- like all +    /// other external references -- by ResolveExternals(). +    //------------------------------------------------------------------ + +    //------------------------------------------------------------------ +    /// Handle a single allocation of a persistent variable +    /// +    /// @param[in] persistent_alloc +    ///     The allocation of the persistent variable. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RewritePersistentAlloc (llvm::Instruction *persistent_alloc); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] basic_block +    ///     The basic block currently being processed. +    //------------------------------------------------------------------ +    bool  +    RewritePersistentAllocs (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// A function-level pass to find all external variables and functions  +    /// used in the IR.  Each found external variable is added to the  +    /// struct, and each external function is resolved in place, its call +    /// replaced with a call to a function pointer whose value is the  +    /// address of the function in the target process. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// Write an initializer to a memory array of assumed sufficient +    /// size. +    /// +    /// @param[in] data +    ///     A pointer to the data to write to. +    /// +    /// @param[in] initializer +    ///     The initializer itself. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool +    MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); +     +    //------------------------------------------------------------------ +    /// Move an internal variable into the static allocation section. +    /// +    /// @param[in] global_variable +    ///     The variable. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool +    MaterializeInternalVariable (llvm::GlobalVariable *global_variable); +     +    //------------------------------------------------------------------ +    /// Handle a single externally-defined variable +    /// +    /// @param[in] value +    ///     The variable. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    MaybeHandleVariable (llvm::Value *value); +     +    //------------------------------------------------------------------ +    /// Handle a single externally-defined symbol +    /// +    /// @param[in] symbol +    ///     The symbol. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool +    HandleSymbol (llvm::Value *symbol); +     +    //------------------------------------------------------------------ +    /// Handle a single externally-defined Objective-C class +    /// +    /// @param[in] classlist_reference +    ///     The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" +    ///     where n (if present) is an index. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool +    HandleObjCClass(llvm::Value *classlist_reference); + +    //------------------------------------------------------------------ +    /// Handle all the arguments to a function call +    /// +    /// @param[in] C +    ///     The call instruction. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    MaybeHandleCallArguments (llvm::CallInst *call_inst); +     +    //------------------------------------------------------------------ +    /// Resolve variable references in calls to external functions +    /// +    /// @param[in] basic_block +    ///     The basic block currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    ResolveCalls (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// Remove calls to __cxa_atexit, which should never be generated by +    /// expressions. +    /// +    /// @param[in] call_inst +    ///     The call instruction. +    /// +    /// @return +    ///     True if the scan was successful; false if some operation +    ///     failed +    //------------------------------------------------------------------ +    bool +    RemoveCXAAtExit (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] basic_block +    ///     The function currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    ResolveExternals (llvm::Function &llvm_function); +     +    //------------------------------------------------------------------ +    /// A basic block-level pass to excise guard variables from the code. +    /// The result for the function is passed through Clang as a static +    /// variable.  Static variables normally have guard variables to +    /// ensure that they are only initialized once.   +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// Rewrite a load to a guard variable to return constant 0. +    /// +    /// @param[in] guard_load +    ///     The load instruction to zero out. +    //------------------------------------------------------------------ +    void +    TurnGuardLoadIntoZero(llvm::Instruction* guard_load); +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] basic_block +    ///     The basic block currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    RemoveGuards (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// A module-level pass to allocate all string literals in a separate +    /// allocation and redirect references to them. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    ReplaceStrings (); +     +    //------------------------------------------------------------------ +    /// A basic block-level pass to find all literals that will be  +    /// allocated as statics by the JIT (in contrast to the Strings,  +    /// which already are statics) and synthesize loads for them. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] basic_block +    ///     The basic block currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    ReplaceStaticLiterals (llvm::BasicBlock &basic_block); +     +    //------------------------------------------------------------------ +    /// A function-level pass to make all external variable references +    /// point at the correct offsets from the void* passed into the +    /// function.  ClangExpressionDeclMap::DoStructLayout() must be called +    /// beforehand, so that the offsets are valid. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] llvm_function +    ///     The function currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    ReplaceVariables (llvm::Function &llvm_function); +     +    //------------------------------------------------------------------ +    /// A module-level pass to remove all global variables from the +    /// module since it no longer should export or import any symbols. +    //------------------------------------------------------------------ +     +    //------------------------------------------------------------------ +    /// The top-level pass implementation +    /// +    /// @param[in] llvm_module +    ///     The module currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool +    StripAllGVs (llvm::Module &llvm_module); +     +    class StaticDataAllocator { +    public: +        StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); +        lldb_private::StreamString &GetStream() +        { +            return m_stream_string; +        } +        lldb::addr_t Allocate(); + +        lldb::TargetSP +        GetTarget(); +    private: +        lldb_private::IRExecutionUnit  &m_execution_unit; +        lldb_private::StreamString      m_stream_string; +        lldb::addr_t                    m_allocation; +    }; +     +    /// Flags +    bool                                    m_resolve_vars;             ///< True if external variable references and persistent variable references should be resolved +    std::string                             m_func_name;                ///< The name of the function to translate +    lldb_private::ConstString               m_result_name;              ///< The name of the result variable ($0, $1, ...) +    lldb_private::TypeFromParser            m_result_type;              ///< The type of the result variable. +    llvm::Module                           *m_module;                   ///< The module being processed, or NULL if that has not been determined yet. +    std::unique_ptr<llvm::DataLayout>       m_target_data;              ///< The target data for the module being processed, or NULL if there is no module. +    lldb_private::ClangExpressionDeclMap   *m_decl_map;                 ///< The DeclMap containing the Decls  +    StaticDataAllocator                     m_data_allocator;           ///< The allocator to use for constant strings +    llvm::Constant                         *m_CFStringCreateWithBytes;  ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type +    llvm::Constant                         *m_sel_registerName;         ///< The address of the function sel_registerName, cast to the appropriate function pointer type +    llvm::IntegerType                      *m_intptr_ty;                ///< The type of an integer large enough to hold a pointer. +    lldb_private::Stream                   *m_error_stream;             ///< If non-NULL, the stream on which errors should be printed +     +    llvm::StoreInst                        *m_result_store;             ///< If non-NULL, the store instruction that writes to the result variable.  If m_has_side_effects is true, this is NULL. +    bool                                    m_result_is_pointer;        ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) +     +    llvm::GlobalVariable                   *m_reloc_placeholder;        ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. +     +    //------------------------------------------------------------------ +    /// UnfoldConstant operates on a constant [Old] which has just been  +    /// replaced with a value [New].  We assume that new_value has  +    /// been properly placed early in the function, in front of the  +    /// first instruction in the entry basic block  +    /// [FirstEntryInstruction].   +    /// +    /// UnfoldConstant reads through the uses of Old and replaces Old  +    /// in those uses with New.  Where those uses are constants, the  +    /// function generates new instructions to compute the result of the  +    /// new, non-constant expression and places them before  +    /// FirstEntryInstruction.  These instructions replace the constant +    /// uses, so UnfoldConstant calls itself recursively for those. +    /// +    /// @param[in] llvm_function +    ///     The function currently being processed. +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +     +    class FunctionValueCache { +    public: +        typedef std::function <llvm::Value *(llvm::Function *)> Maker; + +        FunctionValueCache (Maker const &maker); +        ~FunctionValueCache (); +        llvm::Value *GetValue (llvm::Function *function); +    private: +        Maker const m_maker; +        typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; +        FunctionValueMap m_values; +    }; +     +    FunctionValueCache m_entry_instruction_finder; +     +    static bool +    UnfoldConstant (llvm::Constant *old_constant,  +                    FunctionValueCache &value_maker, +                    FunctionValueCache &entry_instruction_finder); +     +    //------------------------------------------------------------------ +    /// Construct a reference to m_reloc_placeholder with a given type +    /// and offset.  This typically happens after inserting data into +    /// m_data_allocator. +    /// +    /// @param[in] type +    ///     The type of the value being loaded. +    /// +    /// @param[in] offset +    ///     The offset of the value from the base of m_data_allocator. +    /// +    /// @return +    ///     The Constant for the reference, usually a ConstantExpr. +    //------------------------------------------------------------------ +    llvm::Constant * +    BuildRelocation(llvm::Type *type,  +                    uint64_t offset); +     +    //------------------------------------------------------------------ +    /// Commit the allocation in m_data_allocator and use its final +    /// location to replace m_reloc_placeholder. +    /// +    /// @param[in] module +    ///     The module that m_data_allocator resides in +    /// +    /// @return +    ///     True on success; false otherwise +    //------------------------------------------------------------------ +    bool  +    CompleteDataAllocation (); + +}; + +#endif // liblldb_IRForTarget_h_ diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h new file mode 100644 index 0000000000000..6d51240eab5cc --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoAST.h @@ -0,0 +1,3225 @@ +//===-- GoAST.h -------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// DO NOT EDIT. +// Generated by gen_go_ast.py + +#ifndef liblldb_GoAST_h +#define liblldb_GoAST_h + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "llvm/Support/Casting.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ + +class GoASTNode +{ +  public: +    typedef GoLexer::TokenType TokenType; +    typedef GoLexer::Token Token; +    enum ChanDir +    { +        eChanBidir, +        eChanSend, +        eChanRecv, +    }; +    enum NodeKind +    { +        eBadDecl, +        eFuncDecl, +        eGenDecl, +        eArrayType, +        eBadExpr, +        eBasicLit, +        eBinaryExpr, +        eIdent, +        eCallExpr, +        eChanType, +        eCompositeLit, +        eEllipsis, +        eFuncType, +        eFuncLit, +        eIndexExpr, +        eInterfaceType, +        eKeyValueExpr, +        eMapType, +        eParenExpr, +        eSelectorExpr, +        eSliceExpr, +        eStarExpr, +        eStructType, +        eTypeAssertExpr, +        eUnaryExpr, +        eImportSpec, +        eTypeSpec, +        eValueSpec, +        eAssignStmt, +        eBadStmt, +        eBlockStmt, +        eBranchStmt, +        eCaseClause, +        eCommClause, +        eDeclStmt, +        eDeferStmt, +        eEmptyStmt, +        eExprStmt, +        eForStmt, +        eGoStmt, +        eIfStmt, +        eIncDecStmt, +        eLabeledStmt, +        eRangeStmt, +        eReturnStmt, +        eSelectStmt, +        eSendStmt, +        eSwitchStmt, +        eTypeSwitchStmt, +        eField, +        eFieldList, +    }; + +    virtual ~GoASTNode() = default; + +    NodeKind +    GetKind() const +    { +        return m_kind; +    } + +    virtual const char *GetKindName() const = 0; + +    template <typename V> void WalkChildren(V &v); + +  protected: +    explicit GoASTNode(NodeKind kind) : m_kind(kind) { } + +  private: +    const NodeKind m_kind; +     +    GoASTNode(const GoASTNode &) = delete; +    const GoASTNode &operator=(const GoASTNode &) = delete; +}; + + +class GoASTDecl : public GoASTNode +{ +  public: +    template <typename R, typename V> R Visit(V *v) const; + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl; +    } + +  protected: +    explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) { } +  private: + +    GoASTDecl(const GoASTDecl &) = delete; +    const GoASTDecl &operator=(const GoASTDecl &) = delete; +}; + +class GoASTExpr : public GoASTNode +{ +  public: +    template <typename R, typename V> R Visit(V *v) const; + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr; +    } + +  protected: +    explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) { } +  private: + +    GoASTExpr(const GoASTExpr &) = delete; +    const GoASTExpr &operator=(const GoASTExpr &) = delete; +}; + +class GoASTSpec : public GoASTNode +{ +  public: +    template <typename R, typename V> R Visit(V *v) const; + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec; +    } + +  protected: +    explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) { } +  private: + +    GoASTSpec(const GoASTSpec &) = delete; +    const GoASTSpec &operator=(const GoASTSpec &) = delete; +}; + +class GoASTStmt : public GoASTNode +{ +  public: +    template <typename R, typename V> R Visit(V *v) const; + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt; +    } + +  protected: +    explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) { } +  private: + +    GoASTStmt(const GoASTStmt &) = delete; +    const GoASTStmt &operator=(const GoASTStmt &) = delete; +}; + + +class GoASTArrayType : public GoASTExpr +{ +  public: +    GoASTArrayType(GoASTExpr *len, GoASTExpr *elt) : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {} +    ~GoASTArrayType() override = default; + +    const char * +    GetKindName() const override +    { +        return "ArrayType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eArrayType; +    } +     +    const GoASTExpr * +    GetLen() const +    { +        return m_len_up.get(); +    } +    void +    SetLen(GoASTExpr *len) +    { +        m_len_up.reset(len); +    } + +    const GoASTExpr * +    GetElt() const +    { +        return m_elt_up.get(); +    } +    void +    SetElt(GoASTExpr *elt) +    { +        m_elt_up.reset(elt); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_len_up; +    std::unique_ptr<GoASTExpr> m_elt_up; + +    GoASTArrayType(const GoASTArrayType &) = delete; +    const GoASTArrayType &operator=(const GoASTArrayType &) = delete; +}; + +class GoASTAssignStmt : public GoASTStmt +{ +  public: +    explicit GoASTAssignStmt(bool define) : GoASTStmt(eAssignStmt), m_define(define) {} +    ~GoASTAssignStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "AssignStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eAssignStmt; +    } +     +    size_t +    NumLhs() const +    { +        return m_lhs.size(); +    } +    const GoASTExpr * +    GetLhs(int i) const +    { +        return m_lhs[i].get(); +    } +    void +    AddLhs(GoASTExpr *lhs) +    { +        m_lhs.push_back(std::unique_ptr<GoASTExpr>(lhs)); +    } + +    size_t +    NumRhs() const +    { +        return m_rhs.size(); +    } +    const GoASTExpr * +    GetRhs(int i) const +    { +        return m_rhs[i].get(); +    } +    void +    AddRhs(GoASTExpr *rhs) +    { +        m_rhs.push_back(std::unique_ptr<GoASTExpr>(rhs)); +    } + +    bool  +    GetDefine() const +    { +        return m_define; +    } +    void +    SetDefine(bool define) +    { +        m_define = define; +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTExpr> > m_lhs; +    std::vector<std::unique_ptr<GoASTExpr> > m_rhs; +    bool m_define; + +    GoASTAssignStmt(const GoASTAssignStmt &) = delete; +    const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete; +}; + +class GoASTBadDecl : public GoASTDecl +{ +  public: +    GoASTBadDecl() : GoASTDecl(eBadDecl) {} +    ~GoASTBadDecl() override = default; + +    const char * +    GetKindName() const override +    { +        return "BadDecl"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBadDecl; +    } +     +    GoASTBadDecl(const GoASTBadDecl &) = delete; +    const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete; +}; + +class GoASTBadExpr : public GoASTExpr +{ +  public: +    GoASTBadExpr() : GoASTExpr(eBadExpr) {} +    ~GoASTBadExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "BadExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBadExpr; +    } +     +    GoASTBadExpr(const GoASTBadExpr &) = delete; +    const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete; +}; + +class GoASTBadStmt : public GoASTStmt +{ +  public: +    GoASTBadStmt() : GoASTStmt(eBadStmt) {} +    ~GoASTBadStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "BadStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBadStmt; +    } +     +    GoASTBadStmt(const GoASTBadStmt &) = delete; +    const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete; +}; + +class GoASTBasicLit : public GoASTExpr +{ +  public: +    explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {} +    ~GoASTBasicLit() override = default; + +    const char * +    GetKindName() const override +    { +        return "BasicLit"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBasicLit; +    } +     +    Token  +    GetValue() const +    { +        return m_value; +    } +    void +    SetValue(Token value) +    { +        m_value = value; +    } + +  private: +    friend class GoASTNode; +    Token m_value; + +    GoASTBasicLit(const GoASTBasicLit &) = delete; +    const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete; +}; + +class GoASTBinaryExpr : public GoASTExpr +{ +  public: +    GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op) : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {} +    ~GoASTBinaryExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "BinaryExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBinaryExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTExpr * +    GetY() const +    { +        return m_y_up.get(); +    } +    void +    SetY(GoASTExpr *y) +    { +        m_y_up.reset(y); +    } + +    TokenType  +    GetOp() const +    { +        return m_op; +    } +    void +    SetOp(TokenType op) +    { +        m_op = op; +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTExpr> m_y_up; +    TokenType m_op; + +    GoASTBinaryExpr(const GoASTBinaryExpr &) = delete; +    const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete; +}; + +class GoASTBlockStmt : public GoASTStmt +{ +  public: +    GoASTBlockStmt() : GoASTStmt(eBlockStmt) {} +    ~GoASTBlockStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "BlockStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBlockStmt; +    } +     +    size_t +    NumList() const +    { +        return m_list.size(); +    } +    const GoASTStmt * +    GetList(int i) const +    { +        return m_list[i].get(); +    } +    void +    AddList(GoASTStmt *list) +    { +        m_list.push_back(std::unique_ptr<GoASTStmt>(list)); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTStmt> > m_list; + +    GoASTBlockStmt(const GoASTBlockStmt &) = delete; +    const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete; +}; + +class GoASTIdent : public GoASTExpr +{ +  public: +    explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {} +    ~GoASTIdent() override = default; + +    const char * +    GetKindName() const override +    { +        return "Ident"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eIdent; +    } +     +    Token  +    GetName() const +    { +        return m_name; +    } +    void +    SetName(Token name) +    { +        m_name = name; +    } + +  private: +    friend class GoASTNode; +    Token m_name; + +    GoASTIdent(const GoASTIdent &) = delete; +    const GoASTIdent &operator=(const GoASTIdent &) = delete; +}; + +class GoASTBranchStmt : public GoASTStmt +{ +  public: +    GoASTBranchStmt(GoASTIdent *label, TokenType tok) : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {} +    ~GoASTBranchStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "BranchStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eBranchStmt; +    } +     +    const GoASTIdent * +    GetLabel() const +    { +        return m_label_up.get(); +    } +    void +    SetLabel(GoASTIdent *label) +    { +        m_label_up.reset(label); +    } + +    TokenType  +    GetTok() const +    { +        return m_tok; +    } +    void +    SetTok(TokenType tok) +    { +        m_tok = tok; +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTIdent> m_label_up; +    TokenType m_tok; + +    GoASTBranchStmt(const GoASTBranchStmt &) = delete; +    const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete; +}; + +class GoASTCallExpr : public GoASTExpr +{ +  public: +    explicit GoASTCallExpr(bool ellipsis) : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {} +    ~GoASTCallExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "CallExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eCallExpr; +    } +     +    const GoASTExpr * +    GetFun() const +    { +        return m_fun_up.get(); +    } +    void +    SetFun(GoASTExpr *fun) +    { +        m_fun_up.reset(fun); +    } + +    size_t +    NumArgs() const +    { +        return m_args.size(); +    } +    const GoASTExpr * +    GetArgs(int i) const +    { +        return m_args[i].get(); +    } +    void +    AddArgs(GoASTExpr *args) +    { +        m_args.push_back(std::unique_ptr<GoASTExpr>(args)); +    } + +    bool  +    GetEllipsis() const +    { +        return m_ellipsis; +    } +    void +    SetEllipsis(bool ellipsis) +    { +        m_ellipsis = ellipsis; +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_fun_up; +    std::vector<std::unique_ptr<GoASTExpr> > m_args; +    bool m_ellipsis; + +    GoASTCallExpr(const GoASTCallExpr &) = delete; +    const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete; +}; + +class GoASTCaseClause : public GoASTStmt +{ +  public: +    GoASTCaseClause() : GoASTStmt(eCaseClause) {} +    ~GoASTCaseClause() override = default; + +    const char * +    GetKindName() const override +    { +        return "CaseClause"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eCaseClause; +    } +     +    size_t +    NumList() const +    { +        return m_list.size(); +    } +    const GoASTExpr * +    GetList(int i) const +    { +        return m_list[i].get(); +    } +    void +    AddList(GoASTExpr *list) +    { +        m_list.push_back(std::unique_ptr<GoASTExpr>(list)); +    } + +    size_t +    NumBody() const +    { +        return m_body.size(); +    } +    const GoASTStmt * +    GetBody(int i) const +    { +        return m_body[i].get(); +    } +    void +    AddBody(GoASTStmt *body) +    { +        m_body.push_back(std::unique_ptr<GoASTStmt>(body)); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTExpr> > m_list; +    std::vector<std::unique_ptr<GoASTStmt> > m_body; + +    GoASTCaseClause(const GoASTCaseClause &) = delete; +    const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete; +}; + +class GoASTChanType : public GoASTExpr +{ +  public: +    GoASTChanType(ChanDir dir, GoASTExpr *value) : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {} +    ~GoASTChanType() override = default; + +    const char * +    GetKindName() const override +    { +        return "ChanType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eChanType; +    } +     +    ChanDir  +    GetDir() const +    { +        return m_dir; +    } +    void +    SetDir(ChanDir dir) +    { +        m_dir = dir; +    } + +    const GoASTExpr * +    GetValue() const +    { +        return m_value_up.get(); +    } +    void +    SetValue(GoASTExpr *value) +    { +        m_value_up.reset(value); +    } + +  private: +    friend class GoASTNode; +    ChanDir m_dir; +    std::unique_ptr<GoASTExpr> m_value_up; + +    GoASTChanType(const GoASTChanType &) = delete; +    const GoASTChanType &operator=(const GoASTChanType &) = delete; +}; + +class GoASTCommClause : public GoASTStmt +{ +  public: +    GoASTCommClause() : GoASTStmt(eCommClause) {} +    ~GoASTCommClause() override = default; + +    const char * +    GetKindName() const override +    { +        return "CommClause"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eCommClause; +    } +     +    const GoASTStmt * +    GetComm() const +    { +        return m_comm_up.get(); +    } +    void +    SetComm(GoASTStmt *comm) +    { +        m_comm_up.reset(comm); +    } + +    size_t +    NumBody() const +    { +        return m_body.size(); +    } +    const GoASTStmt * +    GetBody(int i) const +    { +        return m_body[i].get(); +    } +    void +    AddBody(GoASTStmt *body) +    { +        m_body.push_back(std::unique_ptr<GoASTStmt>(body)); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTStmt> m_comm_up; +    std::vector<std::unique_ptr<GoASTStmt> > m_body; + +    GoASTCommClause(const GoASTCommClause &) = delete; +    const GoASTCommClause &operator=(const GoASTCommClause &) = delete; +}; + +class GoASTCompositeLit : public GoASTExpr +{ +  public: +    GoASTCompositeLit() : GoASTExpr(eCompositeLit) {} +    ~GoASTCompositeLit() override = default; + +    const char * +    GetKindName() const override +    { +        return "CompositeLit"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eCompositeLit; +    } +     +    const GoASTExpr * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTExpr *type) +    { +        m_type_up.reset(type); +    } + +    size_t +    NumElts() const +    { +        return m_elts.size(); +    } +    const GoASTExpr * +    GetElts(int i) const +    { +        return m_elts[i].get(); +    } +    void +    AddElts(GoASTExpr *elts) +    { +        m_elts.push_back(std::unique_ptr<GoASTExpr>(elts)); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_type_up; +    std::vector<std::unique_ptr<GoASTExpr> > m_elts; + +    GoASTCompositeLit(const GoASTCompositeLit &) = delete; +    const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete; +}; + +class GoASTDeclStmt : public GoASTStmt +{ +  public: +    explicit GoASTDeclStmt(GoASTDecl *decl) : GoASTStmt(eDeclStmt), m_decl_up(decl) {} +    ~GoASTDeclStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "DeclStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eDeclStmt; +    } +     +    const GoASTDecl * +    GetDecl() const +    { +        return m_decl_up.get(); +    } +    void +    SetDecl(GoASTDecl *decl) +    { +        m_decl_up.reset(decl); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTDecl> m_decl_up; + +    GoASTDeclStmt(const GoASTDeclStmt &) = delete; +    const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete; +}; + +class GoASTDeferStmt : public GoASTStmt +{ +  public: +    explicit GoASTDeferStmt(GoASTCallExpr *call) : GoASTStmt(eDeferStmt), m_call_up(call) {} +    ~GoASTDeferStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "DeferStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eDeferStmt; +    } +     +    const GoASTCallExpr * +    GetCall() const +    { +        return m_call_up.get(); +    } +    void +    SetCall(GoASTCallExpr *call) +    { +        m_call_up.reset(call); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTCallExpr> m_call_up; + +    GoASTDeferStmt(const GoASTDeferStmt &) = delete; +    const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete; +}; + +class GoASTEllipsis : public GoASTExpr +{ +  public: +    explicit GoASTEllipsis(GoASTExpr *elt) : GoASTExpr(eEllipsis), m_elt_up(elt) {} +    ~GoASTEllipsis() override = default; + +    const char * +    GetKindName() const override +    { +        return "Ellipsis"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eEllipsis; +    } +     +    const GoASTExpr * +    GetElt() const +    { +        return m_elt_up.get(); +    } +    void +    SetElt(GoASTExpr *elt) +    { +        m_elt_up.reset(elt); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_elt_up; + +    GoASTEllipsis(const GoASTEllipsis &) = delete; +    const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete; +}; + +class GoASTEmptyStmt : public GoASTStmt +{ +  public: +    GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {} +    ~GoASTEmptyStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "EmptyStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eEmptyStmt; +    } +     +    GoASTEmptyStmt(const GoASTEmptyStmt &) = delete; +    const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete; +}; + +class GoASTExprStmt : public GoASTStmt +{ +  public: +    explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {} +    ~GoASTExprStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "ExprStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eExprStmt; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; + +    GoASTExprStmt(const GoASTExprStmt &) = delete; +    const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete; +}; + +class GoASTField : public GoASTNode +{ +  public: +    GoASTField() : GoASTNode(eField) {} +    ~GoASTField() override = default; + +    const char * +    GetKindName() const override +    { +        return "Field"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eField; +    } +     +    size_t +    NumNames() const +    { +        return m_names.size(); +    } +    const GoASTIdent * +    GetNames(int i) const +    { +        return m_names[i].get(); +    } +    void +    AddNames(GoASTIdent *names) +    { +        m_names.push_back(std::unique_ptr<GoASTIdent>(names)); +    } + +    const GoASTExpr * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTExpr *type) +    { +        m_type_up.reset(type); +    } + +    const GoASTBasicLit * +    GetTag() const +    { +        return m_tag_up.get(); +    } +    void +    SetTag(GoASTBasicLit *tag) +    { +        m_tag_up.reset(tag); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTIdent> > m_names; +    std::unique_ptr<GoASTExpr> m_type_up; +    std::unique_ptr<GoASTBasicLit> m_tag_up; + +    GoASTField(const GoASTField &) = delete; +    const GoASTField &operator=(const GoASTField &) = delete; +}; + +class GoASTFieldList : public GoASTNode +{ +  public: +    GoASTFieldList() : GoASTNode(eFieldList) {} +    ~GoASTFieldList() override = default; + +    const char * +    GetKindName() const override +    { +        return "FieldList"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eFieldList; +    } +     +    size_t +    NumList() const +    { +        return m_list.size(); +    } +    const GoASTField * +    GetList(int i) const +    { +        return m_list[i].get(); +    } +    void +    AddList(GoASTField *list) +    { +        m_list.push_back(std::unique_ptr<GoASTField>(list)); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTField> > m_list; + +    GoASTFieldList(const GoASTFieldList &) = delete; +    const GoASTFieldList &operator=(const GoASTFieldList &) = delete; +}; + +class GoASTForStmt : public GoASTStmt +{ +  public: +    GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post, GoASTBlockStmt *body) : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post), m_body_up(body) {} +    ~GoASTForStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "ForStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eForStmt; +    } +     +    const GoASTStmt * +    GetInit() const +    { +        return m_init_up.get(); +    } +    void +    SetInit(GoASTStmt *init) +    { +        m_init_up.reset(init); +    } + +    const GoASTExpr * +    GetCond() const +    { +        return m_cond_up.get(); +    } +    void +    SetCond(GoASTExpr *cond) +    { +        m_cond_up.reset(cond); +    } + +    const GoASTStmt * +    GetPost() const +    { +        return m_post_up.get(); +    } +    void +    SetPost(GoASTStmt *post) +    { +        m_post_up.reset(post); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTStmt> m_init_up; +    std::unique_ptr<GoASTExpr> m_cond_up; +    std::unique_ptr<GoASTStmt> m_post_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTForStmt(const GoASTForStmt &) = delete; +    const GoASTForStmt &operator=(const GoASTForStmt &) = delete; +}; + +class GoASTFuncType : public GoASTExpr +{ +  public: +    GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results) : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {} +    ~GoASTFuncType() override = default; + +    const char * +    GetKindName() const override +    { +        return "FuncType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eFuncType; +    } +     +    const GoASTFieldList * +    GetParams() const +    { +        return m_params_up.get(); +    } +    void +    SetParams(GoASTFieldList *params) +    { +        m_params_up.reset(params); +    } + +    const GoASTFieldList * +    GetResults() const +    { +        return m_results_up.get(); +    } +    void +    SetResults(GoASTFieldList *results) +    { +        m_results_up.reset(results); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTFieldList> m_params_up; +    std::unique_ptr<GoASTFieldList> m_results_up; + +    GoASTFuncType(const GoASTFuncType &) = delete; +    const GoASTFuncType &operator=(const GoASTFuncType &) = delete; +}; + +class GoASTFuncDecl : public GoASTDecl +{ +  public: +    GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type, GoASTBlockStmt *body) : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type), m_body_up(body) {} +    ~GoASTFuncDecl() override = default; + +    const char * +    GetKindName() const override +    { +        return "FuncDecl"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eFuncDecl; +    } +     +    const GoASTFieldList * +    GetRecv() const +    { +        return m_recv_up.get(); +    } +    void +    SetRecv(GoASTFieldList *recv) +    { +        m_recv_up.reset(recv); +    } + +    const GoASTIdent * +    GetName() const +    { +        return m_name_up.get(); +    } +    void +    SetName(GoASTIdent *name) +    { +        m_name_up.reset(name); +    } + +    const GoASTFuncType * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTFuncType *type) +    { +        m_type_up.reset(type); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTFieldList> m_recv_up; +    std::unique_ptr<GoASTIdent> m_name_up; +    std::unique_ptr<GoASTFuncType> m_type_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTFuncDecl(const GoASTFuncDecl &) = delete; +    const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete; +}; + +class GoASTFuncLit : public GoASTExpr +{ +  public: +    GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body) : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {} +    ~GoASTFuncLit() override = default; + +    const char * +    GetKindName() const override +    { +        return "FuncLit"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eFuncLit; +    } +     +    const GoASTFuncType * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTFuncType *type) +    { +        m_type_up.reset(type); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTFuncType> m_type_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTFuncLit(const GoASTFuncLit &) = delete; +    const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete; +}; + +class GoASTGenDecl : public GoASTDecl +{ +  public: +    explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {} +    ~GoASTGenDecl() override = default; + +    const char * +    GetKindName() const override +    { +        return "GenDecl"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eGenDecl; +    } +     +    TokenType  +    GetTok() const +    { +        return m_tok; +    } +    void +    SetTok(TokenType tok) +    { +        m_tok = tok; +    } + +    size_t +    NumSpecs() const +    { +        return m_specs.size(); +    } +    const GoASTSpec * +    GetSpecs(int i) const +    { +        return m_specs[i].get(); +    } +    void +    AddSpecs(GoASTSpec *specs) +    { +        m_specs.push_back(std::unique_ptr<GoASTSpec>(specs)); +    } + +  private: +    friend class GoASTNode; +    TokenType m_tok; +    std::vector<std::unique_ptr<GoASTSpec> > m_specs; + +    GoASTGenDecl(const GoASTGenDecl &) = delete; +    const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete; +}; + +class GoASTGoStmt : public GoASTStmt +{ +  public: +    explicit GoASTGoStmt(GoASTCallExpr *call) : GoASTStmt(eGoStmt), m_call_up(call) {} +    ~GoASTGoStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "GoStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eGoStmt; +    } +     +    const GoASTCallExpr * +    GetCall() const +    { +        return m_call_up.get(); +    } +    void +    SetCall(GoASTCallExpr *call) +    { +        m_call_up.reset(call); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTCallExpr> m_call_up; + +    GoASTGoStmt(const GoASTGoStmt &) = delete; +    const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete; +}; + +class GoASTIfStmt : public GoASTStmt +{ +  public: +    GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body, GoASTStmt *els) : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body), m_els_up(els) {} +    ~GoASTIfStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "IfStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eIfStmt; +    } +     +    const GoASTStmt * +    GetInit() const +    { +        return m_init_up.get(); +    } +    void +    SetInit(GoASTStmt *init) +    { +        m_init_up.reset(init); +    } + +    const GoASTExpr * +    GetCond() const +    { +        return m_cond_up.get(); +    } +    void +    SetCond(GoASTExpr *cond) +    { +        m_cond_up.reset(cond); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +    const GoASTStmt * +    GetEls() const +    { +        return m_els_up.get(); +    } +    void +    SetEls(GoASTStmt *els) +    { +        m_els_up.reset(els); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTStmt> m_init_up; +    std::unique_ptr<GoASTExpr> m_cond_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; +    std::unique_ptr<GoASTStmt> m_els_up; + +    GoASTIfStmt(const GoASTIfStmt &) = delete; +    const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete; +}; + +class GoASTImportSpec : public GoASTSpec +{ +  public: +    GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path) : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {} +    ~GoASTImportSpec() override = default; + +    const char * +    GetKindName() const override +    { +        return "ImportSpec"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eImportSpec; +    } +     +    const GoASTIdent * +    GetName() const +    { +        return m_name_up.get(); +    } +    void +    SetName(GoASTIdent *name) +    { +        m_name_up.reset(name); +    } + +    const GoASTBasicLit * +    GetPath() const +    { +        return m_path_up.get(); +    } +    void +    SetPath(GoASTBasicLit *path) +    { +        m_path_up.reset(path); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTIdent> m_name_up; +    std::unique_ptr<GoASTBasicLit> m_path_up; + +    GoASTImportSpec(const GoASTImportSpec &) = delete; +    const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete; +}; + +class GoASTIncDecStmt : public GoASTStmt +{ +  public: +    GoASTIncDecStmt(GoASTExpr *x, TokenType tok) : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {} +    ~GoASTIncDecStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "IncDecStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eIncDecStmt; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    TokenType  +    GetTok() const +    { +        return m_tok; +    } +    void +    SetTok(TokenType tok) +    { +        m_tok = tok; +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    TokenType m_tok; + +    GoASTIncDecStmt(const GoASTIncDecStmt &) = delete; +    const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete; +}; + +class GoASTIndexExpr : public GoASTExpr +{ +  public: +    GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index) : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {} +    ~GoASTIndexExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "IndexExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eIndexExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTExpr * +    GetIndex() const +    { +        return m_index_up.get(); +    } +    void +    SetIndex(GoASTExpr *index) +    { +        m_index_up.reset(index); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTExpr> m_index_up; + +    GoASTIndexExpr(const GoASTIndexExpr &) = delete; +    const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete; +}; + +class GoASTInterfaceType : public GoASTExpr +{ +  public: +    explicit GoASTInterfaceType(GoASTFieldList *methods) : GoASTExpr(eInterfaceType), m_methods_up(methods) {} +    ~GoASTInterfaceType() override = default; + +    const char * +    GetKindName() const override +    { +        return "InterfaceType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eInterfaceType; +    } +     +    const GoASTFieldList * +    GetMethods() const +    { +        return m_methods_up.get(); +    } +    void +    SetMethods(GoASTFieldList *methods) +    { +        m_methods_up.reset(methods); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTFieldList> m_methods_up; + +    GoASTInterfaceType(const GoASTInterfaceType &) = delete; +    const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete; +}; + +class GoASTKeyValueExpr : public GoASTExpr +{ +  public: +    GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {} +    ~GoASTKeyValueExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "KeyValueExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eKeyValueExpr; +    } +     +    const GoASTExpr * +    GetKey() const +    { +        return m_key_up.get(); +    } +    void +    SetKey(GoASTExpr *key) +    { +        m_key_up.reset(key); +    } + +    const GoASTExpr * +    GetValue() const +    { +        return m_value_up.get(); +    } +    void +    SetValue(GoASTExpr *value) +    { +        m_value_up.reset(value); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_key_up; +    std::unique_ptr<GoASTExpr> m_value_up; + +    GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete; +    const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete; +}; + +class GoASTLabeledStmt : public GoASTStmt +{ +  public: +    GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt) : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {} +    ~GoASTLabeledStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "LabeledStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eLabeledStmt; +    } +     +    const GoASTIdent * +    GetLabel() const +    { +        return m_label_up.get(); +    } +    void +    SetLabel(GoASTIdent *label) +    { +        m_label_up.reset(label); +    } + +    const GoASTStmt * +    GetStmt() const +    { +        return m_stmt_up.get(); +    } +    void +    SetStmt(GoASTStmt *stmt) +    { +        m_stmt_up.reset(stmt); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTIdent> m_label_up; +    std::unique_ptr<GoASTStmt> m_stmt_up; + +    GoASTLabeledStmt(const GoASTLabeledStmt &) = delete; +    const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete; +}; + +class GoASTMapType : public GoASTExpr +{ +  public: +    GoASTMapType(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {} +    ~GoASTMapType() override = default; + +    const char * +    GetKindName() const override +    { +        return "MapType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eMapType; +    } +     +    const GoASTExpr * +    GetKey() const +    { +        return m_key_up.get(); +    } +    void +    SetKey(GoASTExpr *key) +    { +        m_key_up.reset(key); +    } + +    const GoASTExpr * +    GetValue() const +    { +        return m_value_up.get(); +    } +    void +    SetValue(GoASTExpr *value) +    { +        m_value_up.reset(value); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_key_up; +    std::unique_ptr<GoASTExpr> m_value_up; + +    GoASTMapType(const GoASTMapType &) = delete; +    const GoASTMapType &operator=(const GoASTMapType &) = delete; +}; + +class GoASTParenExpr : public GoASTExpr +{ +  public: +    explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {} +    ~GoASTParenExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "ParenExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eParenExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; + +    GoASTParenExpr(const GoASTParenExpr &) = delete; +    const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete; +}; + +class GoASTRangeStmt : public GoASTStmt +{ +  public: +    GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x, GoASTBlockStmt *body) : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value), m_define(define), m_x_up(x), m_body_up(body) {} +    ~GoASTRangeStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "RangeStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eRangeStmt; +    } +     +    const GoASTExpr * +    GetKey() const +    { +        return m_key_up.get(); +    } +    void +    SetKey(GoASTExpr *key) +    { +        m_key_up.reset(key); +    } + +    const GoASTExpr * +    GetValue() const +    { +        return m_value_up.get(); +    } +    void +    SetValue(GoASTExpr *value) +    { +        m_value_up.reset(value); +    } + +    bool  +    GetDefine() const +    { +        return m_define; +    } +    void +    SetDefine(bool define) +    { +        m_define = define; +    } + +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_key_up; +    std::unique_ptr<GoASTExpr> m_value_up; +    bool m_define; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTRangeStmt(const GoASTRangeStmt &) = delete; +    const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete; +}; + +class GoASTReturnStmt : public GoASTStmt +{ +  public: +    GoASTReturnStmt() : GoASTStmt(eReturnStmt) {} +    ~GoASTReturnStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "ReturnStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eReturnStmt; +    } +     +    size_t +    NumResults() const +    { +        return m_results.size(); +    } +    const GoASTExpr * +    GetResults(int i) const +    { +        return m_results[i].get(); +    } +    void +    AddResults(GoASTExpr *results) +    { +        m_results.push_back(std::unique_ptr<GoASTExpr>(results)); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTExpr> > m_results; + +    GoASTReturnStmt(const GoASTReturnStmt &) = delete; +    const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete; +}; + +class GoASTSelectStmt : public GoASTStmt +{ +  public: +    explicit GoASTSelectStmt(GoASTBlockStmt *body) : GoASTStmt(eSelectStmt), m_body_up(body) {} +    ~GoASTSelectStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "SelectStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eSelectStmt; +    } +     +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTSelectStmt(const GoASTSelectStmt &) = delete; +    const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete; +}; + +class GoASTSelectorExpr : public GoASTExpr +{ +  public: +    GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel) : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {} +    ~GoASTSelectorExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "SelectorExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eSelectorExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTIdent * +    GetSel() const +    { +        return m_sel_up.get(); +    } +    void +    SetSel(GoASTIdent *sel) +    { +        m_sel_up.reset(sel); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTIdent> m_sel_up; + +    GoASTSelectorExpr(const GoASTSelectorExpr &) = delete; +    const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete; +}; + +class GoASTSendStmt : public GoASTStmt +{ +  public: +    GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value) : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {} +    ~GoASTSendStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "SendStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eSendStmt; +    } +     +    const GoASTExpr * +    GetChan() const +    { +        return m_chan_up.get(); +    } +    void +    SetChan(GoASTExpr *chan) +    { +        m_chan_up.reset(chan); +    } + +    const GoASTExpr * +    GetValue() const +    { +        return m_value_up.get(); +    } +    void +    SetValue(GoASTExpr *value) +    { +        m_value_up.reset(value); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_chan_up; +    std::unique_ptr<GoASTExpr> m_value_up; + +    GoASTSendStmt(const GoASTSendStmt &) = delete; +    const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete; +}; + +class GoASTSliceExpr : public GoASTExpr +{ +  public: +    GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max, bool slice3) : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high), m_max_up(max), m_slice3(slice3) {} +    ~GoASTSliceExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "SliceExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eSliceExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTExpr * +    GetLow() const +    { +        return m_low_up.get(); +    } +    void +    SetLow(GoASTExpr *low) +    { +        m_low_up.reset(low); +    } + +    const GoASTExpr * +    GetHigh() const +    { +        return m_high_up.get(); +    } +    void +    SetHigh(GoASTExpr *high) +    { +        m_high_up.reset(high); +    } + +    const GoASTExpr * +    GetMax() const +    { +        return m_max_up.get(); +    } +    void +    SetMax(GoASTExpr *max) +    { +        m_max_up.reset(max); +    } + +    bool  +    GetSlice3() const +    { +        return m_slice3; +    } +    void +    SetSlice3(bool slice3) +    { +        m_slice3 = slice3; +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTExpr> m_low_up; +    std::unique_ptr<GoASTExpr> m_high_up; +    std::unique_ptr<GoASTExpr> m_max_up; +    bool m_slice3; + +    GoASTSliceExpr(const GoASTSliceExpr &) = delete; +    const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete; +}; + +class GoASTStarExpr : public GoASTExpr +{ +  public: +    explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {} +    ~GoASTStarExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "StarExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eStarExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; + +    GoASTStarExpr(const GoASTStarExpr &) = delete; +    const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete; +}; + +class GoASTStructType : public GoASTExpr +{ +  public: +    explicit GoASTStructType(GoASTFieldList *fields) : GoASTExpr(eStructType), m_fields_up(fields) {} +    ~GoASTStructType() override = default; + +    const char * +    GetKindName() const override +    { +        return "StructType"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eStructType; +    } +     +    const GoASTFieldList * +    GetFields() const +    { +        return m_fields_up.get(); +    } +    void +    SetFields(GoASTFieldList *fields) +    { +        m_fields_up.reset(fields); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTFieldList> m_fields_up; + +    GoASTStructType(const GoASTStructType &) = delete; +    const GoASTStructType &operator=(const GoASTStructType &) = delete; +}; + +class GoASTSwitchStmt : public GoASTStmt +{ +  public: +    GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body) : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag), m_body_up(body) {} +    ~GoASTSwitchStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "SwitchStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eSwitchStmt; +    } +     +    const GoASTStmt * +    GetInit() const +    { +        return m_init_up.get(); +    } +    void +    SetInit(GoASTStmt *init) +    { +        m_init_up.reset(init); +    } + +    const GoASTExpr * +    GetTag() const +    { +        return m_tag_up.get(); +    } +    void +    SetTag(GoASTExpr *tag) +    { +        m_tag_up.reset(tag); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTStmt> m_init_up; +    std::unique_ptr<GoASTExpr> m_tag_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTSwitchStmt(const GoASTSwitchStmt &) = delete; +    const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete; +}; + +class GoASTTypeAssertExpr : public GoASTExpr +{ +  public: +    GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type) : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {} +    ~GoASTTypeAssertExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "TypeAssertExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eTypeAssertExpr; +    } +     +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +    const GoASTExpr * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTExpr *type) +    { +        m_type_up.reset(type); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTExpr> m_x_up; +    std::unique_ptr<GoASTExpr> m_type_up; + +    GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete; +    const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete; +}; + +class GoASTTypeSpec : public GoASTSpec +{ +  public: +    GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type) : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {} +    ~GoASTTypeSpec() override = default; + +    const char * +    GetKindName() const override +    { +        return "TypeSpec"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eTypeSpec; +    } +     +    const GoASTIdent * +    GetName() const +    { +        return m_name_up.get(); +    } +    void +    SetName(GoASTIdent *name) +    { +        m_name_up.reset(name); +    } + +    const GoASTExpr * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTExpr *type) +    { +        m_type_up.reset(type); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTIdent> m_name_up; +    std::unique_ptr<GoASTExpr> m_type_up; + +    GoASTTypeSpec(const GoASTTypeSpec &) = delete; +    const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete; +}; + +class GoASTTypeSwitchStmt : public GoASTStmt +{ +  public: +    GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body) : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign), m_body_up(body) {} +    ~GoASTTypeSwitchStmt() override = default; + +    const char * +    GetKindName() const override +    { +        return "TypeSwitchStmt"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eTypeSwitchStmt; +    } +     +    const GoASTStmt * +    GetInit() const +    { +        return m_init_up.get(); +    } +    void +    SetInit(GoASTStmt *init) +    { +        m_init_up.reset(init); +    } + +    const GoASTStmt * +    GetAssign() const +    { +        return m_assign_up.get(); +    } +    void +    SetAssign(GoASTStmt *assign) +    { +        m_assign_up.reset(assign); +    } + +    const GoASTBlockStmt * +    GetBody() const +    { +        return m_body_up.get(); +    } +    void +    SetBody(GoASTBlockStmt *body) +    { +        m_body_up.reset(body); +    } + +  private: +    friend class GoASTNode; +    std::unique_ptr<GoASTStmt> m_init_up; +    std::unique_ptr<GoASTStmt> m_assign_up; +    std::unique_ptr<GoASTBlockStmt> m_body_up; + +    GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete; +    const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete; +}; + +class GoASTUnaryExpr : public GoASTExpr +{ +  public: +    GoASTUnaryExpr(TokenType op, GoASTExpr *x) : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {} +    ~GoASTUnaryExpr() override = default; + +    const char * +    GetKindName() const override +    { +        return "UnaryExpr"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eUnaryExpr; +    } +     +    TokenType  +    GetOp() const +    { +        return m_op; +    } +    void +    SetOp(TokenType op) +    { +        m_op = op; +    } + +    const GoASTExpr * +    GetX() const +    { +        return m_x_up.get(); +    } +    void +    SetX(GoASTExpr *x) +    { +        m_x_up.reset(x); +    } + +  private: +    friend class GoASTNode; +    TokenType m_op; +    std::unique_ptr<GoASTExpr> m_x_up; + +    GoASTUnaryExpr(const GoASTUnaryExpr &) = delete; +    const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete; +}; + +class GoASTValueSpec : public GoASTSpec +{ +  public: +    GoASTValueSpec() : GoASTSpec(eValueSpec) {} +    ~GoASTValueSpec() override = default; + +    const char * +    GetKindName() const override +    { +        return "ValueSpec"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == eValueSpec; +    } +     +    size_t +    NumNames() const +    { +        return m_names.size(); +    } +    const GoASTIdent * +    GetNames(int i) const +    { +        return m_names[i].get(); +    } +    void +    AddNames(GoASTIdent *names) +    { +        m_names.push_back(std::unique_ptr<GoASTIdent>(names)); +    } + +    const GoASTExpr * +    GetType() const +    { +        return m_type_up.get(); +    } +    void +    SetType(GoASTExpr *type) +    { +        m_type_up.reset(type); +    } + +    size_t +    NumValues() const +    { +        return m_values.size(); +    } +    const GoASTExpr * +    GetValues(int i) const +    { +        return m_values[i].get(); +    } +    void +    AddValues(GoASTExpr *values) +    { +        m_values.push_back(std::unique_ptr<GoASTExpr>(values)); +    } + +  private: +    friend class GoASTNode; +    std::vector<std::unique_ptr<GoASTIdent> > m_names; +    std::unique_ptr<GoASTExpr> m_type_up; +    std::vector<std::unique_ptr<GoASTExpr> > m_values; + +    GoASTValueSpec(const GoASTValueSpec &) = delete; +    const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete; +}; + + +template <typename R, typename V> +R GoASTDecl::Visit(V* v) const +{ +    switch(GetKind()) +    { +    case eBadDecl: +        return v->VisitBadDecl(llvm::cast<const GoASTBadDecl>(this)); +    case eFuncDecl: +        return v->VisitFuncDecl(llvm::cast<const GoASTFuncDecl>(this)); +    case eGenDecl: +        return v->VisitGenDecl(llvm::cast<const GoASTGenDecl>(this)); +    default: +        assert(false && "Invalid kind"); +    } +} + +template <typename R, typename V> +R GoASTExpr::Visit(V* v) const +{ +    switch(GetKind()) +    { +    case eArrayType: +        return v->VisitArrayType(llvm::cast<const GoASTArrayType>(this)); +    case eBadExpr: +        return v->VisitBadExpr(llvm::cast<const GoASTBadExpr>(this)); +    case eBasicLit: +        return v->VisitBasicLit(llvm::cast<const GoASTBasicLit>(this)); +    case eBinaryExpr: +        return v->VisitBinaryExpr(llvm::cast<const GoASTBinaryExpr>(this)); +    case eIdent: +        return v->VisitIdent(llvm::cast<const GoASTIdent>(this)); +    case eCallExpr: +        return v->VisitCallExpr(llvm::cast<const GoASTCallExpr>(this)); +    case eChanType: +        return v->VisitChanType(llvm::cast<const GoASTChanType>(this)); +    case eCompositeLit: +        return v->VisitCompositeLit(llvm::cast<const GoASTCompositeLit>(this)); +    case eEllipsis: +        return v->VisitEllipsis(llvm::cast<const GoASTEllipsis>(this)); +    case eFuncType: +        return v->VisitFuncType(llvm::cast<const GoASTFuncType>(this)); +    case eFuncLit: +        return v->VisitFuncLit(llvm::cast<const GoASTFuncLit>(this)); +    case eIndexExpr: +        return v->VisitIndexExpr(llvm::cast<const GoASTIndexExpr>(this)); +    case eInterfaceType: +        return v->VisitInterfaceType(llvm::cast<const GoASTInterfaceType>(this)); +    case eKeyValueExpr: +        return v->VisitKeyValueExpr(llvm::cast<const GoASTKeyValueExpr>(this)); +    case eMapType: +        return v->VisitMapType(llvm::cast<const GoASTMapType>(this)); +    case eParenExpr: +        return v->VisitParenExpr(llvm::cast<const GoASTParenExpr>(this)); +    case eSelectorExpr: +        return v->VisitSelectorExpr(llvm::cast<const GoASTSelectorExpr>(this)); +    case eSliceExpr: +        return v->VisitSliceExpr(llvm::cast<const GoASTSliceExpr>(this)); +    case eStarExpr: +        return v->VisitStarExpr(llvm::cast<const GoASTStarExpr>(this)); +    case eStructType: +        return v->VisitStructType(llvm::cast<const GoASTStructType>(this)); +    case eTypeAssertExpr: +        return v->VisitTypeAssertExpr(llvm::cast<const GoASTTypeAssertExpr>(this)); +    case eUnaryExpr: +        return v->VisitUnaryExpr(llvm::cast<const GoASTUnaryExpr>(this)); +    default: +        assert(false && "Invalid kind"); +    } +} + +template <typename R, typename V> +R GoASTSpec::Visit(V* v) const +{ +    switch(GetKind()) +    { +    case eImportSpec: +        return v->VisitImportSpec(llvm::cast<const GoASTImportSpec>(this)); +    case eTypeSpec: +        return v->VisitTypeSpec(llvm::cast<const GoASTTypeSpec>(this)); +    case eValueSpec: +        return v->VisitValueSpec(llvm::cast<const GoASTValueSpec>(this)); +    default: +        assert(false && "Invalid kind"); +    } +} + +template <typename R, typename V> +R GoASTStmt::Visit(V* v) const +{ +    switch(GetKind()) +    { +    case eAssignStmt: +        return v->VisitAssignStmt(llvm::cast<const GoASTAssignStmt>(this)); +    case eBadStmt: +        return v->VisitBadStmt(llvm::cast<const GoASTBadStmt>(this)); +    case eBlockStmt: +        return v->VisitBlockStmt(llvm::cast<const GoASTBlockStmt>(this)); +    case eBranchStmt: +        return v->VisitBranchStmt(llvm::cast<const GoASTBranchStmt>(this)); +    case eCaseClause: +        return v->VisitCaseClause(llvm::cast<const GoASTCaseClause>(this)); +    case eCommClause: +        return v->VisitCommClause(llvm::cast<const GoASTCommClause>(this)); +    case eDeclStmt: +        return v->VisitDeclStmt(llvm::cast<const GoASTDeclStmt>(this)); +    case eDeferStmt: +        return v->VisitDeferStmt(llvm::cast<const GoASTDeferStmt>(this)); +    case eEmptyStmt: +        return v->VisitEmptyStmt(llvm::cast<const GoASTEmptyStmt>(this)); +    case eExprStmt: +        return v->VisitExprStmt(llvm::cast<const GoASTExprStmt>(this)); +    case eForStmt: +        return v->VisitForStmt(llvm::cast<const GoASTForStmt>(this)); +    case eGoStmt: +        return v->VisitGoStmt(llvm::cast<const GoASTGoStmt>(this)); +    case eIfStmt: +        return v->VisitIfStmt(llvm::cast<const GoASTIfStmt>(this)); +    case eIncDecStmt: +        return v->VisitIncDecStmt(llvm::cast<const GoASTIncDecStmt>(this)); +    case eLabeledStmt: +        return v->VisitLabeledStmt(llvm::cast<const GoASTLabeledStmt>(this)); +    case eRangeStmt: +        return v->VisitRangeStmt(llvm::cast<const GoASTRangeStmt>(this)); +    case eReturnStmt: +        return v->VisitReturnStmt(llvm::cast<const GoASTReturnStmt>(this)); +    case eSelectStmt: +        return v->VisitSelectStmt(llvm::cast<const GoASTSelectStmt>(this)); +    case eSendStmt: +        return v->VisitSendStmt(llvm::cast<const GoASTSendStmt>(this)); +    case eSwitchStmt: +        return v->VisitSwitchStmt(llvm::cast<const GoASTSwitchStmt>(this)); +    case eTypeSwitchStmt: +        return v->VisitTypeSwitchStmt(llvm::cast<const GoASTTypeSwitchStmt>(this)); +    default: +        assert(false && "Invalid kind"); +    } +} + +template <typename V> +void GoASTNode::WalkChildren(V &v) +{ +    switch (m_kind) +    { + + +    case eArrayType: +        { +            GoASTArrayType *n = llvm::cast<GoASTArrayType>(this); +            (void)n; +            v(n->m_len_up.get()); +            v(n->m_elt_up.get()); +            return; +        } +    case eAssignStmt: +        { +            GoASTAssignStmt *n = llvm::cast<GoASTAssignStmt>(this); +            (void)n; +            for (auto& e : n->m_lhs) { v(e.get()); } +            for (auto& e : n->m_rhs) { v(e.get()); } +            return; +        } +    case eBasicLit: +        { +            GoASTBasicLit *n = llvm::cast<GoASTBasicLit>(this); +            (void)n; +            return; +        } +    case eBinaryExpr: +        { +            GoASTBinaryExpr *n = llvm::cast<GoASTBinaryExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            v(n->m_y_up.get()); +            return; +        } +    case eBlockStmt: +        { +            GoASTBlockStmt *n = llvm::cast<GoASTBlockStmt>(this); +            (void)n; +            for (auto& e : n->m_list) { v(e.get()); } +            return; +        } +    case eIdent: +        { +            GoASTIdent *n = llvm::cast<GoASTIdent>(this); +            (void)n; +            return; +        } +    case eBranchStmt: +        { +            GoASTBranchStmt *n = llvm::cast<GoASTBranchStmt>(this); +            (void)n; +            v(n->m_label_up.get()); +            return; +        } +    case eCallExpr: +        { +            GoASTCallExpr *n = llvm::cast<GoASTCallExpr>(this); +            (void)n; +            v(n->m_fun_up.get()); +            for (auto& e : n->m_args) { v(e.get()); } +            return; +        } +    case eCaseClause: +        { +            GoASTCaseClause *n = llvm::cast<GoASTCaseClause>(this); +            (void)n; +            for (auto& e : n->m_list) { v(e.get()); } +            for (auto& e : n->m_body) { v(e.get()); } +            return; +        } +    case eChanType: +        { +            GoASTChanType *n = llvm::cast<GoASTChanType>(this); +            (void)n; +            v(n->m_value_up.get()); +            return; +        } +    case eCommClause: +        { +            GoASTCommClause *n = llvm::cast<GoASTCommClause>(this); +            (void)n; +            v(n->m_comm_up.get()); +            for (auto& e : n->m_body) { v(e.get()); } +            return; +        } +    case eCompositeLit: +        { +            GoASTCompositeLit *n = llvm::cast<GoASTCompositeLit>(this); +            (void)n; +            v(n->m_type_up.get()); +            for (auto& e : n->m_elts) { v(e.get()); } +            return; +        } +    case eDeclStmt: +        { +            GoASTDeclStmt *n = llvm::cast<GoASTDeclStmt>(this); +            (void)n; +            v(n->m_decl_up.get()); +            return; +        } +    case eDeferStmt: +        { +            GoASTDeferStmt *n = llvm::cast<GoASTDeferStmt>(this); +            (void)n; +            v(n->m_call_up.get()); +            return; +        } +    case eEllipsis: +        { +            GoASTEllipsis *n = llvm::cast<GoASTEllipsis>(this); +            (void)n; +            v(n->m_elt_up.get()); +            return; +        } +    case eExprStmt: +        { +            GoASTExprStmt *n = llvm::cast<GoASTExprStmt>(this); +            (void)n; +            v(n->m_x_up.get()); +            return; +        } +    case eField: +        { +            GoASTField *n = llvm::cast<GoASTField>(this); +            (void)n; +            for (auto& e : n->m_names) { v(e.get()); } +            v(n->m_type_up.get()); +            v(n->m_tag_up.get()); +            return; +        } +    case eFieldList: +        { +            GoASTFieldList *n = llvm::cast<GoASTFieldList>(this); +            (void)n; +            for (auto& e : n->m_list) { v(e.get()); } +            return; +        } +    case eForStmt: +        { +            GoASTForStmt *n = llvm::cast<GoASTForStmt>(this); +            (void)n; +            v(n->m_init_up.get()); +            v(n->m_cond_up.get()); +            v(n->m_post_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eFuncType: +        { +            GoASTFuncType *n = llvm::cast<GoASTFuncType>(this); +            (void)n; +            v(n->m_params_up.get()); +            v(n->m_results_up.get()); +            return; +        } +    case eFuncDecl: +        { +            GoASTFuncDecl *n = llvm::cast<GoASTFuncDecl>(this); +            (void)n; +            v(n->m_recv_up.get()); +            v(n->m_name_up.get()); +            v(n->m_type_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eFuncLit: +        { +            GoASTFuncLit *n = llvm::cast<GoASTFuncLit>(this); +            (void)n; +            v(n->m_type_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eGenDecl: +        { +            GoASTGenDecl *n = llvm::cast<GoASTGenDecl>(this); +            (void)n; +            for (auto& e : n->m_specs) { v(e.get()); } +            return; +        } +    case eGoStmt: +        { +            GoASTGoStmt *n = llvm::cast<GoASTGoStmt>(this); +            (void)n; +            v(n->m_call_up.get()); +            return; +        } +    case eIfStmt: +        { +            GoASTIfStmt *n = llvm::cast<GoASTIfStmt>(this); +            (void)n; +            v(n->m_init_up.get()); +            v(n->m_cond_up.get()); +            v(n->m_body_up.get()); +            v(n->m_els_up.get()); +            return; +        } +    case eImportSpec: +        { +            GoASTImportSpec *n = llvm::cast<GoASTImportSpec>(this); +            (void)n; +            v(n->m_name_up.get()); +            v(n->m_path_up.get()); +            return; +        } +    case eIncDecStmt: +        { +            GoASTIncDecStmt *n = llvm::cast<GoASTIncDecStmt>(this); +            (void)n; +            v(n->m_x_up.get()); +            return; +        } +    case eIndexExpr: +        { +            GoASTIndexExpr *n = llvm::cast<GoASTIndexExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            v(n->m_index_up.get()); +            return; +        } +    case eInterfaceType: +        { +            GoASTInterfaceType *n = llvm::cast<GoASTInterfaceType>(this); +            (void)n; +            v(n->m_methods_up.get()); +            return; +        } +    case eKeyValueExpr: +        { +            GoASTKeyValueExpr *n = llvm::cast<GoASTKeyValueExpr>(this); +            (void)n; +            v(n->m_key_up.get()); +            v(n->m_value_up.get()); +            return; +        } +    case eLabeledStmt: +        { +            GoASTLabeledStmt *n = llvm::cast<GoASTLabeledStmt>(this); +            (void)n; +            v(n->m_label_up.get()); +            v(n->m_stmt_up.get()); +            return; +        } +    case eMapType: +        { +            GoASTMapType *n = llvm::cast<GoASTMapType>(this); +            (void)n; +            v(n->m_key_up.get()); +            v(n->m_value_up.get()); +            return; +        } +    case eParenExpr: +        { +            GoASTParenExpr *n = llvm::cast<GoASTParenExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            return; +        } +    case eRangeStmt: +        { +            GoASTRangeStmt *n = llvm::cast<GoASTRangeStmt>(this); +            (void)n; +            v(n->m_key_up.get()); +            v(n->m_value_up.get()); +            v(n->m_x_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eReturnStmt: +        { +            GoASTReturnStmt *n = llvm::cast<GoASTReturnStmt>(this); +            (void)n; +            for (auto& e : n->m_results) { v(e.get()); } +            return; +        } +    case eSelectStmt: +        { +            GoASTSelectStmt *n = llvm::cast<GoASTSelectStmt>(this); +            (void)n; +            v(n->m_body_up.get()); +            return; +        } +    case eSelectorExpr: +        { +            GoASTSelectorExpr *n = llvm::cast<GoASTSelectorExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            v(n->m_sel_up.get()); +            return; +        } +    case eSendStmt: +        { +            GoASTSendStmt *n = llvm::cast<GoASTSendStmt>(this); +            (void)n; +            v(n->m_chan_up.get()); +            v(n->m_value_up.get()); +            return; +        } +    case eSliceExpr: +        { +            GoASTSliceExpr *n = llvm::cast<GoASTSliceExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            v(n->m_low_up.get()); +            v(n->m_high_up.get()); +            v(n->m_max_up.get()); +            return; +        } +    case eStarExpr: +        { +            GoASTStarExpr *n = llvm::cast<GoASTStarExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            return; +        } +    case eStructType: +        { +            GoASTStructType *n = llvm::cast<GoASTStructType>(this); +            (void)n; +            v(n->m_fields_up.get()); +            return; +        } +    case eSwitchStmt: +        { +            GoASTSwitchStmt *n = llvm::cast<GoASTSwitchStmt>(this); +            (void)n; +            v(n->m_init_up.get()); +            v(n->m_tag_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eTypeAssertExpr: +        { +            GoASTTypeAssertExpr *n = llvm::cast<GoASTTypeAssertExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            v(n->m_type_up.get()); +            return; +        } +    case eTypeSpec: +        { +            GoASTTypeSpec *n = llvm::cast<GoASTTypeSpec>(this); +            (void)n; +            v(n->m_name_up.get()); +            v(n->m_type_up.get()); +            return; +        } +    case eTypeSwitchStmt: +        { +            GoASTTypeSwitchStmt *n = llvm::cast<GoASTTypeSwitchStmt>(this); +            (void)n; +            v(n->m_init_up.get()); +            v(n->m_assign_up.get()); +            v(n->m_body_up.get()); +            return; +        } +    case eUnaryExpr: +        { +            GoASTUnaryExpr *n = llvm::cast<GoASTUnaryExpr>(this); +            (void)n; +            v(n->m_x_up.get()); +            return; +        } +    case eValueSpec: +        { +            GoASTValueSpec *n = llvm::cast<GoASTValueSpec>(this); +            (void)n; +            for (auto& e : n->m_names) { v(e.get()); } +            v(n->m_type_up.get()); +            for (auto& e : n->m_values) { v(e.get()); } +            return; +        } + +        case eEmptyStmt: +        case eBadDecl: +        case eBadExpr: +        case eBadStmt: +          break; +    } +} + +}  // namespace lldb_private + +#endif + diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.cpp b/source/Plugins/ExpressionParser/Go/GoLexer.cpp new file mode 100644 index 0000000000000..6de0f5619ca8c --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.cpp @@ -0,0 +1,402 @@ +//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <string.h> + +#include "GoLexer.h" + +using namespace lldb_private; + +llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords; + +GoLexer::GoLexer(const char *src) : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "") +{ +} + +bool +GoLexer::SkipWhitespace() +{ +    bool saw_newline = false; +    for (; m_src < m_end; ++m_src) +    { +        if (*m_src == '\n') +            saw_newline = true; +        if (*m_src == '/' && !SkipComment()) +            return saw_newline; +        else if (!IsWhitespace(*m_src)) +            return saw_newline; +    } +    return saw_newline; +} + +bool +GoLexer::SkipComment() +{ +    if (m_src[0] == '/' && m_src[1] == '/') +    { +        for (const char *c = m_src + 2; c < m_end; ++c) +        { +            if (*c == '\n') +            { +                m_src = c - 1; +                return true; +            } +        } +        return true; +    } +    else if (m_src[0] == '/' && m_src[1] == '*') +    { +        for (const char *c = m_src + 2; c < m_end; ++c) +        { +            if (c[0] == '*' && c[1] == '/') +            { +                m_src = c + 1; +                return true; +            } +        } +    } +    return false; +} + +const GoLexer::Token & +GoLexer::Lex() +{ +    bool newline = SkipWhitespace(); +    const char *start = m_src; +    m_last_token.m_type = InternalLex(newline); +    m_last_token.m_value = llvm::StringRef(start, m_src - start); +    return m_last_token; +} + +GoLexer::TokenType +GoLexer::InternalLex(bool newline) +{ +    if (m_src >= m_end) +    { +        return TOK_EOF; +    } +    if (newline) +    { +        switch (m_last_token.m_type) +        { +            case TOK_IDENTIFIER: +            case LIT_FLOAT: +            case LIT_IMAGINARY: +            case LIT_INTEGER: +            case LIT_RUNE: +            case LIT_STRING: +            case KEYWORD_BREAK: +            case KEYWORD_CONTINUE: +            case KEYWORD_FALLTHROUGH: +            case KEYWORD_RETURN: +            case OP_PLUS_PLUS: +            case OP_MINUS_MINUS: +            case OP_RPAREN: +            case OP_RBRACK: +            case OP_RBRACE: +                return OP_SEMICOLON; +            default: +                break; +        } +    } +    char c = *m_src; +    switch (c) +    { +        case '0': +        case '1': +        case '2': +        case '3': +        case '4': +        case '5': +        case '6': +        case '7': +        case '8': +        case '9': +            return DoNumber(); +        case '+': +        case '-': +        case '*': +        case '/': +        case '%': +        case '&': +        case '|': +        case '^': +        case '<': +        case '>': +        case '!': +        case ':': +        case ';': +        case '(': +        case ')': +        case '[': +        case ']': +        case '{': +        case '}': +        case ',': +        case '=': +            return DoOperator(); +        case '.': +            if (IsDecimal(m_src[1])) +                return DoNumber(); +            return DoOperator(); +        case '$': +            // For lldb persistent vars. +            return DoIdent(); +        case '"': +        case '`': +            return DoString(); +        case '\'': +            return DoRune(); +        default: +            break; +    } +    if (IsLetterOrDigit(c)) +        return DoIdent(); +    ++m_src; +    return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::DoOperator() +{ +    TokenType t = TOK_INVALID; +    if (m_end - m_src > 2) +    { +        t = LookupKeyword(llvm::StringRef(m_src, 3)); +        if (t != TOK_INVALID) +            m_src += 3; +    } +    if (t == TOK_INVALID && m_end - m_src > 1) +    { +        t = LookupKeyword(llvm::StringRef(m_src, 2)); +        if (t != TOK_INVALID) +            m_src += 2; +    } +    if (t == TOK_INVALID) +    { +        t = LookupKeyword(llvm::StringRef(m_src, 1)); +        ++m_src; +    } +    return t; +} + +GoLexer::TokenType +GoLexer::DoIdent() +{ +    const char *start = m_src++; +    while (m_src < m_end && IsLetterOrDigit(*m_src)) +    { +        ++m_src; +    } +    TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start)); +    if (kw != TOK_INVALID) +        return kw; +    return TOK_IDENTIFIER; +} + +GoLexer::TokenType +GoLexer::DoNumber() +{ +    if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X')) +    { +        m_src += 2; +        while (IsHexChar(*m_src)) +            ++m_src; +        return LIT_INTEGER; +    } +    bool dot_ok = true; +    bool e_ok = true; +    while (true) +    { +        while (IsDecimal(*m_src)) +            ++m_src; +        switch (*m_src) +        { +            case 'i': +                ++m_src; +                return LIT_IMAGINARY; +            case '.': +                if (!dot_ok) +                    return LIT_FLOAT; +                ++m_src; +                dot_ok = false; +                break; +            case 'e': +            case 'E': +                if (!e_ok) +                    return LIT_FLOAT; +                dot_ok = e_ok = false; +                ++m_src; +                if (*m_src == '+' || *m_src == '-') +                    ++m_src; +                break; +            default: +                if (dot_ok) +                    return LIT_INTEGER; +                return LIT_FLOAT; +        } +    } +} + +GoLexer::TokenType +GoLexer::DoRune() +{ +    while (++m_src < m_end) +    { +        switch (*m_src) +        { +            case '\'': +                ++m_src; +                return LIT_RUNE; +            case '\n': +                return TOK_INVALID; +            case '\\': +                if (m_src[1] == '\n') +                    return TOK_INVALID; +                ++m_src; +        } +    } +    return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::DoString() +{ +    if (*m_src == '`') +    { +        while (++m_src < m_end) +        { +            if (*m_src == '`') +            { +                ++m_src; +                return LIT_STRING; +            } +        } +        return TOK_INVALID; +    } +    while (++m_src < m_end) +    { +        switch (*m_src) +        { +            case '"': +                ++m_src; +                return LIT_STRING; +            case '\n': +                return TOK_INVALID; +            case '\\': +                if (m_src[1] == '\n') +                    return TOK_INVALID; +                ++m_src; +        } +    } +    return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::LookupKeyword(llvm::StringRef id) +{ +    if (m_keywords == nullptr) +        m_keywords = InitKeywords(); +    const auto &it = m_keywords->find(id); +    if (it == m_keywords->end()) +        return TOK_INVALID; +    return it->second; +} + +llvm::StringRef +GoLexer::LookupToken(TokenType t) +{ +    if (m_keywords == nullptr) +        m_keywords = InitKeywords(); +    for (const auto &e : *m_keywords) +    { +        if (e.getValue() == t) +            return e.getKey(); +    } +    return ""; +} + +llvm::StringMap<GoLexer::TokenType> * +GoLexer::InitKeywords() +{ +    auto &result = *new llvm::StringMap<TokenType>(128); +    result["break"] = KEYWORD_BREAK; +    result["default"] = KEYWORD_DEFAULT; +    result["func"] = KEYWORD_FUNC; +    result["interface"] = KEYWORD_INTERFACE; +    result["select"] = KEYWORD_SELECT; +    result["case"] = KEYWORD_CASE; +    result["defer"] = KEYWORD_DEFER; +    result["go"] = KEYWORD_GO; +    result["map"] = KEYWORD_MAP; +    result["struct"] = KEYWORD_STRUCT; +    result["chan"] = KEYWORD_CHAN; +    result["else"] = KEYWORD_ELSE; +    result["goto"] = KEYWORD_GOTO; +    result["package"] = KEYWORD_PACKAGE; +    result["switch"] = KEYWORD_SWITCH; +    result["const"] = KEYWORD_CONST; +    result["fallthrough"] = KEYWORD_FALLTHROUGH; +    result["if"] = KEYWORD_IF; +    result["range"] = KEYWORD_RANGE; +    result["type"] = KEYWORD_TYPE; +    result["continue"] = KEYWORD_CONTINUE; +    result["for"] = KEYWORD_FOR; +    result["import"] = KEYWORD_IMPORT; +    result["return"] = KEYWORD_RETURN; +    result["var"] = KEYWORD_VAR; +    result["+"] = OP_PLUS; +    result["-"] = OP_MINUS; +    result["*"] = OP_STAR; +    result["/"] = OP_SLASH; +    result["%"] = OP_PERCENT; +    result["&"] = OP_AMP; +    result["|"] = OP_PIPE; +    result["^"] = OP_CARET; +    result["<<"] = OP_LSHIFT; +    result[">>"] = OP_RSHIFT; +    result["&^"] = OP_AMP_CARET; +    result["+="] = OP_PLUS_EQ; +    result["-="] = OP_MINUS_EQ; +    result["*="] = OP_STAR_EQ; +    result["/="] = OP_SLASH_EQ; +    result["%="] = OP_PERCENT_EQ; +    result["&="] = OP_AMP_EQ; +    result["|="] = OP_PIPE_EQ; +    result["^="] = OP_CARET_EQ; +    result["<<="] = OP_LSHIFT_EQ; +    result[">>="] = OP_RSHIFT_EQ; +    result["&^="] = OP_AMP_CARET_EQ; +    result["&&"] = OP_AMP_AMP; +    result["||"] = OP_PIPE_PIPE; +    result["<-"] = OP_LT_MINUS; +    result["++"] = OP_PLUS_PLUS; +    result["--"] = OP_MINUS_MINUS; +    result["=="] = OP_EQ_EQ; +    result["<"] = OP_LT; +    result[">"] = OP_GT; +    result["="] = OP_EQ; +    result["!"] = OP_BANG; +    result["!="] = OP_BANG_EQ; +    result["<="] = OP_LT_EQ; +    result[">="] = OP_GT_EQ; +    result[":="] = OP_COLON_EQ; +    result["..."] = OP_DOTS; +    result["("] = OP_LPAREN; +    result["["] = OP_LBRACK; +    result["{"] = OP_LBRACE; +    result[","] = OP_COMMA; +    result["."] = OP_DOT; +    result[")"] = OP_RPAREN; +    result["]"] = OP_RBRACK; +    result["}"] = OP_RBRACE; +    result[";"] = OP_SEMICOLON; +    result[":"] = OP_COLON; +    return &result; +} diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.h b/source/Plugins/ExpressionParser/Go/GoLexer.h new file mode 100644 index 0000000000000..e8e1635bab771 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.h @@ -0,0 +1,201 @@ +//===-- GoLexer.h -----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoLexer_h +#define liblldb_GoLexer_h + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" + +namespace lldb_private +{ + +class GoLexer +{ +  public: +    explicit GoLexer(const char *src); + +    enum TokenType +    { +        TOK_EOF, +        TOK_INVALID, +        TOK_IDENTIFIER, +        LIT_INTEGER, +        LIT_FLOAT, +        LIT_IMAGINARY, +        LIT_RUNE, +        LIT_STRING, +        KEYWORD_BREAK, +        KEYWORD_DEFAULT, +        KEYWORD_FUNC, +        KEYWORD_INTERFACE, +        KEYWORD_SELECT, +        KEYWORD_CASE, +        KEYWORD_DEFER, +        KEYWORD_GO, +        KEYWORD_MAP, +        KEYWORD_STRUCT, +        KEYWORD_CHAN, +        KEYWORD_ELSE, +        KEYWORD_GOTO, +        KEYWORD_PACKAGE, +        KEYWORD_SWITCH, +        KEYWORD_CONST, +        KEYWORD_FALLTHROUGH, +        KEYWORD_IF, +        KEYWORD_RANGE, +        KEYWORD_TYPE, +        KEYWORD_CONTINUE, +        KEYWORD_FOR, +        KEYWORD_IMPORT, +        KEYWORD_RETURN, +        KEYWORD_VAR, +        OP_PLUS, +        OP_MINUS, +        OP_STAR, +        OP_SLASH, +        OP_PERCENT, +        OP_AMP, +        OP_PIPE, +        OP_CARET, +        OP_LSHIFT, +        OP_RSHIFT, +        OP_AMP_CARET, +        OP_PLUS_EQ, +        OP_MINUS_EQ, +        OP_STAR_EQ, +        OP_SLASH_EQ, +        OP_PERCENT_EQ, +        OP_AMP_EQ, +        OP_PIPE_EQ, +        OP_CARET_EQ, +        OP_LSHIFT_EQ, +        OP_RSHIFT_EQ, +        OP_AMP_CARET_EQ, +        OP_AMP_AMP, +        OP_PIPE_PIPE, +        OP_LT_MINUS, +        OP_PLUS_PLUS, +        OP_MINUS_MINUS, +        OP_EQ_EQ, +        OP_LT, +        OP_GT, +        OP_EQ, +        OP_BANG, +        OP_BANG_EQ, +        OP_LT_EQ, +        OP_GT_EQ, +        OP_COLON_EQ, +        OP_DOTS, +        OP_LPAREN, +        OP_LBRACK, +        OP_LBRACE, +        OP_COMMA, +        OP_DOT, +        OP_RPAREN, +        OP_RBRACK, +        OP_RBRACE, +        OP_SEMICOLON, +        OP_COLON, +    }; + +    struct Token +    { +        explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {} +        TokenType m_type; +        llvm::StringRef m_value; +    }; + +    const Token &Lex(); + +    size_t +    BytesRemaining() const +    { +        return m_end - m_src; +    } +    llvm::StringRef +    GetString(int len) const +    { +        return llvm::StringRef(m_src, len); +    } + +    static TokenType LookupKeyword(llvm::StringRef id); +    static llvm::StringRef LookupToken(TokenType t); + +  private: +    bool +    IsDecimal(char c) +    { +        return c >= '0' && c <= '9'; +    } +    bool +    IsHexChar(char c) +    { +        if (c >= '0' && c <= '9') +            return true; +        if (c >= 'A' && c <= 'F') +            return true; +        if (c >= 'a' && c <= 'f') +            return true; +        return false; +    } +    bool +    IsLetterOrDigit(char c) +    { +        if (c >= 'a' && c <= 'z') +            return true; +        if (c >= 'A' && c <= 'Z') +            return true; +        if (c == '_') +            return true; +        if (c >= '0' && c <= '9') +            return true; +        // Treat all non-ascii chars as letters for simplicity. +        return 0 != (c & 0x80); +    } +    bool +    IsWhitespace(char c) +    { +        switch (c) +        { +            case ' ': +            case '\t': +            case '\r': +                return true; +        } +        return false; +    } + +    bool SkipWhitespace(); +    bool SkipComment(); + +    TokenType InternalLex(bool newline); + +    TokenType DoOperator(); + +    TokenType DoIdent(); + +    TokenType DoNumber(); + +    TokenType DoRune(); + +    TokenType DoString(); + +    static llvm::StringMap<TokenType> *InitKeywords(); + +    static llvm::StringMap<TokenType> *m_keywords; + +    const char *m_src; +    const char *m_end; +    Token m_last_token; +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp new file mode 100644 index 0000000000000..0f136f7e61dc8 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp @@ -0,0 +1,1035 @@ +//===-- GoParser.cpp ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <vector> + +#include "GoParser.h" + +#include "lldb/Core/Error.h" +#include "llvm/ADT/SmallString.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" + +using namespace lldb_private; +using namespace lldb; + +namespace +{ +llvm::StringRef +DescribeToken(GoLexer::TokenType t) +{ +    switch (t) +    { +        case GoLexer::TOK_EOF: +            return "<eof>"; +        case GoLexer::TOK_IDENTIFIER: +            return "identifier"; +        case GoLexer::LIT_FLOAT: +            return "float"; +        case GoLexer::LIT_IMAGINARY: +            return "imaginary"; +        case GoLexer::LIT_INTEGER: +            return "integer"; +        case GoLexer::LIT_RUNE: +            return "rune"; +        case GoLexer::LIT_STRING: +            return "string"; +        default: +            return GoLexer::LookupToken(t); +    } +} +} // namespace + +class GoParser::Rule +{ +  public: +    Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {} + +    std::nullptr_t +    error() +    { +        if (!m_parser->m_failed) +        { +            // Set m_error in case this is the top level. +            if (m_parser->m_last_tok == GoLexer::TOK_INVALID) +                m_parser->m_error = m_parser->m_last; +            else +                m_parser->m_error = DescribeToken(m_parser->m_last_tok); +            // And set m_last in case it isn't. +            m_parser->m_last = m_name; +            m_parser->m_last_tok = GoLexer::TOK_INVALID; +            m_parser->m_pos = m_pos; +        } +        return nullptr; +    } + +  private: +    llvm::StringRef m_name; +    GoParser *m_parser; +    size_t m_pos; +}; + +GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) +{ +} + +GoASTStmt * +GoParser::Statement() +{ +    Rule r("Statement", this); +    GoLexer::TokenType t = peek(); +    GoASTStmt *ret = nullptr; +    switch (t) +    { +        case GoLexer::TOK_EOF: +        case GoLexer::OP_SEMICOLON: +        case GoLexer::OP_RPAREN: +        case GoLexer::OP_RBRACE: +        case GoLexer::TOK_INVALID: +            return EmptyStmt(); +        case GoLexer::OP_LBRACE: +            return Block(); + +        /*      TODO: +    case GoLexer::KEYWORD_GO: +        return GoStmt(); +    case GoLexer::KEYWORD_RETURN: +        return ReturnStmt(); +    case GoLexer::KEYWORD_BREAK: +    case GoLexer::KEYWORD_CONTINUE: +    case GoLexer::KEYWORD_GOTO: +    case GoLexer::KEYWORD_FALLTHROUGH: +        return BranchStmt(); +    case GoLexer::KEYWORD_IF: +        return IfStmt(); +    case GoLexer::KEYWORD_SWITCH: +        return SwitchStmt(); +    case GoLexer::KEYWORD_SELECT: +        return SelectStmt(); +    case GoLexer::KEYWORD_FOR: +        return ForStmt(); +    case GoLexer::KEYWORD_DEFER: +        return DeferStmt(); +    case GoLexer::KEYWORD_CONST: +    case GoLexer::KEYWORD_TYPE: +    case GoLexer::KEYWORD_VAR: +        return DeclStmt(); +    case GoLexer::TOK_IDENTIFIER: +        if ((ret = LabeledStmt()) || +            (ret = ShortVarDecl())) +        { +            return ret; +        } +*/ +        default: +            break; +    } +    GoASTExpr *expr = Expression(); +    if (expr == nullptr) +        return r.error(); +    if (/*(ret = SendStmt(expr)) ||*/ +        (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr))) +    { +        return ret; +    } +    delete expr; +    return r.error(); +} + +GoASTStmt * +GoParser::ExpressionStmt(GoASTExpr *e) +{ +    if (Semicolon()) +        return new GoASTExprStmt(e); +    return nullptr; +} + +GoASTStmt * +GoParser::IncDecStmt(GoASTExpr *e) +{ +    Rule r("IncDecStmt", this); +    if (match(GoLexer::OP_PLUS_PLUS)) +        return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error(); +    if (match(GoLexer::OP_MINUS_MINUS)) +        return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error(); +    return nullptr; +} + +GoASTStmt * +GoParser::Assignment(lldb_private::GoASTExpr *e) +{ +    Rule r("Assignment", this); +    std::vector<std::unique_ptr<GoASTExpr>> lhs; +    for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) +        lhs.push_back(std::unique_ptr<GoASTExpr>(l)); +    switch (peek()) +    { +        case GoLexer::OP_EQ: +        case GoLexer::OP_PLUS_EQ: +        case GoLexer::OP_MINUS_EQ: +        case GoLexer::OP_PIPE_EQ: +        case GoLexer::OP_CARET_EQ: +        case GoLexer::OP_STAR_EQ: +        case GoLexer::OP_SLASH_EQ: +        case GoLexer::OP_PERCENT_EQ: +        case GoLexer::OP_LSHIFT_EQ: +        case GoLexer::OP_RSHIFT_EQ: +        case GoLexer::OP_AMP_EQ: +        case GoLexer::OP_AMP_CARET_EQ: +            break; +        default: +            return r.error(); +    } +    // We don't want to own e until we know this is an assignment. +    std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false)); +    stmt->AddLhs(e); +    for (auto &l : lhs) +        stmt->AddLhs(l.release()); +    for (GoASTExpr *r = Expression(); r; r = MoreExpressionList()) +        stmt->AddRhs(r); +    if (!Semicolon() || stmt->NumRhs() == 0) +        return new GoASTBadStmt; +    return stmt.release(); +} + +GoASTStmt * +GoParser::EmptyStmt() +{ +    if (match(GoLexer::TOK_EOF)) +        return nullptr; +    if (Semicolon()) +        return new GoASTEmptyStmt; +    return nullptr; +} + +GoASTStmt * +GoParser::GoStmt() +{ +    if (match(GoLexer::KEYWORD_GO)) +    { +        if (GoASTCallExpr *e = llvm::dyn_cast_or_null<GoASTCallExpr>(Expression())) +        { +            return FinishStmt(new GoASTGoStmt(e)); +        } +        m_last = "call expression"; +        m_failed = true; +        return new GoASTBadStmt(); +    } +    return nullptr; +} + +GoASTStmt * +GoParser::ReturnStmt() +{ +    if (match(GoLexer::KEYWORD_RETURN)) +    { +        std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt()); +        for (GoASTExpr *e = Expression(); e; e = MoreExpressionList()) +            r->AddResults(e); +        return FinishStmt(r.release()); +    } +    return nullptr; +} + +GoASTStmt * +GoParser::BranchStmt() +{ +    GoLexer::Token *tok; +    if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) || +        (tok = match(GoLexer::KEYWORD_GOTO))) +    { +        auto *e = Identifier(); +        if (tok->m_type == GoLexer::KEYWORD_GOTO && !e) +            return syntaxerror(); +        return FinishStmt(new GoASTBranchStmt(e, tok->m_type)); +    } +    if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH))) +        return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type)); + +    return nullptr; +} + +GoASTIdent * +GoParser::Identifier() +{ +    if (auto *tok = match(GoLexer::TOK_IDENTIFIER)) +        return new GoASTIdent(*tok); +    return nullptr; +} + +GoASTExpr * +GoParser::MoreExpressionList() +{ +    if (match(GoLexer::OP_COMMA)) +    { +        auto *e = Expression(); +        if (!e) +            return syntaxerror(); +        return e; +    } +    return nullptr; +} + +GoASTIdent * +GoParser::MoreIdentifierList() +{ +    if (match(GoLexer::OP_COMMA)) +    { +        auto *i = Identifier(); +        if (!i) +            return syntaxerror(); +        return i; +    } +    return nullptr; +} + +GoASTExpr * +GoParser::Expression() +{ +    Rule r("Expression", this); +    if (GoASTExpr *ret = OrExpr()) +        return ret; +    return r.error(); +} + +GoASTExpr * +GoParser::UnaryExpr() +{ +    switch (peek()) +    { +        case GoLexer::OP_PLUS: +        case GoLexer::OP_MINUS: +        case GoLexer::OP_BANG: +        case GoLexer::OP_CARET: +        case GoLexer::OP_STAR: +        case GoLexer::OP_AMP: +        case GoLexer::OP_LT_MINUS: +        { +            const GoLexer::Token t = next(); +            if (GoASTExpr *e = UnaryExpr()) +            { +                if (t.m_type == GoLexer::OP_STAR) +                    return new GoASTStarExpr(e); +                else +                    return new GoASTUnaryExpr(t.m_type, e); +            } +            return syntaxerror(); +        } +        default: +            return PrimaryExpr(); +    } +} + +GoASTExpr * +GoParser::OrExpr() +{ +    std::unique_ptr<GoASTExpr> l(AndExpr()); +    if (l) +    { +        while (match(GoLexer::OP_PIPE_PIPE)) +        { +            GoASTExpr *r = AndExpr(); +            if (r) +                l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE)); +            else +                return syntaxerror(); +        } +        return l.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::AndExpr() +{ +    std::unique_ptr<GoASTExpr> l(RelExpr()); +    if (l) +    { +        while (match(GoLexer::OP_AMP_AMP)) +        { +            GoASTExpr *r = RelExpr(); +            if (r) +                l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP)); +            else +                return syntaxerror(); +        } +        return l.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::RelExpr() +{ +    std::unique_ptr<GoASTExpr> l(AddExpr()); +    if (l) +    { +        for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) || +                                (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) || +                                (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));) +        { +            GoLexer::TokenType op = t->m_type; +            GoASTExpr *r = AddExpr(); +            if (r) +                l.reset(new GoASTBinaryExpr(l.release(), r, op)); +            else +                return syntaxerror(); +        } +        return l.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::AddExpr() +{ +    std::unique_ptr<GoASTExpr> l(MulExpr()); +    if (l) +    { +        for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) || +                                (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));) +        { +            GoLexer::TokenType op = t->m_type; +            GoASTExpr *r = MulExpr(); +            if (r) +                l.reset(new GoASTBinaryExpr(l.release(), r, op)); +            else +                return syntaxerror(); +        } +        return l.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::MulExpr() +{ +    std::unique_ptr<GoASTExpr> l(UnaryExpr()); +    if (l) +    { +        for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) || +                                (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) || +                                (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) || +                                (t = match(GoLexer::OP_AMP_CARET));) +        { +            GoLexer::TokenType op = t->m_type; +            GoASTExpr *r = UnaryExpr(); +            if (r) +                l.reset(new GoASTBinaryExpr(l.release(), r, op)); +            else +                return syntaxerror(); +        } +        return l.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::PrimaryExpr() +{ +    GoASTExpr *l; +    GoASTExpr *r; +    (l = Conversion()) || (l = Operand()); +    if (!l) +        return nullptr; +    while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l))) +    { +        l = r; +    } +    return l; +} + +GoASTExpr * +GoParser::Operand() +{ +    GoLexer::Token *lit; +    if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) || +        (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING))) +        return new GoASTBasicLit(*lit); +    if (match(GoLexer::OP_LPAREN)) +    { +        GoASTExpr *e; +        if (!((e = Expression()) && match(GoLexer::OP_RPAREN))) +            return syntaxerror(); +        return e; +    } +    // MethodExpr should be handled by Selector +    if (GoASTExpr *e = CompositeLit()) +        return e; +    if (GoASTExpr *n = Name()) +        return n; +    return FunctionLit(); +} + +GoASTExpr * +GoParser::FunctionLit() +{ +    if (!match(GoLexer::KEYWORD_FUNC)) +        return nullptr; +    auto *sig = Signature(); +    if (!sig) +        return syntaxerror(); +    auto *body = Block(); +    if (!body) +    { +        delete sig; +        return syntaxerror(); +    } +    return new GoASTFuncLit(sig, body); +} + +GoASTBlockStmt * +GoParser::Block() +{ +    if (!match(GoLexer::OP_LBRACE)) +        return nullptr; +    std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt); +    for (auto *s = Statement(); s; s = Statement()) +        block->AddList(s); +    if (!match(GoLexer::OP_RBRACE)) +        return syntaxerror(); +    return block.release(); +} + +GoASTExpr * +GoParser::CompositeLit() +{ +    Rule r("CompositeLit", this); +    GoASTExpr *type; +    (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name()); +    if (!type) +        return r.error(); +    GoASTCompositeLit *lit = LiteralValue(); +    if (!lit) +        return r.error(); +    lit->SetType(type); +    return lit; +} + +GoASTCompositeLit * +GoParser::LiteralValue() +{ +    if (!match(GoLexer::OP_LBRACE)) +        return nullptr; +    std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit); +    for (GoASTExpr *e = Element(); e; e = Element()) +    { +        lit->AddElts(e); +        if (!match(GoLexer::OP_COMMA)) +            break; +    } +    if (!mustMatch(GoLexer::OP_RBRACE)) +        return nullptr; +    return lit.release(); +} + +GoASTExpr * +GoParser::Element() +{ +    GoASTExpr *key; +    if (!((key = Expression()) || (key = LiteralValue()))) +        return nullptr; +    if (!match(GoLexer::OP_COLON)) +        return key; +    GoASTExpr *value; +    if ((value = Expression()) || (value = LiteralValue())) +        return new GoASTKeyValueExpr(key, value); +    delete key; +    return syntaxerror(); +} + +GoASTExpr * +GoParser::Selector(GoASTExpr *e) +{ +    Rule r("Selector", this); +    if (match(GoLexer::OP_DOT)) +    { +        if (auto *name = Identifier()) +            return new GoASTSelectorExpr(e, name); +    } +    return r.error(); +} + +GoASTExpr * +GoParser::IndexOrSlice(GoASTExpr *e) +{ +    Rule r("IndexOrSlice", this); +    if (match(GoLexer::OP_LBRACK)) +    { +        std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3; +        bool slice = false; +        if (match(GoLexer::OP_COLON)) +        { +            slice = true; +            i2.reset(Expression()); +            if (i2 && match(GoLexer::OP_COLON)) +            { +                i3.reset(Expression()); +                if (!i3) +                    return syntaxerror(); +            } +        } +        if (!(slice || i1)) +            return syntaxerror(); +        if (!mustMatch(GoLexer::OP_RBRACK)) +            return nullptr; +        if (slice) +        { +            bool slice3 = i3.get(); +            return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3); +        } +        return new GoASTIndexExpr(e, i1.release()); +    } +    return r.error(); +} + +GoASTExpr * +GoParser::TypeAssertion(GoASTExpr *e) +{ +    Rule r("TypeAssertion", this); +    if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN)) +    { +        if (auto *t = Type()) +        { +            if (!mustMatch(GoLexer::OP_RPAREN)) +                return nullptr; +            return new GoASTTypeAssertExpr(e, t); +        } +        return syntaxerror(); +    } +    return r.error(); +} + +GoASTExpr * +GoParser::Arguments(GoASTExpr *e) +{ +    if (match(GoLexer::OP_LPAREN)) +    { +        std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false)); +        GoASTExpr *arg; +        // ( ExpressionList | Type [ "," ExpressionList ] ) +        for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList()) +        { +            call->AddArgs(arg); +        } +        if (match(GoLexer::OP_DOTS)) +            call->SetEllipsis(true); + +        // Eat trailing comma +        match(GoLexer::OP_COMMA); + +        if (!mustMatch(GoLexer::OP_RPAREN)) +            return nullptr; +        call->SetFun(e); +        return call.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::Conversion() +{ +    Rule r("Conversion", this); +    if (GoASTExpr *t = Type2()) +    { +        if (match(GoLexer::OP_LPAREN)) +        { +            GoASTExpr *v = Expression(); +            if (!v) +                return syntaxerror(); +            match(GoLexer::OP_COMMA); +            if (!mustMatch(GoLexer::OP_RPAREN)) +                return r.error(); +            GoASTCallExpr *call = new GoASTCallExpr(false); +            call->SetFun(t); +            call->AddArgs(v); +            return call; +        } +    } +    return r.error(); +} + +GoASTExpr * +GoParser::Type2() +{ +    switch (peek()) +    { +        case GoLexer::OP_LBRACK: +            return ArrayOrSliceType(false); +        case GoLexer::KEYWORD_STRUCT: +            return StructType(); +        case GoLexer::KEYWORD_FUNC: +            return FunctionType(); +        case GoLexer::KEYWORD_INTERFACE: +            return InterfaceType(); +        case GoLexer::KEYWORD_MAP: +            return MapType(); +        case GoLexer::KEYWORD_CHAN: +            return ChanType2(); +        default: +            return nullptr; +    } +} + +GoASTExpr * +GoParser::ArrayOrSliceType(bool allowEllipsis) +{ +    Rule r("ArrayType", this); +    if (match(GoLexer::OP_LBRACK)) +    { +        std::unique_ptr<GoASTExpr> len; +        if (allowEllipsis && match(GoLexer::OP_DOTS)) +        { +            len.reset(new GoASTEllipsis(nullptr)); +        } +        else +        { +            len.reset(Expression()); +        } + +        if (!match(GoLexer::OP_RBRACK)) +            return r.error(); +        GoASTExpr *elem = Type(); +        if (!elem) +            return syntaxerror(); +        return new GoASTArrayType(len.release(), elem); +    } +    return r.error(); +} + +GoASTExpr * +GoParser::StructType() +{ +    if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE))) +        return nullptr; +    std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList); +    while (auto *field = FieldDecl()) +        fields->AddList(field); +    if (!mustMatch(GoLexer::OP_RBRACE)) +        return nullptr; +    return new GoASTStructType(fields.release()); +} + +GoASTField * +GoParser::FieldDecl() +{ +    std::unique_ptr<GoASTField> f(new GoASTField); +    GoASTExpr *t = FieldNamesAndType(f.get()); +    if (!t) +        t = AnonymousFieldType(); +    if (!t) +        return nullptr; + +    if (auto *tok = match(GoLexer::LIT_STRING)) +        f->SetTag(new GoASTBasicLit(*tok)); +    if (!Semicolon()) +        return syntaxerror(); +    return f.release(); +} + +GoASTExpr * +GoParser::FieldNamesAndType(GoASTField *field) +{ +    Rule r("FieldNames", this); +    for (auto *id = Identifier(); id; id = MoreIdentifierList()) +        field->AddNames(id); +    if (m_failed) +        return nullptr; +    GoASTExpr *t = Type(); +    if (t) +        return t; +    return r.error(); +} + +GoASTExpr * +GoParser::AnonymousFieldType() +{ +    bool pointer = match(GoLexer::OP_STAR); +    GoASTExpr *t = Type(); +    if (!t) +        return nullptr; +    if (pointer) +        return new GoASTStarExpr(t); +    return t; +} + +GoASTExpr * +GoParser::FunctionType() +{ +    if (!match(GoLexer::KEYWORD_FUNC)) +        return nullptr; +    return Signature(); +} + +GoASTFuncType * +GoParser::Signature() +{ +    auto *params = Params(); +    if (!params) +        return syntaxerror(); +    auto *result = Params(); +    if (!result) +    { +        if (auto *t = Type()) +        { +            result = new GoASTFieldList; +            auto *f = new GoASTField; +            f->SetType(t); +            result->AddList(f); +        } +    } +    return new GoASTFuncType(params, result); +} + +GoASTFieldList * +GoParser::Params() +{ +    if (!match(GoLexer::OP_LPAREN)) +        return nullptr; +    std::unique_ptr<GoASTFieldList> l(new GoASTFieldList); +    while (GoASTField *p = ParamDecl()) +    { +        l->AddList(p); +        if (!match(GoLexer::OP_COMMA)) +            break; +    } +    if (!mustMatch(GoLexer::OP_RPAREN)) +        return nullptr; +    return l.release(); +} + +GoASTField * +GoParser::ParamDecl() +{ +    std::unique_ptr<GoASTField> field(new GoASTField); +    GoASTIdent *id = Identifier(); +    if (id) +    { +        // Try `IdentifierList [ "..." ] Type`. +        // If that fails, backtrack and try `[ "..." ] Type`. +        Rule r("NamedParam", this); +        for (; id; id = MoreIdentifierList()) +            field->AddNames(id); +        GoASTExpr *t = ParamType(); +        if (t) +        { +            field->SetType(t); +            return field.release(); +        } +        field.reset(new GoASTField); +        r.error(); +    } +    GoASTExpr *t = ParamType(); +    if (t) +    { +        field->SetType(t); +        return field.release(); +    } +    return nullptr; +} + +GoASTExpr * +GoParser::ParamType() +{ +    bool dots = match(GoLexer::OP_DOTS); +    GoASTExpr *t = Type(); +    if (!dots) +        return t; +    if (!t) +        return syntaxerror(); +    return new GoASTEllipsis(t); +} + +GoASTExpr * +GoParser::InterfaceType() +{ +    if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE)) +        return nullptr; +    std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList); +    while (true) +    { +        Rule r("MethodSpec", this); +        // ( identifier Signature | TypeName ) ; +        std::unique_ptr<GoASTIdent> id(Identifier()); +        if (!id) +            break; +        GoASTExpr *type = Signature(); +        if (!type) +        { +            r.error(); +            id.reset(); +            type = Name(); +        } +        if (!Semicolon()) +            return syntaxerror(); +        auto *f = new GoASTField; +        if (id) +            f->AddNames(id.release()); +        f->SetType(type); +        methods->AddList(f); +    } +    if (!mustMatch(GoLexer::OP_RBRACE)) +        return nullptr; +    return new GoASTInterfaceType(methods.release()); +} + +GoASTExpr * +GoParser::MapType() +{ +    if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK))) +        return nullptr; +    std::unique_ptr<GoASTExpr> key(Type()); +    if (!key) +        return syntaxerror(); +    if (!mustMatch(GoLexer::OP_RBRACK)) +        return nullptr; +    auto *elem = Type(); +    if (!elem) +        return syntaxerror(); +    return new GoASTMapType(key.release(), elem); +} + +GoASTExpr * +GoParser::ChanType() +{ +    Rule r("chan", this); +    if (match(GoLexer::OP_LT_MINUS)) +    { +        if (match(GoLexer::KEYWORD_CHAN)) +        { +            auto *elem = Type(); +            if (!elem) +                return syntaxerror(); +            return new GoASTChanType(GoASTNode::eChanRecv, elem); +        } +        return r.error(); +    } +    return ChanType2(); +} + +GoASTExpr * +GoParser::ChanType2() +{ +    if (!match(GoLexer::KEYWORD_CHAN)) +        return nullptr; +    auto dir = GoASTNode::eChanBidir; +    if (match(GoLexer::OP_LT_MINUS)) +        dir = GoASTNode::eChanSend; +    auto *elem = Type(); +    if (!elem) +        return syntaxerror(); +    return new GoASTChanType(dir, elem); +} + +GoASTExpr * +GoParser::Type() +{ +    if (GoASTExpr *t = Type2()) +        return t; +    if (GoASTExpr *t = Name()) +        return t; +    if (GoASTExpr *t = ChanType()) +        return t; +    if (match(GoLexer::OP_STAR)) +    { +        GoASTExpr *t = Type(); +        if (!t) +            return syntaxerror(); +        return new GoASTStarExpr(t); +    } +    if (match(GoLexer::OP_LPAREN)) +    { +        std::unique_ptr<GoASTExpr> t(Type()); +        if (!t || !match(GoLexer::OP_RPAREN)) +            return syntaxerror(); +        return t.release(); +    } +    return nullptr; +} + +bool +GoParser::Semicolon() +{ +    if (match(GoLexer::OP_SEMICOLON)) +        return true; +    switch (peek()) +    { +        case GoLexer::OP_RPAREN: +        case GoLexer::OP_RBRACE: +        case GoLexer::TOK_EOF: +            return true; +        default: +            return false; +    } +} + +GoASTExpr * +GoParser::Name() +{ +    if (auto *id = Identifier()) +    { +        if (GoASTExpr *qual = QualifiedIdent(id)) +            return qual; +        return id; +    } +    return nullptr; +} + +GoASTExpr * +GoParser::QualifiedIdent(lldb_private::GoASTIdent *p) +{ +    Rule r("QualifiedIdent", this); +    llvm::SmallString<32> path(p->GetName().m_value); +    GoLexer::Token *next; +    bool have_slashes = false; +    // LLDB extension: support full/package/path.name +    while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER))) +    { +        have_slashes = true; +        path.append("/"); +        path.append(next->m_value); +    } +    if (match(GoLexer::OP_DOT)) +    { +        auto *name = Identifier(); +        if (name) +        { +            if (have_slashes) +            { +                p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path))); +            } +            return new GoASTSelectorExpr(p, name); +        } +    } +    return r.error(); +} + +llvm::StringRef +GoParser::CopyString(llvm::StringRef s) +{ +    return m_strings.insert(std::make_pair(s, 'x')).first->getKey(); +} + +void +GoParser::GetError(Error &error) +{ +    llvm::StringRef want; +    if (m_failed) +        want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last; +    else +        want = m_error; +    size_t len = m_lexer.BytesRemaining(); +    if (len > 10) +        len = 10; +    llvm::StringRef got; +    if (len == 0) +        got = "<eof>"; +    else +        got = m_lexer.GetString(len); +    error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str()); +} diff --git a/source/Plugins/ExpressionParser/Go/GoParser.h b/source/Plugins/ExpressionParser/Go/GoParser.h new file mode 100644 index 0000000000000..9ceb670ccd117 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.h @@ -0,0 +1,165 @@ +//===-- GoParser.h -----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoParser_h +#define liblldb_GoParser_h + +#include "lldb/lldb-private.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ +class GoParser +{ +  public: +    explicit GoParser(const char *src); + +    GoASTStmt *Statement(); + +    GoASTStmt *GoStmt(); +    GoASTStmt *ReturnStmt(); +    GoASTStmt *BranchStmt(); +    GoASTStmt *EmptyStmt(); +    GoASTStmt *ExpressionStmt(GoASTExpr *e); +    GoASTStmt *IncDecStmt(GoASTExpr *e); +    GoASTStmt *Assignment(GoASTExpr *e); +    GoASTBlockStmt *Block(); + +    GoASTExpr *MoreExpressionList();  // ["," Expression] +    GoASTIdent *MoreIdentifierList(); // ["," Identifier] + +    GoASTExpr *Expression(); +    GoASTExpr *UnaryExpr(); +    GoASTExpr *OrExpr(); +    GoASTExpr *AndExpr(); +    GoASTExpr *RelExpr(); +    GoASTExpr *AddExpr(); +    GoASTExpr *MulExpr(); +    GoASTExpr *PrimaryExpr(); +    GoASTExpr *Operand(); +    GoASTExpr *Conversion(); + +    GoASTExpr *Selector(GoASTExpr *e); +    GoASTExpr *IndexOrSlice(GoASTExpr *e); +    GoASTExpr *TypeAssertion(GoASTExpr *e); +    GoASTExpr *Arguments(GoASTExpr *e); + +    GoASTExpr *Type(); +    GoASTExpr *Type2(); +    GoASTExpr *ArrayOrSliceType(bool allowEllipsis); +    GoASTExpr *StructType(); +    GoASTExpr *FunctionType(); +    GoASTExpr *InterfaceType(); +    GoASTExpr *MapType(); +    GoASTExpr *ChanType(); +    GoASTExpr *ChanType2(); + +    GoASTExpr *Name(); +    GoASTExpr *QualifiedIdent(GoASTIdent *p); +    GoASTIdent *Identifier(); + +    GoASTField *FieldDecl(); +    GoASTExpr *AnonymousFieldType(); +    GoASTExpr *FieldNamesAndType(GoASTField *f); + +    GoASTFieldList *Params(); +    GoASTField *ParamDecl(); +    GoASTExpr *ParamType(); +    GoASTFuncType *Signature(); +    GoASTExpr *CompositeLit(); +    GoASTExpr *FunctionLit(); +    GoASTExpr *Element(); +    GoASTCompositeLit *LiteralValue(); + +    bool +    Failed() const +    { +        return m_failed; +    } +    bool +    AtEOF() const +    { +        return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size(); +    } + +    void GetError(Error &error); + +  private: +    class Rule; +    friend class Rule; + +    std::nullptr_t +    syntaxerror() +    { +        m_failed = true; +        return nullptr; +    } +    GoLexer::Token & +    next() +    { +        if (m_pos >= m_tokens.size()) +        { +            if (m_pos != 0 && +                (m_tokens.back().m_type == GoLexer::TOK_EOF || m_tokens.back().m_type == GoLexer::TOK_INVALID)) +                return m_tokens.back(); +            m_pos = m_tokens.size(); +            m_tokens.push_back(m_lexer.Lex()); +        } +        return m_tokens[m_pos++]; +    } +    GoLexer::TokenType +    peek() +    { +        GoLexer::Token &tok = next(); +        --m_pos; +        return tok.m_type; +    } +    GoLexer::Token * +    match(GoLexer::TokenType t) +    { +        GoLexer::Token &tok = next(); +        if (tok.m_type == t) +            return &tok; +        --m_pos; +        m_last_tok = t; +        return nullptr; +    } +    GoLexer::Token * +    mustMatch(GoLexer::TokenType t) +    { +        GoLexer::Token *tok = match(t); +        if (tok) +            return tok; +        return syntaxerror(); +    } +    bool Semicolon(); + +    GoASTStmt * +    FinishStmt(GoASTStmt *s) +    { +        if (!Semicolon()) +            m_failed = true; +        return s; +    } + +    llvm::StringRef CopyString(llvm::StringRef s); + +    GoLexer m_lexer; +    std::vector<GoLexer::Token> m_tokens; +    size_t m_pos; +    llvm::StringRef m_error; +    llvm::StringRef m_last; +    GoLexer::TokenType m_last_tok; +    llvm::StringMap<uint8_t> m_strings; +    bool m_failed; +}; +} + +#endif diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp new file mode 100644 index 0000000000000..3f12a2b6255bb --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -0,0 +1,756 @@ +//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include <stdio.h> +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +// C++ Includes +#include <cstdlib> +#include <memory> +#include <string> +#include <vector> + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" + +// Project includes +#include "GoUserExpression.h" + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataEncoder.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "Plugins/ExpressionParser/Go/GoAST.h" +#include "Plugins/ExpressionParser/Go/GoParser.h" + +using namespace lldb_private; +using namespace lldb; + +class GoUserExpression::GoInterpreter +{ +  public: +    GoInterpreter(ExecutionContext &exe_ctx, const char *expr) +        : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) +    { +        if (m_frame) +        { +            const SymbolContext &ctx = m_frame->GetSymbolContext(eSymbolContextFunction); +            ConstString fname = ctx.GetFunctionName(); +            if (fname.GetLength() > 0) +            { +                size_t dot = fname.GetStringRef().find('.'); +                if (dot != llvm::StringRef::npos) +                    m_package = llvm::StringRef(fname.AsCString(), dot); +            } +        } +    } + +    void +    set_use_dynamic(DynamicValueType use_dynamic) +    { +        m_use_dynamic = use_dynamic; +    } + +    bool Parse(); +    lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx); +    lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s); +    lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e); + +    ValueObjectSP +    VisitBadExpr(const GoASTBadExpr *e) +    { +        m_parser.GetError(m_error); +        return nullptr; +    } + +    ValueObjectSP VisitParenExpr(const GoASTParenExpr *e); +    ValueObjectSP VisitIdent(const GoASTIdent *e); +    ValueObjectSP VisitStarExpr(const GoASTStarExpr *e); +    ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e); +    ValueObjectSP VisitBasicLit(const GoASTBasicLit *e); +    ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e); +    ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e); +    ValueObjectSP VisitCallExpr(const GoASTCallExpr *e); + +    ValueObjectSP +    VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitBinaryExpr(const GoASTBinaryExpr *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitArrayType(const GoASTArrayType *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitChanType(const GoASTChanType *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitCompositeLit(const GoASTCompositeLit *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitEllipsis(const GoASTEllipsis *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitFuncType(const GoASTFuncType *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitFuncLit(const GoASTFuncLit *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitInterfaceType(const GoASTInterfaceType *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitKeyValueExpr(const GoASTKeyValueExpr *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitMapType(const GoASTMapType *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitSliceExpr(const GoASTSliceExpr *e) +    { +        return NotImplemented(e); +    } + +    ValueObjectSP +    VisitStructType(const GoASTStructType *e) +    { +        return NotImplemented(e); +    } + +    CompilerType EvaluateType(const GoASTExpr *e); + +    Error & +    error() +    { +        return m_error; +    } + +  private: +    std::nullptr_t +    NotImplemented(const GoASTExpr *e) +    { +        m_error.SetErrorStringWithFormat("%s node not implemented", e->GetKindName()); +        return nullptr; +    } + +    ExecutionContext m_exe_ctx; +    lldb::StackFrameSP m_frame; +    GoParser m_parser; +    DynamicValueType m_use_dynamic; +    Error m_error; +    llvm::StringRef m_package; +    std::vector<std::unique_ptr<GoASTStmt>> m_statements; +}; + +VariableSP +FindGlobalVariable(TargetSP target, llvm::Twine name) +{ +    ConstString fullname(name.str()); +    VariableList variable_list; +    const bool append = true; +    if (!target) +    { +        return nullptr; +    } +    const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 1, variable_list); +    if (match_count == 1) +    { +        return variable_list.GetVariableAtIndex(0); +    } +    return nullptr; +} + +CompilerType +LookupType(TargetSP target, ConstString name) +{ +    if (!target) +        return CompilerType(); +    SymbolContext sc; +    TypeList type_list; +    uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list); +    if (num_matches > 0) +    { +        return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); +    } +    return CompilerType(); +} + +GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, +                                   lldb::LanguageType language, ResultType desired_type, +                                   const EvaluateExpressionOptions &options) +    : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options) +{ +} + +bool +GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, +                        bool keep_result_in_memory, bool generate_debug_info) +{ +    InstallContext(exe_ctx); +    m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText())); +    if (m_interpreter->Parse()) +        return true; +    const char *error_cstr = m_interpreter->error().AsCString(); +    if (error_cstr && error_cstr[0]) +        error_stream.Printf("error: %s\n", error_cstr); +    else +        error_stream.Printf("error: expression can't be interpreted or run\n"); +    return false; +} + +lldb::ExpressionResults +GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, +                          lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +{ +    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + +    lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); +    lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + +    Process *process = exe_ctx.GetProcessPtr(); +    Target *target = exe_ctx.GetTargetPtr(); + +    if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped) +    { +        if (execution_policy == eExecutionPolicyAlways) +        { +            if (log) +                log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant =="); + +            error_stream.Printf("expression needed to run but couldn't"); + +            return execution_results; +        } +    } + +    m_interpreter->set_use_dynamic(options.GetUseDynamic()); +    ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); +    Error err = m_interpreter->error(); +    m_interpreter.reset(); + +    if (!result_val_sp) +    { +        const char *error_cstr = err.AsCString(); +        if (error_cstr && error_cstr[0]) +            error_stream.Printf("error: %s\n", error_cstr); +        else +            error_stream.Printf("error: expression can't be interpreted or run\n"); +        return lldb::eExpressionDiscarded; +    } +    result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); +    result->m_live_sp = result->m_frozen_sp = result_val_sp; +    result->m_flags |= ExpressionVariable::EVIsProgramReference; +    PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); +    if (pv != nullptr) +    { +        result->SetName(pv->GetNextPersistentVariableName()); +        pv->AddVariable(result); +    } +    return lldb::eExpressionCompleted; +} + +bool +GoUserExpression::GoInterpreter::Parse() +{ +    for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt; stmt.reset(m_parser.Statement())) +    { +        if (m_parser.Failed()) +            break; +        m_statements.emplace_back(std::move(stmt)); +    } +    if (m_parser.Failed() || !m_parser.AtEOF()) +        m_parser.GetError(m_error); + +    return m_error.Success(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) +{ +    m_exe_ctx = exe_ctx; +    ValueObjectSP result; +    for (const std::unique_ptr<GoASTStmt> &stmt : m_statements) +    { +        result = EvaluateStatement(stmt.get()); +        if (m_error.Fail()) +            return nullptr; +    } +    return result; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::EvaluateStatement(const lldb_private::GoASTStmt *stmt) +{ +    ValueObjectSP result; +    switch (stmt->GetKind()) +    { +        case GoASTNode::eBlockStmt: +        { +            const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt); +            for (size_t i = 0; i < block->NumList(); ++i) +                result = EvaluateStatement(block->GetList(i)); +            break; +        } +        case GoASTNode::eBadStmt: +            m_parser.GetError(m_error); +            break; +        case GoASTNode::eExprStmt: +        { +            const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt); +            return EvaluateExpr(expr->GetX()); +        } +        default: +            m_error.SetErrorStringWithFormat("%s node not supported", stmt->GetKindName()); +    } +    return result; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::EvaluateExpr(const lldb_private::GoASTExpr *e) +{ +    if (e) +        return e->Visit<ValueObjectSP>(this); +    return ValueObjectSP(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitParenExpr(const lldb_private::GoASTParenExpr *e) +{ +    return EvaluateExpr(e->GetX()); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) +{ +    ValueObjectSP val; +    if (m_frame) +    { +        VariableSP var_sp; +        std::string varname = e->GetName().m_value.str(); +        if (varname.size() > 1 && varname[0] == '$') +        { +            RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext(); +            const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1); +            if (reg) +            { +                std::string type; +                switch (reg->encoding) +                { +                    case lldb::eEncodingSint: +                        type.append("int"); +                        break; +                    case lldb::eEncodingUint: +                        type.append("uint"); +                        break; +                    case lldb::eEncodingIEEE754: +                        type.append("float"); +                        break; +                    default: +                        m_error.SetErrorString("Invaild register encoding"); +                        return nullptr; +                } +                switch (reg->byte_size) +                { +                    case 8: +                        type.append("64"); +                        break; +                    case 4: +                        type.append("32"); +                        break; +                    case 2: +                        type.append("16"); +                        break; +                    case 1: +                        type.append("8"); +                        break; +                    default: +                        m_error.SetErrorString("Invaild register size"); +                        return nullptr; +                } +                ValueObjectSP regVal = +                    ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]); +                CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type)); +                if (regVal) +                { +                    regVal = regVal->Cast(goType); +                    return regVal; +                } +            } +            m_error.SetErrorString("Invaild register name"); +            return nullptr; +        } +        VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false)); +        if (var_list_sp) +        { +            var_sp = var_list_sp->FindVariable(ConstString(varname)); +            if (var_sp) +                val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); +            else +            { +                // When a variable is on the heap instead of the stack, go records a variable +                // '&x' instead of 'x'. +                var_sp = var_list_sp->FindVariable(ConstString("&" + varname)); +                if (var_sp) +                { +                    val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); +                    if (val) +                        val = val->Dereference(m_error); +                    if (m_error.Fail()) +                        return nullptr; +                } +            } +        } +        if (!val) +        { +            m_error.Clear(); +            TargetSP target = m_frame->CalculateTarget(); +            if (!target) +            { +                m_error.SetErrorString("No target"); +                return nullptr; +            } +            var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value); +            if (var_sp) +                return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic); +        } +    } +    if (!val) +        m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str()); +    return val; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) +{ +    ValueObjectSP target = EvaluateExpr(e->GetX()); +    if (!target) +        return nullptr; +    return target->Dereference(m_error); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e) +{ +    ValueObjectSP target = EvaluateExpr(e->GetX()); +    if (target) +    { +        if (target->GetCompilerType().IsPointerType()) +        { +            target = target->Dereference(m_error); +            if (m_error.Fail()) +                return nullptr; +        } +        ConstString field(e->GetSel()->GetName().m_value); +        ValueObjectSP result = target->GetChildMemberWithName(field, true); +        if (!result) +            m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString()); +        return result; +    } +    if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) +    { +        if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(), +                                                   package->GetName().m_value + "." + e->GetSel()->GetName().m_value)) +        { +            if (m_frame) +            { +                m_error.Clear(); +                return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic); +            } +        } +    } +    if (const GoASTBasicLit *packageLit = llvm::dyn_cast<GoASTBasicLit>(e->GetX())) +    { +        if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) +        { +            std::string value = packageLit->GetValue().m_value.str(); +            value = value.substr(1, value.size() - 2); +            if (VariableSP global = +                    FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value)) +            { +                if (m_frame) +                { +                    m_error.Clear(); +                    return m_frame->TrackGlobalVariable(global, m_use_dynamic); +                } +            } +        } +    } +    // EvaluateExpr should have already set m_error. +    return target; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitBasicLit(const lldb_private::GoASTBasicLit *e) +{ +    std::string value = e->GetValue().m_value.str(); +    if (e->GetValue().m_type != GoLexer::LIT_INTEGER) +    { +        m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str()); +        return nullptr; +    } +    errno = 0; +    int64_t intvalue = strtol(value.c_str(), nullptr, 0); +    if (errno != 0) +    { +        m_error.SetErrorToErrno(); +        return nullptr; +    } +    DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0)); +    TargetSP target = m_exe_ctx.GetTargetSP(); +    if (!target) +    { +        m_error.SetErrorString("No target"); +        return nullptr; +    } +    ByteOrder order = target->GetArchitecture().GetByteOrder(); +    uint8_t addr_size = target->GetArchitecture().GetAddressByteSize(); +    DataEncoder enc(buf, order, addr_size); +    enc.PutU64(0, static_cast<uint64_t>(intvalue)); +    DataExtractor data(buf, order, addr_size); + +    CompilerType type = LookupType(target, ConstString("int64")); +    return ValueObject::CreateValueObjectFromData(nullptr, data, m_exe_ctx, type); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e) +{ +    ValueObjectSP target = EvaluateExpr(e->GetX()); +    if (!target) +        return nullptr; +    ValueObjectSP index = EvaluateExpr(e->GetIndex()); +    if (!index) +        return nullptr; +    bool is_signed; +    if (!index->GetCompilerType().IsIntegerType(is_signed)) +    { +        m_error.SetErrorString("Unsupported index"); +        return nullptr; +    } +    size_t idx; +    if (is_signed) +        idx = index->GetValueAsSigned(0); +    else +        idx = index->GetValueAsUnsigned(0); +    if (GoASTContext::IsGoSlice(target->GetCompilerType())) +    { +        target = target->GetStaticValue(); +        ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true); +        if (cap) +        { +            uint64_t capval = cap->GetValueAsUnsigned(0); +            if (idx >= capval) +            { +                m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval); +                return nullptr; +            } +        } +        target = target->GetChildMemberWithName(ConstString("array"), true); +        if (target && m_use_dynamic != eNoDynamicValues) +        { +            ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic); +            if (dynamic) +                target = dynamic; +        } +        if (!target) +            return nullptr; +        return target->GetSyntheticArrayMember(idx, true); +    } +    return target->GetChildAtIndex(idx, true); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) +{ +    ValueObjectSP x = EvaluateExpr(e->GetX()); +    if (!x) +        return nullptr; +    switch (e->GetOp()) +    { +        case GoLexer::OP_AMP: +        { +            CompilerType type = x->GetCompilerType().GetPointerType(); +            uint64_t address = x->GetAddressOf(); +            return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type); +        } +        case GoLexer::OP_PLUS: +            return x; +        default: +            m_error.SetErrorStringWithFormat("Operator %s not supported", +                                             GoLexer::LookupToken(e->GetOp()).str().c_str()); +            return nullptr; +    } +} + +CompilerType +GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) +{ +    TargetSP target = m_exe_ctx.GetTargetSP(); +    if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) +    { +        CompilerType result = LookupType(target, ConstString(id->GetName().m_value)); +        if (result.IsValid()) +            return result; +        std::string fullname = (m_package + "." + id->GetName().m_value).str(); +        result = LookupType(target, ConstString(fullname)); +        if (!result) +            m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); +        return result; +    } +    if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) +    { +        std::string package; +        if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) +        { +            package = pkg_node->GetName().m_value.str(); +        } +        else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) +        { +            if (str_node->GetValue().m_type == GoLexer::LIT_STRING) +            { +                package = str_node->GetValue().m_value.substr(1).str(); +                package.resize(package.length() - 1); +            } +        } +        if (package.empty()) +        { +            m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName()); +            return CompilerType(); +        } +        std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str(); +        CompilerType result = LookupType(target, ConstString(fullname)); +        if (!result) +            m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); +        return result; +    } +    if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) +    { +        CompilerType elem = EvaluateType(star->GetX()); +        return elem.GetPointerType(); +    } +    if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e)) +        return EvaluateType(paren->GetX()); +    if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) +    { +        CompilerType elem = EvaluateType(array->GetElt()); +    } + +    m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName()); +    return CompilerType(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitCallExpr(const lldb_private::GoASTCallExpr *e) +{ +    ValueObjectSP x = EvaluateExpr(e->GetFun()); +    if (x || e->NumArgs() != 1) +    { +        m_error.SetErrorStringWithFormat("Code execution not supported"); +        return nullptr; +    } +    m_error.Clear(); +    CompilerType type = EvaluateType(e->GetFun()); +    if (!type) +    { +        return nullptr; +    } +    ValueObjectSP value = EvaluateExpr(e->GetArgs(0)); +    if (!value) +        return nullptr; +    // TODO: Handle special conversions +    return value->Cast(type); +} + +GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo) +{ +} + +ConstString +GoPersistentExpressionState::GetNextPersistentVariableName() +{ +    char name_cstr[256]; +    // We can't use the same variable format as clang. +    ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++); +    ConstString name(name_cstr); +    return name; +} + +void +GoPersistentExpressionState::RemovePersistentVariable(lldb::ExpressionVariableSP variable) +{ +    RemoveVariable(variable); + +    const char *name = variable->GetName().AsCString(); + +    if (*(name++) != '$') +        return; +    if (*(name++) != 'g') +        return; +    if (*(name++) != 'o') +        return; + +    if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) +        m_next_persistent_variable_id--; +} diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h new file mode 100644 index 0000000000000..b429c68f023d5 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -0,0 +1,98 @@ +//===-- GoUserExpression.h --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoUserExpression_h_ +#define liblldb_GoUserExpression_h_ + +// C Includes +// C++ Includes +#include <memory> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ +class GoParser; + +class GoPersistentExpressionState : public PersistentExpressionState +{ +  public: +    GoPersistentExpressionState(); + +    ConstString GetNextPersistentVariableName() override; + +    void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; + +    lldb::addr_t +    LookupSymbol(const ConstString &name) override +    { +        return LLDB_INVALID_ADDRESS; +    } + +    static bool +    classof(const PersistentExpressionState *pv) +    { +        return pv->getKind() == PersistentExpressionState::eKindGo; +    } + +  private: +    uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). +}; + +//---------------------------------------------------------------------- +/// @class GoUserExpression GoUserExpression.h "lldb/Expression/GoUserExpression.h" +/// @brief Encapsulates a single expression for use with Go +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command.  GoUserExpression encapsulates +/// the objects needed to parse and interpret an expression. +//---------------------------------------------------------------------- +class GoUserExpression : public UserExpression +{ +  public: +    GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, +                     lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); + +    bool +    Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, +          bool keep_result_in_memory, bool generate_debug_info) override; + +    lldb::ExpressionResults +    Execute(Stream &error_stream, ExecutionContext &exe_ctx, +            const EvaluateExpressionOptions &options, +            lldb::UserExpressionSP &shared_ptr_to_me, +            lldb::ExpressionVariableSP &result) override; + +    bool +    CanInterpret() override +    { +        return true; +    } +    bool +    FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, +                         lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, +                         lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override +    { +        return true; +    } + +  private: +    class GoInterpreter; +    std::unique_ptr<GoInterpreter> m_interpreter; +}; + +} // namespace lldb_private + +#endif // liblldb_GoUserExpression_h_ diff --git a/source/Plugins/ExpressionParser/Go/gen_go_ast.py b/source/Plugins/ExpressionParser/Go/gen_go_ast.py new file mode 100644 index 0000000000000..05b589a9976cb --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/gen_go_ast.py @@ -0,0 +1,356 @@ +import StringIO + +def addNodes(): +    addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr") +    addNode("AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool") +    addNode("BadDecl", "Decl") +    addNode("BadExpr", "Expr") +    addNode("BadStmt", "Stmt") +    addNode("BasicLit", "Expr", "value", "Token") +    addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType") +    addNode("BlockStmt", "Stmt", "list", "[]Stmt") +    addNode("Ident", "Expr", "name", "Token") +    addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType") +    addNode("CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool") +    addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt") +    addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr") +    addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt") +    addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr") +    addNode("DeclStmt", "Stmt", "decl", "Decl") +    addNode("DeferStmt", "Stmt", "call", "CallExpr") +    addNode("Ellipsis", "Expr", "elt", "Expr") +    addNode("EmptyStmt", "Stmt") +    addNode("ExprStmt", "Stmt", "x", "Expr") +    addNode("Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit") +    addNode("FieldList", "Node", "list", "[]Field") +    addNode("ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt") +    addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList") +    addNode("FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt") +    addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt") +    addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec") +    addNode("GoStmt", "Stmt", "call", "CallExpr") +    addNode("IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt") +    addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit") +    addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType") +    addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr") +    addNode("InterfaceType", "Expr", "methods", "FieldList") +    addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr") +    addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt") +    addNode("MapType", "Expr", "key", "Expr", "value", "Expr") +    addNode("ParenExpr", "Expr", "x", "Expr") +    addNode("RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt") +    addNode("ReturnStmt", "Stmt", "results", "[]Expr") +    addNode("SelectStmt", "Stmt", "body", "BlockStmt") +    addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident") +    addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr") +    addNode("SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool") +    addNode("StarExpr", "Expr", "x", "Expr") +    addNode("StructType", "Expr", "fields", "FieldList") +    addNode("SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt") +    addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr") +    addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr") +    addNode("TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt") +    addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr") +    addNode("ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr") +    addParent("Decl", "Node") +    addParent("Expr", "Node") +    addParent("Spec", "Node") +    addParent("Stmt", "Node") + + +class Member(object): +    def __init__(self, name, typename): +        self.title = name.title() +        self.sname = name +        self.mname = 'm_' + name +        self.is_list = typename.startswith("[]") +        self.is_value = isValueType(typename) +        if self.is_value: +            self.argtype = typename +            self.mtype = typename +        elif self.is_list: +            self.argtype = 'GoAST' + typename[2:] +            self.mtype = 'std::vector<std::unique_ptr<%s> >' % self.argtype +        else: +            self.argtype = 'GoAST' + typename +            self.mtype = 'std::unique_ptr<%s>' % self.argtype +            self.mname = self.mname + '_up' +     + +kinds = {} +parentClasses = StringIO.StringIO() +childClasses = StringIO.StringIO() +walker = StringIO.StringIO() + +def startClass(name, parent, out): +    out.write(""" +class GoAST%s : public GoAST%s +{ +  public: +""" % (name, parent)) + +def endClass(name, out): +    out.write(""" +    %(name)s(const %(name)s &) = delete; +    const %(name)s &operator=(const %(name)s &) = delete; +}; +""" % {'name': 'GoAST' + name}) + +def addNode(name, parent, *children): +    startClass(name, parent, childClasses) +    l = kinds.setdefault(parent, []) +    l.append(name) +    children = createMembers(name, children) +    addConstructor(name, parent, children) +    childClasses.write(""" +    const char * +    GetKindName() const override +    { +        return "%(name)s"; +    } + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() == e%(name)s; +    } +    """ % {'name':name}) +    addChildren(name, children) +    endClass(name, childClasses) + +def isValueType(typename): +    if typename[0].islower(): +        return True +    if typename[0].isupper(): +        return typename.startswith('Token') or typename == 'ChanDir' +    return False + + +def createMembers(name, children): +    l = len(children) +    if (l % 2) != 0: +        raise Exception("Invalid children for %s: %s" % (name, children)) +    return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)] + + +def addConstructor(name, parent, children): +    for c in children: +        if c.is_list: +            children = [x for x in children if x.is_value] +            break +    childClasses.write('    ') +    if len(children) == 1: +        childClasses.write('explicit ') +    childClasses.write('GoAST%s(' % name) +    for i in xrange(len(children)): +        if i > 0: +            childClasses.write(', ') + +        c = children[i] +        if c.is_value: +            childClasses.write(c.argtype) +            childClasses.write(' ') +        else: +            childClasses.write('%s *' % c.argtype) +        childClasses.write(c.sname) +    childClasses.write(') : GoAST%s(e%s)' % (parent, name)) +    for c in children: +        childClasses.write(', ') +        childClasses.write('%(mname)s(%(sname)s)' % c.__dict__) +    childClasses.write(""" {} +    ~GoAST%s() override = default; +""" % name) + +     +def addChildren(name, children): +    if len(children) == 0: +        return +    walker.write(""" +    case e%(n)s: +        { +            GoAST%(n)s *n = llvm::cast<GoAST%(n)s>(this); +            (void)n;""" % {'n':name}) +    for c in children: +        if c.is_list: +            childClasses.write(""" +    size_t +    Num%(title)s() const +    { +        return %(mname)s.size(); +    } +    const %(argtype)s * +    Get%(title)s(int i) const +    { +        return %(mname)s[i].get(); +    } +    void +    Add%(title)s(%(argtype)s *%(sname)s) +    { +        %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s)); +    } +""" % c.__dict__) +            walker.write(""" +            for (auto& e : n->%s) { v(e.get()); }""" % c.mname) +        else: +            const = '' +            get = '' +            set = '' +            t = c.argtype +            if isValueType(t): +                set = '%(mname)s = %(sname)s' % c.__dict__ +                t = t + ' ' +            else: +                t = t + ' *' +                const = 'const ' +                get = '.get()' +                set = '%(mname)s.reset(%(sname)s)' % c.__dict__ +                walker.write(""" +            v(n->%s.get());""" % c.mname) +            childClasses.write(""" +    %(const)s%(type)s +    Get%(title)s() const +    { +        return %(mname)s%(get)s; +    } +    void +    Set%(title)s(%(type)s%(sname)s) +    { +        %(set)s; +    } +""" % {'const':const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname}) +    childClasses.write('\n  private:\n    friend class GoASTNode;\n') +    walker.write(""" +            return; +        }""") +    for c in children: +        childClasses.write('    %s %s;\n' %(c.mtype, c.mname)) +     + +def addParent(name, parent): +    startClass(name, parent, parentClasses) +    l = kinds[name] +    minName = l[0] +    maxName = l[-1] +    parentClasses.write("""    template <typename R, typename V> R Visit(V *v) const; + +    static bool +    classof(const GoASTNode *n) +    { +        return n->GetKind() >= e%s && n->GetKind() <= e%s; +    } + +  protected: +    explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { } +  private: +""" % (minName, maxName, name)) +    endClass(name, parentClasses) +     +addNodes() + +print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// DO NOT EDIT. +// Generated by gen_go_ast.py + +#ifndef liblldb_GoAST_h +#define liblldb_GoAST_h + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "llvm/Support/Casting.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ + +class GoASTNode +{ +  public: +    typedef GoLexer::TokenType TokenType; +    typedef GoLexer::Token Token; +    enum ChanDir +    { +        eChanBidir, +        eChanSend, +        eChanRecv, +    }; +    enum NodeKind +    {""" +for l in kinds.itervalues(): +    for x in l: +        print "        e%s," % x +print """    }; + +    virtual ~GoASTNode() = default; + +    NodeKind +    GetKind() const +    { +        return m_kind; +    } + +    virtual const char *GetKindName() const = 0; + +    template <typename V> void WalkChildren(V &v); + +  protected: +    explicit GoASTNode(NodeKind kind) : m_kind(kind) { } + +  private: +    const NodeKind m_kind; +     +    GoASTNode(const GoASTNode &) = delete; +    const GoASTNode &operator=(const GoASTNode &) = delete; +}; +""" + + +print parentClasses.getvalue() +print childClasses.getvalue() + +for k, l in kinds.iteritems(): +    if k == 'Node': +        continue +    print """ +template <typename R, typename V> +R GoAST%s::Visit(V* v) const +{ +    switch(GetKind()) +    {""" % k +    for subtype in l: +        print """    case e%(n)s: +        return v->Visit%(n)s(llvm::cast<const GoAST%(n)s>(this));""" % {'n':subtype} + +    print """    default: +        assert(false && "Invalid kind"); +    } +}""" + +print """ +template <typename V> +void GoASTNode::WalkChildren(V &v) +{ +    switch (m_kind) +    { +""" +print walker.getvalue() +print""" +        case eEmptyStmt: +        case eBadDecl: +        case eBadExpr: +        case eBadStmt: +          break; +    } +} + +}  // namespace lldb_private + +#endif +""" diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 95ae549e0e4b3..d646d4d4754a1 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -290,9 +290,8 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re  uint32_t  EmulateInstructionARM::GetFramePointerRegisterNumber () const  { -    if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android) +    if (m_arch.GetTriple().isAndroid())          return LLDB_INVALID_REGNUM; // Don't use frame pointer on android -      bool is_apple = false;      if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)          is_apple = true; @@ -301,6 +300,8 @@ EmulateInstructionARM::GetFramePointerRegisterNumber () const              case llvm::Triple::Darwin:              case llvm::Triple::MacOSX:              case llvm::Triple::IOS: +            case llvm::Triple::TvOS: +            case llvm::Triple::WatchOS:                  is_apple = true;                  break;              default: @@ -387,9 +388,8 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc      }  #endif -    bool conditional = false;      bool success = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          const uint32_t addr_byte_size = GetAddressByteSize();          const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -442,10 +442,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc          uint32_t i;          EmulateInstruction::Context context; -        if (conditional) -            context.type = EmulateInstruction::eContextRegisterStore; -        else -            context.type = EmulateInstruction::eContextPushRegisterOnStack; +        context.type = EmulateInstruction::eContextPushRegisterOnStack;          RegisterInfo reg_info;          RegisterInfo sp_reg;          GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -511,8 +508,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco      bool success = false; -    bool conditional = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          const uint32_t addr_byte_size = GetAddressByteSize();          const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -574,10 +570,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco          uint32_t i, data;          EmulateInstruction::Context context; -        if (conditional) -            context.type = EmulateInstruction::eContextRegisterLoad; -        else -            context.type = EmulateInstruction::eContextPopRegisterOffStack; +        context.type = EmulateInstruction::eContextPopRegisterOffStack;          RegisterInfo sp_reg;          GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -586,7 +579,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco          {              if (BitIsSet (registers, i))              { -                context.SetRegisterPlusOffset (sp_reg, addr - sp); +                context.SetAddress(addr);                  data = MemARead(context, addr, 4, 0, &success);                  if (!success)                      return false;     @@ -900,12 +893,12 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding                  break;              case eEncodingA1: -                // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); +                // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);                  Rd = Bits32 (opcode, 15, 12);                  setflags = BitIsSet (opcode, 20);                  imm32 = ARMExpandImm_C (opcode, APSR_C, carry); -                // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; +                // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;                  if ((Rd == 15) && setflags)                      return EmulateSUBSPcLrEtc (opcode, encoding); @@ -1971,9 +1964,8 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding      }  #endif -    bool conditional = false;      bool success = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          const uint32_t addr_byte_size = GetAddressByteSize();          const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2018,10 +2010,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding              addr = sp;          EmulateInstruction::Context context; -        if (conditional) -            context.type = EmulateInstruction::eContextRegisterStore; -        else -            context.type = EmulateInstruction::eContextPushRegisterOnStack; +        context.type = EmulateInstruction::eContextPushRegisterOnStack;          RegisterInfo sp_reg;          RegisterInfo dwarf_reg; @@ -2082,8 +2071,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en  #endif      bool success = false; -    bool conditional = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          const uint32_t addr_byte_size = GetAddressByteSize();          const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2125,10 +2113,8 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en          uint32_t i;          EmulateInstruction::Context context; -        if (conditional) -            context.type = EmulateInstruction::eContextRegisterStore; -        else -            context.type = EmulateInstruction::eContextPushRegisterOnStack; +        context.type = EmulateInstruction::eContextPushRegisterOnStack; +          RegisterInfo dwarf_reg;          RegisterInfo sp_reg;          GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -2178,8 +2164,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc  #endif      bool success = false; -    bool conditional = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          const uint32_t addr_byte_size = GetAddressByteSize();          const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2222,17 +2207,15 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc          uint64_t data; // uint64_t to accommodate 64-bit registers.          EmulateInstruction::Context context; -        if (conditional) -            context.type = EmulateInstruction::eContextRegisterLoad; -        else -            context.type = EmulateInstruction::eContextPopRegisterOffStack; +        context.type = EmulateInstruction::eContextPopRegisterOffStack; +          RegisterInfo dwarf_reg;          RegisterInfo sp_reg;          GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);          for (i=0; i<regs; ++i)          {              GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); -            context.SetRegisterPlusOffset (sp_reg, addr - sp); +            context.SetAddress(addr);              data = MemARead(context, addr, reg_byte_size, 0, &success);              if (!success)                  return false;     @@ -3462,8 +3445,7 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco  #endif      bool success = false; -    bool conditional = false; -    if (ConditionPassed(opcode, &conditional)) +    if (ConditionPassed(opcode))      {          uint32_t n;          uint32_t registers = 0; @@ -3536,10 +3518,8 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco                  context.SetRegisterPlusOffset (dwarf_reg, offset);                  if (wback && (n == 13)) // Pop Instruction                  { -                    if (conditional) -                        context.type = EmulateInstruction::eContextRegisterLoad; -                    else -                        context.type = EmulateInstruction::eContextPopRegisterOffStack; +                    context.type = EmulateInstruction::eContextPopRegisterOffStack; +                    context.SetAddress(base_address + offset);                  }                  // R[i] = MemA [address, 4]; address = address + 4; @@ -4459,7 +4439,7 @@ EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding en                  break;              case eEncodingA1: -                // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;  +                // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH;                   if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)                  {                      // See Push @@ -4801,7 +4781,11 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding              address = base_address;          EmulateInstruction::Context context; -        context.type = eContextRegisterStore; +        if (n == 13) +            context.type = eContextPushRegisterOnStack; +        else +            context.type = eContextRegisterStore; +          RegisterInfo base_reg;          GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); @@ -4829,8 +4813,12 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding          // if wback then R[n] = offset_addr;          if (wback)          { -            context.type = eContextRegisterLoad; +            if (n == 13) +                context.type = eContextAdjustStackPointer; +            else +                context.type = eContextAdjustBaseRegister;              context.SetAddress (offset_addr); +              if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))                  return false;          } @@ -9579,7 +9567,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding      if ConditionPassed() then          EncodingSpecificOperations();          shifted = Shift(R[m], shift_t, shift_n, APSR.C); -        (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ); +        (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');          if d == 15 then // Can only occur for ARM encoding              ALUWritePC(result); // setflags is always FALSE here          else @@ -9604,7 +9592,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding          switch (encoding)          {              case eEncodingT1: -                // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ); +                // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');                  d = Bits32 (opcode, 11, 8);                  m = Bits32 (opcode, 3, 0);                  setflags = BitIsSet (opcode, 20); @@ -9622,12 +9610,12 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding                  break;              case eEncodingA1: -                // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ); +                // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');                  d = Bits32 (opcode, 15, 12);                  m = Bits32 (opcode, 3, 0);                  setflags = BitIsSet (opcode, 20); -                // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; +                // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;                  if (d == 15 && setflags)                      EmulateSUBSPcLrEtc (opcode, encoding); @@ -9648,7 +9636,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding          if (!success)              return false; -        // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ); +        // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');          uint32_t sp_val = ReadCoreReg (SP_REG, &success);          if (!success)              return false; @@ -9679,7 +9667,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod          EncodingSpecificOperations();          shift_n = UInt(R[s]<7:0>);          shifted = Shift(R[m], shift_t, shift_n, APSR.C); -        (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ); +        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');          R[d] = result;          if setflags then              APSR.N = result<31>; @@ -9708,7 +9696,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod                  m = Bits32 (opcode, 3, 0);                  s = Bits32 (opcode, 11, 8); -                // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type); +                // setflags = (S == '1'); shift_t = DecodeRegShift(type);                  setflags = BitIsSet (opcode, 20);                  shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); @@ -9737,7 +9725,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod          if (!success)              return false; -        // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ); +        // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');          uint32_t Rn = ReadCoreReg (n, &success);          if (!success)              return false; @@ -9776,7 +9764,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e      if ConditionPassed() then          EncodingSpecificOperations();          shifted = Shift(R[m], shift_t, shift_n, APSR.C); -        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ); +        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');          if d == 15 then // Can only occur for ARM encoding              ALUWritePC(result); // setflags is always FALSE here          else @@ -9839,14 +9827,14 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e                  break;              case eEncodingA1: -                // if Rn == Ô1101Õ then SEE SUB (SP minus register); -                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ); +                // if Rn == '1101' then SEE SUB (SP minus register); +                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');                  d = Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16);                  m = Bits32 (opcode, 3, 0);                  setflags = BitIsSet (opcode, 20); -                // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; +                // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;                  if ((d == 15) && setflags)                      EmulateSUBSPcLrEtc (opcode, encoding); @@ -9868,7 +9856,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e          if (!success)              return false; -        // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ); +        // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');          uint32_t Rn = ReadCoreReg (n, &success);          if (!success)              return false; @@ -9929,7 +9917,7 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en          switch (encoding)          {              case eEncodingT1: -                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);                  d = Bits32 (opcode, 11, 8);                  t = Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16); @@ -10037,13 +10025,13 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi          switch (encoding)          {              case eEncodingA1: -                // if P == Ô0Õ && W == Ô1Õ then SEE STRBT; +                // if P == '0' && W == '1' then SEE STRBT;                  // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);                  t = Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 11, 0); -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10135,14 +10123,14 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin          switch (encoding)          {              case eEncodingA1: -                // if P == Ô0Õ && W == Ô1Õ then SEE STRT; -                // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH; +                // if P == '0' && W == '1' then SEE STRT; +                // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;                  // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);                  t = Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 11, 0); -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10247,15 +10235,15 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc          switch (encoding)          {              case eEncodingT1: -                //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                //if Rn == Ô1111Õ then SEE LDRD (literal); -                //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                //if P == '0' && W == '0' then SEE 'Related encodings'; +                //if Rn == '1111' then SEE LDRD (literal); +                //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);                  t = Bits32 (opcode, 15, 12);                  t2 = Bits32 (opcode, 11, 8);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 7, 0) << 2; -                //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ); +                //index = (P == '1'); add = (U == '1'); wback = (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21); @@ -10271,8 +10259,8 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc                  break;              case eEncodingA1: -                //if Rn == Ô1111Õ then SEE LDRD (literal); -                //if Rt<0> == Ô1Õ then UNPREDICTABLE; +                //if Rn == '1111' then SEE LDRD (literal); +                //if Rt<0> == '1' then UNPREDICTABLE;                  //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);                  t = Bits32 (opcode, 15, 12);                  if (BitIsSet (t, 0)) @@ -10281,12 +10269,12 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc                  n = Bits32 (opcode, 19, 16);                  imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); -                //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); -                //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; +                //if P == '0' && W == '1' then UNPREDICTABLE;                  if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))                      return false; @@ -10327,8 +10315,11 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc          GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);          EmulateInstruction::Context context; -        context.type = eContextRegisterLoad; -        context.SetRegisterPlusOffset (base_reg, address - Rn); +        if (n == 13) +            context.type = eContextPopRegisterOffStack; +        else +            context.type = eContextRegisterLoad; +        context.SetAddress(address);          const uint32_t addr_byte_size = GetAddressByteSize();          uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); @@ -10339,8 +10330,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc              return false;          //R[t2] = MemA[address+4,4]; -                   -        context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); +        context.SetAddress(address + 4);          data = MemARead (context, address + 4, addr_byte_size, 0, &success);          if (!success)              return false; @@ -10392,7 +10382,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco          switch (encoding)          {              case eEncodingA1: -                // if Rt<0> == Ô1Õ then UNPREDICTABLE; +                // if Rt<0> == '1' then UNPREDICTABLE;                  // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);                  t = Bits32 (opcode, 15, 12);                  if (BitIsSet (t, 0)) @@ -10401,12 +10391,12 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco                  n = Bits32 (opcode, 19, 16);                  m = Bits32 (opcode, 3, 0); -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); -                // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; +                // if P == '0' && W == '1' then UNPREDICTABLE;                    if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))                    return false; @@ -10454,8 +10444,11 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco              address = Rn;          EmulateInstruction::Context context; -        context.type = eContextRegisterLoad; -        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); +        if (n == 13) +            context.type = eContextPopRegisterOffStack; +        else +            context.type = eContextRegisterLoad; +        context.SetAddress(address);          // R[t] = MemA[address,4];          const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10519,14 +10512,14 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding          switch (encoding)          {              case eEncodingT1: -                // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // if P == '0' && W == '0' then SEE 'Related encodings'; +                // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);                  t = Bits32 (opcode, 15, 12);                  t2 = Bits32 (opcode, 11, 8);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 7, 0) << 2; -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21); @@ -10542,7 +10535,7 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding                  break;              case eEncodingA1: -                // if Rt<0> == Ô1Õ then UNPREDICTABLE; +                // if Rt<0> == '1' then UNPREDICTABLE;                  // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);                  t = Bits32 (opcode, 15, 12);                  if (BitIsSet (t, 0)) @@ -10552,12 +10545,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding                  n = Bits32 (opcode, 19, 16);                  imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); -                // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; +                // if P == '0' && W == '1' then UNPREDICTABLE;                  if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))                      return false; @@ -10605,7 +10598,10 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding              return false;          EmulateInstruction::Context context; -        context.type = eContextRegisterStore; +        if (n == 13) +            context.type = eContextPushRegisterOnStack; +        else +            context.type = eContextRegisterStore;          context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);          const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10627,9 +10623,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding          //if wback then R[n] = offset_addr;          if (wback)          { -            context.type = eContextAdjustBaseRegister; +            if (n == 13) +                context.type = eContextAdjustStackPointer; +            else +                context.type = eContextAdjustBaseRegister;              context.SetAddress (offset_addr); -                   +              if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))                  return false;          } @@ -10667,7 +10666,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding          switch (encoding)          {              case eEncodingA1: -                // if Rt<0> == Ô1Õ then UNPREDICTABLE; +                // if Rt<0> == '1' then UNPREDICTABLE;                  // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);                  t = Bits32 (opcode, 15, 12);                  if (BitIsSet (t, 0)) @@ -10677,12 +10676,12 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding                  n = Bits32 (opcode, 19, 16);                  m = Bits32 (opcode, 3, 0); -                // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); +                // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');                  index = BitIsSet (opcode, 24);                  add = BitIsSet (opcode, 23);                  wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); -                // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; +                // if P == '0' && W == '1' then UNPREDICTABLE;                  if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))                     return false; @@ -10737,7 +10736,11 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding              return false;          EmulateInstruction::Context context; -        context.type = eContextRegisterStore; +        if (t == 13) +            context.type = eContextPushRegisterOnStack; +        else +            context.type = eContextRegisterStore; +                  GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);          context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); @@ -10808,25 +10811,25 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc          {              case eEncodingT1:              case eEncodingA1: -                // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP; -                // if P == Ô1Õ && W == Ô0Õ then SEE VLDR; -                // if P == U && W == Ô1Õ then UNDEFINED; +                // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; +                // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; +                // if P == '1' && W == '0' then SEE VLDR; +                // if P == U && W == '1' then UNDEFINED;                  if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))                      return false;                  // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) -                // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ); +                // single_regs = FALSE; add = (U == '1'); wback = (W == '1');                  single_regs = false;                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21); -                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);                  d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 7, 0) << 2; -                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ. +                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.                  regs = Bits32 (opcode, 7, 0) / 2;                  // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -10841,22 +10844,22 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc              case eEncodingT2:              case eEncodingA2: -                // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP; -                // if P == Ô1Õ && W == Ô0Õ then SEE VLDR; -                // if P == U && W == Ô1Õ then UNDEFINED; +                // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; +                // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; +                // if P == '1' && W == '0' then SEE VLDR; +                // if P == U && W == '1' then UNDEFINED;                  if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))                      return false;                  // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) -                // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn); +                // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);                  single_regs = true;                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21);                  d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);                  n = Bits32 (opcode, 19, 16); -                // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8); +                // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);                  imm32 = Bits32 (opcode, 7, 0) << 2;                  regs = Bits32 (opcode, 7, 0); @@ -11000,25 +11003,25 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc          {              case eEncodingT1:              case eEncodingA1: -                // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH; -                // if P == Ô1Õ && W == Ô0Õ then SEE VSTR; -                // if P == U && W == Ô1Õ then UNDEFINED; +                // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; +                // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; +                // if P == '1' && W == '0' then SEE VSTR; +                // if P == U && W == '1' then UNDEFINED;                  if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))                      return false;                  // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) -                // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ); +                // single_regs = FALSE; add = (U == '1'); wback = (W == '1');                  single_regs = false;                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21); -                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);                  d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);                  n = Bits32 (opcode, 19, 16);                  imm32 = Bits32 (opcode, 7, 0) << 2; -                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ. +                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.                  regs = Bits32 (opcode, 7, 0) / 2;                  // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -11033,22 +11036,22 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc              case eEncodingT2:              case eEncodingA2: -                // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; -                // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH; -                // if P == Ô1Õ && W == Ô0Õ then SEE VSTR; -                // if P == U && W == Ô1Õ then UNDEFINED; +                // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; +                // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; +                // if P == '1' && W == '0' then SEE VSTR; +                // if P == U && W == '1' then UNDEFINED;                  if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))                      return false;                  // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) -                // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn); +                // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);                  single_regs = true;                  add = BitIsSet (opcode, 23);                  wback = BitIsSet (opcode, 21);                  d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);                  n = Bits32 (opcode, 19, 16); -                // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8); +                // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);                  imm32 = Bits32 (opcode, 7, 0) << 2;                  regs = Bits32 (opcode, 7, 0); @@ -11193,7 +11196,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)          {              case eEncodingT1:              case eEncodingA1: -                // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);                  single_reg = false;                  add = BitIsSet (opcode, 23);                  imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11206,7 +11209,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)              case eEncodingT2:              case eEncodingA2: -                // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);                  single_reg = true;                  add = BitIsSet (opcode, 23);                  imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11322,7 +11325,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)          {              case eEncodingT1:              case eEncodingA1: -                // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);                  single_reg = false;                  add = BitIsSet (opcode, 23);                  imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11339,7 +11342,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)              case eEncodingT2:              case eEncodingA2: -                // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); +                // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);                  single_reg = true;                  add = BitIsSet (opcode, 23);                  imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11461,16 +11464,16 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e              case eEncodingA1:              {                  // case type of -                    // when Ô0111Õ -                        // regs = 1; if align<1> == Ô1Õ then UNDEFINED; -                    // when Ô1010Õ -                        // regs = 2; if align == Ô11Õ then UNDEFINED; -                    // when Ô0110Õ -                        // regs = 3; if align<1> == Ô1Õ then UNDEFINED; -                    // when Ô0010Õ +                    // when '0111' +                        // regs = 1; if align<1> == '1' then UNDEFINED; +                    // when '1010' +                        // regs = 2; if align == '11' then UNDEFINED; +                    // when '0110' +                        // regs = 3; if align<1> == '1' then UNDEFINED; +                    // when '0010'                          // regs = 4;                      // otherwise -                        // SEE ÒRelated encodingsÓ; +                        // SEE 'Related encodings';                  uint32_t type = Bits32 (opcode, 11, 8);                  uint32_t align = Bits32 (opcode, 5, 4);                  if (type == 7) // '0111' @@ -11499,7 +11502,7 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e                  else                      return false; -                // alignment = if align == Ô00Õ then 1 else 4 << UInt(align); +                // alignment = if align == '00' then 1 else 4 << UInt(align);                  if (align == 0)                      alignment = 1;                  else @@ -11624,13 +11627,13 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi              {                  uint32_t size = Bits32 (opcode, 11, 10);                  uint32_t index_align = Bits32 (opcode, 7, 4); -                // if size == Ô11Õ then SEE VLD1 (single element to all lanes); +                // if size == '11' then SEE VLD1 (single element to all lanes);                  if (size == 3)                     return EmulateVLD1SingleAll (opcode, encoding);                  // case size of                  if (size == 0) // when '00'                  { -                    // if index_align<0> != Ô0Õ then UNDEFINED; +                    // if index_align<0> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 0))                          return false; @@ -11640,9 +11643,9 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi                      index = Bits32 (index_align, 3, 1);                      alignment = 1;                  } -                else if (size == 1) // when Ô01Õ +                else if (size == 1) // when '01'                  { -                    // if index_align<1> != Ô0Õ then UNDEFINED; +                    // if index_align<1> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 1))                          return false; @@ -11651,19 +11654,19 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi                      esize = 16;                      index = Bits32 (index_align, 3, 2); -                    // alignment = if index_align<0> == Ô0Õ then 1 else 2; +                    // alignment = if index_align<0> == '0' then 1 else 2;                      if (BitIsClear (index_align, 0))                          alignment = 1;                      else                          alignment = 2;                  } -                else if (size == 2) // when Ô10Õ +                else if (size == 2) // when '10'                  { -                    // if index_align<2> != Ô0Õ then UNDEFINED; +                    // if index_align<2> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 2))                          return false; -                    // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED; +                    // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;                      if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))                          return false; @@ -11672,7 +11675,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi                      esize = 32;                      index = Bit32 (index_align, 3); -                    // alignment = if index_align<1:0> == Ô00Õ then 1 else 4; +                    // alignment = if index_align<1:0> == '00' then 1 else 4;                      if (Bits32 (index_align, 1, 0) == 0)                          alignment = 1;                      else @@ -11806,35 +11809,35 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e                  uint32_t align = Bits32 (opcode, 5, 4);                  // case type of -                if (type == 7)    // when Ô0111Õ +                if (type == 7)    // when '0111'                  { -                    // regs = 1; if align<1> == Ô1Õ then UNDEFINED; +                    // regs = 1; if align<1> == '1' then UNDEFINED;                      regs = 1;                      if (BitIsSet (align, 1))                          return false;                  } -                else if (type == 10) // when Ô1010Õ +                else if (type == 10) // when '1010'                  { -                    // regs = 2; if align == Ô11Õ then UNDEFINED; +                    // regs = 2; if align == '11' then UNDEFINED;                      regs = 2;                      if (align == 3)                          return false;                  } -                else if (type == 6) // when Ô0110Õ +                else if (type == 6) // when '0110'                  { -                    // regs = 3; if align<1> == Ô1Õ then UNDEFINED; +                    // regs = 3; if align<1> == '1' then UNDEFINED;                      regs = 3;                      if (BitIsSet (align, 1))                          return false;                  } -                else if (type == 2) // when Ô0010Õ +                else if (type == 2) // when '0010'                      // regs = 4;                      regs = 4;                  else // otherwise -                    // SEE ÒRelated encodingsÓ; +                    // SEE 'Related encodings';                      return false; -                // alignment = if align == Ô00Õ then 1 else 4 << UInt(align); +                // alignment = if align == '00' then 1 else 4 << UInt(align);                  if (align == 0)                      alignment = 1;                  else @@ -11964,14 +11967,14 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc                  uint32_t size = Bits32 (opcode, 11, 10);                  uint32_t index_align = Bits32 (opcode, 7, 4); -                // if size == Ô11Õ then UNDEFINED; +                // if size == '11' then UNDEFINED;                  if (size == 3)                      return false;                  // case size of -                if (size == 0) // when Ô00Õ +                if (size == 0) // when '00'                  { -                    // if index_align<0> != Ô0Õ then UNDEFINED; +                    // if index_align<0> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 0))                          return false;                      // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; @@ -11980,9 +11983,9 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc                      index = Bits32 (index_align, 3, 1);                      alignment = 1;                  } -                else if (size == 1) // when Ô01Õ +                else if (size == 1) // when '01'                  { -                    // if index_align<1> != Ô0Õ then UNDEFINED; +                    // if index_align<1> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 1))                          return false; @@ -11991,19 +11994,19 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc                      esize = 16;                      index = Bits32 (index_align, 3, 2); -                    // alignment = if index_align<0> == Ô0Õ then 1 else 2; +                    // alignment = if index_align<0> == '0' then 1 else 2;                      if (BitIsClear (index_align, 0))                          alignment = 1;                      else                          alignment = 2;                  } -                else if (size == 2) // when Ô10Õ +                else if (size == 2) // when '10'                  { -                    // if index_align<2> != Ô0Õ then UNDEFINED; +                    // if index_align<2> != '0' then UNDEFINED;                      if (BitIsClear (index_align, 2))                          return false; -                    // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED; +                    // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;                      if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))                          return false; @@ -12012,7 +12015,7 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc                      esize = 32;                      index = Bit32 (index_align, 3); -                    // alignment = if index_align<1:0> == Ô00Õ then 1 else 4; +                    // alignment = if index_align<1:0> == '00' then 1 else 4;                      if (Bits32 (index_align, 1, 0) == 0)                          alignment = 1;                      else @@ -12125,12 +12128,12 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc              case eEncodingT1:              case eEncodingA1:              { -                //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED; +                //if size == '11' || (size == '00' && a == '1') then UNDEFINED;                  uint32_t size = Bits32 (opcode, 7, 6);                  if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))                      return false; -                //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2; +                //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2;                  ebytes = 1 << size;                  elements = 8 / ebytes;                  if (BitIsClear (opcode, 5)) @@ -12138,7 +12141,7 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc                  else                      regs = 2; -                //alignment = if a == Ô0Õ then 1 else ebytes; +                //alignment = if a == '0' then 1 else ebytes;                  if (BitIsClear (opcode, 4))                      alignment = 1;                  else @@ -12235,19 +12238,19 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod              UNPREDICTABLE;          operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;          case opcode of -            when Ô0000Õ result = R[n] AND operand2; // AND -            when Ô0001Õ result = R[n] EOR operand2; // EOR -            when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB -            when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB -            when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD -            when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC -            when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC -            when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC -            when Ô1100Õ result = R[n] OR operand2; // ORR -            when Ô1101Õ result = operand2; // MOV -            when Ô1110Õ result = R[n] AND NOT(operand2); // BIC -            when Ô1111Õ result = NOT(operand2); // MVN -        CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE); +            when '0000' result = R[n] AND operand2; // AND +            when '0001' result = R[n] EOR operand2; // EOR +            when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB +            when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB +            when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD +            when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC +            when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC +            when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC +            when '1100' result = R[n] OR operand2; // ORR +            when '1101' result = operand2; // MOV +            when '1110' result = R[n] AND NOT(operand2); // BIC +            when '1111' result = NOT(operand2); // MVN +        CPSRWriteByInstr(SPSR[], '1111', TRUE);          BranchWritePC(result);  #endif @@ -12267,7 +12270,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod          {              case eEncodingT1:                  // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE -                // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB +                // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB                  n = 14;                  imm32 = Bits32 (opcode, 7, 0);                  register_form = false; @@ -12329,62 +12332,62 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod          // case opcode of          switch (code)          { -            case 0: // when Ô0000Õ  +            case 0: // when '0000'                   // result = R[n] AND operand2; // AND                  result.result = Rn & operand2;                  break; -            case 1: // when Ô0001Õ  +            case 1: // when '0001'                   // result = R[n] EOR operand2; // EOR                  result.result = Rn ^ operand2;                  break; -            case 2: // when Ô0010Õ  -                // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB +            case 2: // when '0010'  +                // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB                  result = AddWithCarry (Rn, ~(operand2), 1);                  break; -            case 3: // when Ô0011Õ  -                // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB +            case 3: // when '0011'  +                // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB                  result = AddWithCarry (~(Rn), operand2, 1);                  break; -            case 4: // when Ô0100Õ  -                // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD +            case 4: // when '0100'  +                // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD                  result = AddWithCarry (Rn, operand2, 0);                  break; -            case 5: // when Ô0101Õ  +            case 5: // when '0101'                   // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC                  result = AddWithCarry (Rn, operand2, APSR_C);                  break; -            case 6: // when Ô0110Õ  +            case 6: // when '0110'                   // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC                  result = AddWithCarry (Rn, ~(operand2), APSR_C);                  break; -            case 7: // when Ô0111Õ  +            case 7: // when '0111'                   // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC                  result = AddWithCarry (~(Rn), operand2, APSR_C);                  break; -            case 10: // when Ô1100Õ  +            case 10: // when '1100'                   // result = R[n] OR operand2; // ORR                  result.result = Rn | operand2;                  break; -            case 11: // when Ô1101Õ  +            case 11: // when '1101'                   // result = operand2; // MOV                  result.result = operand2;                  break; -            case 12: // when Ô1110Õ  +            case 12: // when '1110'                   // result = R[n] AND NOT(operand2); // BIC                  result.result = Rn & ~(operand2);                  break; -            case 15: // when Ô1111Õ  +            case 15: // when '1111'                   // result = NOT(operand2); // MVN                  result.result = ~(operand2);                  break; @@ -12392,7 +12395,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod              default:                  return false;          } -        // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE); +        // CPSRWriteByInstr(SPSR[], '1111', TRUE);          // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for          // the best. @@ -13076,7 +13079,7 @@ EmulateInstructionARM::ArchVersion ()  }  bool -EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional) +EmulateInstructionARM::ConditionPassed (const uint32_t opcode)  {     // If we are ignoring conditions, then always return true.     // this allows us to iterate over disassembly code and still @@ -13084,12 +13087,8 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio     // bits set in the CPSR register...      if (m_ignore_conditions)          return true; -     -    if (is_conditional) -        *is_conditional = true;      const uint32_t cond = CurrentCond (opcode); -          if (cond == UINT32_MAX)          return false; @@ -13149,8 +13148,6 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio      case 7:           // Always execute (cond == 0b1110, or the special 0b1111 which gives          // opcodes different meanings, but always means execution happens. -        if (is_conditional) -            *is_conditional = false;          return true;      } @@ -13643,6 +13640,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)  }  bool +EmulateInstructionARM::IsInstructionConditional() +{ +    const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); +    return cond != 0xe && cond != 0xf && cond != UINT32_MAX; +} + +bool  EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)  {      if (!test_data) diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index d107ca6bc702e..893f43f199779 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -94,20 +94,20 @@ public:          return false;      } -    virtual lldb_private::ConstString -    GetPluginName() +    lldb_private::ConstString +    GetPluginName() override      {          return GetPluginNameStatic();      } -    virtual uint32_t -    GetPluginVersion() +    uint32_t +    GetPluginVersion()  override      {          return 1;      }      bool -    SetTargetTriple (const ArchSpec &arch); +    SetTargetTriple (const ArchSpec &arch)  override;      enum Mode      { @@ -148,8 +148,8 @@ public:  //    {  //    } -    virtual bool -    SupportsEmulatingInstructionsOfType (InstructionType inst_type) +    bool +    SupportsEmulatingInstructionsOfType (InstructionType inst_type)  override      {          return SupportsEmulatingInstructionsOfTypeStatic (inst_type);      } @@ -157,32 +157,32 @@ public:      virtual bool      SetArchitecture (const ArchSpec &arch); -    virtual bool  -    ReadInstruction (); +    bool +    ReadInstruction ()  override; -    virtual bool -    SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target); +    bool +    SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)  override; -    virtual bool -    EvaluateInstruction (uint32_t evaluate_options); -     -    virtual bool -    TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data); +    bool +    EvaluateInstruction (uint32_t evaluate_options) override; -    virtual bool -    GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info); -     +    bool +    IsInstructionConditional() override; -    virtual bool -    CreateFunctionEntryUnwind (UnwindPlan &unwind_plan); +    bool +    TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)  override; + +    bool +    GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info)  override; + +    bool +    CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override;      uint32_t      ArchVersion();      bool -    ConditionPassed (const uint32_t opcode,  -                     bool *is_conditional = NULL);  // Filled in with true if the opcode is a conditional opcode -                                                    // Filled in with false if the opcode is always executed +    ConditionPassed (const uint32_t opcode);      uint32_t      CurrentCond (const uint32_t opcode); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 992df1fba59e6..372ccf9b05f4b 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -231,58 +231,72 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)          //----------------------------------------------------------------------          // push register(s) -        { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS  <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS  <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, - -        { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, -        { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, - -        { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "STP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "STP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "STP  <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "STP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "STP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - -        { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - -        { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - -        { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "LDP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "LDP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "LDP  <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "LDP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, -        { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off,  "LDP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - -        { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre,  "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - -        { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, -        { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - -        { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB,              "B <label>"                            }, -        { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond,          "B.<cond> <label>"                     }, -        { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,            "CBZ <Wt>, <label>"                    }, -        { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,            "CBNZ <Wt>, <label>"                   }, -        { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,            "TBZ <R><t>, #<imm>, <label>"          }, -        { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,            "TBNZ <R><t>, #<imm>, <label>"         }, +        { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, +        { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"   }, +        { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD  <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, +        { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS  <Xd>, <Xn|SP>, #<imm> {, <shift>}"   }, + +        { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, +        { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"    }, +        { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD  <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, +        { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS  <Wd>, <Wn|WSP>, #<imm> {, <shift>}"    }, + +        { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP  <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, + +        { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, + +        { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, + +        { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP  <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP  <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP  <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP  <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, +        { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP  <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, + +        { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, + +        { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP  <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP  <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP  <St>, <St2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP  <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, +        { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP  <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, + +        { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Wt>, [<Xn|SP>], #<simm>"   }, +        { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Xt>, [<Xn|SP>], #<simm>"   }, +        { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,  "STR <Wt>, [<Xn|SP>, #<simm>]!"  }, +        { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,  "STR <Xt>, [<Xn|SP>, #<simm>]!"  }, +        { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,  "STR <Wt>, [<Xn|SP>{, #<pimm>}]" }, +        { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,  "STR <Xt>, [<Xn|SP>{, #<pimm>}]" }, + +        { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Wt>, [<Xn|SP>], #<simm>"   }, +        { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Xt>, [<Xn|SP>], #<simm>"   }, +        { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,  "LDR <Wt>, [<Xn|SP>, #<simm>]!"  }, +        { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>,  "LDR <Xt>, [<Xn|SP>, #<simm>]!"  }, +        { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,  "LDR <Wt>, [<Xn|SP>{, #<pimm>}]" }, +        { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>,  "LDR <Xt>, [<Xn|SP>{, #<pimm>}]" }, + +        { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB,     "B <label>"                    }, +        { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>"             }, +        { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,   "CBZ <Wt>, <label>"            }, +        { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ,   "CBNZ <Wt>, <label>"           }, +        { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,   "TBZ <R><t>, #<imm>, <label>"  }, +        { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ,   "TBNZ <R><t>, #<imm>, <label>" },      };      static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); @@ -391,7 +405,7 @@ EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)  uint32_t  EmulateInstructionARM64::GetFramePointerRegisterNumber () const  { -    if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android) +    if (m_arch.GetTriple().isAndroid())          return LLDB_INVALID_REGNUM; // Don't use frame pointer on android      return arm64_dwarf::sp; @@ -462,7 +476,7 @@ EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t ta  }  bool -EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_conditional) +EmulateInstructionARM64::ConditionHolds (const uint32_t cond)  {     // If we are ignoring conditions, then always return true.     // this allows us to iterate over disassembly code and still @@ -470,10 +484,7 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition     // bits set in the CPSR register...      if (m_ignore_conditions)          return true; -     -    if (is_conditional) -        *is_conditional = true; -   +      bool result = false;      switch (UnsignedBits(cond, 3, 1))      { @@ -499,19 +510,18 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition          result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);          break;      case 7: -        result = true; -        if (is_conditional) -            *is_conditional = false; -        break; +        // Always execute (cond == 0b1110, or the special 0b1111 which gives +        // opcodes different meanings, but always means execution happens. +        return true;      } -    if (cond & 1 && cond != 15) +    if (cond & 1)          result = !result;      return result;  }  bool -EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode) +EmulateInstructionARM64::EmulateADDSUBImm (const uint32_t opcode)  {      // integer d = UInt(Rd);      // integer n = UInt(Rn); @@ -628,26 +638,8 @@ EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)      return false;  } -bool -EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode) -{ -    return Emulate_ldstpair (opcode, AddrMode_OFF); -} - -bool -EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode) -{ -    return Emulate_ldstpair (opcode, AddrMode_PRE); -} - -bool -EmulateInstructionARM64::Emulate_ldstpair_post (const uint32_t opcode) -{ -    return Emulate_ldstpair (opcode, AddrMode_POST); -} - -bool -EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode) +template <EmulateInstructionARM64::AddrMode a_mode> bool +EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)  {      uint32_t opc = Bits32(opcode, 31, 30);      uint32_t V = Bit32(opcode, 26); @@ -776,10 +768,6 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod      Context context_t;      Context context_t2; -    context_t.type = eContextRegisterPlusOffset; -    context_t2.type = eContextRegisterPlusOffset; -    context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); -    context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);      uint8_t buffer [RegisterValue::kMaxRegisterByteSize];      Error error; @@ -792,6 +780,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod                  context_t.type = eContextPushRegisterOnStack;                  context_t2.type = eContextPushRegisterOnStack;              } +            else +            { +                context_t.type = eContextRegisterStore; +                context_t2.type = eContextRegisterStore; +            } +            context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); +            context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);              if (!ReadRegister (®_info_Rt, data_Rt))                  return false; @@ -820,6 +815,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod                  context_t.type = eContextPopRegisterOffStack;                  context_t2.type = eContextPopRegisterOffStack;              } +            else +            { +                context_t.type = eContextRegisterLoad; +                context_t2.type = eContextRegisterLoad; +            } +            context_t.SetAddress(address); +            context_t2.SetAddress(address + size);              if (rt_unknown)                  memset (buffer, 'U', reg_info_Rt.byte_size); @@ -874,6 +876,132 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod      return true;  } +template <EmulateInstructionARM64::AddrMode a_mode> bool +EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) +{ +    uint32_t size = Bits32(opcode, 31, 30); +    uint32_t opc = Bits32(opcode, 23, 22); +    uint32_t n = Bits32(opcode, 9, 5); +    uint32_t t = Bits32(opcode, 4, 0); + +    bool wback; +    bool postindex; +    uint64_t offset; + +    switch (a_mode) +    { +        case AddrMode_POST: +            wback = true; +            postindex = true; +            offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); +            break; +        case AddrMode_PRE: +            wback = true; +            postindex = false; +            offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); +            break; +        case AddrMode_OFF: +            wback = false; +            postindex = false; +            offset = LSL(Bits32(opcode, 21, 10), size); +            break; +    } + +    MemOp memop; + +    if (Bit32(opc, 1) == 0) +    { +        memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE; +    } +    else +    { +        memop = MemOp_LOAD; +        if (size == 2 && Bit32(opc, 0) == 1) +            return false; +    } + +    Error error; +    bool success = false; +    uint64_t address; +    uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; +    RegisterValue data_Rt; + +    if (n == 31) +        address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); +    else +        address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); + +    if (!success) +        return false; + +    if (!postindex) +        address += offset; + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) +        return false; + +    RegisterInfo reg_info_Rt; +    if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) +        return false; + +    Context context; +    switch (memop) +    { +        case MemOp_STORE: +            if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register +                context.type = eContextPushRegisterOnStack; +            else +                context.type = eContextRegisterStore; +            context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset); + +            if (!ReadRegister (®_info_Rt, data_Rt)) +                return false; +             +            if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) +                return false; + +            if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) +                return false; +            break; +             +        case MemOp_LOAD: +            if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register +                context.type = eContextPopRegisterOffStack; +            else +                context.type = eContextRegisterLoad; +            context.SetAddress(address); + +            if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size)) +                return false; + +            if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) +                return false; + +            if (!WriteRegister (context, ®_info_Rt, data_Rt)) +                return false; + +        default: +            return false; +    } + +    if (wback) +    { +        if (postindex) +            address += offset; + +        if (n == 31) +            context.type = eContextAdjustStackPointer; +        else +            context.type = eContextAdjustBaseRegister; +        context.SetImmediateSigned (offset); + +        if (!WriteRegisterUnsigned (context, ®_info_base, address)) +            return false; +    } +    return true; +} +  bool  EmulateInstructionARM64::EmulateB (const uint32_t opcode)  { diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h index b74eddeaaf639..d9333c2824d29 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h @@ -1,4 +1,4 @@ -//===-- EmulateInstructionARM64.h ------------------------------------*- C++ -*-===// +//===-- EmulateInstructionARM64.h -------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,6 +10,10 @@  #ifndef EmulateInstructionARM64_h_  #define EmulateInstructionARM64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/EmulateInstruction.h"  #include "lldb/Core/Error.h"  #include "lldb/Interpreter/OptionValue.h" @@ -18,6 +22,14 @@  class EmulateInstructionARM64 : public lldb_private::EmulateInstruction  {  public:  +    EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) : +        EmulateInstruction (arch), +        m_opcode_pstate (), +        m_emulated_pstate (), +        m_ignore_conditions (false) +    { +    } +      static void      Initialize (); @@ -50,61 +62,46 @@ public:          return false;      } -    virtual lldb_private::ConstString -    GetPluginName(); - -    virtual lldb_private::ConstString -    GetShortPluginName() -    { -        return GetPluginNameStatic(); -    } +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion() +    uint32_t +    GetPluginVersion() override      {          return 1;      }      bool -    SetTargetTriple (const lldb_private::ArchSpec &arch); +    SetTargetTriple(const lldb_private::ArchSpec &arch) override; -    EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) : -        EmulateInstruction (arch), -        m_opcode_pstate (), -        m_emulated_pstate (), -        m_ignore_conditions (false) -    { -    } - -    virtual bool -    SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) +    bool +    SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override      {          return SupportsEmulatingInstructionsOfTypeStatic (inst_type);      } -    virtual bool  -    ReadInstruction (); +    bool +    ReadInstruction() override; -    virtual bool -    EvaluateInstruction (uint32_t evaluate_options); +    bool +    EvaluateInstruction(uint32_t evaluate_options) override; -    virtual bool -    TestEmulation (lldb_private::Stream *out_stream,  -                   lldb_private::ArchSpec &arch,  -                   lldb_private::OptionValueDictionary *test_data) +    bool +    TestEmulation(lldb_private::Stream *out_stream, +                  lldb_private::ArchSpec &arch, +                  lldb_private::OptionValueDictionary *test_data) override      {          return false;      } -    virtual bool -    GetRegisterInfo (lldb::RegisterKind reg_kind, -                     uint32_t reg_num,  -                     lldb_private::RegisterInfo ®_info); +    bool +    GetRegisterInfo(lldb::RegisterKind reg_kind, +                    uint32_t reg_num, +                    lldb_private::RegisterInfo ®_info) override; -    virtual bool -    CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; -          typedef enum       {          AddrMode_OFF,  @@ -141,7 +138,6 @@ public:          BitwiseOp_NOT,           BitwiseOp_RBIT      } BitwiseOp; -          typedef enum      { @@ -252,7 +248,6 @@ public:      } ProcState;  protected: -      typedef struct      {          uint32_t mask; @@ -272,25 +267,19 @@ protected:      BranchTo (const Context &context, uint32_t N, lldb::addr_t target);      bool -    ConditionHolds (const uint32_t cond, bool *is_conditional = nullptr); +    ConditionHolds (const uint32_t cond);      bool      UsingAArch32 ();      bool -    Emulate_addsub_imm (const uint32_t opcode); - -    bool -    Emulate_ldstpair_off (const uint32_t opcode); +    EmulateADDSUBImm (const uint32_t opcode); -    bool -    Emulate_ldstpair_pre (const uint32_t opcode); - -    bool -    Emulate_ldstpair_post (const uint32_t opcode); +    template <AddrMode a_mode> bool +    EmulateLDPSTP (const uint32_t opcode); -    bool -    Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode); +    template <AddrMode a_mode> bool +    EmulateLDRSTRImm (const uint32_t opcode);      bool      EmulateB (const uint32_t opcode); @@ -309,4 +298,4 @@ protected:      bool m_ignore_conditions;  }; -#endif  // EmulateInstructionARM64_h_ +#endif // EmulateInstructionARM64_h_ diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 66866c73a5cb2..d6485f686e2c9 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -29,6 +29,7 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/Stream.h"  #include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Target.h"  #include "llvm/ADT/STLExtras.h" @@ -132,10 +133,6 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar          features += "+dsp,";      if (arch_flags & ArchSpec::eMIPSAse_dspr2)          features += "+dspr2,"; -    if (arch_flags & ArchSpec::eMIPSAse_mips16) -        features += "+mips16,"; -    if (arch_flags & ArchSpec::eMIPSAse_micromips) -        features += "+micromips,";      m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));      assert (m_reg_info.get()); @@ -152,6 +149,21 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar      m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));      assert (m_disasm.get()); + +    /* Create alternate disassembler for microMIPS */ +    if (arch_flags & ArchSpec::eMIPSAse_mips16) +        features += "+mips16,"; +    else if (arch_flags & ArchSpec::eMIPSAse_micromips) +        features += "+micromips,"; + +    m_alt_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); +    assert (m_alt_subtype_info.get()); + +    m_alt_disasm.reset (target->createMCDisassembler (*m_alt_subtype_info, *m_context)); +    assert (m_alt_disasm.get()); + +    m_next_inst_size = 0; +    m_use_alt_disaasm = false;  }  void @@ -221,41 +233,76 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)      {          switch (reg_num)          { -            case gcc_dwarf_sp_mips:  return "r29";  -            case gcc_dwarf_r30_mips: return "r30";  -            case gcc_dwarf_ra_mips:  return "r31"; -            case gcc_dwarf_f0_mips:  return "f0"; -            case gcc_dwarf_f1_mips:  return "f1"; -            case gcc_dwarf_f2_mips:  return "f2"; -            case gcc_dwarf_f3_mips:  return "f3"; -            case gcc_dwarf_f4_mips:  return "f4"; -            case gcc_dwarf_f5_mips:  return "f5"; -            case gcc_dwarf_f6_mips:  return "f6"; -            case gcc_dwarf_f7_mips:  return "f7"; -            case gcc_dwarf_f8_mips:  return "f8"; -            case gcc_dwarf_f9_mips:  return "f9"; -            case gcc_dwarf_f10_mips: return "f10"; -            case gcc_dwarf_f11_mips: return "f11"; -            case gcc_dwarf_f12_mips: return "f12"; -            case gcc_dwarf_f13_mips: return "f13"; -            case gcc_dwarf_f14_mips: return "f14"; -            case gcc_dwarf_f15_mips: return "f15"; -            case gcc_dwarf_f16_mips: return "f16"; -            case gcc_dwarf_f17_mips: return "f17"; -            case gcc_dwarf_f18_mips: return "f18"; -            case gcc_dwarf_f19_mips: return "f19"; -            case gcc_dwarf_f20_mips: return "f20"; -            case gcc_dwarf_f21_mips: return "f21"; -            case gcc_dwarf_f22_mips: return "f22"; -            case gcc_dwarf_f23_mips: return "f23"; -            case gcc_dwarf_f24_mips: return "f24"; -            case gcc_dwarf_f25_mips: return "f25"; -            case gcc_dwarf_f26_mips: return "f26"; -            case gcc_dwarf_f27_mips: return "f27"; -            case gcc_dwarf_f28_mips: return "f28"; -            case gcc_dwarf_f29_mips: return "f29"; -            case gcc_dwarf_f30_mips: return "f30"; -            case gcc_dwarf_f31_mips: return "f31"; +            case dwarf_sp_mips:          return "r29";  +            case dwarf_r30_mips:         return "r30";  +            case dwarf_ra_mips:          return "r31"; +            case dwarf_f0_mips:          return "f0"; +            case dwarf_f1_mips:          return "f1"; +            case dwarf_f2_mips:          return "f2"; +            case dwarf_f3_mips:          return "f3"; +            case dwarf_f4_mips:          return "f4"; +            case dwarf_f5_mips:          return "f5"; +            case dwarf_f6_mips:          return "f6"; +            case dwarf_f7_mips:          return "f7"; +            case dwarf_f8_mips:          return "f8"; +            case dwarf_f9_mips:          return "f9"; +            case dwarf_f10_mips:         return "f10"; +            case dwarf_f11_mips:         return "f11"; +            case dwarf_f12_mips:         return "f12"; +            case dwarf_f13_mips:         return "f13"; +            case dwarf_f14_mips:         return "f14"; +            case dwarf_f15_mips:         return "f15"; +            case dwarf_f16_mips:         return "f16"; +            case dwarf_f17_mips:         return "f17"; +            case dwarf_f18_mips:         return "f18"; +            case dwarf_f19_mips:         return "f19"; +            case dwarf_f20_mips:         return "f20"; +            case dwarf_f21_mips:         return "f21"; +            case dwarf_f22_mips:         return "f22"; +            case dwarf_f23_mips:         return "f23"; +            case dwarf_f24_mips:         return "f24"; +            case dwarf_f25_mips:         return "f25"; +            case dwarf_f26_mips:         return "f26"; +            case dwarf_f27_mips:         return "f27"; +            case dwarf_f28_mips:         return "f28"; +            case dwarf_f29_mips:         return "f29"; +            case dwarf_f30_mips:         return "f30"; +            case dwarf_f31_mips:         return "f31"; +            case dwarf_w0_mips:          return "w0"; +            case dwarf_w1_mips:          return "w1"; +            case dwarf_w2_mips:          return "w2"; +            case dwarf_w3_mips:          return "w3"; +            case dwarf_w4_mips:          return "w4"; +            case dwarf_w5_mips:          return "w5"; +            case dwarf_w6_mips:          return "w6"; +            case dwarf_w7_mips:          return "w7"; +            case dwarf_w8_mips:          return "w8"; +            case dwarf_w9_mips:          return "w9"; +            case dwarf_w10_mips:         return "w10"; +            case dwarf_w11_mips:         return "w11"; +            case dwarf_w12_mips:         return "w12"; +            case dwarf_w13_mips:         return "w13"; +            case dwarf_w14_mips:         return "w14"; +            case dwarf_w15_mips:         return "w15"; +            case dwarf_w16_mips:         return "w16"; +            case dwarf_w17_mips:         return "w17"; +            case dwarf_w18_mips:         return "w18"; +            case dwarf_w19_mips:         return "w19"; +            case dwarf_w20_mips:         return "w20"; +            case dwarf_w21_mips:         return "w21"; +            case dwarf_w22_mips:         return "w22"; +            case dwarf_w23_mips:         return "w23"; +            case dwarf_w24_mips:         return "w24"; +            case dwarf_w25_mips:         return "w25"; +            case dwarf_w26_mips:         return "w26"; +            case dwarf_w27_mips:         return "w27"; +            case dwarf_w28_mips:         return "w28"; +            case dwarf_w29_mips:         return "w29"; +            case dwarf_w30_mips:         return "w30"; +            case dwarf_w31_mips:         return "w31"; +            case dwarf_mir_mips:         return "mir"; +            case dwarf_mcsr_mips:        return "mcsr"; +            case dwarf_config5_mips:     return "config5";              default:                  break;          } @@ -264,78 +311,113 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)      switch (reg_num)      { -        case gcc_dwarf_zero_mips:     return "r0"; -        case gcc_dwarf_r1_mips:       return "r1"; -        case gcc_dwarf_r2_mips:       return "r2"; -        case gcc_dwarf_r3_mips:       return "r3"; -        case gcc_dwarf_r4_mips:       return "r4"; -        case gcc_dwarf_r5_mips:       return "r5"; -        case gcc_dwarf_r6_mips:       return "r6"; -        case gcc_dwarf_r7_mips:       return "r7"; -        case gcc_dwarf_r8_mips:       return "r8"; -        case gcc_dwarf_r9_mips:       return "r9"; -        case gcc_dwarf_r10_mips:      return "r10"; -        case gcc_dwarf_r11_mips:      return "r11"; -        case gcc_dwarf_r12_mips:      return "r12"; -        case gcc_dwarf_r13_mips:      return "r13"; -        case gcc_dwarf_r14_mips:      return "r14"; -        case gcc_dwarf_r15_mips:      return "r15"; -        case gcc_dwarf_r16_mips:      return "r16"; -        case gcc_dwarf_r17_mips:      return "r17"; -        case gcc_dwarf_r18_mips:      return "r18"; -        case gcc_dwarf_r19_mips:      return "r19"; -        case gcc_dwarf_r20_mips:      return "r20"; -        case gcc_dwarf_r21_mips:      return "r21"; -        case gcc_dwarf_r22_mips:      return "r22"; -        case gcc_dwarf_r23_mips:      return "r23"; -        case gcc_dwarf_r24_mips:      return "r24"; -        case gcc_dwarf_r25_mips:      return "r25"; -        case gcc_dwarf_r26_mips:      return "r26"; -        case gcc_dwarf_r27_mips:      return "r27"; -        case gcc_dwarf_gp_mips:       return "gp"; -        case gcc_dwarf_sp_mips:       return "sp"; -        case gcc_dwarf_r30_mips:      return "fp"; -        case gcc_dwarf_ra_mips:       return "ra"; -        case gcc_dwarf_sr_mips:       return "sr"; -        case gcc_dwarf_lo_mips:       return "lo"; -        case gcc_dwarf_hi_mips:       return "hi"; -        case gcc_dwarf_bad_mips:      return "bad"; -        case gcc_dwarf_cause_mips:    return "cause"; -        case gcc_dwarf_pc_mips:       return "pc"; -        case gcc_dwarf_f0_mips:       return "f0"; -        case gcc_dwarf_f1_mips:       return "f1"; -        case gcc_dwarf_f2_mips:       return "f2"; -        case gcc_dwarf_f3_mips:       return "f3"; -        case gcc_dwarf_f4_mips:       return "f4"; -        case gcc_dwarf_f5_mips:       return "f5"; -        case gcc_dwarf_f6_mips:       return "f6"; -        case gcc_dwarf_f7_mips:       return "f7"; -        case gcc_dwarf_f8_mips:       return "f8"; -        case gcc_dwarf_f9_mips:       return "f9"; -        case gcc_dwarf_f10_mips:      return "f10"; -        case gcc_dwarf_f11_mips:      return "f11"; -        case gcc_dwarf_f12_mips:      return "f12"; -        case gcc_dwarf_f13_mips:      return "f13"; -        case gcc_dwarf_f14_mips:      return "f14"; -        case gcc_dwarf_f15_mips:      return "f15"; -        case gcc_dwarf_f16_mips:      return "f16"; -        case gcc_dwarf_f17_mips:      return "f17"; -        case gcc_dwarf_f18_mips:      return "f18"; -        case gcc_dwarf_f19_mips:      return "f19"; -        case gcc_dwarf_f20_mips:      return "f20"; -        case gcc_dwarf_f21_mips:      return "f21"; -        case gcc_dwarf_f22_mips:      return "f22"; -        case gcc_dwarf_f23_mips:      return "f23"; -        case gcc_dwarf_f24_mips:      return "f24"; -        case gcc_dwarf_f25_mips:      return "f25"; -        case gcc_dwarf_f26_mips:      return "f26"; -        case gcc_dwarf_f27_mips:      return "f27"; -        case gcc_dwarf_f28_mips:      return "f28"; -        case gcc_dwarf_f29_mips:      return "f29"; -        case gcc_dwarf_f30_mips:      return "f30"; -        case gcc_dwarf_f31_mips:      return "f31"; -        case gcc_dwarf_fcsr_mips:     return "fcsr"; -        case gcc_dwarf_fir_mips:      return "fir"; +        case dwarf_zero_mips:         return "r0"; +        case dwarf_r1_mips:           return "r1"; +        case dwarf_r2_mips:           return "r2"; +        case dwarf_r3_mips:           return "r3"; +        case dwarf_r4_mips:           return "r4"; +        case dwarf_r5_mips:           return "r5"; +        case dwarf_r6_mips:           return "r6"; +        case dwarf_r7_mips:           return "r7"; +        case dwarf_r8_mips:           return "r8"; +        case dwarf_r9_mips:           return "r9"; +        case dwarf_r10_mips:          return "r10"; +        case dwarf_r11_mips:          return "r11"; +        case dwarf_r12_mips:          return "r12"; +        case dwarf_r13_mips:          return "r13"; +        case dwarf_r14_mips:          return "r14"; +        case dwarf_r15_mips:          return "r15"; +        case dwarf_r16_mips:          return "r16"; +        case dwarf_r17_mips:          return "r17"; +        case dwarf_r18_mips:          return "r18"; +        case dwarf_r19_mips:          return "r19"; +        case dwarf_r20_mips:          return "r20"; +        case dwarf_r21_mips:          return "r21"; +        case dwarf_r22_mips:          return "r22"; +        case dwarf_r23_mips:          return "r23"; +        case dwarf_r24_mips:          return "r24"; +        case dwarf_r25_mips:          return "r25"; +        case dwarf_r26_mips:          return "r26"; +        case dwarf_r27_mips:          return "r27"; +        case dwarf_gp_mips:           return "gp"; +        case dwarf_sp_mips:           return "sp"; +        case dwarf_r30_mips:          return "fp"; +        case dwarf_ra_mips:           return "ra"; +        case dwarf_sr_mips:           return "sr"; +        case dwarf_lo_mips:           return "lo"; +        case dwarf_hi_mips:           return "hi"; +        case dwarf_bad_mips:          return "bad"; +        case dwarf_cause_mips:        return "cause"; +        case dwarf_pc_mips:           return "pc"; +        case dwarf_f0_mips:           return "f0"; +        case dwarf_f1_mips:           return "f1"; +        case dwarf_f2_mips:           return "f2"; +        case dwarf_f3_mips:           return "f3"; +        case dwarf_f4_mips:           return "f4"; +        case dwarf_f5_mips:           return "f5"; +        case dwarf_f6_mips:           return "f6"; +        case dwarf_f7_mips:           return "f7"; +        case dwarf_f8_mips:           return "f8"; +        case dwarf_f9_mips:           return "f9"; +        case dwarf_f10_mips:          return "f10"; +        case dwarf_f11_mips:          return "f11"; +        case dwarf_f12_mips:          return "f12"; +        case dwarf_f13_mips:          return "f13"; +        case dwarf_f14_mips:          return "f14"; +        case dwarf_f15_mips:          return "f15"; +        case dwarf_f16_mips:          return "f16"; +        case dwarf_f17_mips:          return "f17"; +        case dwarf_f18_mips:          return "f18"; +        case dwarf_f19_mips:          return "f19"; +        case dwarf_f20_mips:          return "f20"; +        case dwarf_f21_mips:          return "f21"; +        case dwarf_f22_mips:          return "f22"; +        case dwarf_f23_mips:          return "f23"; +        case dwarf_f24_mips:          return "f24"; +        case dwarf_f25_mips:          return "f25"; +        case dwarf_f26_mips:          return "f26"; +        case dwarf_f27_mips:          return "f27"; +        case dwarf_f28_mips:          return "f28"; +        case dwarf_f29_mips:          return "f29"; +        case dwarf_f30_mips:          return "f30"; +        case dwarf_f31_mips:          return "f31"; +        case dwarf_fcsr_mips:         return "fcsr"; +        case dwarf_fir_mips:          return "fir"; +        case dwarf_w0_mips:           return "w0"; +        case dwarf_w1_mips:           return "w1"; +        case dwarf_w2_mips:           return "w2"; +        case dwarf_w3_mips:           return "w3"; +        case dwarf_w4_mips:           return "w4"; +        case dwarf_w5_mips:           return "w5"; +        case dwarf_w6_mips:           return "w6"; +        case dwarf_w7_mips:           return "w7"; +        case dwarf_w8_mips:           return "w8"; +        case dwarf_w9_mips:           return "w9"; +        case dwarf_w10_mips:          return "w10"; +        case dwarf_w11_mips:          return "w11"; +        case dwarf_w12_mips:          return "w12"; +        case dwarf_w13_mips:          return "w13"; +        case dwarf_w14_mips:          return "w14"; +        case dwarf_w15_mips:          return "w15"; +        case dwarf_w16_mips:          return "w16"; +        case dwarf_w17_mips:          return "w17"; +        case dwarf_w18_mips:          return "w18"; +        case dwarf_w19_mips:          return "w19"; +        case dwarf_w20_mips:          return "w20"; +        case dwarf_w21_mips:          return "w21"; +        case dwarf_w22_mips:          return "w22"; +        case dwarf_w23_mips:          return "w23"; +        case dwarf_w24_mips:          return "w24"; +        case dwarf_w25_mips:          return "w25"; +        case dwarf_w26_mips:          return "w26"; +        case dwarf_w27_mips:          return "w27"; +        case dwarf_w28_mips:          return "w28"; +        case dwarf_w29_mips:          return "w29"; +        case dwarf_w30_mips:          return "w30"; +        case dwarf_w31_mips:          return "w31"; +        case dwarf_mcsr_mips:         return "mcsr"; +        case dwarf_mir_mips:          return "mir"; +        case dwarf_config5_mips:      return "config5";      }      return nullptr;  } @@ -347,11 +429,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num      {          switch (reg_num)          { -            case LLDB_REGNUM_GENERIC_PC:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips; break; -            case LLDB_REGNUM_GENERIC_SP:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips; break; -            case LLDB_REGNUM_GENERIC_FP:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips; break; -            case LLDB_REGNUM_GENERIC_RA:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips; break; -            case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips; break; +            case LLDB_REGNUM_GENERIC_PC:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips; break; +            case LLDB_REGNUM_GENERIC_SP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips; break; +            case LLDB_REGNUM_GENERIC_FP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips; break; +            case LLDB_REGNUM_GENERIC_RA:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips; break; +            case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips; break;              default:                  return false;          } @@ -362,18 +444,24 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num         ::memset (®_info, 0, sizeof(RegisterInfo));         ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); -       if (reg_num == gcc_dwarf_sr_mips || reg_num == gcc_dwarf_fcsr_mips || reg_num == gcc_dwarf_fir_mips) +       if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips || reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips || reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips)         {             reg_info.byte_size = 4;             reg_info.format = eFormatHex;             reg_info.encoding = eEncodingUint;         } -       else if ((int)reg_num >= gcc_dwarf_zero_mips && (int)reg_num <= gcc_dwarf_f31_mips) +       else if ((int)reg_num >= dwarf_zero_mips && (int)reg_num <= dwarf_f31_mips)         {             reg_info.byte_size = 4;             reg_info.format = eFormatHex;             reg_info.encoding = eEncodingUint;         } +       else if ((int)reg_num >= dwarf_w0_mips && (int)reg_num <= dwarf_w31_mips) +       { +           reg_info.byte_size = 16; +           reg_info.format = eFormatVectorOfUInt8; +           reg_info.encoding = eEncodingVector; +       }         else         {             return false; @@ -385,11 +473,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num         switch (reg_num)         { -           case gcc_dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; -           case gcc_dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; -           case gcc_dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; -           case gcc_dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; -           case gcc_dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; +           case dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; +           case dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; +           case dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; +           case dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; +           case dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;             default: break;         }         return true; @@ -409,6 +497,96 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)          { "ADDiu",      &EmulateInstructionMIPS::Emulate_ADDiu,       "ADDIU rt,rs,immediate"    },          { "SW",         &EmulateInstructionMIPS::Emulate_SW,          "SW rt,offset(rs)"         },          { "LW",         &EmulateInstructionMIPS::Emulate_LW,          "LW rt,offset(base)"       }, +        //---------------------------------------------------------------------- +        // MicroMIPS Prologue/Epilogue instructions +        //---------------------------------------------------------------------- +        { "ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP,     "ADDIU immediate"            }, +        { "ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5,     "ADDIUS5 rd,immediate"       }, +        { "SWSP_MM",    &EmulateInstructionMIPS::Emulate_SWSP,        "SWSP rt,offset(sp)"         }, +        { "SWM16_MM",   &EmulateInstructionMIPS::Emulate_SWM16_32,    "SWM16 reglist,offset(sp)"   }, +        { "SWM32_MM",   &EmulateInstructionMIPS::Emulate_SWM16_32,    "SWM32 reglist,offset(base)" }, +        { "SWP_MM",     &EmulateInstructionMIPS::Emulate_SWM16_32,    "SWP rs1,offset(base)"       }, +        { "LWSP_MM",    &EmulateInstructionMIPS::Emulate_LWSP,        "LWSP rt,offset(sp)"         }, +        { "LWM16_MM",   &EmulateInstructionMIPS::Emulate_LWM16_32,    "LWM16 reglist,offset(sp)"   }, +        { "LWM32_MM",   &EmulateInstructionMIPS::Emulate_LWM16_32,    "LWM32 reglist,offset(base)" }, +        { "LWP_MM",     &EmulateInstructionMIPS::Emulate_LWM16_32,    "LWP rd,offset(base)"        }, +        { "JRADDIUSP",  &EmulateInstructionMIPS::Emulate_JRADDIUSP,   "JRADDIUSP immediate"        }, +        //---------------------------------------------------------------------- + +        // Load/Store  instructions +        //---------------------------------------------------------------------- +        /* Following list of emulated instructions are required by implementation of hardware watchpoint +           for MIPS in lldb. As we just need the address accessed by instructions, we have generalised  +           all these instructions in 2 functions depending on their addressing modes */ + +        { "LB",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LB    rt, offset(base)" }, +        { "LBE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LBE   rt, offset(base)" }, +        { "LBU",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LBU   rt, offset(base)" }, +        { "LBUE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LBUE  rt, offset(base)" }, +        { "LDC1",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LDC1  ft, offset(base)" }, +        { "LD",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LD    rt, offset(base)" }, +        { "LDL",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LDL   rt, offset(base)" }, +        { "LDR",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LDR   rt, offset(base)" }, +        { "LLD",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LLD   rt, offset(base)" }, +        { "LDC2",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LDC2  rt, offset(base)" }, +        { "LDXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "LDXC1 fd, index (base)" }, +        { "LH",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LH    rt, offset(base)" }, +        { "LHE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LHE   rt, offset(base)" }, +        { "LHU",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LHU   rt, offset(base)" }, +        { "LHUE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LHUE  rt, offset(base)" }, +        { "LL",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LL    rt, offset(base)" }, +        { "LLE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LLE   rt, offset(base)" }, +        { "LUXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "LUXC1 fd, index (base)" }, +        { "LW",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LW    rt, offset(base)" }, +        { "LWC1",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWC1  ft, offset(base)" }, +        { "LWC2",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWC2  rt, offset(base)" }, +        { "LWE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWE   rt, offset(base)" }, +        { "LWL",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWL   rt, offset(base)" }, +        { "LWLE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWLE  rt, offset(base)" }, +        { "LWR",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWR   rt, offset(base)" }, +        { "LWRE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LWRE  rt, offset(base)" }, +        { "LWXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "LWXC1 fd, index (base)" }, +        { "LLX",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LLX   rt, offset(base)" }, +        { "LLXE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LLXE  rt, offset(base)" }, +        { "LLDX",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "LLDX  rt, offset(base)" }, + +        { "SB",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SB    rt, offset(base)" }, +        { "SBE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SBE   rt, offset(base)" }, +        { "SC",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SC    rt, offset(base)" }, +        { "SCE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SCE   rt, offset(base)" }, +        { "SCD",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SCD   rt, offset(base)" }, +        { "SD",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SD    rt, offset(base)" }, +        { "SDL",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SDL   rt, offset(base)" }, +        { "SDR",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SDR   rt, offset(base)" }, +        { "SDC1",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SDC1  ft, offset(base)" }, +        { "SDC2",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SDC2  rt, offset(base)" }, +        { "SDXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "SDXC1 fs, index(base)"  }, +        { "SH",         &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SH    rt, offset(base)" }, +        { "SHE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SHE   rt, offset(base)" }, +        { "SUXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "SUXC1 fs, index (base)" }, +        { "SWC1",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWC1  ft, offset(base)" }, +        { "SWC2",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWC2  rt, offset(base)" }, +        { "SWE",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWE   rt, offset(base)" }, +        { "SWL",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWL   rt, offset(base)" }, +        { "SWLE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWLE  rt, offset(base)" }, +        { "SWR",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWR   rt, offset(base)" }, +        { "SWRE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SWRE  rt, offset(base)" }, +        { "SWXC1",      &EmulateInstructionMIPS::Emulate_LDST_Reg,          "SWXC1 fs, index (base)" }, +        { "SCX",        &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SCX   rt, offset(base)" }, +        { "SCXE",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SCXE  rt, offset(base)" }, +        { "SCDX",       &EmulateInstructionMIPS::Emulate_LDST_Imm,          "SCDX  rt, offset(base)" }, + +        //---------------------------------------------------------------------- +        // MicroMIPS Load/Store instructions +        //---------------------------------------------------------------------- +        { "LBU16_MM",      &EmulateInstructionMIPS::Emulate_LDST_Imm,       "LBU16 rt, decoded_offset(base)"       }, +        { "LHU16_MM",      &EmulateInstructionMIPS::Emulate_LDST_Imm,       "LHU16 rt, left_shifted_offset(base)"  }, +        { "LW16_MM",       &EmulateInstructionMIPS::Emulate_LDST_Imm,       "LW16  rt, left_shifted_offset(base)"  }, +        { "LWGP_MM",       &EmulateInstructionMIPS::Emulate_LDST_Imm,       "LWGP  rt, left_shifted_offset(gp)"    }, +        { "SH16_MM",       &EmulateInstructionMIPS::Emulate_LDST_Imm,       "SH16  rt, left_shifted_offset(base)"  }, +        { "SW16_MM",       &EmulateInstructionMIPS::Emulate_LDST_Imm,       "SW16  rt, left_shifted_offset(base)"  }, +        { "SW_MM",         &EmulateInstructionMIPS::Emulate_LDST_Imm,       "SWSP  rt, left_shifted_offset(base)"  }, +        { "SB16_MM",       &EmulateInstructionMIPS::Emulate_LDST_Imm,       "SB16  rt, offset(base)"               },          //----------------------------------------------------------------------          // Branch instructions @@ -471,6 +649,34 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)          { "BC1ANY2T",   &EmulateInstructionMIPS::Emulate_BC1ANY2T,    "BC1ANY2T cc, offset"       },          { "BC1ANY4F",   &EmulateInstructionMIPS::Emulate_BC1ANY4F,    "BC1ANY4F cc, offset"       },          { "BC1ANY4T",   &EmulateInstructionMIPS::Emulate_BC1ANY4T,    "BC1ANY4T cc, offset"       }, +        { "BNZ_B",      &EmulateInstructionMIPS::Emulate_BNZB,        "BNZ.b wt,s16"              }, +        { "BNZ_H",      &EmulateInstructionMIPS::Emulate_BNZH,        "BNZ.h wt,s16"              }, +        { "BNZ_W",      &EmulateInstructionMIPS::Emulate_BNZW,        "BNZ.w wt,s16"              }, +        { "BNZ_D",      &EmulateInstructionMIPS::Emulate_BNZD,        "BNZ.d wt,s16"              }, +        { "BZ_B",       &EmulateInstructionMIPS::Emulate_BZB,         "BZ.b wt,s16"               }, +        { "BZ_H",       &EmulateInstructionMIPS::Emulate_BZH,         "BZ.h wt,s16"               }, +        { "BZ_W",       &EmulateInstructionMIPS::Emulate_BZW,         "BZ.w wt,s16"               }, +        { "BZ_D",       &EmulateInstructionMIPS::Emulate_BZD,         "BZ.d wt,s16"               }, +        { "BNZ_V",      &EmulateInstructionMIPS::Emulate_BNZV,        "BNZ.V wt,s16"              }, +        { "BZ_V",       &EmulateInstructionMIPS::Emulate_BZV,         "BZ.V wt,s16"               }, + +        //---------------------------------------------------------------------- +        // MicroMIPS Branch instructions +        //---------------------------------------------------------------------- +        { "B16_MM",     &EmulateInstructionMIPS::Emulate_B16_MM,        "B16 offset"              }, +        { "BEQZ16_MM",  &EmulateInstructionMIPS::Emulate_Branch_MM,     "BEQZ16 rs, offset"       }, +        { "BNEZ16_MM",  &EmulateInstructionMIPS::Emulate_Branch_MM,     "BNEZ16 rs, offset"       }, +        { "BEQZC_MM",   &EmulateInstructionMIPS::Emulate_Branch_MM,     "BEQZC rs, offset"        }, +        { "BNEZC_MM",   &EmulateInstructionMIPS::Emulate_Branch_MM,     "BNEZC rs, offset"        }, +        { "BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,     "BGEZALS rs, offset"      }, +        { "BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM,     "BLTZALS rs, offset"      }, +        { "JALR16_MM",  &EmulateInstructionMIPS::Emulate_JALRx16_MM,    "JALR16 rs"               }, +        { "JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM,    "JALRS16 rs"              }, +        { "JR16_MM",    &EmulateInstructionMIPS::Emulate_JR,            "JR16 rs rs"              }, +        { "JRC16_MM",   &EmulateInstructionMIPS::Emulate_JR,            "JRC16 rs rs"             }, +        { "JALS_MM",    &EmulateInstructionMIPS::Emulate_JALx,          "JALS target"             }, +        { "JALX_MM",    &EmulateInstructionMIPS::Emulate_JALx,          "JALX target"             }, +        { "JALRS_MM",   &EmulateInstructionMIPS::Emulate_JALRS,         "JALRS rt, rs"            },      };      static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); @@ -484,6 +690,76 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)      return NULL;  } +uint32_t +EmulateInstructionMIPS::GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr) +{ +    uint64_t next_inst_size = 0; +    llvm::MCInst mc_insn; +    llvm::MCDisassembler::DecodeStatus decode_status; +    llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); + +    if (m_use_alt_disaasm) +        decode_status = m_alt_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls()); +    else +        decode_status = m_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls()); + +    if (decode_status != llvm::MCDisassembler::Success) +        return false; +     +    return m_insn_info->get(mc_insn.getOpcode()).getSize(); +} + +bool +EmulateInstructionMIPS::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) +{ +    m_use_alt_disaasm = false; + +    if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) +    { +        if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA) +        { +            Error error; +            lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + +            /*  +             * The address belongs to microMIPS function. To find the size of +             * next instruction use microMIPS disassembler. +            */ +             m_use_alt_disaasm = true; + +            uint32_t current_inst_size = insn_opcode.GetByteSize(); +            uint8_t buf[sizeof(uint32_t)]; +            uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size; +            Address next_addr (next_inst_addr); + +            const size_t bytes_read = target->ReadMemory (next_addr,      /* Address of next instruction */ +                                                          true,           /* prefer_file_cache */ +                                                          buf, +                                                          sizeof(uint32_t),  +                                                          error, +                                                          &load_addr); + +            if (bytes_read == 0) +                return true; + +            DataExtractor data (buf, sizeof(uint32_t), GetByteOrder(), GetAddressByteSize()); +            m_next_inst_size = GetSizeOfInstruction (data, next_inst_addr); +            return true; +        } +        else +        { +            /*  +             * If the address class is not eAddressClassCodeAlternateISA then +             * the function is not microMIPS. In this case instruction size is  +             * always 4 bytes. +            */ +            m_next_inst_size = 4; +            return true; +        } +    } +    return false; +} +  bool   EmulateInstructionMIPS::ReadInstruction ()  { @@ -514,7 +790,11 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)      {          llvm::MCDisassembler::DecodeStatus decode_status;          llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); -        decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); +        if (m_use_alt_disaasm) +            decode_status = m_alt_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); +        else +            decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); +          if (decode_status != llvm::MCDisassembler::Success)              return false;      } @@ -542,7 +822,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)      if (auto_advance_pc)      { -        old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +        old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);          if (!success)              return false;      } @@ -554,7 +834,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)      if (auto_advance_pc)      { -        new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +        new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);          if (!success)              return false; @@ -563,7 +843,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)          {              new_pc += 4;              Context context; -            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, new_pc)) +            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, new_pc))                  return false;          }      } @@ -581,10 +861,10 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)      const bool can_replace = false;      // Our previous Call Frame Address is the stack pointer -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);      // Our previous PC is in the RA -    row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips, gcc_dwarf_ra_mips, can_replace); +    row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);      unwind_plan.AppendRow (row); @@ -592,6 +872,7 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)      unwind_plan.SetSourceName ("EmulateInstructionMIPS");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);      unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); +    unwind_plan.SetReturnAddressRegister (dwarf_ra_mips);      return true;  } @@ -601,18 +882,18 @@ EmulateInstructionMIPS::nonvolatile_reg_p (uint32_t regnum)  {      switch (regnum)      { -        case gcc_dwarf_r16_mips: -        case gcc_dwarf_r17_mips: -        case gcc_dwarf_r18_mips: -        case gcc_dwarf_r19_mips: -        case gcc_dwarf_r20_mips: -        case gcc_dwarf_r21_mips: -        case gcc_dwarf_r22_mips: -        case gcc_dwarf_r23_mips: -        case gcc_dwarf_gp_mips: -        case gcc_dwarf_sp_mips: -        case gcc_dwarf_r30_mips: -        case gcc_dwarf_ra_mips: +        case dwarf_r16_mips: +        case dwarf_r17_mips: +        case dwarf_r18_mips: +        case dwarf_r19_mips: +        case dwarf_r20_mips: +        case dwarf_r21_mips: +        case dwarf_r22_mips: +        case dwarf_r23_mips: +        case dwarf_gp_mips: +        case dwarf_sp_mips: +        case dwarf_r30_mips: +        case dwarf_ra_mips:              return true;          default:              return false; @@ -633,10 +914,10 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)      src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      /* Check if this is addiu sp,<src>,imm16 */ -    if (dst == gcc_dwarf_sp_mips) +    if (dst == dwarf_sp_mips)      {          /* read <src> register */ -        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, 0, &success); +        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);          if (!success)              return false; @@ -644,13 +925,13 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)          Context context;          RegisterInfo reg_info_sp; -        if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips, reg_info_sp)) +        if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))              context.SetRegisterPlusOffset (reg_info_sp, imm);          /* We are allocating bytes on stack */          context.type = eContextAdjustStackPointer; -        WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips, result); +        WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);      }      return true; @@ -663,30 +944,206 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)      uint32_t imm16 = insn.getOperand(2).getImm();      uint32_t imm = SignedBits(imm16, 15, 0);      uint32_t src, base; +    int32_t address; +    Context bad_vaddr_context; + +    RegisterInfo reg_info_base;      src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    /* read base register */ +    address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + imm; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); +      /* We look for sp based non-volatile register stores */ -    if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src)) +    if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) +    { + +        RegisterInfo reg_info_src; + +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) +            return false; + +        Context context; +        RegisterValue data_src; +        context.type = eContextPushRegisterOnStack; +        context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + +        uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; +        Error error; + +        if (!ReadRegister (®_info_base, data_src)) +            return false; + +        if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) +            return false; + +        if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) +            return false; + +        return true; +    } + +    return false; +} + +bool +EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn) +{ +  bool success =false; +    uint32_t src, base; +    int32_t imm, address; +    Context bad_vaddr_context; + +    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); +    imm = insn.getOperand(2).getImm(); + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    /* read base register */ +    address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + imm; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    if (base == dwarf_sp_mips && nonvolatile_reg_p (src))      { -        uint32_t address; -        RegisterInfo reg_info_base; +        RegisterValue data_src;          RegisterInfo reg_info_src; -        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, reg_info_base) -            || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src)) +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))              return false; -        /* read SP */ -        address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, 0, &success); +        Context context; +        context.type = eContextPopRegisterOffStack; +        context.SetAddress (address); + +        if (!WriteRegister (context, ®_info_src, data_src)) +            return false; + +        return true; +    } + +    return false; +} + +bool +EmulateInstructionMIPS::Emulate_ADDIUSP (llvm::MCInst& insn) +{ +    bool success = false; +    const uint32_t imm9 = insn.getOperand(0).getImm(); +    uint64_t result; + +    // This instruction operates implicitly on stack pointer, so read <sp> register. +    uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success); +    if (!success) +        return false; + +    result = src_opd_val + imm9; + +    Context context; +    RegisterInfo reg_info_sp; +    if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) +        context.SetRegisterPlusOffset (reg_info_sp, imm9); + +    // We are adjusting the stack. +    context.type = eContextAdjustStackPointer; + +    WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_ADDIUS5 (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t base; +    const uint32_t imm4 = insn.getOperand(2).getImm(); +    uint64_t result; + +    // The source and destination register is same for this instruction. +    base = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + +    // We are looking for stack adjustment only +    if (base == dwarf_sp_mips) +    { +        // Read stack pointer register +        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);          if (!success)              return false; -        /* destination address */ -        address = address + imm; +        result = src_opd_val + imm4;          Context context; +        RegisterInfo reg_info_sp; +        if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) +            context.SetRegisterPlusOffset (reg_info_sp, imm4); + +        // We are adjusting the stack. +        context.type = eContextAdjustStackPointer; + +        WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); +    } + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_SWSP (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t imm5 = insn.getOperand(2).getImm(); +    uint32_t src, base; +    Context bad_vaddr_context; +    uint32_t address; + +    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + +    RegisterInfo reg_info_base; + +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    // read base register +    address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    // destination address +    address = address + imm5; + +    // We use bad_vaddr_context to store base address which is used by H/W watchpoint +    // Set the bad_vaddr register with base address used in the instruction +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    // We look for sp based non-volatile register stores. +    if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) +    { +        RegisterInfo reg_info_src; +        Context context;          RegisterValue data_src;          context.type = eContextPushRegisterOnStack;          context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); @@ -709,24 +1166,118 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)      return false;  } +/* Emulate SWM16,SWM32 and SWP instruction. + +   SWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand). +   SWM32 and SWP can have base register other than stack pointer. +*/  bool -EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn) +EmulateInstructionMIPS::Emulate_SWM16_32 (llvm::MCInst& insn)  { +    bool success = false;      uint32_t src, base; +    uint32_t num_operands = insn.getNumOperands();  // No of operands vary based on no of regs to store. -    src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); -    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); +    // Base register is second last operand of the instruction. +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); + +    // We are looking for sp based stores so if base is not a stack pointer then don't proceed. +    if (base != dwarf_sp_mips) +        return false; + +    // offset is always the last operand. +    uint32_t offset = insn.getOperand(num_operands-1).getImm();  + +    RegisterInfo reg_info_base; +    RegisterInfo reg_info_src; +     +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    // read SP +    uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    // Resulting base addrss +    base_address = base_address + offset; + +    // Total no of registers to be stored are num_operands-2. +    for (uint32_t i = 0; i < num_operands - 2; i++) +    { +        // Get the register number to be stored. +        src = m_reg_info->getEncodingValue (insn.getOperand(i).getReg()); + +        /*  +            Record only non-volatile stores. +            This check is required for SWP instruction because source operand could be any register. +            SWM16 and SWM32 instruction always has saved registers as source operands. +        */ +        if (!nonvolatile_reg_p (src)) +            return false; + +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) +            return false; + +        Context context; +        RegisterValue data_src; +        context.type = eContextPushRegisterOnStack; +        context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + +        uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; +        Error error; + +        if (!ReadRegister (®_info_base, data_src)) +            return false; + +        if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) +            return false; + +        if (!WriteMemory (context, base_address, buffer, reg_info_src.byte_size)) +            return false; + +        // Stack address for next register +        base_address = base_address + reg_info_src.byte_size; +    } +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_LWSP (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    uint32_t base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); +    uint32_t imm5 = insn.getOperand(2).getImm(); +    Context bad_vaddr_context; + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; -    if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src)) +    // read base register +    uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    base_address = base_address + imm5; + +    // We use bad_vaddr_context to store base address which is used by H/W watchpoint +    // Set the bad_vaddr register with base address used in the instruction +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, base_address); + +    if (base == dwarf_sp_mips && nonvolatile_reg_p (src))      {          RegisterValue data_src;          RegisterInfo reg_info_src; -        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src)) +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))              return false;          Context context; -        context.type = eContextRegisterLoad; +        context.type = eContextPopRegisterOffStack; +        context.SetAddress (base_address);          if (!WriteRegister (context, ®_info_src, data_src))              return false; @@ -737,6 +1288,105 @@ EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)      return false;  } +/* Emulate LWM16, LWM32 and LWP instructions. + +   LWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand). +   LWM32 and LWP can have base register other than stack pointer. +*/ +bool +EmulateInstructionMIPS::Emulate_LWM16_32 (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t dst, base; +    uint32_t num_operands = insn.getNumOperands();  // No of operands vary based on no of regs to store. +    uint32_t imm = insn.getOperand(num_operands-1).getImm();    // imm is the last operand in the instruction. +     +    // Base register is second last operand of the instruction. +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); + +    // We are looking for sp based loads so if base is not a stack pointer then don't proceed. +    if (base != dwarf_sp_mips) +        return false; + +    uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    base_address = base_address + imm; + +    RegisterValue data_dst; +    RegisterInfo reg_info_dst; + +    // Total no of registers to be re-stored are num_operands-2. +    for (uint32_t i = 0; i < num_operands - 2; i++) +    { +        // Get the register number to be re-stored. +        dst = m_reg_info->getEncodingValue (insn.getOperand(i).getReg()); + +        /* +            Record only non-volatile loads. +            This check is required for LWP instruction because destination operand could be any register. +            LWM16 and LWM32 instruction always has saved registers as destination operands. +        */ +        if (!nonvolatile_reg_p (dst)) +            return false; +         +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + dst, reg_info_dst)) +            return false; + +        Context context; +        context.type = eContextPopRegisterOffStack; +        context.SetAddress (base_address + (i*4)); + +        if (!WriteRegister (context, ®_info_dst, data_dst)) +            return false; +    } + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_JRADDIUSP (llvm::MCInst& insn) +{ +    bool success = false; +    int32_t imm5 = insn.getOperand(0).getImm(); + +    /* JRADDIUSP immediate +    *       PC <- RA +    *       SP <- SP + zero_extend(Immediate << 2) +    */ +     +    // This instruction operates implicitly on stack pointer, so read <sp> register. +    int32_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success); +    if (!success) +        return false; + +    int32_t ra_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_ra_mips, 0, &success); +    if (!success) +        return false; +     +    int32_t result = src_opd_val + imm5; + +    Context context; + +    // Update the PC +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, ra_val)) +        return false; +     +    RegisterInfo reg_info_sp; +    if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) +        context.SetRegisterPlusOffset (reg_info_sp, imm5); + +    // We are adjusting stack +    context.type = eContextAdjustStackPointer; + +    // update SP +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result)) +        return false; + +    return true; +} +  bool  EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)  { @@ -754,15 +1404,15 @@ EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -774,13 +1424,270 @@ EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true;  }  bool +EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn) +{ +    bool success = false; +    int32_t offset, pc, target; +    uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + +    offset = insn.getOperand(0).getImm(); + +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    // unconditional branch +    target = pc + offset; + +    Context context; +    context.type = eContextRelativeBranchImmediate; +    context.SetImmediate (current_inst_size + offset); + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) +        return false; + +    return true; +} + +/* +   BEQZC, BNEZC are 32 bit compact instructions without a delay slot. +   BEQZ16, BNEZ16 are 16 bit instructions with delay slot. +   BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot. +*/ +bool +EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn) +{ +    bool success = false; +    int32_t target = 0; +    uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); +    const char *op_name = m_insn_info->getName (insn.getOpcode ()); +    bool update_ra = false; +    uint32_t ra_offset = 0; + +    /* +     * BEQZ16 rs, offset +     *      condition <- (GPR[rs] = 0) +     *      if condition then +     *          PC = PC + sign_ext (offset || 0) +     * +     * BNEZ16 rs, offset +     *      condition <- (GPR[rs] != 0) +     *      if condition then +     *          PC = PC + sign_ext (offset || 0) +     * +     * BEQZC rs, offset     (compact instruction: No delay slot) +     *      condition <- (GPR[rs] == 0) +     *      if condition then +     *         PC = PC + 4 + sign_ext (offset || 0) +    */ + +    uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    int32_t offset = insn.getOperand(1).getImm(); + +    int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); +    if (!success) +        return false; + +    if (!strcasecmp (op_name, "BEQZ16_MM")) +    { +        if (rs_val == 0) +            target = pc + offset; +        else +            target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. +    } +    else if (!strcasecmp (op_name, "BNEZ16_MM")) +    { +        if (rs_val != 0) +            target = pc + offset; +        else +            target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. +    } +    else if (!strcasecmp (op_name, "BEQZC_MM")) +    { +        if (rs_val == 0) +            target = pc + 4 + offset; +        else +            target = pc + 4;         // 32 bit instruction and does not have delay slot instruction. +    } +    else if (!strcasecmp (op_name, "BNEZC_MM")) +    { +        if (rs_val != 0) +            target = pc + 4 + offset; +        else +            target = pc + 4;         // 32 bit instruction and does not have delay slot instruction. +    } +    else if (!strcasecmp (op_name, "BGEZALS_MM")) +    { +        if (rs_val >= 0) +            target = pc + offset; +        else +            target = pc + 6;        // 32 bit instruction with short (2-byte) delay slot +         +        update_ra = true; +        ra_offset = 6; +    } +    else if (!strcasecmp (op_name, "BLTZALS_MM")) +    { +        if (rs_val >= 0) +            target = pc + offset; +        else +            target = pc + 6;        // 32 bit instruction with short (2-byte) delay slot +         +        update_ra = true; +        ra_offset = 6; +    } + +    Context context; +    context.type = eContextRelativeBranchImmediate; +    context.SetImmediate (current_inst_size + offset); + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) +        return false; + +    if (update_ra) +    { +        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) +            return false; +    } +    return true; +} + +/* Emulate micromips jump instructions. +   JALR16,JALRS16 +*/ +bool +EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t ra_offset = 0; +    const char *op_name = m_insn_info->getName (insn.getOpcode ()); + +    uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + +    uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); +    if (!success) +        return false; + +    if (!strcasecmp (op_name, "JALR16_MM")) +        ra_offset = 6;      // 2-byte instruction with 4-byte delay slot. +    else if (!strcasecmp (op_name, "JALRS16_MM")) +        ra_offset = 4;      // 2-byte instruction with 2-byte delay slot. + +    Context context; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) +        return false; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) +        return false; + +    return true; +} + +/* Emulate JALS and JALX instructions. +    JALS 32 bit instruction with short (2-byte) delay slot. +    JALX 32 bit instruction with 4-byte delay slot. +*/ +bool +EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t offset=0, target=0, pc=0, ra_offset=0; +    const char *op_name = m_insn_info->getName (insn.getOpcode ()); +     +    /*  +     * JALS target +     *      RA = PC + 6 +     *      offset = sign_ext (offset << 1) +     *      PC = PC[31-27] | offset +     * JALX target +     *      RA = PC + 8 +     *      offset = sign_ext (offset << 2) +     *      PC = PC[31-28] | offset +    */ +    offset = insn.getOperand(0).getImm(); + +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    // These are PC-region branches and not PC-relative. +    if (!strcasecmp (op_name, "JALS_MM")) +    { +        // target address is in the “current†128 MB-aligned region +        target = (pc & 0xF8000000UL) | offset; +        ra_offset = 6; +    } +    else if (!strcasecmp (op_name, "JALX_MM")) +    { +        // target address is in the “current†256 MB-aligned region +        target = (pc & 0xF0000000UL) | offset; +        ra_offset = 8; +    } + +    Context context; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) +        return false; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) +        return false; + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_JALRS (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t rs=0, rt=0; +    int32_t pc=0, rs_val=0; +     +    /* +        JALRS rt, rs +            GPR[rt] <- PC + 6 +            PC <- GPR[rs] +    */ + +    rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); +    if (!success) +        return false; + +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; +     +    Context context; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) +        return false; + +    // This is 4-byte instruction with 2-byte delay slot. +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6)) +        return false; +     +    return true; +} + +bool  EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)  {      bool success = false; @@ -797,15 +1704,15 @@ EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -817,7 +1724,7 @@ EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -840,15 +1747,15 @@ EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -860,7 +1767,7 @@ EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -883,15 +1790,15 @@ EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -903,7 +1810,7 @@ EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -926,11 +1833,11 @@ EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -942,7 +1849,7 @@ EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -965,11 +1872,11 @@ EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -981,7 +1888,7 @@ EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1004,11 +1911,11 @@ EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1020,7 +1927,7 @@ EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1043,11 +1950,11 @@ EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1059,7 +1966,7 @@ EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1082,11 +1989,11 @@ EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1098,7 +2005,7 @@ EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1121,11 +2028,11 @@ EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1137,7 +2044,7 @@ EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1160,11 +2067,11 @@ EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1176,7 +2083,7 @@ EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1199,11 +2106,11 @@ EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1215,10 +2122,10 @@ EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -1238,7 +2145,7 @@ EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; @@ -1246,10 +2153,10 @@ EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -1269,7 +2176,7 @@ EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; @@ -1277,10 +2184,10 @@ EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1305,11 +2212,11 @@ EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1320,10 +2227,10 @@ EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -1348,11 +2255,11 @@ EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1363,10 +2270,10 @@ EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -1391,11 +2298,11 @@ EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1406,10 +2313,10 @@ EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)      else          target = pc + 8;    /* skip delay slot */ -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -1435,11 +2342,11 @@ EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1450,10 +2357,10 @@ EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1478,11 +2385,11 @@ EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1493,10 +2400,10 @@ EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1521,11 +2428,11 @@ EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1536,10 +2443,10 @@ EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1564,11 +2471,11 @@ EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1579,10 +2486,10 @@ EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1606,11 +2513,11 @@ EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1621,10 +2528,10 @@ EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1648,11 +2555,11 @@ EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1663,10 +2570,10 @@ EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -1689,11 +2596,11 @@ EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -1704,7 +2611,7 @@ EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1723,7 +2630,7 @@ EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; @@ -1731,7 +2638,7 @@ EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1754,15 +2661,15 @@ EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1774,7 +2681,7 @@ EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1797,15 +2704,15 @@ EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1817,7 +2724,7 @@ EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1841,15 +2748,15 @@ EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1861,7 +2768,7 @@ EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1885,15 +2792,15 @@ EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1905,7 +2812,7 @@ EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1929,15 +2836,15 @@ EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1949,7 +2856,7 @@ EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -1973,15 +2880,15 @@ EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -1993,7 +2900,7 @@ EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2016,11 +2923,11 @@ EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2032,7 +2939,7 @@ EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2055,11 +2962,11 @@ EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2071,7 +2978,7 @@ EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2094,11 +3001,11 @@ EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2110,7 +3017,7 @@ EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2133,11 +3040,11 @@ EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2149,7 +3056,7 @@ EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2172,11 +3079,11 @@ EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2188,7 +3095,7 @@ EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2211,11 +3118,11 @@ EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; @@ -2227,7 +3134,7 @@ EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2258,15 +3165,15 @@ EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -2278,7 +3185,7 @@ EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2302,15 +3209,15 @@ EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -2322,7 +3229,7 @@ EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2341,7 +3248,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; @@ -2350,7 +3257,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, pc)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc))          return false;      return true; @@ -2369,7 +3276,7 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; @@ -2378,10 +3285,10 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))          return false;      return true; @@ -2402,20 +3309,20 @@ EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false;      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8))          return false;      return true; @@ -2437,11 +3344,11 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -2449,10 +3356,10 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))          return false;      return true; @@ -2473,7 +3380,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success); +    rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);      if (!success)          return false; @@ -2481,7 +3388,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2500,13 +3407,13 @@ EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn)      */      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);      if (!success)          return false;      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))          return false;      return true; @@ -2529,11 +3436,11 @@ EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2547,7 +3454,7 @@ EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2570,11 +3477,11 @@ EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2588,7 +3495,7 @@ EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2611,11 +3518,11 @@ EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2629,7 +3536,7 @@ EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2652,11 +3559,11 @@ EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2670,7 +3577,7 @@ EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2694,11 +3601,11 @@ EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)      ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success); +    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);      if (!success)          return false; @@ -2709,7 +3616,7 @@ EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2733,11 +3640,11 @@ EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)      ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success); +    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);      if (!success)          return false; @@ -2748,7 +3655,7 @@ EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2772,11 +3679,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2791,7 +3698,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2815,11 +3722,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2834,7 +3741,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2860,11 +3767,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2879,7 +3786,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true; @@ -2905,11 +3812,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);      if (!success)          return false; @@ -2924,8 +3831,234 @@ EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) +        return false; + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_BNZB (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 1, true); +} + +bool +EmulateInstructionMIPS::Emulate_BNZH (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 2, true); +} + +bool +EmulateInstructionMIPS::Emulate_BNZW (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 4, true); +} + +bool +EmulateInstructionMIPS::Emulate_BNZD (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 8, true); +} + +bool +EmulateInstructionMIPS::Emulate_BZB (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 1, false); +} + +bool +EmulateInstructionMIPS::Emulate_BZH (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 2, false); +} + +bool +EmulateInstructionMIPS::Emulate_BZW (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 4, false); +} + +bool +EmulateInstructionMIPS::Emulate_BZD (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 8, false); +} + +bool +EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) +{ +    bool success = false, branch_hit = true; +    int32_t target = 0; +    RegisterValue reg_value; +    uint8_t * ptr = NULL; + +    uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    int32_t offset = insn.getOperand(1).getImm(); + +    int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) +        ptr = (uint8_t *)reg_value.GetBytes(); +    else +        return false; + +    for(int i = 0; i < 16 / element_byte_size; i++) +    { +        switch(element_byte_size) +        { +            case 1: +                if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) +                    branch_hit = false; +                break; +            case 2: +                if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +            case 4: +                if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +            case 8: +                if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +        } +        if(!branch_hit) +           break; +        ptr = ptr + element_byte_size; +    } + +    if(branch_hit) +        target = pc + offset; +    else +        target = pc + 8; + +    Context context; +    context.type = eContextRelativeBranchImmediate; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))          return false;      return true;  } + +bool +EmulateInstructionMIPS::Emulate_BNZV (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_V (insn, true); +} + +bool +EmulateInstructionMIPS::Emulate_BZV (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_V (insn, false); +} + +bool +EmulateInstructionMIPS::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) +{ +    bool success = false; +    int32_t target = 0; +    llvm::APInt wr_val = llvm::APInt::getNullValue(128); +    llvm::APInt fail_value = llvm::APInt::getMaxValue(128); +    llvm::APInt zero_value = llvm::APInt::getNullValue(128); +    RegisterValue reg_value; + +    uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    int32_t offset = insn.getOperand(1).getImm(); + +    int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); +    if (!success) +        return false; + +    if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) +        wr_val = reg_value.GetAsUInt128(fail_value); +    else +        return false; + +    if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) +        target = pc + offset; +    else +        target = pc + 8; + +    Context context; +    context.type = eContextRelativeBranchImmediate; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) +        return false; + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_LDST_Imm (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t base; +    int32_t imm, address; +    Context bad_vaddr_context; + +    uint32_t num_operands = insn.getNumOperands(); +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); +    imm = insn.getOperand(num_operands-1).getImm(); + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    /* read base register */ +    address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + imm; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    return true; +} + +bool +EmulateInstructionMIPS::Emulate_LDST_Reg (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t base, index; +    int32_t address, index_address; +    Context bad_vaddr_context; + +    uint32_t num_operands = insn.getNumOperands(); +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); +    index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); + +    RegisterInfo reg_info_base, reg_info_index; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) +        return false; + +    /* read base register */ +    address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* read index register */ +    index_address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + index_address; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    return true; +} diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h index 25d8fc8891d5b..e1340f9832785 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -60,53 +60,52 @@ public:          return false;      } -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual lldb_private::ConstString -    GetShortPluginName() -    { -        return GetPluginNameStatic(); -    } - -    virtual uint32_t -    GetPluginVersion() +    uint32_t +    GetPluginVersion() override      {          return 1;      }      bool -    SetTargetTriple (const lldb_private::ArchSpec &arch); +    SetTargetTriple (const lldb_private::ArchSpec &arch) override;      EmulateInstructionMIPS (const lldb_private::ArchSpec &arch); -    virtual bool -    SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) +    bool +    SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) override      {          return SupportsEmulatingInstructionsOfTypeStatic (inst_type);      } -    virtual bool  -    ReadInstruction (); -     -    virtual bool -    EvaluateInstruction (uint32_t evaluate_options); +    bool +    ReadInstruction () override; -    virtual bool +    bool +    EvaluateInstruction (uint32_t evaluate_options) override; + +    bool +    SetInstruction (const lldb_private::Opcode &insn_opcode,  +                    const lldb_private::Address &inst_addr,  +                    lldb_private::Target *target) override; + +    bool      TestEmulation (lldb_private::Stream *out_stream,                      lldb_private::ArchSpec &arch,  -                   lldb_private::OptionValueDictionary *test_data) +                   lldb_private::OptionValueDictionary *test_data) override      {          return false;      } -    virtual bool +    bool      GetRegisterInfo (lldb::RegisterKind reg_kind,                       uint32_t reg_num,  -                     lldb_private::RegisterInfo ®_info); +                     lldb_private::RegisterInfo ®_info) override; -    virtual bool -    CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan); +    bool +    CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan) override;  protected: @@ -121,6 +120,9 @@ protected:      static MipsOpcode*      GetOpcodeForInstruction (const char *op_name); +    uint32_t +    GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr); +      bool      Emulate_ADDiu (llvm::MCInst& insn); @@ -131,6 +133,33 @@ protected:      Emulate_LW (llvm::MCInst& insn);      bool +    Emulate_ADDIUSP (llvm::MCInst& insn); + +    bool +    Emulate_ADDIUS5 (llvm::MCInst& insn); + +    bool +    Emulate_SWSP (llvm::MCInst& insn); + +    bool +    Emulate_SWM16_32 (llvm::MCInst& insn); + +    bool +    Emulate_LWSP (llvm::MCInst& insn); + +    bool +    Emulate_LWM16_32 (llvm::MCInst& insn); + +    bool +    Emulate_JRADDIUSP (llvm::MCInst& insn); + +    bool +    Emulate_LDST_Imm (llvm::MCInst& insn); + +    bool +    Emulate_LDST_Reg (llvm::MCInst& insn); + +    bool      Emulate_BEQ (llvm::MCInst& insn);      bool @@ -296,6 +325,57 @@ protected:      Emulate_BC1ANY4T  (llvm::MCInst& insn);      bool +    Emulate_BNZB  (llvm::MCInst& insn); + +    bool +    Emulate_BNZH  (llvm::MCInst& insn); + +    bool +    Emulate_BNZW  (llvm::MCInst& insn); + +    bool +    Emulate_BNZD  (llvm::MCInst& insn); + +    bool +    Emulate_BZB  (llvm::MCInst& insn); + +    bool +    Emulate_BZH  (llvm::MCInst& insn); + +    bool +    Emulate_BZW  (llvm::MCInst& insn); + +    bool +    Emulate_BZD  (llvm::MCInst& insn); + +    bool +    Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz); + +    bool +    Emulate_BNZV  (llvm::MCInst& insn); + +    bool +    Emulate_BZV  (llvm::MCInst& insn); + +    bool +    Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz); + +    bool +    Emulate_B16_MM (llvm::MCInst& insn); + +    bool +    Emulate_Branch_MM (llvm::MCInst& insn); + +    bool +    Emulate_JALRx16_MM (llvm::MCInst& insn); + +    bool +    Emulate_JALx (llvm::MCInst& insn); + +    bool +    Emulate_JALRS (llvm::MCInst& insn); + +    bool      nonvolatile_reg_p (uint32_t regnum);      const char * @@ -303,11 +383,15 @@ protected:  private:      std::unique_ptr<llvm::MCDisassembler>   m_disasm; +    std::unique_ptr<llvm::MCDisassembler>   m_alt_disasm;      std::unique_ptr<llvm::MCSubtargetInfo>  m_subtype_info; +    std::unique_ptr<llvm::MCSubtargetInfo>  m_alt_subtype_info;      std::unique_ptr<llvm::MCRegisterInfo>   m_reg_info;      std::unique_ptr<llvm::MCAsmInfo>        m_asm_info;      std::unique_ptr<llvm::MCContext>        m_context;      std::unique_ptr<llvm::MCInstrInfo>      m_insn_info; +    uint32_t                                m_next_inst_size; +    bool                                    m_use_alt_disaasm;  };  #endif  // EmulateInstructionMIPS_h_ diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index a574e7d348e15..28eba093f3179 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -221,41 +221,76 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name      {          switch (reg_num)          { -            case gcc_dwarf_sp_mips64:  return "r29";  -            case gcc_dwarf_r30_mips64: return "r30";  -            case gcc_dwarf_ra_mips64:  return "r31"; -            case gcc_dwarf_f0_mips64:  return "f0"; -            case gcc_dwarf_f1_mips64:  return "f1"; -            case gcc_dwarf_f2_mips64:  return "f2"; -            case gcc_dwarf_f3_mips64:  return "f3"; -            case gcc_dwarf_f4_mips64:  return "f4"; -            case gcc_dwarf_f5_mips64:  return "f5"; -            case gcc_dwarf_f6_mips64:  return "f6"; -            case gcc_dwarf_f7_mips64:  return "f7"; -            case gcc_dwarf_f8_mips64:  return "f8"; -            case gcc_dwarf_f9_mips64:  return "f9"; -            case gcc_dwarf_f10_mips64: return "f10"; -            case gcc_dwarf_f11_mips64: return "f11"; -            case gcc_dwarf_f12_mips64: return "f12"; -            case gcc_dwarf_f13_mips64: return "f13"; -            case gcc_dwarf_f14_mips64: return "f14"; -            case gcc_dwarf_f15_mips64: return "f15"; -            case gcc_dwarf_f16_mips64: return "f16"; -            case gcc_dwarf_f17_mips64: return "f17"; -            case gcc_dwarf_f18_mips64: return "f18"; -            case gcc_dwarf_f19_mips64: return "f19"; -            case gcc_dwarf_f20_mips64: return "f20"; -            case gcc_dwarf_f21_mips64: return "f21"; -            case gcc_dwarf_f22_mips64: return "f22"; -            case gcc_dwarf_f23_mips64: return "f23"; -            case gcc_dwarf_f24_mips64: return "f24"; -            case gcc_dwarf_f25_mips64: return "f25"; -            case gcc_dwarf_f26_mips64: return "f26"; -            case gcc_dwarf_f27_mips64: return "f27"; -            case gcc_dwarf_f28_mips64: return "f28"; -            case gcc_dwarf_f29_mips64: return "f29"; -            case gcc_dwarf_f30_mips64: return "f30"; -            case gcc_dwarf_f31_mips64: return "f31"; +            case dwarf_sp_mips64:      return "r29";  +            case dwarf_r30_mips64:     return "r30";  +            case dwarf_ra_mips64:      return "r31"; +            case dwarf_f0_mips64:      return "f0"; +            case dwarf_f1_mips64:      return "f1"; +            case dwarf_f2_mips64:      return "f2"; +            case dwarf_f3_mips64:      return "f3"; +            case dwarf_f4_mips64:      return "f4"; +            case dwarf_f5_mips64:      return "f5"; +            case dwarf_f6_mips64:      return "f6"; +            case dwarf_f7_mips64:      return "f7"; +            case dwarf_f8_mips64:      return "f8"; +            case dwarf_f9_mips64:      return "f9"; +            case dwarf_f10_mips64:     return "f10"; +            case dwarf_f11_mips64:     return "f11"; +            case dwarf_f12_mips64:     return "f12"; +            case dwarf_f13_mips64:     return "f13"; +            case dwarf_f14_mips64:     return "f14"; +            case dwarf_f15_mips64:     return "f15"; +            case dwarf_f16_mips64:     return "f16"; +            case dwarf_f17_mips64:     return "f17"; +            case dwarf_f18_mips64:     return "f18"; +            case dwarf_f19_mips64:     return "f19"; +            case dwarf_f20_mips64:     return "f20"; +            case dwarf_f21_mips64:     return "f21"; +            case dwarf_f22_mips64:     return "f22"; +            case dwarf_f23_mips64:     return "f23"; +            case dwarf_f24_mips64:     return "f24"; +            case dwarf_f25_mips64:     return "f25"; +            case dwarf_f26_mips64:     return "f26"; +            case dwarf_f27_mips64:     return "f27"; +            case dwarf_f28_mips64:     return "f28"; +            case dwarf_f29_mips64:     return "f29"; +            case dwarf_f30_mips64:     return "f30"; +            case dwarf_f31_mips64:     return "f31"; +            case dwarf_w0_mips64:      return "w0"; +            case dwarf_w1_mips64:      return "w1"; +            case dwarf_w2_mips64:      return "w2"; +            case dwarf_w3_mips64:      return "w3"; +            case dwarf_w4_mips64:      return "w4"; +            case dwarf_w5_mips64:      return "w5"; +            case dwarf_w6_mips64:      return "w6"; +            case dwarf_w7_mips64:      return "w7"; +            case dwarf_w8_mips64:      return "w8"; +            case dwarf_w9_mips64:      return "w9"; +            case dwarf_w10_mips64:     return "w10"; +            case dwarf_w11_mips64:     return "w11"; +            case dwarf_w12_mips64:     return "w12"; +            case dwarf_w13_mips64:     return "w13"; +            case dwarf_w14_mips64:     return "w14"; +            case dwarf_w15_mips64:     return "w15"; +            case dwarf_w16_mips64:     return "w16"; +            case dwarf_w17_mips64:     return "w17"; +            case dwarf_w18_mips64:     return "w18"; +            case dwarf_w19_mips64:     return "w19"; +            case dwarf_w20_mips64:     return "w20"; +            case dwarf_w21_mips64:     return "w21"; +            case dwarf_w22_mips64:     return "w22"; +            case dwarf_w23_mips64:     return "w23"; +            case dwarf_w24_mips64:     return "w24"; +            case dwarf_w25_mips64:     return "w25"; +            case dwarf_w26_mips64:     return "w26"; +            case dwarf_w27_mips64:     return "w27"; +            case dwarf_w28_mips64:     return "w28"; +            case dwarf_w29_mips64:     return "w29"; +            case dwarf_w30_mips64:     return "w30"; +            case dwarf_w31_mips64:     return "w31"; +            case dwarf_mir_mips64:     return "mir"; +            case dwarf_mcsr_mips64:    return "mcsr"; +            case dwarf_config5_mips64: return "config5";              default:                  break;          } @@ -264,78 +299,113 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name      switch (reg_num)      { -        case gcc_dwarf_zero_mips64:     return "r0"; -        case gcc_dwarf_r1_mips64:       return "r1"; -        case gcc_dwarf_r2_mips64:       return "r2"; -        case gcc_dwarf_r3_mips64:       return "r3"; -        case gcc_dwarf_r4_mips64:       return "r4"; -        case gcc_dwarf_r5_mips64:       return "r5"; -        case gcc_dwarf_r6_mips64:       return "r6"; -        case gcc_dwarf_r7_mips64:       return "r7"; -        case gcc_dwarf_r8_mips64:       return "r8"; -        case gcc_dwarf_r9_mips64:       return "r9"; -        case gcc_dwarf_r10_mips64:      return "r10"; -        case gcc_dwarf_r11_mips64:      return "r11"; -        case gcc_dwarf_r12_mips64:      return "r12"; -        case gcc_dwarf_r13_mips64:      return "r13"; -        case gcc_dwarf_r14_mips64:      return "r14"; -        case gcc_dwarf_r15_mips64:      return "r15"; -        case gcc_dwarf_r16_mips64:      return "r16"; -        case gcc_dwarf_r17_mips64:      return "r17"; -        case gcc_dwarf_r18_mips64:      return "r18"; -        case gcc_dwarf_r19_mips64:      return "r19"; -        case gcc_dwarf_r20_mips64:      return "r20"; -        case gcc_dwarf_r21_mips64:      return "r21"; -        case gcc_dwarf_r22_mips64:      return "r22"; -        case gcc_dwarf_r23_mips64:      return "r23"; -        case gcc_dwarf_r24_mips64:      return "r24"; -        case gcc_dwarf_r25_mips64:      return "r25"; -        case gcc_dwarf_r26_mips64:      return "r26"; -        case gcc_dwarf_r27_mips64:      return "r27"; -        case gcc_dwarf_gp_mips64:       return "gp"; -        case gcc_dwarf_sp_mips64:       return "sp"; -        case gcc_dwarf_r30_mips64:      return "fp"; -        case gcc_dwarf_ra_mips64:       return "ra"; -        case gcc_dwarf_sr_mips64:       return "sr"; -        case gcc_dwarf_lo_mips64:       return "lo"; -        case gcc_dwarf_hi_mips64:       return "hi"; -        case gcc_dwarf_bad_mips64:      return "bad"; -        case gcc_dwarf_cause_mips64:    return "cause"; -        case gcc_dwarf_pc_mips64:       return "pc"; -        case gcc_dwarf_f0_mips64:       return "f0"; -        case gcc_dwarf_f1_mips64:       return "f1"; -        case gcc_dwarf_f2_mips64:       return "f2"; -        case gcc_dwarf_f3_mips64:       return "f3"; -        case gcc_dwarf_f4_mips64:       return "f4"; -        case gcc_dwarf_f5_mips64:       return "f5"; -        case gcc_dwarf_f6_mips64:       return "f6"; -        case gcc_dwarf_f7_mips64:       return "f7"; -        case gcc_dwarf_f8_mips64:       return "f8"; -        case gcc_dwarf_f9_mips64:       return "f9"; -        case gcc_dwarf_f10_mips64:      return "f10"; -        case gcc_dwarf_f11_mips64:      return "f11"; -        case gcc_dwarf_f12_mips64:      return "f12"; -        case gcc_dwarf_f13_mips64:      return "f13"; -        case gcc_dwarf_f14_mips64:      return "f14"; -        case gcc_dwarf_f15_mips64:      return "f15"; -        case gcc_dwarf_f16_mips64:      return "f16"; -        case gcc_dwarf_f17_mips64:      return "f17"; -        case gcc_dwarf_f18_mips64:      return "f18"; -        case gcc_dwarf_f19_mips64:      return "f19"; -        case gcc_dwarf_f20_mips64:      return "f20"; -        case gcc_dwarf_f21_mips64:      return "f21"; -        case gcc_dwarf_f22_mips64:      return "f22"; -        case gcc_dwarf_f23_mips64:      return "f23"; -        case gcc_dwarf_f24_mips64:      return "f24"; -        case gcc_dwarf_f25_mips64:      return "f25"; -        case gcc_dwarf_f26_mips64:      return "f26"; -        case gcc_dwarf_f27_mips64:      return "f27"; -        case gcc_dwarf_f28_mips64:      return "f28"; -        case gcc_dwarf_f29_mips64:      return "f29"; -        case gcc_dwarf_f30_mips64:      return "f30"; -        case gcc_dwarf_f31_mips64:      return "f31"; -        case gcc_dwarf_fcsr_mips64:     return "fcsr"; -        case gcc_dwarf_fir_mips64:      return "fir"; +        case dwarf_zero_mips64:     return "r0"; +        case dwarf_r1_mips64:       return "r1"; +        case dwarf_r2_mips64:       return "r2"; +        case dwarf_r3_mips64:       return "r3"; +        case dwarf_r4_mips64:       return "r4"; +        case dwarf_r5_mips64:       return "r5"; +        case dwarf_r6_mips64:       return "r6"; +        case dwarf_r7_mips64:       return "r7"; +        case dwarf_r8_mips64:       return "r8"; +        case dwarf_r9_mips64:       return "r9"; +        case dwarf_r10_mips64:      return "r10"; +        case dwarf_r11_mips64:      return "r11"; +        case dwarf_r12_mips64:      return "r12"; +        case dwarf_r13_mips64:      return "r13"; +        case dwarf_r14_mips64:      return "r14"; +        case dwarf_r15_mips64:      return "r15"; +        case dwarf_r16_mips64:      return "r16"; +        case dwarf_r17_mips64:      return "r17"; +        case dwarf_r18_mips64:      return "r18"; +        case dwarf_r19_mips64:      return "r19"; +        case dwarf_r20_mips64:      return "r20"; +        case dwarf_r21_mips64:      return "r21"; +        case dwarf_r22_mips64:      return "r22"; +        case dwarf_r23_mips64:      return "r23"; +        case dwarf_r24_mips64:      return "r24"; +        case dwarf_r25_mips64:      return "r25"; +        case dwarf_r26_mips64:      return "r26"; +        case dwarf_r27_mips64:      return "r27"; +        case dwarf_gp_mips64:       return "gp"; +        case dwarf_sp_mips64:       return "sp"; +        case dwarf_r30_mips64:      return "fp"; +        case dwarf_ra_mips64:       return "ra"; +        case dwarf_sr_mips64:       return "sr"; +        case dwarf_lo_mips64:       return "lo"; +        case dwarf_hi_mips64:       return "hi"; +        case dwarf_bad_mips64:      return "bad"; +        case dwarf_cause_mips64:    return "cause"; +        case dwarf_pc_mips64:       return "pc"; +        case dwarf_f0_mips64:       return "f0"; +        case dwarf_f1_mips64:       return "f1"; +        case dwarf_f2_mips64:       return "f2"; +        case dwarf_f3_mips64:       return "f3"; +        case dwarf_f4_mips64:       return "f4"; +        case dwarf_f5_mips64:       return "f5"; +        case dwarf_f6_mips64:       return "f6"; +        case dwarf_f7_mips64:       return "f7"; +        case dwarf_f8_mips64:       return "f8"; +        case dwarf_f9_mips64:       return "f9"; +        case dwarf_f10_mips64:      return "f10"; +        case dwarf_f11_mips64:      return "f11"; +        case dwarf_f12_mips64:      return "f12"; +        case dwarf_f13_mips64:      return "f13"; +        case dwarf_f14_mips64:      return "f14"; +        case dwarf_f15_mips64:      return "f15"; +        case dwarf_f16_mips64:      return "f16"; +        case dwarf_f17_mips64:      return "f17"; +        case dwarf_f18_mips64:      return "f18"; +        case dwarf_f19_mips64:      return "f19"; +        case dwarf_f20_mips64:      return "f20"; +        case dwarf_f21_mips64:      return "f21"; +        case dwarf_f22_mips64:      return "f22"; +        case dwarf_f23_mips64:      return "f23"; +        case dwarf_f24_mips64:      return "f24"; +        case dwarf_f25_mips64:      return "f25"; +        case dwarf_f26_mips64:      return "f26"; +        case dwarf_f27_mips64:      return "f27"; +        case dwarf_f28_mips64:      return "f28"; +        case dwarf_f29_mips64:      return "f29"; +        case dwarf_f30_mips64:      return "f30"; +        case dwarf_f31_mips64:      return "f31"; +        case dwarf_fcsr_mips64:     return "fcsr"; +        case dwarf_fir_mips64:      return "fir"; +        case dwarf_w0_mips64:       return "w0"; +        case dwarf_w1_mips64:       return "w1"; +        case dwarf_w2_mips64:       return "w2"; +        case dwarf_w3_mips64:       return "w3"; +        case dwarf_w4_mips64:       return "w4"; +        case dwarf_w5_mips64:       return "w5"; +        case dwarf_w6_mips64:       return "w6"; +        case dwarf_w7_mips64:       return "w7"; +        case dwarf_w8_mips64:       return "w8"; +        case dwarf_w9_mips64:       return "w9"; +        case dwarf_w10_mips64:      return "w10"; +        case dwarf_w11_mips64:      return "w11"; +        case dwarf_w12_mips64:      return "w12"; +        case dwarf_w13_mips64:      return "w13"; +        case dwarf_w14_mips64:      return "w14"; +        case dwarf_w15_mips64:      return "w15"; +        case dwarf_w16_mips64:      return "w16"; +        case dwarf_w17_mips64:      return "w17"; +        case dwarf_w18_mips64:      return "w18"; +        case dwarf_w19_mips64:      return "w19"; +        case dwarf_w20_mips64:      return "w20"; +        case dwarf_w21_mips64:      return "w21"; +        case dwarf_w22_mips64:      return "w22"; +        case dwarf_w23_mips64:      return "w23"; +        case dwarf_w24_mips64:      return "w24"; +        case dwarf_w25_mips64:      return "w25"; +        case dwarf_w26_mips64:      return "w26"; +        case dwarf_w27_mips64:      return "w27"; +        case dwarf_w28_mips64:      return "w28"; +        case dwarf_w29_mips64:      return "w29"; +        case dwarf_w30_mips64:      return "w30"; +        case dwarf_w31_mips64:      return "w31"; +        case dwarf_mcsr_mips64:     return "mcsr"; +        case dwarf_mir_mips64:      return "mir"; +        case dwarf_config5_mips64:  return "config5";      }      return nullptr;  } @@ -347,11 +417,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n      {          switch (reg_num)          { -            case LLDB_REGNUM_GENERIC_PC:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break; -            case LLDB_REGNUM_GENERIC_SP:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break; -            case LLDB_REGNUM_GENERIC_FP:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break; -            case LLDB_REGNUM_GENERIC_RA:    reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break; -            case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break; +            case LLDB_REGNUM_GENERIC_PC:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips64; break; +            case LLDB_REGNUM_GENERIC_SP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips64; break; +            case LLDB_REGNUM_GENERIC_FP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips64; break; +            case LLDB_REGNUM_GENERIC_RA:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips64; break; +            case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips64; break;              default:                  return false;          } @@ -362,18 +432,24 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n         ::memset (®_info, 0, sizeof(RegisterInfo));         ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); -       if (reg_num == gcc_dwarf_sr_mips64 || reg_num == gcc_dwarf_fcsr_mips64 || reg_num == gcc_dwarf_fir_mips64) +       if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64)         {             reg_info.byte_size = 4;             reg_info.format = eFormatHex;             reg_info.encoding = eEncodingUint;         } -       else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_f31_mips64) +       else if ((int)reg_num >= dwarf_zero_mips64 && (int)reg_num <= dwarf_f31_mips64)         {             reg_info.byte_size = 8;             reg_info.format = eFormatHex;             reg_info.encoding = eEncodingUint;         } +       else if ((int)reg_num >= dwarf_w0_mips64 && (int)reg_num <= dwarf_w31_mips64) +       { +           reg_info.byte_size = 16; +           reg_info.format = eFormatVectorOfUInt8; +           reg_info.encoding = eEncodingVector; +       }         else         {             return false; @@ -385,11 +461,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n         switch (reg_num)         { -           case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; -           case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; -           case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; -           case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; -           case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; +           case dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; +           case dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; +           case dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; +           case dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; +           case dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;             default: break;         }         return true; @@ -410,8 +486,65 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)          { "SD",         &EmulateInstructionMIPS64::Emulate_SD,          "SD rt,offset(rs)"          },          { "LD",         &EmulateInstructionMIPS64::Emulate_LD,          "LD rt,offset(base)"        }, -        { "SW",         &EmulateInstructionMIPS64::Emulate_SW,          "SW rt,offset(rs)"          }, -        { "LW",         &EmulateInstructionMIPS64::Emulate_LW,          "LW rt,offset(rs)"          }, + + + +        //---------------------------------------------------------------------- +        // Load/Store  instructions +        //---------------------------------------------------------------------- +        /* Following list of emulated instructions are required by implementation of hardware watchpoint +           for MIPS in lldb. As we just need the address accessed by instructions, we have generalised  +           all these instructions in 2 functions depending on their addressing modes */ + +        { "LB",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LB    rt, offset(base)" }, +        { "LBE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LBE   rt, offset(base)" }, +        { "LBU",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LBU   rt, offset(base)" }, +        { "LBUE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LBUE  rt, offset(base)" }, +        { "LDC1",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LDC1  ft, offset(base)" }, +        { "LDL",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LDL   rt, offset(base)" }, +        { "LDR",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LDR   rt, offset(base)" }, +        { "LLD",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LLD   rt, offset(base)" }, +        { "LDC2",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LDC2  rt, offset(base)" }, +        { "LDXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "LDXC1 fd, index (base)" }, +        { "LH",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LH    rt, offset(base)" }, +        { "LHE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LHE   rt, offset(base)" }, +        { "LHU",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LHU   rt, offset(base)" }, +        { "LHUE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LHUE  rt, offset(base)" }, +        { "LL",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LL    rt, offset(base)" }, +        { "LLE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LLE   rt, offset(base)" }, +        { "LUXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "LUXC1 fd, index (base)" }, +        { "LW",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LW    rt, offset(rs)"   }, +        { "LWC1",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWC1  ft, offset(base)" }, +        { "LWC2",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWC2  rt, offset(base)" }, +        { "LWE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWE   rt, offset(base)" }, +        { "LWL",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWL   rt, offset(base)" }, +        { "LWLE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWLE  rt, offset(base)" }, +        { "LWR",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWR   rt, offset(base)" }, +        { "LWRE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "LWRE  rt, offset(base)" }, +        { "LWXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "LWXC1 fd, index (base)" }, + +        { "SB",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SB    rt, offset(base)" }, +        { "SBE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SBE   rt, offset(base)" }, +        { "SC",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SC    rt, offset(base)" }, +        { "SCE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SCE   rt, offset(base)" }, +        { "SCD",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SCD   rt, offset(base)" }, +        { "SDL",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SDL   rt, offset(base)" }, +        { "SDR",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SDR   rt, offset(base)" }, +        { "SDC1",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SDC1  ft, offset(base)" }, +        { "SDC2",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SDC2  rt, offset(base)" }, +        { "SDXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "SDXC1 fs, index (base)" }, +        { "SH",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SH    rt, offset(base)" }, +        { "SHE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SHE   rt, offset(base)" }, +        { "SUXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "SUXC1 fs, index (base)" }, +        { "SW",         &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SW    rt, offset(rs)"   }, +        { "SWC1",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWC1  ft, offset(base)" }, +        { "SWC2",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWC2  rt, offset(base)" }, +        { "SWE",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWE   rt, offset(base)" }, +        { "SWL",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWL   rt, offset(base)" }, +        { "SWLE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWLE  rt, offset(base)" }, +        { "SWR",        &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWR   rt, offset(base)" }, +        { "SWRE",       &EmulateInstructionMIPS64::Emulate_LDST_Imm,          "SWRE  rt, offset(base)" }, +        { "SWXC1",      &EmulateInstructionMIPS64::Emulate_LDST_Reg,          "SWXC1 fs, index (base)" },          //----------------------------------------------------------------------          // Branch instructions @@ -474,6 +607,16 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)          { "BC1ANY2T",   &EmulateInstructionMIPS64::Emulate_BC1ANY2T,    "BC1ANY2T cc, offset"       },          { "BC1ANY4F",   &EmulateInstructionMIPS64::Emulate_BC1ANY4F,    "BC1ANY4F cc, offset"       },          { "BC1ANY4T",   &EmulateInstructionMIPS64::Emulate_BC1ANY4T,    "BC1ANY4T cc, offset"       }, +        { "BNZ_B",      &EmulateInstructionMIPS64::Emulate_BNZB,        "BNZ.b wt,s16"              }, +        { "BNZ_H",      &EmulateInstructionMIPS64::Emulate_BNZH,        "BNZ.h wt,s16"              }, +        { "BNZ_W",      &EmulateInstructionMIPS64::Emulate_BNZW,        "BNZ.w wt,s16"              }, +        { "BNZ_D",      &EmulateInstructionMIPS64::Emulate_BNZD,        "BNZ.d wt,s16"              }, +        { "BZ_B",       &EmulateInstructionMIPS64::Emulate_BZB,         "BZ.b wt,s16"               }, +        { "BZ_H",       &EmulateInstructionMIPS64::Emulate_BZH,         "BZ.h wt,s16"               }, +        { "BZ_W",       &EmulateInstructionMIPS64::Emulate_BZW,         "BZ.w wt,s16"               }, +        { "BZ_D",       &EmulateInstructionMIPS64::Emulate_BZD,         "BZ.d wt,s16"               }, +        { "BNZ_V",      &EmulateInstructionMIPS64::Emulate_BNZV,        "BNZ.V wt,s16"              }, +        { "BZ_V",       &EmulateInstructionMIPS64::Emulate_BZV,         "BZ.V wt,s16"               },      };      static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); @@ -545,7 +688,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)      if (auto_advance_pc)      { -        old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +        old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);          if (!success)              return false;      } @@ -557,7 +700,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)      if (auto_advance_pc)      { -        new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +        new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);          if (!success)              return false; @@ -566,7 +709,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)          {              new_pc += 4;              Context context; -            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc)) +            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc))                  return false;          }      } @@ -584,10 +727,10 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)      const bool can_replace = false;      // Our previous Call Frame Address is the stack pointer -    row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0); +    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);      // Our previous PC is in the RA -    row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace); +    row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace);      unwind_plan.AppendRow (row); @@ -595,6 +738,7 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)      unwind_plan.SetSourceName ("EmulateInstructionMIPS64");      unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);      unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); +    unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64);      return true;  } @@ -604,18 +748,18 @@ EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum)  {      switch (regnum)      { -        case gcc_dwarf_r16_mips64: -        case gcc_dwarf_r17_mips64: -        case gcc_dwarf_r18_mips64: -        case gcc_dwarf_r19_mips64: -        case gcc_dwarf_r20_mips64: -        case gcc_dwarf_r21_mips64: -        case gcc_dwarf_r22_mips64: -        case gcc_dwarf_r23_mips64: -        case gcc_dwarf_gp_mips64: -        case gcc_dwarf_sp_mips64: -        case gcc_dwarf_r30_mips64: -        case gcc_dwarf_ra_mips64: +        case dwarf_r16_mips64: +        case dwarf_r17_mips64: +        case dwarf_r18_mips64: +        case dwarf_r19_mips64: +        case dwarf_r20_mips64: +        case dwarf_r21_mips64: +        case dwarf_r22_mips64: +        case dwarf_r23_mips64: +        case dwarf_gp_mips64: +        case dwarf_sp_mips64: +        case dwarf_r30_mips64: +        case dwarf_ra_mips64:              return true;          default:              return false; @@ -636,10 +780,10 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)      src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      /* Check if this is daddiu sp,<src>,imm16 */ -    if (dst == gcc_dwarf_sp_mips64) +    if (dst == dwarf_sp_mips64)      {          /* read <src> register */ -        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success); +        uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);          if (!success)              return false; @@ -647,79 +791,19 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)          Context context;          RegisterInfo reg_info_sp; -        if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp)) +        if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))              context.SetRegisterPlusOffset (reg_info_sp, imm);          /* We are allocating bytes on stack */          context.type = eContextAdjustStackPointer; -        WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result); +        WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result);      }      return true;  }  bool -EmulateInstructionMIPS64::Emulate_SW (llvm::MCInst& insn) -{ -    bool success = false; -    uint32_t base; -    int64_t imm, address; -    Context bad_vaddr_context; - -    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); -    imm = insn.getOperand(2).getImm(); - -    RegisterInfo reg_info_base; -    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)) -        return false; - -    /* read base register */ -    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success); -    if (!success) -        return false; - -    /* destination address */ -    address = address + imm; - -    /* Set the bad_vaddr register with base address used in the instruction */ -    bad_vaddr_context.type = eContextInvalid; -    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address); - -    return true; -} - -bool -EmulateInstructionMIPS64::Emulate_LW (llvm::MCInst& insn) -{ -    bool success = false; -    uint32_t base; -    int64_t imm, address; -    Context bad_vaddr_context; - -    base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); -    imm = insn.getOperand(2).getImm(); - -    RegisterInfo reg_info_base; -    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)) -        return false; - -    /* read base register */ -    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success); -    if (!success) -        return false; - -    /* destination address */ -    address = address + imm; - -    /* Set the bad_vaddr register with base address used in the instruction */ -    bad_vaddr_context.type = eContextInvalid; -    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address); - -    return true; -} - -bool  EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)  {      uint64_t address; @@ -734,12 +818,12 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)      src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); -    if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base) -        || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base) +        || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))          return false;      /* read SP */ -    address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success); +    address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success);      if (!success)          return false; @@ -747,7 +831,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)      address = address + imm;      /* We look for sp based non-volatile register stores */ -    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) +    if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))      {          Context context;          RegisterValue data_src; @@ -769,7 +853,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)      /* Set the bad_vaddr register with base address used in the instruction */      bad_vaddr_context.type = eContextInvalid; -    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address); +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address);      return true;  } @@ -777,17 +861,38 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)  bool  EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)  { +    bool success =false;      uint32_t src, base; +    int64_t imm, address; +    Context bad_vaddr_context;      src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); +    imm = insn.getOperand(2).getImm(); + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)) +        return false; + +    /* read base register */ +    address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); +    if (!success) +        return false; -    if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src)) +    /* destination address */ +    address = address + imm; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); + + +    if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))      {          RegisterValue data_src;          RegisterInfo reg_info_src; -        if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src)) +        if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))              return false;          Context context; @@ -821,15 +926,15 @@ EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -841,7 +946,7 @@ EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -864,15 +969,15 @@ EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -884,7 +989,7 @@ EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -907,15 +1012,15 @@ EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -927,7 +1032,7 @@ EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -950,15 +1055,15 @@ EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -970,7 +1075,7 @@ EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -993,11 +1098,11 @@ EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1009,7 +1114,7 @@ EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1032,11 +1137,11 @@ EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1048,7 +1153,7 @@ EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1071,11 +1176,11 @@ EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1087,7 +1192,7 @@ EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1110,11 +1215,11 @@ EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1126,7 +1231,7 @@ EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1149,11 +1254,11 @@ EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1165,7 +1270,7 @@ EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1188,11 +1293,11 @@ EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1204,7 +1309,7 @@ EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1227,11 +1332,11 @@ EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1243,7 +1348,7 @@ EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1266,11 +1371,11 @@ EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1282,10 +1387,10 @@ EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -1305,7 +1410,7 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; @@ -1313,10 +1418,10 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -1336,7 +1441,7 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; @@ -1344,10 +1449,10 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1372,11 +1477,11 @@ EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1387,10 +1492,10 @@ EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -1415,11 +1520,11 @@ EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1430,10 +1535,10 @@ EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -1458,11 +1563,11 @@ EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1473,10 +1578,10 @@ EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)      else          target = pc + 8;    /* skip delay slot */ -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -1502,11 +1607,11 @@ EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1517,10 +1622,10 @@ EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1545,11 +1650,11 @@ EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1560,10 +1665,10 @@ EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1588,11 +1693,11 @@ EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1603,10 +1708,10 @@ EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1631,11 +1736,11 @@ EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1646,10 +1751,10 @@ EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1673,11 +1778,11 @@ EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1688,10 +1793,10 @@ EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1715,11 +1820,11 @@ EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1730,10 +1835,10 @@ EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)      else          target = pc + 4; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -1756,11 +1861,11 @@ EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -1771,7 +1876,7 @@ EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)      else          target = pc + 8; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1790,7 +1895,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; @@ -1798,7 +1903,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1821,15 +1926,15 @@ EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -1841,7 +1946,7 @@ EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1864,15 +1969,15 @@ EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -1884,7 +1989,7 @@ EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1908,15 +2013,15 @@ EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -1928,7 +2033,7 @@ EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1952,15 +2057,15 @@ EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -1972,7 +2077,7 @@ EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -1996,15 +2101,15 @@ EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2016,7 +2121,7 @@ EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2040,15 +2145,15 @@ EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2060,7 +2165,7 @@ EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2083,11 +2188,11 @@ EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2099,7 +2204,7 @@ EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2122,11 +2227,11 @@ EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2138,7 +2243,7 @@ EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2161,11 +2266,11 @@ EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2177,7 +2282,7 @@ EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2200,11 +2305,11 @@ EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2216,7 +2321,7 @@ EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2239,11 +2344,11 @@ EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2255,7 +2360,7 @@ EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2278,11 +2383,11 @@ EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; @@ -2294,7 +2399,7 @@ EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2325,15 +2430,15 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2345,7 +2450,7 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2369,15 +2474,15 @@ EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());      offset = insn.getOperand(2).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2389,7 +2494,7 @@ EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)      Context context;      context.type = eContextRelativeBranchImmediate; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2408,7 +2513,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; @@ -2417,7 +2522,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, pc)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc))          return false;      return true; @@ -2436,7 +2541,7 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)      */      offset = insn.getOperand(0).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; @@ -2445,10 +2550,10 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))          return false;      return true; @@ -2469,20 +2574,20 @@ EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false;      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, pc + 8)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8))          return false;      return true; @@ -2504,11 +2609,11 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2516,10 +2621,10 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))          return false;      return true; @@ -2540,7 +2645,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)      rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success); +    rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);      if (!success)          return false; @@ -2548,7 +2653,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2567,13 +2672,13 @@ EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn)      */      rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); -    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success); +    rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);      if (!success)          return false;      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))          return false;      return true; @@ -2596,11 +2701,11 @@ EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2614,7 +2719,7 @@ EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2637,11 +2742,11 @@ EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2655,7 +2760,7 @@ EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2678,11 +2783,11 @@ EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2696,7 +2801,7 @@ EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2719,11 +2824,11 @@ EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2737,7 +2842,7 @@ EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2761,11 +2866,11 @@ EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)      ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success); +    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);      if (!success)          return false; @@ -2776,7 +2881,7 @@ EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2800,11 +2905,11 @@ EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)      ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success); +    ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);      if (!success)          return false; @@ -2815,7 +2920,7 @@ EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2839,11 +2944,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2858,7 +2963,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2882,11 +2987,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2901,7 +3006,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2927,11 +3032,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2946,7 +3051,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true; @@ -2972,11 +3077,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)      cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());      offset = insn.getOperand(1).getImm(); -    pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success); +    pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);      if (!success)          return false; -    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success); +    fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);      if (!success)          return false; @@ -2991,8 +3096,234 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)      Context context; -    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target)) +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))          return false;      return true;  } + +bool +EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 1, true); +} + +bool +EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 2, true); +} + +bool +EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 4, true); +} + +bool +EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 8, true); +} + +bool +EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 1, false); +} + +bool +EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 2, false); +} + +bool +EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 4, false); +} + +bool +EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_DF(insn, 8, false); +} + +bool +EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) +{ +    bool success = false, branch_hit = true; +    int64_t target = 0; +    RegisterValue reg_value; +    uint8_t * ptr = NULL; + +    uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    int64_t offset = insn.getOperand(1).getImm(); + +    int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); +    if (!success) +        return false; + +    if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) +        ptr = (uint8_t *)reg_value.GetBytes(); +    else +        return false; + +    for(int i = 0; i < 16 / element_byte_size; i++) +    { +        switch(element_byte_size) +        { +            case 1: +                if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) +                    branch_hit = false; +                break; +            case 2: +                if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +            case 4: +                if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +            case 8: +                if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz)) +                    branch_hit = false; +                break; +        } +        if(!branch_hit) +           break; +        ptr = ptr + element_byte_size; +    } + +    if(branch_hit) +        target = pc + offset; +    else +        target = pc + 8; + +    Context context; +    context.type = eContextRelativeBranchImmediate; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) +        return false; + +    return true; +} + +bool +EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_V (insn, true); +} + +bool +EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn) +{ +    return Emulate_MSA_Branch_V (insn, false); +} + +bool +EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) +{ +    bool success = false; +    int64_t target = 0; +    llvm::APInt wr_val = llvm::APInt::getNullValue(128); +    llvm::APInt fail_value = llvm::APInt::getMaxValue(128); +    llvm::APInt zero_value = llvm::APInt::getNullValue(128); +    RegisterValue reg_value; + +    uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); +    int64_t offset = insn.getOperand(1).getImm(); + +    int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); +    if (!success) +        return false; + +    if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) +        wr_val = reg_value.GetAsUInt128(fail_value); +    else +        return false; + +    if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) +        target = pc + offset; +    else +        target = pc + 8; + +    Context context; +    context.type = eContextRelativeBranchImmediate; + +    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) +        return false; + +    return true; +} + +bool +EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t base; +    int64_t imm, address; +    Context bad_vaddr_context; + +    uint32_t num_operands = insn.getNumOperands(); +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); +    imm = insn.getOperand(num_operands-1).getImm(); + +    RegisterInfo reg_info_base; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    /* read base register */ +    address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + imm; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    return true; +} + +bool +EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn) +{ +    bool success = false; +    uint32_t base, index; +    int64_t address, index_address; +    Context bad_vaddr_context; + +    uint32_t num_operands = insn.getNumOperands(); +    base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); +    index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); + +    RegisterInfo reg_info_base, reg_info_index; +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) +        return false; + +    if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) +        return false; + +    /* read base register */ +    address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); +    if (!success) +        return false; + +    /* read index register */ +    index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); +    if (!success) +        return false; + +    /* destination address */ +    address = address + index_address; + +    /* Set the bad_vaddr register with base address used in the instruction */ +    bad_vaddr_context.type = eContextInvalid; +    WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + +    return true; +} diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h index faefd329a8e46..e0b20792ae1f9 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -1,4 +1,4 @@ -//===-- EmulateInstructionMIPS64.h ------------------------------------*- C++ -*-===// +//===-- EmulateInstructionMIPS64.h ------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,6 +10,14 @@  #ifndef EmulateInstructionMIPS64_h_  #define EmulateInstructionMIPS64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Core/Error.h" +#include "lldb/Interpreter/OptionValue.h" +  namespace llvm  {      class MCDisassembler; @@ -19,15 +27,13 @@ namespace llvm      class MCContext;      class MCInstrInfo;      class MCInst; -} - -#include "lldb/Core/EmulateInstruction.h" -#include "lldb/Core/Error.h" -#include "lldb/Interpreter/OptionValue.h" +} // namespace llvm  class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction  {  public:  +    EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch); +      static void      Initialize (); @@ -60,57 +66,47 @@ public:          return false;      } -    virtual lldb_private::ConstString -    GetPluginName(); - -    virtual lldb_private::ConstString -    GetShortPluginName() -    { -        return GetPluginNameStatic(); -    } +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion() +    uint32_t +    GetPluginVersion() override      {          return 1;      }      bool -    SetTargetTriple (const lldb_private::ArchSpec &arch); +    SetTargetTriple(const lldb_private::ArchSpec &arch) override; -    EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch); - -    virtual bool -    SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) +    bool +    SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override      {          return SupportsEmulatingInstructionsOfTypeStatic (inst_type);      } -    virtual bool  -    ReadInstruction (); +    bool +    ReadInstruction() override; -    virtual bool -    EvaluateInstruction (uint32_t evaluate_options); +    bool +    EvaluateInstruction(uint32_t evaluate_options) override; -    virtual bool -    TestEmulation (lldb_private::Stream *out_stream,  -                   lldb_private::ArchSpec &arch,  -                   lldb_private::OptionValueDictionary *test_data) +    bool +    TestEmulation(lldb_private::Stream *out_stream, +                  lldb_private::ArchSpec &arch, +                  lldb_private::OptionValueDictionary *test_data) override      {          return false;      } -    virtual bool -    GetRegisterInfo (lldb::RegisterKind reg_kind, -                     uint32_t reg_num,  -                     lldb_private::RegisterInfo ®_info); - -    virtual bool -    CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan); +    bool +    GetRegisterInfo(lldb::RegisterKind reg_kind, +                    uint32_t reg_num, +                    lldb_private::RegisterInfo ®_info) override; +    bool +    CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override;  protected: -      typedef struct      {          const char *op_name; @@ -128,13 +124,13 @@ protected:      Emulate_SD (llvm::MCInst& insn);      bool -    Emulate_SW (llvm::MCInst& insn); +    Emulate_LD (llvm::MCInst& insn);      bool -    Emulate_LW (llvm::MCInst& insn); +    Emulate_LDST_Imm (llvm::MCInst& insn);      bool -    Emulate_LD (llvm::MCInst& insn); +    Emulate_LDST_Reg (llvm::MCInst& insn);      bool      Emulate_BEQ (llvm::MCInst& insn); @@ -302,6 +298,42 @@ protected:      Emulate_BC1ANY4T  (llvm::MCInst& insn);      bool +    Emulate_BNZB  (llvm::MCInst& insn); + +    bool +    Emulate_BNZH  (llvm::MCInst& insn); + +    bool +    Emulate_BNZW  (llvm::MCInst& insn); + +    bool +    Emulate_BNZD  (llvm::MCInst& insn); + +    bool +    Emulate_BZB  (llvm::MCInst& insn); + +    bool +    Emulate_BZH  (llvm::MCInst& insn); + +    bool +    Emulate_BZW  (llvm::MCInst& insn); + +    bool +    Emulate_BZD  (llvm::MCInst& insn); + +    bool +    Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz); + +    bool +    Emulate_BNZV  (llvm::MCInst& insn); + +    bool +    Emulate_BZV  (llvm::MCInst& insn); + +    bool +    Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz); + +    bool      nonvolatile_reg_p (uint64_t regnum);      const char * @@ -316,4 +348,4 @@ private:      std::unique_ptr<llvm::MCInstrInfo>      m_insn_info;  }; -#endif  // EmulateInstructionMIPS64_h_ +#endif // EmulateInstructionMIPS64_h_ diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp index 9b72ceb71bd01..c2f1f2e95c838 100644 --- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -66,9 +66,11 @@ AddressSanitizerRuntime::GetTypeStatic()  AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :      m_is_active(false),      m_runtime_module(), -    m_process(process_sp), +    m_process_wp(),      m_breakpoint_id(0)  { +    if (process_sp) +        m_process_wp = process_sp;  }  AddressSanitizerRuntime::~AddressSanitizerRuntime() @@ -78,14 +80,11 @@ AddressSanitizerRuntime::~AddressSanitizerRuntime()  bool ModuleContainsASanRuntime(Module * module)  { -    SymbolContextList sc_list; -    const bool include_symbols = true; -    const bool append = true; -    const bool include_inlines = true; -     -    size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); -     -    return num_matches > 0; +    const Symbol* symbol = module->FindFirstSymbolWithNameAndType( +            ConstString("__asan_get_alloc_stack"), +            lldb::eSymbolTypeAny); + +    return symbol != nullptr;  }  void @@ -164,7 +163,11 @@ t  StructuredData::ObjectSP  AddressSanitizerRuntime::RetrieveReportData()  { -    ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread(); +    ProcessSP process_sp = GetProcessSP(); +    if (!process_sp) +        return StructuredData::ObjectSP(); + +    ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();      StackFrameSP frame_sp = thread_sp->GetSelectedFrame();      if (!frame_sp) @@ -178,7 +181,7 @@ AddressSanitizerRuntime::RetrieveReportData()      options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);      ValueObjectSP return_value_sp; -    if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted) +    if (process_sp->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)          return StructuredData::ObjectSP();      int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0); @@ -196,7 +199,7 @@ AddressSanitizerRuntime::RetrieveReportData()      addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);      std::string description;      Error error; -    m_process->ReadCStringFromMemory(description_ptr, description, error); +    process_sp->ReadCStringFromMemory(description_ptr, description, error);      StructuredData::Dictionary *dict = new StructuredData::Dictionary();      dict->AddStringItem("instrumentation_class", "AddressSanitizer"); @@ -252,27 +255,31 @@ AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackConte      assert (baton && "null baton");      if (!baton)          return false; -     +      AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton); -     +      StructuredData::ObjectSP report = instance->RetrieveReportData();      std::string description;      if (report) {          description = instance->FormatDescription(report);      } -    ThreadSP thread = context->exe_ctx_ref.GetThreadSP(); -    thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report)); - -    if (instance->m_process) +    ProcessSP process_sp = instance->GetProcessSP(); +    // Make sure this is the right process +    if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP())      { -        StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile()); +        ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); +        if (thread_sp) +            thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread_sp, description.c_str(), report)); +         +        StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());          if (stream_sp)          {              stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");          } +        return true;    // Return true to stop the target      } -    // Return true to stop the target, false to just let the target run. -    return true; +    else +        return false;   // Let target run  }  void @@ -281,6 +288,10 @@ AddressSanitizerRuntime::Activate()      if (m_is_active)          return; +    ProcessSP process_sp = GetProcessSP(); +    if (!process_sp) +        return; +      ConstString symbol_name ("__asan::AsanDie()");      const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode); @@ -290,7 +301,7 @@ AddressSanitizerRuntime::Activate()      if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())          return; -    Target &target = m_process->GetTarget(); +    Target &target = process_sp->GetTarget();      addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);      if (symbol_address == LLDB_INVALID_ADDRESS) @@ -298,18 +309,15 @@ AddressSanitizerRuntime::Activate()      bool internal = true;      bool hardware = false; -    Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get(); +    Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();      breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);      breakpoint->SetBreakpointKind ("address-sanitizer-report");      m_breakpoint_id = breakpoint->GetID(); -    if (m_process) +    StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile()); +    if (stream_sp)      { -        StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile()); -        if (stream_sp) -        { -                stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n"); -        } +            stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");      }      m_is_active = true; @@ -320,8 +328,12 @@ AddressSanitizerRuntime::Deactivate()  {      if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)      { -        m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id); -        m_breakpoint_id = LLDB_INVALID_BREAK_ID; +        ProcessSP process_sp = GetProcessSP(); +        if (process_sp) +        { +            process_sp->GetTarget().RemoveBreakpointByID(m_breakpoint_id); +            m_breakpoint_id = LLDB_INVALID_BREAK_ID; +        }      }      m_is_active = false;  } diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h index 69c134cbedaff..fe12ab847e76d 100644 --- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h +++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h @@ -10,6 +10,10 @@  #ifndef liblldb_AddressSanitizerRuntime_h_  #define liblldb_AddressSanitizerRuntime_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/ABI.h"  #include "lldb/Target/InstrumentationRuntime.h" @@ -21,7 +25,8 @@ namespace lldb_private {  class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime  {  public: -     +    ~AddressSanitizerRuntime() override; +      static lldb::InstrumentationRuntimeSP      CreateInstance (const lldb::ProcessSP &process_sp); @@ -36,29 +41,37 @@ public:      static lldb::InstrumentationRuntimeType      GetTypeStatic(); -     -    virtual -    ~AddressSanitizerRuntime(); -     -    virtual lldb_private::ConstString -    GetPluginName() { return GetPluginNameStatic(); } + +    lldb_private::ConstString +    GetPluginName() override +    {  +        return GetPluginNameStatic(); +    }      virtual lldb::InstrumentationRuntimeType      GetType() { return GetTypeStatic(); } -    virtual uint32_t -    GetPluginVersion() { return 1; } +    uint32_t +    GetPluginVersion() override +    { +        return 1; +    } -    virtual void -    ModulesDidLoad(lldb_private::ModuleList &module_list); +    void +    ModulesDidLoad(lldb_private::ModuleList &module_list) override; -    virtual bool -    IsActive(); +    bool +    IsActive() override;  private: -          AddressSanitizerRuntime(const lldb::ProcessSP &process_sp); -     + +    lldb::ProcessSP +    GetProcessSP () +    { +        return m_process_wp.lock(); +    } +      void      Activate(); @@ -76,11 +89,10 @@ private:      bool m_is_active;      lldb::ModuleSP m_runtime_module; -    lldb::ProcessSP m_process; +    lldb::ProcessWP m_process_wp;      lldb::user_id_t m_breakpoint_id; -  };  } // namespace lldb_private -#endif  // liblldb_InstrumentationRuntime_h_ +#endif // liblldb_AddressSanitizerRuntime_h_ diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 8e454e712fe80..143e447940576 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -16,6 +16,7 @@  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/Section.h"  #include "lldb/Core/StreamString.h" +#include "lldb/Interpreter/OptionValueProperties.h"  #include "lldb/Symbol/SymbolContext.h"  #include "lldb/Symbol/SymbolVendor.h"  #include "lldb/Target/Process.h" @@ -27,6 +28,58 @@  using namespace lldb;  using namespace lldb_private; +namespace { + +    PropertyDefinition +    g_properties[] = +    { +        { "enable-jit-breakpoint", OptionValue::eTypeBoolean, true,  true , nullptr, nullptr, "Enable breakpoint on __jit_debug_register_code." }, +        {  nullptr               , OptionValue::eTypeInvalid, false, 0,     nullptr, nullptr, nullptr } +    }; + +    enum +    { +        ePropertyEnableJITBreakpoint +    }; + + +    class PluginProperties : public Properties +    { +    public: +        static ConstString +        GetSettingName() +        { +            return JITLoaderGDB::GetPluginNameStatic(); +        } + +        PluginProperties() +        { +            m_collection_sp.reset (new OptionValueProperties(GetSettingName())); +            m_collection_sp->Initialize(g_properties); +        } + +        bool +        GetEnableJITBreakpoint() const +        { +            return m_collection_sp->GetPropertyAtIndexAsBoolean( +                nullptr, +                ePropertyEnableJITBreakpoint, +                g_properties[ePropertyEnableJITBreakpoint].default_uint_value != 0); +        } + +    }; + +    typedef std::shared_ptr<PluginProperties> JITLoaderGDBPropertiesSP; + +    static const JITLoaderGDBPropertiesSP& +    GetGlobalPluginProperties() +    { +        static const auto g_settings_sp(std::make_shared<PluginProperties>()); +        return g_settings_sp; +    } + +}  // anonymous namespace end +  //------------------------------------------------------------------  // Debug Interface Structures  //------------------------------------------------------------------ @@ -37,7 +90,6 @@ typedef enum      JIT_UNREGISTER_FN  } jit_actions_t; -#pragma pack(push, 4)  template <typename ptr_t>  struct jit_code_entry  { @@ -54,7 +106,6 @@ struct jit_descriptor      ptr_t    relevant_entry; // pointer      ptr_t    first_entry; // pointer  }; -#pragma pack(pop)  JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :      JITLoader(process), @@ -70,6 +121,19 @@ JITLoaderGDB::~JITLoaderGDB ()          m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);  } +void +JITLoaderGDB::DebuggerInitialize(Debugger &debugger) +{ +    if (!PluginManager::GetSettingForJITLoaderPlugin(debugger, PluginProperties::GetSettingName())) +    { +        const bool is_global_setting = true; +        PluginManager::CreateSettingForJITLoaderPlugin(debugger, +                                                       GetGlobalPluginProperties()->GetValueProperties(), +                                                       ConstString ("Properties for the JIT LoaderGDB plug-in."), +                                                       is_global_setting); +    } +} +  void JITLoaderGDB::DidAttach()  {      Target &target = m_process->GetTarget(); @@ -88,7 +152,7 @@ void  JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)  {      if (!DidSetJITBreakpoint() && m_process->IsAlive()) -	SetJITBreakpoint(module_list); +        SetJITBreakpoint(module_list);  }  //------------------------------------------------------------------ @@ -97,11 +161,13 @@ JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)  void  JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list)  { -    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER)); +    if (!GetGlobalPluginProperties()->GetEnableJITBreakpoint()) +        return;      if ( DidSetJITBreakpoint() )          return; +    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));      if (log)          log->Printf("JITLoaderGDB::%s looking for JIT register hook",                      __FUNCTION__); @@ -407,7 +473,8 @@ JITLoaderGDB::Initialize()  {      PluginManager::RegisterPlugin (GetPluginNameStatic(),                                     GetPluginDescriptionStatic(), -                                   CreateInstance); +                                   CreateInstance, +                                   DebuggerInitialize);  }  void diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h index bfa1721d3349c..10bd989c328f6 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h @@ -13,15 +13,19 @@  // C Includes  // C++ Includes  #include <map> -#include <vector> -#include <string> +// Other libraries and framework includes +// Project includes  #include "lldb/Target/JITLoader.h"  #include "lldb/Target/Process.h"  class JITLoaderGDB : public lldb_private::JITLoader  {  public: +    JITLoaderGDB(lldb_private::Process *process); + +    ~JITLoaderGDB() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -40,31 +44,29 @@ public:      static lldb::JITLoaderSP      CreateInstance (lldb_private::Process *process, bool force); -    JITLoaderGDB (lldb_private::Process *process); - -    virtual -    ~JITLoaderGDB (); +    static void +    DebuggerInitialize(lldb_private::Debugger &debugger);      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;      //------------------------------------------------------------------      // JITLoader interface      //------------------------------------------------------------------ -    virtual void -    DidAttach (); +    void +    DidAttach() override; -    virtual void -    DidLaunch (); +    void +    DidLaunch() override; -    virtual void -    ModulesDidLoad (lldb_private::ModuleList &module_list); +    void +    ModulesDidLoad(lldb_private::ModuleList &module_list) override;  private:      lldb::addr_t @@ -105,4 +107,4 @@ private:  }; -#endif +#endif // liblldb_JITLoaderGDB_h_ diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp new file mode 100644 index 0000000000000..a554aa57d58e5 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -0,0 +1,792 @@ +//===-- CPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CPlusPlusLanguage.h" + + +#include "llvm/ADT/StringRef.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/DataFormatters/CXXFunctionPointer.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/VectorType.h" + +#include "CxxStringTypes.h" +#include "LibCxx.h" +#include "LibStdcpp.h" + +#include <cstring> +#include <cctype> +#include <functional> +#include <mutex> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +CPlusPlusLanguage::Initialize() +{ +    PluginManager::RegisterPlugin (GetPluginNameStatic(), +                                   "C++ Language", +                                   CreateInstance); +} + +void +CPlusPlusLanguage::Terminate() +{ +    PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +CPlusPlusLanguage::GetPluginNameStatic() +{ +    static ConstString g_name("cplusplus"); +    return g_name; +} + + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +CPlusPlusLanguage::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +CPlusPlusLanguage::GetPluginVersion() +{ +    return 1; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +Language * +CPlusPlusLanguage::CreateInstance (lldb::LanguageType language) +{ +    if (Language::LanguageIsCPlusPlus(language)) +        return new CPlusPlusLanguage(); +    return nullptr; +} + +void +CPlusPlusLanguage::MethodName::Clear() +{ +    m_full.Clear(); +    m_basename = llvm::StringRef(); +    m_context = llvm::StringRef(); +    m_arguments = llvm::StringRef(); +    m_qualifiers = llvm::StringRef(); +    m_type = eTypeInvalid; +    m_parsed = false; +    m_parse_error = false; +} + +bool +ReverseFindMatchingChars (const llvm::StringRef &s, +                          const llvm::StringRef &left_right_chars, +                          size_t &left_pos, +                          size_t &right_pos, +                          size_t pos = llvm::StringRef::npos) +{ +    assert (left_right_chars.size() == 2); +    left_pos = llvm::StringRef::npos; +    const char left_char = left_right_chars[0]; +    const char right_char = left_right_chars[1]; +    pos = s.find_last_of(left_right_chars, pos); +    if (pos == llvm::StringRef::npos || s[pos] == left_char) +        return false; +    right_pos = pos; +    uint32_t depth = 1; +    while (pos > 0 && depth > 0) +    { +        pos = s.find_last_of(left_right_chars, pos); +        if (pos == llvm::StringRef::npos) +            return false; +        if (s[pos] == left_char) +        { +            if (--depth == 0) +            { +                left_pos = pos; +                return left_pos < right_pos; +            }             +        } +        else if (s[pos] == right_char) +        { +            ++depth; +        } +    } +    return false; +} + +static bool +IsValidBasename(const llvm::StringRef& basename) +{ +    // Check that the basename matches with the following regular expression or is an operator name: +    // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$" +    // We are using a hand written implementation because it is significantly more efficient then +    // using the general purpose regular expression library. +    size_t idx = 0; +    if (basename.size() > 0 && basename[0] == '~') +        idx = 1; + +    if (basename.size() <= idx) +        return false; // Empty string or "~" + +    if (!std::isalpha(basename[idx]) && basename[idx] != '_') +        return false; // First charater (after removing the possible '~'') isn't in [A-Za-z_] + +    // Read all characters matching [A-Za-z_0-9] +    ++idx; +    while (idx < basename.size()) +    { +        if (!std::isalnum(basename[idx]) && basename[idx] != '_') +            break; +        ++idx; +    } + +    // We processed all characters. It is a vaild basename. +    if (idx == basename.size()) +        return true; + +    // Check for basename with template arguments +    // TODO: Improve the quality of the validation with validating the template arguments +    if (basename[idx] == '<' && basename.back() == '>') +        return true; + +    // Check if the basename is a vaild C++ operator name +    if (!basename.startswith("operator")) +        return false; + +    static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$"); +    std::string basename_str(basename.str()); +    return g_operator_regex.Execute(basename_str.c_str(), nullptr); +} + +void +CPlusPlusLanguage::MethodName::Parse() +{ +    if (!m_parsed && m_full) +    { +//        ConstString mangled; +//        m_full.GetMangledCounterpart(mangled); +//        printf ("\n   parsing = '%s'\n", m_full.GetCString()); +//        if (mangled) +//            printf ("   mangled = '%s'\n", mangled.GetCString()); +        m_parse_error = false; +        m_parsed = true; +        llvm::StringRef full (m_full.GetCString()); +         +        size_t arg_start, arg_end; +        llvm::StringRef parens("()", 2); +        if (ReverseFindMatchingChars (full, parens, arg_start, arg_end)) +        { +            m_arguments = full.substr(arg_start, arg_end - arg_start + 1); +            if (arg_end + 1 < full.size()) +                m_qualifiers = full.substr(arg_end + 1); +            if (arg_start > 0) +            { +                size_t basename_end = arg_start; +                size_t context_start = 0; +                size_t context_end = llvm::StringRef::npos; +                if (basename_end > 0 && full[basename_end-1] == '>') +                { +                    // TODO: handle template junk... +                    // Templated function +                    size_t template_start, template_end; +                    llvm::StringRef lt_gt("<>", 2); +                    if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end)) +                    { +                        // Check for templated functions that include return type like: 'void foo<Int>()' +                        context_start = full.rfind(' ', template_start); +                        if (context_start == llvm::StringRef::npos) +                            context_start = 0; + +                        context_end = full.rfind(':', template_start); +                        if (context_end == llvm::StringRef::npos || context_end < context_start) +                            context_end = context_start; +                    } +                    else +                    { +                        context_end = full.rfind(':', basename_end); +                    } +                } +                else if (context_end == llvm::StringRef::npos) +                { +                    context_end = full.rfind(':', basename_end); +                } + +                if (context_end == llvm::StringRef::npos) +                    m_basename = full.substr(0, basename_end); +                else +                { +                    if (context_start < context_end) +                        m_context = full.substr(context_start, context_end - 1); +                    const size_t basename_begin = context_end + 1; +                    m_basename = full.substr(basename_begin, basename_end - basename_begin); +                } +                m_type = eTypeUnknownMethod; +            } +            else +            { +                m_parse_error = true; +                return; +            } + +            if (!IsValidBasename(m_basename)) +            { +                // The C++ basename doesn't match our regular expressions so this can't +                // be a valid C++ method, clear everything out and indicate an error +                m_context = llvm::StringRef(); +                m_basename = llvm::StringRef(); +                m_arguments = llvm::StringRef(); +                m_qualifiers = llvm::StringRef(); +                m_parse_error = true; +            } +        } +        else +        { +            m_parse_error = true; +        } +    } +} + +llvm::StringRef +CPlusPlusLanguage::MethodName::GetBasename () +{ +    if (!m_parsed) +        Parse(); +    return m_basename; +} + +llvm::StringRef +CPlusPlusLanguage::MethodName::GetContext () +{ +    if (!m_parsed) +        Parse(); +    return m_context; +} + +llvm::StringRef +CPlusPlusLanguage::MethodName::GetArguments () +{ +    if (!m_parsed) +        Parse(); +    return m_arguments; +} + +llvm::StringRef +CPlusPlusLanguage::MethodName::GetQualifiers () +{ +    if (!m_parsed) +        Parse(); +    return m_qualifiers; +} + +bool +CPlusPlusLanguage::IsCPPMangledName (const char *name) +{ +    // FIXME, we should really run through all the known C++ Language plugins and ask each one if +    // this is a C++ mangled name, but we can put that off till there is actually more than one +    // we care about. +     +    if (name && name[0] == '_' && name[1] == 'Z') +        return true; +    else +        return false; +} + +bool +CPlusPlusLanguage::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier) +{ +    static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$"); +    RegularExpression::Match match(4); +    if (g_basename_regex.Execute (name, &match)) +    { +        match.GetMatchAtIndex(name, 1, context); +        match.GetMatchAtIndex(name, 3, identifier); +        return true; +    } +    return false; +} + +class CPPRuntimeEquivalents +{ +public: +    CPPRuntimeEquivalents () +    { +         +        m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>")); + +        // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container +        m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>")); +         +        m_impl.Sort(); +    } +     +    void +    Add (ConstString& type_name, +         ConstString& type_equivalent) +    { +        m_impl.Insert(type_name.AsCString(), type_equivalent); +    } +     +    uint32_t +    FindExactMatches (ConstString& type_name, +                      std::vector<ConstString>& equivalents) +    { +         +        uint32_t count = 0; + +        for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString()); +             match != NULL; +             match = m_impl.FindNextValueForName(match)) +        { +            equivalents.push_back(match->value); +            count++; +        } + +        return count;         +    } +     +    // partial matches can occur when a name with equivalents is a template argument. +    // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename +    // such as "class Templatized<class Foo, Anything>" we want this to be replaced with +    // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming +    // once we get a partial match, we add it to the exact matches list for faster retrieval +    uint32_t +    FindPartialMatches (ConstString& type_name, +                        std::vector<ConstString>& equivalents) +    { +         +        uint32_t count = 0; +         +        const char* type_name_cstr = type_name.AsCString(); +         +        size_t items_count = m_impl.GetSize(); +         +        for (size_t item = 0; item < items_count; item++) +        { +            const char* key_cstr = m_impl.GetCStringAtIndex(item); +            if ( strstr(type_name_cstr,key_cstr) ) +            { +                count += AppendReplacements(type_name_cstr, +                                            key_cstr, +                                            equivalents); +            } +        } +         +        return count; +         +    } +     +private: +     +    std::string& replace (std::string& target, +                          std::string& pattern, +                          std::string& with) +    { +        size_t pos; +        size_t pattern_len = pattern.size(); +         +        while ( (pos = target.find(pattern)) != std::string::npos ) +            target.replace(pos, pattern_len, with); +         +        return target; +    } +     +    uint32_t +    AppendReplacements (const char* original, +                        const char *matching_key, +                        std::vector<ConstString>& equivalents) +    { +         +        std::string matching_key_str(matching_key); +        ConstString original_const(original); +         +        uint32_t count = 0; +         +        for (ImplData match = m_impl.FindFirstValueForName(matching_key); +             match != NULL; +             match = m_impl.FindNextValueForName(match)) +        { +            std::string target(original); +            std::string equiv_class(match->value.AsCString()); +             +            replace (target, matching_key_str, equiv_class); +             +            ConstString target_const(target.c_str()); + +// you will most probably want to leave this off since it might make this map grow indefinitely +#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW +            Add(original_const, target_const); +#endif +            equivalents.push_back(target_const); +             +            count++; +        } +         +        return count; +    } +     +    typedef UniqueCStringMap<ConstString> Impl; +    typedef const Impl::Entry* ImplData; +    Impl m_impl; +}; + +static CPPRuntimeEquivalents& +GetEquivalentsMap () +{ +    static CPPRuntimeEquivalents g_equivalents_map; +    return g_equivalents_map; +} + + +uint32_t +CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents) +{ +    uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents); + +    bool might_have_partials=  +        ( count == 0 )  // if we have a full name match just use it +        && (strchr(type_name.AsCString(), '<') != NULL  // we should only have partial matches when templates are involved, check that we have +            && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches +     +    if ( might_have_partials ) +        count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); +     +    return count; +} + +static void +LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp) +{ +    if (!cpp_category_sp) +        return; +     +    TypeSummaryImpl::Flags stl_summary_flags; +    stl_summary_flags.SetCascades(true) +    .SetSkipPointers(false) +    .SetSkipReferences(false) +    .SetDontShowChildren(true) +    .SetDontShowValue(true) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +#ifndef LLDB_DISABLE_PYTHON +    lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider")); +    lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider")); +     +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"), +                                                         std_string_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"), +                                                         std_string_summary_sp); +     +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"), +                                                         std_wstring_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"), +                                                         std_wstring_summary_sp); +     +    SyntheticChildren::Flags stl_synth_flags; +    stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); +     +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true); +     +    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")), +                                                               SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, +                                                                                                                 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider"))); +     +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true); +     +    stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); +     +    stl_summary_flags.SetSkipPointers(true); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true); +     +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags); +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true); +     +    AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true); +#endif +} + +static void +LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) +{ +    if (!cpp_category_sp) +        return; +     +    TypeSummaryImpl::Flags stl_summary_flags; +    stl_summary_flags.SetCascades(true) +    .SetSkipPointers(false) +    .SetSkipReferences(false) +    .SetDontShowChildren(true) +    .SetDontShowValue(true) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +    lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags, +                                                                          "${var._M_dataplus._M_p}")); + +    lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, +                                                                                 LibStdcppStringSummaryProvider, +                                                                                 "libstdc++ c++11 std::string summary provider")); +    lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, +                                                                                 LibStdcppWStringSummaryProvider, +                                                                                 "libstdc++ c++11 std::wstring summary provider")); + +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"), +                                                      std_string_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"), +                                                      std_string_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), +                                                      std_string_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"), +                                                      std_string_summary_sp); + +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::string"), +                                                      cxx11_string_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >"), +                                                      cxx11_string_summary_sp); + +    // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*) +    lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags, +                                                                           "${var._M_dataplus._M_p%S}")); +     +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"), +                                                      std_wstring_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"), +                                                      std_wstring_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"), +                                                      std_wstring_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"), +                                                      std_wstring_summary_sp); + +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::wstring"), +                                                      cxx11_wstring_summary_sp); +    cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"), +                                                      cxx11_wstring_summary_sp); + +#ifndef LLDB_DISABLE_PYTHON +     +    SyntheticChildren::Flags stl_synth_flags; +    stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); +     +    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")), +                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, +                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider"))); +    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")), +                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, +                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider"))); +    cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")), +                                                            SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags, +                                                                                                              "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider"))); +    stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true); +    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")), +                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, +                                                                                                     "size=${svar%#}"))); +    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")), +                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, +                                                                                                     "size=${svar%#}"))); +    cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")), +                                                           TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, +                                                                                                     "size=${svar%#}"))); + +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true); +     +    AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true); +#endif +} + +static void +LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) +{ +    if (!cpp_category_sp) +        return; +     +    TypeSummaryImpl::Flags string_flags; +    string_flags.SetCascades(true) +    .SetSkipPointers(true) +    .SetSkipReferences(false) +    .SetDontShowChildren(true) +    .SetDontShowValue(false) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +    TypeSummaryImpl::Flags string_array_flags; +    string_array_flags.SetCascades(true) +    .SetSkipPointers(true) +    .SetSkipReferences(false) +    .SetDontShowChildren(true) +    .SetDontShowValue(true) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +#ifndef LLDB_DISABLE_PYTHON +    // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>) +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags); +    AddCXXSummary(cpp_category_sp, +                  lldb_private::formatters::Char16StringSummaryProvider, +                  "char16_t [] summary provider", +                  ConstString("char16_t \\[[0-9]+\\]"), +                  string_array_flags, +                  true); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags); +    AddCXXSummary(cpp_category_sp, +                  lldb_private::formatters::Char32StringSummaryProvider, +                  "char32_t [] summary provider", +                  ConstString("char32_t \\[[0-9]+\\]"), +                  string_array_flags, +                  true); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags); +     +    TypeSummaryImpl::Flags widechar_flags; +    widechar_flags.SetDontShowValue(true) +    .SetSkipPointers(true) +    .SetSkipReferences(false) +    .SetCascades(true) +    .SetDontShowChildren(true) +    .SetHideItemNames(true) +    .SetShowMembersOneLiner(false); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags); +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags); +     +    AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags); +#endif +} + +lldb::TypeCategoryImplSP +CPlusPlusLanguage::GetFormatters () +{ +    static std::once_flag g_initialize; +    static TypeCategoryImplSP g_category; +     +    std::call_once(g_initialize, [this] () -> void { +        DataVisualization::Categories::GetCategory(GetPluginName(), g_category); +        if (g_category) +        { +            LoadLibCxxFormatters(g_category); +            LoadLibStdcppFormatters(g_category); +            LoadSystemFormatters(g_category); +        } +    }); +    return g_category; +} + +HardcodedFormatters::HardcodedSummaryFinder +CPlusPlusLanguage::GetHardcodedSummaries () +{ +    static std::once_flag g_initialize; +    static ConstString g_vectortypes("VectorTypes"); +    static HardcodedFormatters::HardcodedSummaryFinder g_formatters; +     +    std::call_once(g_initialize, [] () -> void { +        g_formatters.push_back( +                                        [](lldb_private::ValueObject& valobj, +                                           lldb::DynamicValueType, +                                           FormatManager&) -> TypeSummaryImpl::SharedPointer { +                                            static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider")); +                                            if (valobj.GetCompilerType().IsFunctionPointerType()) +                                            { +                                                return formatter_sp; +                                            } +                                            return nullptr; +                                        }); +        g_formatters.push_back( +                                        [](lldb_private::ValueObject& valobj, +                                           lldb::DynamicValueType, +                                           FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer { +                                            static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags() +                                                                                                                                     .SetCascades(true) +                                                                                                                                     .SetDontShowChildren(true) +                                                                                                                                     .SetHideItemNames(true) +                                                                                                                                     .SetShowMembersOneLiner(true) +                                                                                                                                     .SetSkipPointers(true) +                                                                                                                                     .SetSkipReferences(false), +                                                                                                                                     lldb_private::formatters::VectorTypeSummaryProvider, +                                                                                                                                     "vector_type pointer summary provider")); +                                            if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) +                                            { +                                                if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) +                                                    return formatter_sp; +                                            } +                                            return nullptr; +                                        }); +    }); +     +    return g_formatters; +} + +HardcodedFormatters::HardcodedSyntheticFinder +CPlusPlusLanguage::GetHardcodedSynthetics () +{ +    static std::once_flag g_initialize; +    static ConstString g_vectortypes("VectorTypes"); +    static HardcodedFormatters::HardcodedSyntheticFinder g_formatters; +     +    std::call_once(g_initialize, [] () -> void { +        g_formatters.push_back( +                                         [](lldb_private::ValueObject& valobj, +                                            lldb::DynamicValueType, +                                            FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer { +                                             static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true), +                                                                                                                              "vector_type synthetic children", +                                                                                                                              lldb_private::formatters::VectorTypeSyntheticFrontEndCreator)); +                                             if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr)) +                                             { +                                                 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled()) +                                                     return formatter_sp; +                                             } +                                             return nullptr; +                                         }); +    }); +     +    return g_formatters; +} + diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h new file mode 100644 index 0000000000000..1a8c0f6938a5b --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h @@ -0,0 +1,186 @@ +//===-- CPlusPlusLanguage.h -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CPlusPlusLanguage_h_ +#define liblldb_CPlusPlusLanguage_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Target/Language.h" + +namespace lldb_private { +     +class CPlusPlusLanguage : +    public Language +{ +public: +    class MethodName +    { +    public: +        enum Type +        { +            eTypeInvalid, +            eTypeUnknownMethod, +            eTypeClassMethod, +            eTypeInstanceMethod +        }; +         +        MethodName () : +            m_full(), +            m_basename(), +            m_context(), +            m_arguments(), +            m_qualifiers(), +            m_type (eTypeInvalid), +            m_parsed (false), +            m_parse_error (false) +        { +        } + +        MethodName (const ConstString &s) : +            m_full(s), +            m_basename(), +            m_context(), +            m_arguments(), +            m_qualifiers(), +            m_type (eTypeInvalid), +            m_parsed (false), +            m_parse_error (false) +        { +        } + +        void +        Clear(); +         +        bool +        IsValid () +        { +            if (!m_parsed) +                Parse(); +            if (m_parse_error) +                return false; +            if (m_type == eTypeInvalid) +                return false; +            return (bool)m_full; +        } + +        Type +        GetType () const +        { +            return m_type; +        } +         +        const ConstString & +        GetFullName () const +        { +            return m_full; +        } +         +        llvm::StringRef +        GetBasename (); + +        llvm::StringRef +        GetContext (); +         +        llvm::StringRef +        GetArguments (); +         +        llvm::StringRef +        GetQualifiers (); + +    protected: +        void +        Parse(); + +        ConstString     m_full;         // Full name:    "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const" +        llvm::StringRef m_basename;     // Basename:     "GetBreakpointAtIndex" +        llvm::StringRef m_context;      // Decl context: "lldb::SBTarget" +        llvm::StringRef m_arguments;    // Arguments:    "(unsigned int)" +        llvm::StringRef m_qualifiers;   // Qualifiers:   "const" +        Type m_type; +        bool m_parsed; +        bool m_parse_error; +    }; + +    CPlusPlusLanguage() = default; + +    ~CPlusPlusLanguage() override = default; + +    lldb::LanguageType +    GetLanguageType () const override +    { +        return lldb::eLanguageTypeC_plus_plus; +    } +     +    lldb::TypeCategoryImplSP +    GetFormatters () override; +     +    HardcodedFormatters::HardcodedSummaryFinder +    GetHardcodedSummaries () override; +     +    HardcodedFormatters::HardcodedSyntheticFinder +    GetHardcodedSynthetics () override; +     +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void +    Initialize(); +     +    static void +    Terminate(); +     +    static lldb_private::Language * +    CreateInstance (lldb::LanguageType language); +     +    static lldb_private::ConstString +    GetPluginNameStatic(); + +    static bool +    IsCPPMangledName(const char *name); + +    // Extract C++ context and identifier from a string using heuristic matching (as opposed to +    // CPlusPlusLanguage::MethodName which has to have a fully qualified C++ name with parens and arguments. +    // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true, +    // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively. +    // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false +    // and identifier and context will be unchanged. + +    static bool +    ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier); +     +    // in some cases, compilers will output different names for one same type. when that happens, it might be impossible +    // to construct SBType objects for a valid type, because the name that is available is not the same as the name that +    // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names +    // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended +    // to ObjC or other languages if necessary +    static uint32_t +    FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents); + +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    ConstString +    GetPluginName() override; +     +    uint32_t +    GetPluginVersion() override; +}; +     +} // namespace lldb_private + +#endif // liblldb_CPlusPlusLanguage_h_ diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp new file mode 100644 index 0000000000000..7e8d9582a2b58 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -0,0 +1,204 @@ +//===-- CXXStringTypes.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CxxStringTypes.h" + +#include "llvm/Support/ConvertUTF.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ProcessStructReader.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +#include <algorithm> + +#if __ANDROID_NDK__ +#include <sys/types.h> +#endif + +#include "lldb/Host/Time.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); +    if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) +        return false; +     +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetLocation(valobj_addr); +    options.SetProcessSP(process_sp); +    options.SetStream(&stream); +    options.SetPrefixToken("u"); +     +    if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options)) +    { +        stream.Printf("Summary Unavailable"); +        return true; +    } +     +    return true; +} + +bool +lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); +    if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) +        return false; +     +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetLocation(valobj_addr); +    options.SetProcessSP(process_sp); +    options.SetStream(&stream); +    options.SetPrefixToken("U"); +     +    if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options)) +    { +        stream.Printf("Summary Unavailable"); +        return true; +    } +     +    return true; +} + +bool +lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj); +    if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS) +        return false; +     +    // Get a wchar_t basic type from the current type system +    CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); +     +    if (!wchar_compiler_type) +        return false; +     +    const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here +     +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetLocation(valobj_addr); +    options.SetProcessSP(process_sp); +    options.SetStream(&stream); +    options.SetPrefixToken("L"); +     +    switch (wchar_size) +    { +        case 8: +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options); +        case 16: +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); +        case 32: +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options); +        default: +            stream.Printf("size for wchar_t is not valid"); +            return true; +    } +    return true; +} + +bool +lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    DataExtractor data; +    Error error; +    valobj.GetData(data, error); +     +    if (error.Fail()) +        return false; +     +    std::string value; +    valobj.GetValueAsCString(lldb::eFormatUnicode16, value); +    if (!value.empty()) +        stream.Printf("%s ", value.c_str()); +     +    StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); +    options.SetData(data); +    options.SetStream(&stream); +    options.SetPrefixToken("u"); +    options.SetQuote('\''); +    options.SetSourceSize(1); +    options.SetBinaryZeroIsTerminator(false); +     +    return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); +} + +bool +lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    DataExtractor data; +    Error error; +    valobj.GetData(data, error); +     +    if (error.Fail()) +        return false; +     +    std::string value; +    valobj.GetValueAsCString(lldb::eFormatUnicode32, value); +    if (!value.empty()) +        stream.Printf("%s ", value.c_str()); +     +    StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); +    options.SetData(data); +    options.SetStream(&stream); +    options.SetPrefixToken("U"); +    options.SetQuote('\''); +    options.SetSourceSize(1); +    options.SetBinaryZeroIsTerminator(false); +     +    return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32>(options); +} + +bool +lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&) +{ +    DataExtractor data; +    Error error; +    valobj.GetData(data, error); +     +    if (error.Fail()) +        return false; +     +    StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); +    options.SetData(data); +    options.SetStream(&stream); +    options.SetPrefixToken("L"); +    options.SetQuote('\''); +    options.SetSourceSize(1); +    options.SetBinaryZeroIsTerminator(false); +     +    return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); +} diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h new file mode 100644 index 0000000000000..bfb03bda7ee05 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h @@ -0,0 +1,41 @@ +//===-- CxxStringTypes.h ----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CxxStringTypes_h_ +#define liblldb_CxxStringTypes_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" + +namespace lldb_private { +    namespace formatters +    { +        bool +        Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar* +         +        bool +        Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t* +         +        bool +        WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t* +         +        bool +        Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar +         +        bool +        Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t +         +        bool +        WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t +         +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CxxStringTypes_h_ diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp new file mode 100644 index 0000000000000..950bd62c5c9fc --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -0,0 +1,653 @@ +//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxx.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/FormatEntity.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/VectorIterator.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); +    if (!valobj_sp) +        return false; +    ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true)); +    ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} )); +    ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} )); +     +    if (!ptr_sp) +        return false; +     +    if (ptr_sp->GetValueAsUnsigned(0) == 0) +    { +        stream.Printf("nullptr"); +        return true; +    } +    else +    { +        bool print_pointee = false; +        Error error; +        ValueObjectSP pointee_sp = ptr_sp->Dereference(error); +        if (pointee_sp && error.Success()) +        { +            if (pointee_sp->DumpPrintableRepresentation(stream, +                                                        ValueObject::eValueObjectRepresentationStyleSummary, +                                                        lldb::eFormatInvalid, +                                                        ValueObject::ePrintableRepresentationSpecialCasesDisable, +                                                        false)) +                print_pointee = true; +        } +        if (!print_pointee) +            stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); +    } +     +    if (count_sp) +        stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0)); + +    if (weakcount_sp) +        stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0)); +     +    return true; +} + +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_bool_type(), +m_exe_ctx_ref(), +m_count(0), +m_base_data_address(0), +m_children() +{ +    if (valobj_sp) +    { +        Update(); +        m_bool_type = valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool); +    } +} + +size_t +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren () +{ +    return m_count; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    auto iter = m_children.find(idx), +        end = m_children.end(); +    if (iter != end) +        return iter->second; +    if (idx >= m_count) +        return ValueObjectSP(); +    if (m_base_data_address == 0 || m_count == 0) +        return ValueObjectSP(); +    if (!m_bool_type) +        return ValueObjectSP(); +    size_t byte_idx = (idx >> 3); // divide by 8 to get byte index +    size_t bit_index = (idx & 7); // efficient idx % 8 for bit index +    lldb::addr_t byte_location = m_base_data_address + byte_idx; +    ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); +    if (!process_sp) +        return ValueObjectSP(); +    uint8_t byte = 0; +    uint8_t mask = 0; +    Error err; +    size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); +    if (err.Fail() || bytes_read == 0) +        return ValueObjectSP(); +    switch (bit_index) +    { +        case 0: +            mask = 1; break; +        case 1: +            mask = 2; break; +        case 2: +            mask = 4; break; +        case 3: +            mask = 8; break; +        case 4: +            mask = 16; break; +        case 5: +            mask = 32; break; +        case 6: +            mask = 64; break; +        case 7: +            mask = 128; break; +        default: +            return ValueObjectSP(); +    } +    bool bit_set = ((byte & mask) != 0); +    DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0)); +    if (bit_set && buffer_sp && buffer_sp->GetBytes()) +        *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true +    StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type)); +    if (retval_sp) +        m_children[idx] = retval_sp; +    return retval_sp; +} + +/*(std::__1::vector<std::__1::allocator<bool> >) vBool = { + __begin_ = 0x00000001001000e0 + __size_ = 56 + __cap_alloc_ = { + std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = { + __first_ = 1 + } + } + }*/ + +bool +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update() +{ +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true)); +    if (!size_sp) +        return false; +    m_count = size_sp->GetValueAsUnsigned(0); +    if (!m_count) +        return true; +    ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true)); +    if (!begin_sp) +    { +        m_count = 0; +        return false; +    } +    m_base_data_address = begin_sp->GetValueAsUnsigned(0); +    if (!m_base_data_address) +    { +        m_count = 0; +        return false; +    } +    return false; +} + +bool +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (!m_count || !m_base_data_address) +        return UINT32_MAX; +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --raw --ptr-depth 1 + (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = { + __i_ = { + __ptr_ = 0x0000000100103870 { + std::__1::__tree_node_base<void *> = { + std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = { + __left_ = 0x0000000000000000 + } + __right_ = 0x0000000000000000 + __parent_ = 0x00000001001038b0 + __is_black_ = true + } + __value_ = { + first = 0 + second = { std::string } + */ + +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_pair_ptr() +{ +    if (valobj_sp) +        Update(); +} + +bool +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() +{ +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +     +    TargetSP target_sp(valobj_sp->GetTargetSP()); +     +    if (!target_sp) +        return false; + +    if (!valobj_sp) +        return false; + +    // this must be a ValueObject* because it is a child of the ValueObject we are producing children for +    // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator) +    // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory +    m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_", +                                                     NULL, +                                                     NULL, +                                                     NULL, +                                                     ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None), +                                                     NULL).get(); +     +    return false; +} + +size_t +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren () +{ +    return 2; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (!m_pair_ptr) +        return lldb::ValueObjectSP(); +    return m_pair_ptr->GetChildAtIndex(idx, true); +} + +bool +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (name == ConstString("first")) +        return 0; +    if (name == ConstString("second")) +        return 1; +    return UINT32_MAX; +} + +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd () +{ +    // this will be deleted when its parent dies (since it's a child object) +    //delete m_pair_ptr; +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --raw --ptr-depth 1 -T + (std::__1::__wrap_iter<int *>) ibeg = { + (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 { + (int) *__i = 1 + } + } +*/ + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    static ConstString g_item_name; +    if (!g_item_name) +        g_item_name.SetCString("__i"); +    if (!valobj_sp) +        return NULL; +    return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); +} + +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_cntrl(NULL), +m_count_sp(), +m_weak_count_sp(), +m_ptr_size(0), +m_byte_order(lldb::eByteOrderInvalid) +{ +    if (valobj_sp) +        Update(); +} + +size_t +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren () +{ +    return (m_cntrl ? 1 : 0); +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (!m_cntrl) +        return lldb::ValueObjectSP(); + +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return lldb::ValueObjectSP(); + +    if (idx == 0) +        return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true); + +    if (idx > 2) +        return lldb::ValueObjectSP(); + +    if (idx == 1) +    { +        if (!m_count_sp) +        { +            ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true)); +            if (!shared_owners_sp) +                return lldb::ValueObjectSP(); +            uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0); +            DataExtractor data(&count, 8, m_byte_order, m_ptr_size); +            m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetCompilerType()); +        } +        return m_count_sp; +    } +    else /* if (idx == 2) */ +    { +        if (!m_weak_count_sp) +        { +            ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true)); +            if (!shared_weak_owners_sp) +                return lldb::ValueObjectSP(); +            uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0); +            DataExtractor data(&count, 8, m_byte_order, m_ptr_size); +            m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetCompilerType()); +        } +        return m_weak_count_sp; +    } +} + +bool +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() +{ +    m_count_sp.reset(); +    m_weak_count_sp.reset(); +    m_cntrl = NULL; +     +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +     +    TargetSP target_sp(valobj_sp->GetTargetSP()); +    if (!target_sp) +        return false; +     +    m_byte_order = target_sp->GetArchitecture().GetByteOrder(); +    m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize(); +     +    lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true)); +     +    m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency +    return false; +} + +bool +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (name == ConstString("__ptr_")) +        return 0; +    if (name == ConstString("count")) +        return 1; +    if (name == ConstString("weak_count")) +        return 2; +    return UINT32_MAX; +} + +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); +} + +bool +lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    if (valobj.IsPointerType()) +    { +        uint64_t value = valobj.GetValueAsUnsigned(0); +        if (!value) +            return false; +        stream.Printf("0x%016" PRIx64 " ", value); +    } +    return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false); +} + +// the field layout in a libc++ string (cap, side, data or data, size, cap) +enum LibcxxStringLayoutMode +{ +    eLibcxxStringLayoutModeCSD = 0, +    eLibcxxStringLayoutModeDSC = 1, +    eLibcxxStringLayoutModeInvalid = 0xffff +}; + +// this function abstracts away the layout and mode details of a libc++ string +// and returns the address of the data and the size ready for callers to consume +static bool +ExtractLibcxxStringInfo (ValueObject& valobj, +                         ValueObjectSP &location_sp, +                         uint64_t& size) +{ +    ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0})); +    if (!D) +        return false; +     +    ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0})); +     +    // this child should exist +    if (!layout_decider) +        return false; +     +    ConstString g_data_name("__data_"); +    ConstString g_size_name("__size_"); +    bool short_mode = false; // this means the string is in short-mode and the data is stored inline +    LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD; +    uint64_t size_mode_value = 0; +     +    if (layout == eLibcxxStringLayoutModeDSC) +    { +        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0})); +        if (!size_mode) +            return false; +         +        if (size_mode->GetName() != g_size_name) +        { +            // we are hitting the padding structure, move along +            size_mode = D->GetChildAtIndexPath({1,1,1}); +            if (!size_mode) +                return false; +        } +         +        size_mode_value = (size_mode->GetValueAsUnsigned(0)); +        short_mode = ((size_mode_value & 0x80) == 0); +    } +    else +    { +        ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0})); +        if (!size_mode) +            return false; +         +        size_mode_value = (size_mode->GetValueAsUnsigned(0)); +        short_mode = ((size_mode_value & 1) == 0); +    } +     +    if (short_mode) +    { +        ValueObjectSP s(D->GetChildAtIndex(1, true)); +        if (!s) +            return false; +        location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true); +        size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256); +        return (location_sp.get() != nullptr); +    } +    else +    { +        ValueObjectSP l(D->GetChildAtIndex(0, true)); +        if (!l) +            return false; +        // we can use the layout_decider object as the data pointer +        location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true); +        ValueObjectSP size_vo(l->GetChildAtIndex(1, true)); +        if (!size_vo || !location_sp) +            return false; +        size = size_vo->GetValueAsUnsigned(0); +        return true; +    } +} + +bool +lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) +{ +    uint64_t size = 0; +    ValueObjectSP location_sp((ValueObject*)nullptr); +    if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) +        return false; +    if (size == 0) +    { +        stream.Printf("L\"\""); +        return true; +    } +    if (!location_sp) +        return false; +     +    DataExtractor extractor; +     +    StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); +     +    if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) +    { +        const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); +        if (size > max_size) +        { +            size = max_size; +            options.SetIsTruncated(true); +        } +    } +    location_sp->GetPointeeData(extractor, 0, size); +     +    // std::wstring::size() is measured in 'characters', not bytes +    auto wchar_t_size = valobj.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr); +     +    options.SetData(extractor); +    options.SetStream(&stream); +    options.SetPrefixToken("L"); +    options.SetQuote('"'); +    options.SetSourceSize(size); +    options.SetBinaryZeroIsTerminator(false); +     +    switch (wchar_t_size) +    { +        case 1: +            StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF8>(options); +            break; +             +        case 2: +            lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF16>(options); +            break; +             +        case 4: +            lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF32>(options); +            break; +             +        default: +            stream.Printf("size for wchar_t is not valid"); +            return true; +    } +     +    return true; +} + +bool +lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) +{ +    uint64_t size = 0; +    ValueObjectSP location_sp((ValueObject*)nullptr); +     +    if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) +        return false; +     +    if (size == 0) +    { +        stream.Printf("\"\""); +        return true; +    } +     +    if (!location_sp) +        return false; +     +    StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj); +     +    DataExtractor extractor; +    if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped) +    { +        const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary(); +        if (size > max_size) +        { +            size = max_size; +            options.SetIsTruncated(true); +        } +    } +    location_sp->GetPointeeData(extractor, 0, size); +     +    options.SetData(extractor); +    options.SetStream(&stream); +    options.SetPrefixToken(0); +    options.SetQuote('"'); +    options.SetSourceSize(size); +    options.SetBinaryZeroIsTerminator(false); +    StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::ASCII>(options); +     +    return true; +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h new file mode 100644 index 0000000000000..ae00bc0ade340 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxx.h @@ -0,0 +1,141 @@ +//===-- LibCxx.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LibCxx_h_ +#define liblldb_LibCxx_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +namespace lldb_private { +    namespace formatters +    { +         +        bool +        LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string +         +        bool +        LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring +         +        bool +        LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<> +         +        class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); +             +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +            ~LibcxxVectorBoolSyntheticFrontEnd() override; +             +        private: +            CompilerType m_bool_type; +            ExecutionContextRef m_exe_ctx_ref; +            uint64_t m_count; +            lldb::addr_t m_base_data_address; +            std::map<size_t,lldb::ValueObjectSP> m_children; +        }; +         +        SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        bool +        LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); +             +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +            ~LibCxxMapIteratorSyntheticFrontEnd() override; +             +        private: +            ValueObject *m_pair_ptr; +        }; +         +        SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); +             +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +            ~LibcxxSharedPtrSyntheticFrontEnd() override; +             +        private: +            ValueObject* m_cntrl; +            lldb::ValueObjectSP m_count_sp; +            lldb::ValueObjectSP m_weak_count_sp; +            uint8_t m_ptr_size; +            lldb::ByteOrder m_byte_order; +        }; +         +        SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_LibCxx_h_ diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp new file mode 100644 index 0000000000000..9970d49dac624 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -0,0 +1,147 @@ +//===-- LibCxxInitializerList.cpp -------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "LibCxx.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +    namespace formatters { +        class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~LibcxxInitializerListSyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +        private: +            ValueObject* m_start; +            CompilerType m_element_type; +            uint32_t m_element_size; +            size_t m_num_elements; +            std::map<size_t,lldb::ValueObjectSP> m_children; +        }; +    } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_start(NULL), +m_element_type(), +m_element_size(0), +m_num_elements(0), +m_children() +{ +    if (valobj_sp) +        Update(); +} + +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd() +{ +    // this needs to stay around because it's a child object who will follow its parent's life cycle +    // delete m_start; +} + +size_t +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren () +{ +    static ConstString g___size_("__size_"); +    m_num_elements = 0; +    ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true)); +    if (size_sp) +        m_num_elements = size_sp->GetValueAsUnsigned(0); +    return m_num_elements; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (!m_start) +        return lldb::ValueObjectSP(); +     +    auto cached = m_children.find(idx); +    if (cached != m_children.end()) +        return cached->second; +     +    uint64_t offset = idx * m_element_size; +    offset = offset + m_start->GetValueAsUnsigned(0); +    StreamString name; +    name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); +    m_children[idx] = child_sp; +    return child_sp; +} + +bool +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() +{ +    static ConstString g___begin_("__begin_"); + +    m_start = nullptr; +    m_num_elements = 0; +    m_children.clear(); +    lldb::TemplateArgumentKind kind; +    m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind); +    if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid()) +        return false; +     +    m_element_size = m_element_type.GetByteSize(nullptr); +     +    if (m_element_size > 0) +        m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency + +    return false; +} + +bool +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (!m_start) +        return UINT32_MAX; +    return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)); +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp new file mode 100644 index 0000000000000..f86f968ea8573 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -0,0 +1,414 @@ +//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "LibCxx.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace { + +    class ListEntry +    { +    public: +        ListEntry() = default; +        ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} +        ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} +        ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} + +        ListEntry +        next () +        { +            if (!m_entry_sp) +                return ListEntry(); +            return ListEntry(m_entry_sp->GetChildAtIndexPath({0,1})); +        } + +        ListEntry +        prev () +        { +            if (!m_entry_sp) +                return ListEntry(); +            return ListEntry(m_entry_sp->GetChildAtIndexPath({0,0})); +        } + +        uint64_t +        value () const +        { +            if (!m_entry_sp) +                return 0; +            return m_entry_sp->GetValueAsUnsigned(0); +        } + +        bool +        null() +        { +            return (value() == 0); +        } + +        explicit operator bool () +        { +            return GetEntry().get() != nullptr && null() == false; +        } + +        ValueObjectSP +        GetEntry () +        { +            return m_entry_sp; +        } + +        void +        SetEntry (ValueObjectSP entry) +        { +            m_entry_sp = entry; +        } + +        bool +        operator == (const ListEntry& rhs) const +        { +            return value() == rhs.value(); +        } + +        bool +        operator != (const ListEntry& rhs) const +        { +            return !(*this == rhs); +        } + +    private: +        ValueObjectSP m_entry_sp; +    }; +     +    class ListIterator +    { +    public: +        ListIterator() = default; +        ListIterator (ListEntry entry) : m_entry(entry) {} +        ListIterator (ValueObjectSP entry) : m_entry(entry) {} +        ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {} +        ListIterator (ValueObject* entry) : m_entry(entry) {} +         +        ValueObjectSP +        value () +        { +            return m_entry.GetEntry(); +        } +         +        ValueObjectSP +        advance (size_t count) +        { +            if (count == 0) +                return m_entry.GetEntry(); +            if (count == 1) +            { +                next (); +                return m_entry.GetEntry(); +            } +            while (count > 0) +            { +                next (); +                count--; +                if (m_entry.null()) +                    return lldb::ValueObjectSP(); +            } +            return m_entry.GetEntry(); +        } +         +        bool +        operator == (const ListIterator& rhs) const +        { +            return (rhs.m_entry == m_entry); +        } +         +    protected: +        void +        next () +        { +            m_entry = m_entry.next(); +        } +         +        void +        prev () +        { +            m_entry = m_entry.prev(); +        } +         +    private: +        ListEntry m_entry; +    }; + +} // end anonymous namespace + +namespace lldb_private { +    namespace formatters { +        class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~LibcxxStdListSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +        private: +            bool +            HasLoop(size_t count); +             +            size_t m_list_capping_size; +            static const bool g_use_loop_detect = true; + +            size_t m_loop_detected; // The number of elements that have had loop detection run over them. +            ListEntry m_slow_runner; // Used for loop detection +            ListEntry m_fast_runner; // Used for loop detection + +            lldb::addr_t m_node_address; +            ValueObject* m_head; +            ValueObject* m_tail; +            CompilerType m_element_type; +            size_t m_count; +            std::map<size_t,lldb::ValueObjectSP> m_children; +            std::map<size_t, ListIterator> m_iterators; +        }; +    } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_list_capping_size(0), +m_loop_detected(0), +m_node_address(), +m_head(NULL), +m_tail(NULL), +m_element_type(), +m_count(UINT32_MAX), +m_children(), +m_iterators() +{ +    if (valobj_sp) +        Update(); +} + +bool +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count) +{ +    if (g_use_loop_detect == false) +        return false; +    // don't bother checking for a loop if we won't actually need to jump nodes +    if (m_count < 2) +        return false; + +    if (m_loop_detected == 0) +    { +        // This is the first time we are being run (after the last update). Set up the loop +        // invariant for the first element. +        m_slow_runner = ListEntry(m_head).next(); +        m_fast_runner = m_slow_runner.next(); +        m_loop_detected = 1; +    } + +    // Loop invariant: +    // Loop detection has been run over the first m_loop_detected elements. If m_slow_runner == +    // m_fast_runner then the loop has been detected after m_loop_detected elements. +    const size_t steps_to_run = std::min(count,m_count); +    while (m_loop_detected < steps_to_run +            && m_slow_runner +            && m_fast_runner +            && m_slow_runner != m_fast_runner) { + +        m_slow_runner = m_slow_runner.next(); +        m_fast_runner = m_fast_runner.next().next(); +        m_loop_detected++; +    } +    if (count <= m_loop_detected) +        return false; // No loop in the first m_loop_detected elements. +    if (!m_slow_runner || !m_fast_runner) +        return false; // Reached the end of the list. Definitely no loops. +    return m_slow_runner == m_fast_runner; +} + +size_t +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren () +{ +    if (m_count != UINT32_MAX) +        return m_count; +    if (!m_head || !m_tail || m_node_address == 0) +        return 0; +    ValueObjectSP size_alloc(m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true)); +    if (size_alloc) +    { +        ValueObjectSP first(size_alloc->GetChildMemberWithName(ConstString("__first_"), true)); +        if (first) +        { +            m_count = first->GetValueAsUnsigned(UINT32_MAX); +        } +    } +    if (m_count != UINT32_MAX) +    { +        return m_count; +    } +    else +    { +        uint64_t next_val = m_head->GetValueAsUnsigned(0); +        uint64_t prev_val = m_tail->GetValueAsUnsigned(0); +        if (next_val == 0 || prev_val == 0) +            return 0; +        if (next_val == m_node_address) +            return 0; +        if (next_val == prev_val) +            return 1; +        uint64_t size = 2; +        ListEntry current(m_head); +        while (current.next() && current.next().value() != m_node_address) +        { +            size++; +            current = current.next(); +            if (size > m_list_capping_size) +                break; +        } +        return m_count = (size-1); +    } +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (idx >= CalculateNumChildren()) +        return lldb::ValueObjectSP(); +     +    if (!m_head || !m_tail || m_node_address == 0) +        return lldb::ValueObjectSP(); +     +    auto cached = m_children.find(idx); +    if (cached != m_children.end()) +        return cached->second; +     +    if (HasLoop(idx+1)) +        return lldb::ValueObjectSP(); +     +    size_t actual_advance = idx; +     +    ListIterator current(m_head); +    if (idx > 0) +    { +        auto cached_iterator = m_iterators.find(idx-1); +        if (cached_iterator != m_iterators.end()) +        { +            current = cached_iterator->second; +            actual_advance = 1; +        } +    } +     +    ValueObjectSP current_sp(current.advance(actual_advance)); +    if (!current_sp) +        return lldb::ValueObjectSP(); +     +    m_iterators[idx] = current; +     +    current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child +    if (!current_sp) +        return lldb::ValueObjectSP(); +    // we need to copy current_sp into a new object otherwise we will end up with all items named __value_ +    DataExtractor data; +    Error error; +    current_sp->GetData(data, error); +    if (error.Fail()) +        return lldb::ValueObjectSP(); +     +    StreamString name; +    name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); +} + +bool +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() +{ +    m_children.clear(); +    m_iterators.clear(); +    m_head = m_tail = NULL; +    m_node_address = 0; +    m_count = UINT32_MAX; +    m_loop_detected = 0; +    m_slow_runner.SetEntry(nullptr); +    m_fast_runner.SetEntry(nullptr); + +    Error err; +    ValueObjectSP backend_addr(m_backend.AddressOf(err)); +    m_list_capping_size = 0; +    if (m_backend.GetTargetSP()) +        m_list_capping_size = m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); +    if (m_list_capping_size == 0) +        m_list_capping_size = 255; +    if (err.Fail() || backend_addr.get() == NULL) +        return false; +    m_node_address = backend_addr->GetValueAsUnsigned(0); +    if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS) +        return false; +    ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true)); +    if (!impl_sp) +        return false; +    CompilerType list_type = m_backend.GetCompilerType(); +    if (list_type.IsReferenceType()) +        list_type = list_type.GetNonReferenceType(); + +    if (list_type.GetNumTemplateArguments() == 0) +        return false; +    lldb::TemplateArgumentKind kind; +    m_element_type = list_type.GetTemplateArgument(0, kind); +    m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get(); +    m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get(); +    return false; +} + +bool +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return ExtractIndexFromString(name.GetCString()); +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxStdListSyntheticFrontEnd(valobj_sp)); +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp new file mode 100644 index 0000000000000..aa82557edb020 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -0,0 +1,478 @@ +//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "LibCxx.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +class MapEntry +{ +public: +    MapEntry() = default; +    explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} +    MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} +    explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} +     +    ValueObjectSP +    left () const +    { +        static ConstString g_left("__left_"); +        if (!m_entry_sp) +            return m_entry_sp; +        return m_entry_sp->GetChildMemberWithName(g_left, true); +    } +     +    ValueObjectSP +    right () const +    { +        static ConstString g_right("__right_"); +        if (!m_entry_sp) +            return m_entry_sp; +        return m_entry_sp->GetChildMemberWithName(g_right, true); +    } +     +    ValueObjectSP +    parent () const +    { +        static ConstString g_parent("__parent_"); +        if (!m_entry_sp) +            return m_entry_sp; +        return m_entry_sp->GetChildMemberWithName(g_parent, true); +    } +     +    uint64_t +    value () const +    { +        if (!m_entry_sp) +            return 0; +        return m_entry_sp->GetValueAsUnsigned(0); +    } +     +    bool +    error () const +    { +        if (!m_entry_sp) +            return true; +        return m_entry_sp->GetError().Fail(); +    } +     +    bool +    null() const +    { +        return (value() == 0); +    } +     +    ValueObjectSP +    GetEntry () const +    { +        return m_entry_sp; +    } +     +    void +    SetEntry (ValueObjectSP entry) +    { +        m_entry_sp = entry; +    } +     +    bool +    operator == (const MapEntry& rhs) const +    { +        return (rhs.m_entry_sp.get() == m_entry_sp.get()); +    } +     +private: +    ValueObjectSP m_entry_sp; +}; + +class MapIterator +{ +public: +    MapIterator() = default; +    MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} +    MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} +    MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {} +    MapIterator (ValueObject* entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {} +     +    ValueObjectSP +    value () +    { +        return m_entry.GetEntry(); +    } +     +    ValueObjectSP +    advance (size_t count) +    { +        ValueObjectSP fail(nullptr); +        if (m_error) +            return fail; +        size_t steps = 0; +        while (count > 0) +        { +            next(); +            count--, steps++; +            if (m_error || +                m_entry.null() || +                (steps > m_max_depth)) +                return fail; +        } +        return m_entry.GetEntry(); +    } +     +protected: +    void +    next () +    { +        if (m_entry.null()) +            return; +        MapEntry right(m_entry.right()); +        if (right.null() == false) +        { +            m_entry = tree_min(std::move(right)); +            return; +        } +        size_t steps = 0; +        while (!is_left_child(m_entry)) +        { +            if (m_entry.error()) +            { +                m_error = true; +                return; +            } +            m_entry.SetEntry(m_entry.parent()); +            steps++; +            if (steps > m_max_depth) +            { +                m_entry = MapEntry(); +                return; +            } +        } +        m_entry = MapEntry(m_entry.parent()); +    } +     +private: +    MapEntry +    tree_min (MapEntry&& x) +    { +        if (x.null()) +            return MapEntry(); +        MapEntry left(x.left()); +        size_t steps = 0; +        while (left.null() == false) +        { +            if (left.error()) +            { +                m_error = true; +                return MapEntry(); +            } +            x = left; +            left.SetEntry(x.left()); +            steps++; +            if (steps > m_max_depth) +                return MapEntry(); +        } +        return x; +    } +     +    bool +    is_left_child (const MapEntry& x) +    { +        if (x.null()) +            return false; +        MapEntry rhs(x.parent()); +        rhs.SetEntry(rhs.left()); +        return x.value() == rhs.value(); +    } +     +    MapEntry m_entry; +    size_t m_max_depth; +    bool m_error; +}; + +namespace lldb_private { +    namespace formatters { +        class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~LibcxxStdMapSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +        private: +            bool +            GetDataType(); +             +            void +            GetValueOffset (const lldb::ValueObjectSP& node); +             +            ValueObject* m_tree; +            ValueObject* m_root_node; +            CompilerType m_element_type; +            uint32_t m_skip_size; +            size_t m_count; +            std::map<size_t, lldb::ValueObjectSP> m_children; +            std::map<size_t, MapIterator> m_iterators; +        }; +    } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_tree(NULL), +m_root_node(NULL), +m_element_type(), +m_skip_size(UINT32_MAX), +m_count(UINT32_MAX), +m_children(), +m_iterators() +{ +    if (valobj_sp) +        Update(); +} + +size_t +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren () +{ +    static ConstString g___pair3_("__pair3_"); +    static ConstString g___first_("__first_"); + +    if (m_count != UINT32_MAX) +        return m_count; +    if (m_tree == NULL) +        return 0; +    ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true)); +    if (!m_item) +        return 0; +    m_item = m_item->GetChildMemberWithName(g___first_, true); +    if (!m_item) +        return 0; +    m_count = m_item->GetValueAsUnsigned(0); +    return m_count; +} + +bool +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType() +{ +    static ConstString g___value_("__value_"); +     +    if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem()) +        return true; +    m_element_type.Clear(); +    ValueObjectSP deref; +    Error error; +    deref = m_root_node->Dereference(error); +    if (!deref || error.Fail()) +        return false; +    deref = deref->GetChildMemberWithName(g___value_, true); +    if (!deref) +        return false; +    m_element_type = deref->GetCompilerType(); +    return true; +} + +void +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const lldb::ValueObjectSP& node) +{ +    if (m_skip_size != UINT32_MAX) +        return; +    if (!node) +        return; +    CompilerType node_type(node->GetCompilerType()); +    uint64_t bit_offset; +    if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX) +        return; +    m_skip_size = bit_offset / 8u; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    static ConstString g___cc("__cc"); +    static ConstString g___nc("__nc"); +    static ConstString g___value_("__value_"); + +     +    if (idx >= CalculateNumChildren()) +        return lldb::ValueObjectSP(); +    if (m_tree == NULL || m_root_node == NULL) +        return lldb::ValueObjectSP(); +     +    auto cached = m_children.find(idx); +    if (cached != m_children.end()) +        return cached->second; + +    MapIterator iterator(m_root_node, CalculateNumChildren()); +     +    const bool need_to_skip = (idx > 0); +    size_t actual_advancde = idx; +    if (need_to_skip) +    { +        auto cached_iterator = m_iterators.find(idx-1); +        if (cached_iterator != m_iterators.end()) +        { +            iterator = cached_iterator->second; +            actual_advancde = 1; +        } +    } +     +    ValueObjectSP iterated_sp(iterator.advance(actual_advancde)); +    if (iterated_sp.get() == NULL) +    { +        // this tree is garbage - stop +        m_tree = NULL; // this will stop all future searches until an Update() happens +        return iterated_sp; +    } +    if (GetDataType()) +    { +        if (!need_to_skip) +        { +            Error error; +            iterated_sp = iterated_sp->Dereference(error); +            if (!iterated_sp || error.Fail()) +            { +                m_tree = NULL; +                return lldb::ValueObjectSP(); +            } +            GetValueOffset(iterated_sp); +            iterated_sp = iterated_sp->GetChildMemberWithName(g___value_, true); +            if (!iterated_sp) +            { +                m_tree = NULL; +                return lldb::ValueObjectSP(); +            } +        } +        else +        { +            // because of the way our debug info is made, we need to read item 0 first +            // so that we can cache information used to generate other elements +            if (m_skip_size == UINT32_MAX) +                GetChildAtIndex(0); +            if (m_skip_size == UINT32_MAX) +            { +                m_tree = NULL; +                return lldb::ValueObjectSP(); +            } +            iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true); +            if (!iterated_sp) +            { +                m_tree = NULL; +                return lldb::ValueObjectSP(); +            } +        } +    } +    else +    { +        m_tree = NULL; +        return lldb::ValueObjectSP(); +    } +    // at this point we have a valid  +    // we need to copy current_sp into a new object otherwise we will end up with all items named __value_ +    DataExtractor data; +    Error error; +    iterated_sp->GetData(data, error); +    if (error.Fail()) +    { +        m_tree = NULL; +        return lldb::ValueObjectSP(); +    } +    StreamString name; +    name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type); +    if (potential_child_sp) +    { +        switch (potential_child_sp->GetNumChildren()) +        { +            case 1: +            { +                auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); +                if (child0_sp && child0_sp->GetName() == g___cc) +                    potential_child_sp = child0_sp; +                break; +            } +            case 2: +            { +                auto child0_sp = potential_child_sp->GetChildAtIndex(0, true); +                auto child1_sp = potential_child_sp->GetChildAtIndex(1, true); +                if (child0_sp && child0_sp->GetName() == g___cc && +                    child1_sp && child1_sp->GetName() == g___nc) +                    potential_child_sp = child0_sp; +                break; +            } +        } +        potential_child_sp->SetName(ConstString(name.GetData())); +    } +    m_iterators[idx] = iterator; +    return (m_children[idx] = potential_child_sp); +} + +bool +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update() +{ +    static ConstString g___tree_("__tree_"); +    static ConstString g___begin_node_("__begin_node_"); +    m_count = UINT32_MAX; +    m_tree = m_root_node = NULL; +    m_children.clear(); +    m_iterators.clear(); +    m_tree = m_backend.GetChildMemberWithName(g___tree_, true).get(); +    if (!m_tree) +        return false; +    m_root_node = m_tree->GetChildMemberWithName(g___begin_node_, true).get(); +    return false; +} + +bool +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return ExtractIndexFromString(name.GetCString()); +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp)); +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp new file mode 100644 index 0000000000000..8ad806d52bce3 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -0,0 +1,172 @@ +//===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "LibCxx.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +    namespace formatters { +        class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            ValueObject* m_tree; +            size_t m_num_elements; +            ValueObject* m_next_element; +            std::map<size_t,lldb::ValueObjectSP> m_children; +            std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache; +        }; +    } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_tree(NULL), +m_num_elements(0), +m_next_element(nullptr), +m_children(), +m_elements_cache() +{ +    if (valobj_sp) +        Update(); +} + +size_t +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren () +{ +    if (m_num_elements != UINT32_MAX) +        return m_num_elements; +    return 0; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (idx >= CalculateNumChildren()) +        return lldb::ValueObjectSP(); +    if (m_tree == NULL) +        return lldb::ValueObjectSP(); +     +    auto cached = m_children.find(idx); +    if (cached != m_children.end()) +        return cached->second; +     +    while (idx >= m_elements_cache.size()) +    { +        if (m_next_element == nullptr) +            return lldb::ValueObjectSP(); +         +        Error error; +        ValueObjectSP node_sp = m_next_element->Dereference(error); +        if (!node_sp || error.Fail()) +            return lldb::ValueObjectSP(); +         +        ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true); +        ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true); +        if (!hash_sp || !value_sp) +            return lldb::ValueObjectSP(); +        m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)}); +        m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get(); +        if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0) +            m_next_element = nullptr; +    } +     +    std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx]; +    if (!val_hash.first) +        return lldb::ValueObjectSP(); +    StreamString stream; +    stream.Printf("[%" PRIu64 "]", (uint64_t)idx); +    DataExtractor data; +    Error error; +    val_hash.first->GetData(data, error); +    if (error.Fail()) +        return lldb::ValueObjectSP(); +    const bool thread_and_frame_only_if_stopped = true; +    ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped); +    return val_hash.first->CreateValueObjectFromData(stream.GetData(), +                                                     data, +                                                     exe_ctx, +                                                     val_hash.first->GetCompilerType()); +} + +bool +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update() +{ +    m_num_elements = UINT32_MAX; +    m_next_element = nullptr; +    m_elements_cache.clear(); +    m_children.clear(); +    ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true); +    if (!table_sp) +        return false; +    ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")}); +    if (!num_elements_sp) +        return false; +    m_num_elements = num_elements_sp->GetValueAsUnsigned(0); +    m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get(); +    if (m_num_elements > 0) +        m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get(); +    return false; +} + +bool +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return ExtractIndexFromString(name.GetCString()); +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)); +} diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp new file mode 100644 index 0000000000000..9fb4f48e90907 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -0,0 +1,159 @@ +//===-- LibCxxVector.cpp ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "LibCxx.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private { +    namespace formatters { +        class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~LibcxxStdVectorSyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            ValueObject* m_start; +            ValueObject* m_finish; +            CompilerType m_element_type; +            uint32_t m_element_size; +            std::map<size_t,lldb::ValueObjectSP> m_children; +        }; +    } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_start(NULL), +m_finish(NULL), +m_element_type(), +m_element_size(0), +m_children() +{ +    if (valobj_sp) +        Update(); +} + +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd() +{ +    // these need to stay around because they are child objects who will follow their parent's life cycle +    // delete m_start; +    // delete m_finish; +} + +size_t +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren () +{ +    if (!m_start || !m_finish) +        return 0; +    uint64_t start_val = m_start->GetValueAsUnsigned(0); +    uint64_t finish_val = m_finish->GetValueAsUnsigned(0); +     +    if (start_val == 0 || finish_val == 0) +        return 0; +     +    if (start_val >= finish_val) +        return 0; +     +    size_t num_children = (finish_val - start_val); +    if (num_children % m_element_size) +        return 0; +    return num_children/m_element_size; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (!m_start || !m_finish) +        return lldb::ValueObjectSP(); +     +    auto cached = m_children.find(idx); +    if (cached != m_children.end()) +        return cached->second; +     +    uint64_t offset = idx * m_element_size; +    offset = offset + m_start->GetValueAsUnsigned(0); +    StreamString name; +    name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); +    m_children[idx] = child_sp; +    return child_sp; +} + +bool +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() +{ +    m_start = m_finish = NULL; +    m_children.clear(); +    ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); +    if (!data_type_finder_sp) +        return false; +    data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true); +    if (!data_type_finder_sp) +        return false; +    m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType(); +    m_element_size = m_element_type.GetByteSize(nullptr); +     +    if (m_element_size > 0) +    { +        // store raw pointers or end up with a circular dependency +        m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get(); +        m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get(); +    } +    return false; +} + +bool +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (!m_start || !m_finish) +        return UINT32_MAX; +    return ExtractIndexFromString(name.GetCString()); +} + +lldb_private::SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); +} diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp new file mode 100644 index 0000000000000..ed89c5c84ea3a --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -0,0 +1,373 @@ +//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibStdcpp.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/DataFormatters/VectorIterator.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); +     +    size_t +    CalculateNumChildren() override; +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override; +     +    bool +    Update() override; +     +    bool +    MightHaveChildren() override; +     +    size_t +    GetIndexOfChildWithName (const ConstString &name) override; +     +    ~LibstdcppMapIteratorSyntheticFrontEnd() override; +     +private: +    ExecutionContextRef m_exe_ctx_ref; +    lldb::addr_t m_pair_address; +    CompilerType m_pair_type; +    EvaluateExpressionOptions m_options; +    lldb::ValueObjectSP m_pair_sp; +}; + +/* + (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = { + (_Base_ptr) _M_node = 0x0000000100103910 { + (std::_Rb_tree_color) _M_color = _S_black + (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0 + (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000 + (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000 + } + } + */ + +LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd(*valobj_sp.get()), +    m_exe_ctx_ref(), +    m_pair_address(0), +    m_pair_type(), +    m_options(), +    m_pair_sp() +{ +    if (valobj_sp) +        Update(); +    m_options.SetCoerceToId(false); +    m_options.SetUnwindOnError(true); +    m_options.SetKeepInMemory(true); +    m_options.SetUseDynamic(lldb::eDynamicCanRunTarget); +} + +bool +LibstdcppMapIteratorSyntheticFrontEnd::Update() +{ +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +     +    TargetSP target_sp(valobj_sp->GetTargetSP()); +     +    if (!target_sp) +        return false; +     +    bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8); +     +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +     +    ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true)); +    if (!_M_node_sp) +        return false; +     +    m_pair_address = _M_node_sp->GetValueAsUnsigned(0); +    if (m_pair_address == 0) +        return false; +     +    m_pair_address += (is_64bit ? 32 : 16); +     +    CompilerType my_type(valobj_sp->GetCompilerType()); +    if (my_type.GetNumTemplateArguments() >= 1) +    { +        TemplateArgumentKind kind; +        CompilerType pair_type = my_type.GetTemplateArgument(0, kind); +        if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion) +            return false; +        m_pair_type = pair_type; +    } +    else +        return false; +     +    return true; +} + +size_t +LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren () +{ +    return 2; +} + +lldb::ValueObjectSP +LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (m_pair_address != 0 && m_pair_type) +    { +        if (!m_pair_sp) +            m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type); +        if (m_pair_sp) +            return m_pair_sp->GetChildAtIndex(idx, true); +    } +    return lldb::ValueObjectSP(); +} + +bool +LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (name == ConstString("first")) +        return 0; +    if (name == ConstString("second")) +        return 1; +    return UINT32_MAX; +} + +LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd () +{} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return NULL; +    return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp)); +} + +/* + (lldb) fr var ibeg --ptr-depth 1 + (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = { + _M_current = 0x00000001001037a0 { + *_M_current = 1 + } + } + */ + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    static ConstString g_item_name; +    if (!g_item_name) +        g_item_name.SetCString("_M_current"); +    if (!valobj_sp) +        return NULL; +    return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name)); +} + +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, +                                                                                            ConstString item_name) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_item_name(item_name), +m_item_sp() +{ +    if (valobj_sp) +        Update(); +} + +bool +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() +{ +    m_item_sp.reset(); +     +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +     +    if (!valobj_sp) +        return false; +     +    ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true)); +    if (!item_ptr) +        return false; +    if (item_ptr->GetValueAsUnsigned(0) == 0) +        return false; +    Error err; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType()); +    if (err.Fail()) +        m_item_sp.reset(); +    return false; +} + +size_t +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () +{ +    return 1; +} + +lldb::ValueObjectSP +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (idx == 0) +        return m_item_sp; +    return lldb::ValueObjectSP(); +} + +bool +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    if (name == ConstString("item")) +        return 0; +    return UINT32_MAX; +} + +lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd () +{ +} + +bool +lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    const bool scalar_is_load_addr = true; +    AddressType addr_type; +    lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type); +    if (addr_of_string != LLDB_INVALID_ADDRESS) +    { +        switch (addr_type) +        { +            case eAddressTypeLoad: +            { +                ProcessSP process_sp(valobj.GetProcessSP()); +                if (!process_sp) +                    return false; + +                StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +                Error error; +                lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error); +                if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS) +                    return false; +                options.SetLocation(addr_of_data); +                options.SetProcessSP(process_sp); +                options.SetStream(&stream); +                options.SetNeedsZeroTermination(false); +                options.SetBinaryZeroIsTerminator(true); +                lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error); +                if (error.Fail()) +                    return false; +                options.SetSourceSize(size_of_data); + +                if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options)) +                { +                    stream.Printf("Summary Unavailable"); +                    return true; +                } +                else +                    return true; +            } +                break; +            case eAddressTypeHost: +                break; +            case eAddressTypeInvalid: +            case eAddressTypeFile: +                break; +        } +    } +    return false; +} + +bool +lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    const bool scalar_is_load_addr = true; +    AddressType addr_type; +    lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type); +    if (addr_of_string != LLDB_INVALID_ADDRESS) +    { +        switch (addr_type) +        { +            case eAddressTypeLoad: +            { +                ProcessSP process_sp(valobj.GetProcessSP()); +                if (!process_sp) +                    return false; + +                CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar); + +                if (!wchar_compiler_type) +                    return false; + +                const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here + +                StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +                Error error; +                lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error); +                if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS) +                    return false; +                options.SetLocation(addr_of_data); +                options.SetProcessSP(process_sp); +                options.SetStream(&stream); +                options.SetNeedsZeroTermination(false); +                options.SetBinaryZeroIsTerminator(false); +                lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error); +                if (error.Fail()) +                    return false; +                options.SetSourceSize(size_of_data); +                options.SetPrefixToken("L"); + +                switch (wchar_size) +                { +                    case 8: +                        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options); +                    case 16: +                        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); +                    case 32: +                        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options); +                    default: +                        stream.Printf("size for wchar_t is not valid"); +                        return true; +                } +                return true; +            } +                break; +            case eAddressTypeHost: +                break; +            case eAddressTypeInvalid: +            case eAddressTypeFile: +                break; +        } +    } +    return false; +} diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/source/Plugins/Language/CPlusPlus/LibStdcpp.h new file mode 100644 index 0000000000000..347856a1695c4 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.h @@ -0,0 +1,33 @@ +//===-- LibStdCpp.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LibStdCpp_h_ +#define liblldb_LibStdCpp_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +namespace lldb_private { +    namespace formatters +    { +        bool +        LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::string + +        bool +        LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring + +        SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_LibStdCpp_h_ diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/source/Plugins/Language/Go/GoFormatterFunctions.cpp new file mode 100644 index 0000000000000..1d7cd76b97392 --- /dev/null +++ b/source/Plugins/Language/Go/GoFormatterFunctions.cpp @@ -0,0 +1,173 @@ +//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "GoFormatterFunctions.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace +{ +class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +  public: +    GoSliceSyntheticFrontEnd(ValueObject &valobj) +        : SyntheticChildrenFrontEnd(valobj) +    { +        Update(); +    } + +    ~GoSliceSyntheticFrontEnd() override = default; + +    size_t +    CalculateNumChildren() override +    { +        return m_len; +    } + +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        if (idx < m_len) +        { +            ValueObjectSP &cached = m_children[idx]; +            if (!cached) +            { +                StreamString idx_name; +                idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +                lldb::addr_t object_at_idx = m_base_data_address; +                object_at_idx += idx * m_type.GetByteSize(nullptr); +                cached = CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx, +                                                      m_backend.GetExecutionContextRef(), m_type); +            } +            return cached; +        } +        return ValueObjectSP(); +    } + +    bool +    Update() override +    { +        size_t old_count = m_len; + +        ConstString array_const_str("array"); +        ValueObjectSP array_sp = m_backend.GetChildMemberWithName(array_const_str, true); +        if (!array_sp) +        { +            m_children.clear(); +            return old_count == 0; +        } +        m_type = array_sp->GetCompilerType().GetPointeeType(); +        m_base_data_address = array_sp->GetPointerValue(); + +        ConstString len_const_str("len"); +        ValueObjectSP len_sp = m_backend.GetChildMemberWithName(len_const_str, true); +        if (len_sp) +        { +            m_len = len_sp->GetValueAsUnsigned(0); +            m_children.clear(); +        } + +        return old_count == m_len; +    } + +    bool +    MightHaveChildren() override +    { +        return true; +    } + +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        return ExtractIndexFromString(name.AsCString()); +    } + +  private: +    CompilerType m_type; +    lldb::addr_t m_base_data_address; +    size_t m_len; +    std::map<size_t, lldb::ValueObjectSP> m_children; +}; + +} // anonymous namespace + +bool +lldb_private::formatters::GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; + +    if (valobj.IsPointerType()) +    { +        Error err; +        ValueObjectSP deref = valobj.Dereference(err); +        if (!err.Success()) +            return false; +        return GoStringSummaryProvider(*deref, stream, opts); +    } + +    ConstString str_name("str"); +    ConstString len_name("len"); + +    ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true); +    ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true); +    if (!data_sp || !len_sp) +        return false; +    bool success; +    lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success); + +    if (!success) +        return false; + +    uint64_t length = len_sp->GetValueAsUnsigned(0); +    if (length == 0) +    { +        stream.Printf("\"\""); +        return true; +    } + +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetLocation(valobj_addr); +    options.SetProcessSP(process_sp); +    options.SetStream(&stream); +    options.SetSourceSize(length); +    options.SetNeedsZeroTermination(false); +    options.SetLanguage(eLanguageTypeGo); + +    if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options)) +    { +        stream.Printf("Summary Unavailable"); +        return true; +    } + +    return true; +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return nullptr; + +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return nullptr; +    return new GoSliceSyntheticFrontEnd(*valobj_sp); +} diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.h b/source/Plugins/Language/Go/GoFormatterFunctions.h new file mode 100644 index 0000000000000..ae1eda0f0c541 --- /dev/null +++ b/source/Plugins/Language/Go/GoFormatterFunctions.h @@ -0,0 +1,43 @@ +//===-- GoFormatterFunctions.h-----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoFormatterFunctions_h_ +#define liblldb_GoFormatterFunctions_h_ + +// C Includes +#include <stdint.h> +#include <time.h> + +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" + +// Project includes +#include "lldb/lldb-forward.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/DataFormatters/FormatClasses.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +namespace lldb_private +{ +namespace formatters +{ + +bool GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); + +SyntheticChildrenFrontEnd *GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); + +} // namespace formatters +} // namespace lldb_private + +#endif // liblldb_GoFormatterFunctions_h_ diff --git a/source/Plugins/Language/Go/GoLanguage.cpp b/source/Plugins/Language/Go/GoLanguage.cpp new file mode 100644 index 0000000000000..ed010ffa4b2e0 --- /dev/null +++ b/source/Plugins/Language/Go/GoLanguage.cpp @@ -0,0 +1,146 @@ +//===-- GoLanguage.cpp ------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include <string.h> +// C++ Includes +#include <functional> +#include <mutex> + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "GoLanguage.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/GoASTContext.h" +#include "Plugins/Language/Go/GoFormatterFunctions.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +GoLanguage::Initialize() +{ +    PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language", CreateInstance); +} + +void +GoLanguage::Terminate() +{ +    PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +GoLanguage::GetPluginNameStatic() +{ +    static ConstString g_name("Go"); +    return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +GoLanguage::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +GoLanguage::GetPluginVersion() +{ +    return 1; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +Language * +GoLanguage::CreateInstance(lldb::LanguageType language) +{ +    if (language == eLanguageTypeGo) +        return new GoLanguage(); +    return nullptr; +} + +HardcodedFormatters::HardcodedSummaryFinder +GoLanguage::GetHardcodedSummaries() +{ +    static std::once_flag g_initialize; +    static HardcodedFormatters::HardcodedSummaryFinder g_formatters; + +    std::call_once(g_initialize, []() -> void +                   { +                       g_formatters.push_back( +                           [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, +                              FormatManager &) -> TypeSummaryImpl::SharedPointer +                           { +                               static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat( +                                   TypeSummaryImpl::Flags().SetDontShowChildren(true), +                                   lldb_private::formatters::GoStringSummaryProvider, "Go string summary provider")); +                               if (GoASTContext::IsGoString(valobj.GetCompilerType())) +                               { +                                   return formatter_sp; +                               } +                               if (GoASTContext::IsGoString(valobj.GetCompilerType().GetPointeeType())) +                               { +                                   return formatter_sp; +                               } +                               return nullptr; +                           }); +                       g_formatters.push_back( +                           [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, +                              FormatManager &) -> TypeSummaryImpl::SharedPointer +                           { +                               static lldb::TypeSummaryImplSP formatter_sp( +                                   new StringSummaryFormat(TypeSummaryImpl::Flags().SetHideItemNames(true), +                                                           "(len ${var.len}, cap ${var.cap})")); +                               if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) +                               { +                                   return formatter_sp; +                               } +                               if (GoASTContext::IsGoSlice(valobj.GetCompilerType().GetPointeeType())) +                               { +                                   return formatter_sp; +                               } +                               return nullptr; +                           }); +                   }); +    return g_formatters; +} + +HardcodedFormatters::HardcodedSyntheticFinder +GoLanguage::GetHardcodedSynthetics() +{ +    static std::once_flag g_initialize; +    static HardcodedFormatters::HardcodedSyntheticFinder g_formatters; + +    std::call_once(g_initialize, []() -> void +                   { +                       g_formatters.push_back( +                           [](lldb_private::ValueObject &valobj, lldb::DynamicValueType, +                              FormatManager &fmt_mgr) -> SyntheticChildren::SharedPointer +                           { +                               static CXXSyntheticChildren::SharedPointer formatter_sp( +                                   new CXXSyntheticChildren(SyntheticChildren::Flags(), "slice synthetic children", +                                                            lldb_private::formatters::GoSliceSyntheticFrontEndCreator)); +                               if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) +                               { +                                   return formatter_sp; +                               } +                               return nullptr; +                           }); +                   }); + +    return g_formatters; +} diff --git a/source/Plugins/Language/Go/GoLanguage.h b/source/Plugins/Language/Go/GoLanguage.h new file mode 100644 index 0000000000000..67dd04c2a22ee --- /dev/null +++ b/source/Plugins/Language/Go/GoLanguage.h @@ -0,0 +1,66 @@ +//===-- GoLanguage.h --------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoLanguage_h_ +#define liblldb_GoLanguage_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Target/Language.h" + +namespace lldb_private +{ + +class GoLanguage : public Language +{ +  public: +    GoLanguage() = default; + +    ~GoLanguage() override = default; + +    lldb::LanguageType +    GetLanguageType() const override +    { +        return lldb::eLanguageTypeGo; +    } + +    HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override; + +    HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics() override; + +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void Initialize(); + +    static void Terminate(); + +    static lldb_private::Language *CreateInstance(lldb::LanguageType language); + +    static lldb_private::ConstString GetPluginNameStatic(); + +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    ConstString GetPluginName() override; + +    uint32_t GetPluginVersion() override; +}; + +} // namespace lldb_private + +#endif // liblldb_GoLanguage_h_ diff --git a/source/Plugins/Language/ObjC/CF.cpp b/source/Plugins/Language/ObjC/CF.cpp new file mode 100644 index 0000000000000..614eb29a0f7a4 --- /dev/null +++ b/source/Plugins/Language/ObjC/CF.cpp @@ -0,0 +1,334 @@ +//===-- CF.cpp ----------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CF.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    time_t epoch = GetOSXEpoch(); +    epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0); +    tm *tm_date = localtime(&epoch); +    if (!tm_date) +        return false; +    std::string buffer(1024,0); +    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) +        return false; +    stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str()); +    return true; +} + +bool +lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    static ConstString g_TypeHint("CFBag"); +     +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint32_t count = 0; +     +    bool is_type_ok = false; // check to see if this is a CFBag we know about +    if (descriptor->IsCFType()) +    { +        ConstString type_name(valobj.GetTypeName()); +        if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) +        { +            if (valobj.IsPointerType()) +                is_type_ok = true; +        } +    } +     +    if (is_type_ok == false) +    { +        StackFrameSP frame_sp(valobj.GetFrameSP()); +        if (!frame_sp) +            return false; +        ValueObjectSP count_sp; +        StreamString expr; +        expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); +        EvaluateExpressionOptions options; +        options.SetResultIsInternal(true); +        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted) +            return false; +        if (!count_sp) +            return false; +        count = count_sp->GetValueAsUnsigned(0); +    } +    else +    { +        uint32_t offset = 2*ptr_size+4 + valobj_addr; +        Error error; +        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); +        if (error.Fail()) +            return false; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s\"%u value%s\"%s", +                  prefix.c_str(), +                  count,(count == 1 ? "" : "s"), +                  suffix.c_str()); +    return true; +} + +bool +lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint32_t count = 0; +     +    bool is_type_ok = false; // check to see if this is a CFBag we know about +    if (descriptor->IsCFType()) +    { +        ConstString type_name(valobj.GetTypeName()); +        if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef")) +        { +            if (valobj.IsPointerType()) +                is_type_ok = true; +        } +    } +     +    if (is_type_ok == false) +        return false; +     +    Error error; +    count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); +    if (error.Fail()) +        return false; +    uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0); +    addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error); +    if (error.Fail()) +        return false; +    // make sure we do not try to read huge amounts of data +    if (num_bytes > 1024) +        num_bytes = 1024; +    DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0)); +    num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error); +    if (error.Fail() || num_bytes == 0) +        return false; +    uint8_t *bytes = buffer_sp->GetBytes(); +    for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++) +    { +        uint8_t byte = bytes[byte_idx]; +        bool bit0 = (byte & 1) == 1; +        bool bit1 = (byte & 2) == 2; +        bool bit2 = (byte & 4) == 4; +        bool bit3 = (byte & 8) == 8; +        bool bit4 = (byte & 16) == 16; +        bool bit5 = (byte & 32) == 32; +        bool bit6 = (byte & 64) == 64; +        bool bit7 = (byte & 128) == 128; +        stream.Printf("%c%c%c%c %c%c%c%c ", +                      (bit7 ? '1' : '0'), +                      (bit6 ? '1' : '0'), +                      (bit5 ? '1' : '0'), +                      (bit4 ? '1' : '0'), +                      (bit3 ? '1' : '0'), +                      (bit2 ? '1' : '0'), +                      (bit1 ? '1' : '0'), +                      (bit0 ? '1' : '0')); +        count -= 8; +    } +    { +        // print the last byte ensuring we do not print spurious bits +        uint8_t byte = bytes[num_bytes-1]; +        bool bit0 = (byte & 1) == 1; +        bool bit1 = (byte & 2) == 2; +        bool bit2 = (byte & 4) == 4; +        bool bit3 = (byte & 8) == 8; +        bool bit4 = (byte & 16) == 16; +        bool bit5 = (byte & 32) == 32; +        bool bit6 = (byte & 64) == 64; +        bool bit7 = (byte & 128) == 128; +        if (count) +        { +            stream.Printf("%c",bit7 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit6 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit5 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit4 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit3 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit2 ? '1' : '0'); +            count -= 1; +        } +        if (count) +        { +            stream.Printf("%c",bit1 ? '1' : '0'); +            count -= 1; +        } +        if (count) +            stream.Printf("%c",bit0 ? '1' : '0'); +    } +    return true; +} + +bool +lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    static ConstString g_TypeHint("CFBinaryHeap"); +     +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint32_t count = 0; +     +    bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about +    if (descriptor->IsCFType()) +    { +        ConstString type_name(valobj.GetTypeName()); +        if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) +        { +            if (valobj.IsPointerType()) +                is_type_ok = true; +        } +    } +     +    if (is_type_ok == false) +    { +        StackFrameSP frame_sp(valobj.GetFrameSP()); +        if (!frame_sp) +            return false; +        ValueObjectSP count_sp; +        StreamString expr; +        expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue()); +        EvaluateExpressionOptions options; +        options.SetResultIsInternal(true); +        if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted) +            return false; +        if (!count_sp) +            return false; +        count = count_sp->GetValueAsUnsigned(0); +    } +    else +    { +        uint32_t offset = 2*ptr_size; +        Error error; +        count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); +        if (error.Fail()) +            return false; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s\"%u item%s\"%s", +                  prefix.c_str(), +                  count,(count == 1 ? "" : "s"), +                  suffix.c_str()); +    return true; +} diff --git a/source/Plugins/Language/ObjC/CF.h b/source/Plugins/Language/ObjC/CF.h new file mode 100644 index 0000000000000..4044f09f585e2 --- /dev/null +++ b/source/Plugins/Language/ObjC/CF.h @@ -0,0 +1,34 @@ +//===-- CF.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CF_h_ +#define liblldb_CF_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" + +namespace lldb_private { +    namespace formatters +    { +        bool +        CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CF_h_ diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp new file mode 100644 index 0000000000000..aa6e476b61319 --- /dev/null +++ b/source/Plugins/Language/ObjC/Cocoa.cpp @@ -0,0 +1,967 @@ +//===-- Cocoa.cpp -----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/ProcessStructReader.h" + +#include "NSString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"NSBundle")) +    { +        uint64_t offset = 5 * ptr_size; +        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); +         +        StreamString summary_stream; +        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); +        if (was_nsstring_ok && summary_stream.GetSize() > 0) +        { +            stream.Printf("%s",summary_stream.GetData()); +            return true; +        } +    } +    // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle] +    // which is encoded differently and needs to be handled by running code +    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream, options.GetLanguage()); +} + +bool +lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"__NSTimeZone")) +    { +        uint64_t offset = ptr_size; +        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true)); +        StreamString summary_stream; +        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); +        if (was_nsstring_ok && summary_stream.GetSize() > 0) +        { +            stream.Printf("%s",summary_stream.GetData()); +            return true; +        } +    } +    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage()); +} + +bool +lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"NSConcreteNotification")) +    { +        uint64_t offset = ptr_size; +        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true)); +        StreamString summary_stream; +        bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); +        if (was_nsstring_ok && summary_stream.GetSize() > 0) +        { +            stream.Printf("%s",summary_stream.GetData()); +            return true; +        } +    } +    // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle] +    // which is encoded differently and needs to be handled by running code +    return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage()); +} + +bool +lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    uint64_t port_number = 0; +     +    do +    { +        if (!strcmp(class_name,"NSMachPort")) +        { +            uint64_t offset = (ptr_size == 4 ? 12 : 20); +            Error error; +            port_number = process_sp->ReadUnsignedIntegerFromMemory(offset+valobj_addr, 4, 0, error); +            if (error.Success()) +                break; +        } +        if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number)) +            return false; +    } while (false); +     +    stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF)); +    return true; +} + +bool +lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    uint64_t count = 0; +     +    do { +        if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet")) +        { +            Error error; +            uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error); +            if (error.Fail()) +                return false; +            // this means the set is empty - count = 0 +            if ((mode & 1) == 1) +            { +                count = 0; +                break; +            } +            if ((mode & 2) == 2) +                mode = 1; // this means the set only has one range +            else +                mode = 2; // this means the set has multiple ranges +            if (mode == 1) +            { +                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error); +                if (error.Fail()) +                    return false; +            } +            else +            { +                // read a pointer to the data at 2*ptr_size +                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error); +                if (error.Fail()) +                    return false; +                // read the data at 2*ptr_size from the first location +                count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error); +                if (error.Fail()) +                    return false; +            } +        } +        else +        { +            if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count)) +                return false; +        } +    }  while (false); +    stream.Printf("%" PRIu64 " index%s", +                  count, +                  (count == 1 ? "" : "es")); +    return true; +} + +static void +NSNumber_FormatChar (ValueObject& valobj, +                     Stream& stream, +                     char value, +                     lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:char"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%hhd%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +static void +NSNumber_FormatShort (ValueObject& valobj, +                      Stream& stream, +                      short value, +                      lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:short"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%hd%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +static void +NSNumber_FormatInt (ValueObject& valobj, +                    Stream& stream, +                    int value, +                    lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:int"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%d%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +static void +NSNumber_FormatLong (ValueObject& valobj, +                     Stream& stream, +                     uint64_t value, +                     lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:long"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%" PRId64 "%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +static void +NSNumber_FormatFloat (ValueObject& valobj, +                      Stream& stream, +                      float value, +                      lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:float"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%f%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +static void +NSNumber_FormatDouble (ValueObject& valobj, +                       Stream& stream, +                       double value, +                       lldb::LanguageType lang) +{ +    static ConstString g_TypeHint("NSNumber:double"); +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(lang)) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%g%s", +                  prefix.c_str(), +                  value, +                  suffix.c_str()); +} + +bool +lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber")) +    { +        uint64_t value = 0; +        uint64_t i_bits = 0; +        if (descriptor->GetTaggedPointerInfo(&i_bits,&value)) +        { +            switch (i_bits) +            { +                case 0: +                    NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); +                    break; +                case 1: +                case 4: +                    NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); +                    break; +                case 2: +                case 8: +                    NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); +                    break; +                case 3: +                case 12: +                    NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); +                    break; +                default: +                    return false; +            } +            return true; +        } +        else +        { +            Error error; +            uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F); +            uint64_t data_location = valobj_addr + 2*ptr_size; +            uint64_t value = 0; +            if (error.Fail()) +                return false; +            switch (data_type) +            { +                case 1: // 0B00001 +                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error); +                    if (error.Fail()) +                        return false; +                    NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage()); +                    break; +                case 2: // 0B0010 +                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error); +                    if (error.Fail()) +                        return false; +                    NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage()); +                    break; +                case 3: // 0B0011 +                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); +                    if (error.Fail()) +                        return false; +                    NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage()); +                    break; +                case 17: // 0B10001 +                    data_location += 8; +                case 4: // 0B0100 +                    value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); +                    if (error.Fail()) +                        return false; +                    NSNumber_FormatLong(valobj, stream, value, options.GetLanguage()); +                    break; +                case 5: // 0B0101 +                { +                    uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error); +                    if (error.Fail()) +                        return false; +                    float flt_value = *((float*)&flt_as_int); +                    NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); +                    break; +                } +                case 6: // 0B0110 +                { +                    uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); +                    if (error.Fail()) +                        return false; +                    double dbl_value = *((double*)&dbl_as_lng); +                    NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); +                    break; +                } +                default: +                    return false; +            } +            return true; +        } +    } +    else +    { +        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream, options.GetLanguage()); +    } +} + +bool +lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (strcmp(class_name, "NSURL") == 0) +    { +        uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit) +        uint64_t offset_base = offset_text + ptr_size; +        CompilerType type(valobj.GetCompilerType()); +        ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true)); +        ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true)); +        if (!text) +            return false; +        if (text->GetValueAsUnsigned(0) == 0) +            return false; +        StreamString summary; +        if (!NSStringSummaryProvider(*text, summary, options)) +            return false; +        if (base && base->GetValueAsUnsigned(0)) +        { +            if (summary.GetSize() > 0) +                summary.GetString().resize(summary.GetSize()-1); +            summary.Printf(" -- "); +            StreamString base_summary; +            if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0) +                summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData()); +        } +        if (summary.GetSize()) +        { +            stream.Printf("%s",summary.GetData()); +            return true; +        } +    } +    else +    { +        return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream, options.GetLanguage()); +    } +    return false; +} + +bool +lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint64_t date_value_bits = 0; +    double date_value = 0.0; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (strcmp(class_name,"NSDate") == 0 || +        strcmp(class_name,"__NSDate") == 0 || +        strcmp(class_name,"__NSTaggedDate") == 0) +    { +        uint64_t info_bits=0,value_bits = 0; +        if (descriptor->GetTaggedPointerInfo(&info_bits,&value_bits)) +        { +            date_value_bits = ((value_bits << 8) | (info_bits << 4)); +            date_value = *((double*)&date_value_bits); +        } +        else +        { +            Error error; +            date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error); +            date_value = *((double*)&date_value_bits); +            if (error.Fail()) +                return false; +        } +    } +    else if (!strcmp(class_name,"NSCalendarDate")) +    { +        Error error; +        date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error); +        date_value = *((double*)&date_value_bits); +        if (error.Fail()) +            return false; +    } +    else +    { +        if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false) +            return false; +        date_value = *((double*)&date_value_bits); +    } +    if (date_value == -63114076800) +    { +        stream.Printf("0001-12-30 00:00:00 +0000"); +        return true; +    } +    // this snippet of code assumes that time_t == seconds since Jan-1-1970 +    // this is generally true and POSIXly happy, but might break if a library +    // vendor decides to get creative +    time_t epoch = GetOSXEpoch(); +    epoch = epoch + (time_t)date_value; +    tm *tm_date = gmtime(&epoch); +    if (!tm_date) +        return false; +    std::string buffer(1024,0); +    if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0) +        return false; +    stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str()); +    return true; +} + +bool +lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0))); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    ConstString class_name = descriptor->GetClassName(); +     +    if (class_name.IsEmpty()) +        return false; +     +    if (ConstString cs = Mangled(class_name).GetDemangledName(lldb::eLanguageTypeUnknown)) +        class_name = cs; +     +    stream.Printf("%s",class_name.AsCString("<unknown class>")); +    return true; +} + +class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd(*valobj_sp.get()) +    { +    } +     +    ~ObjCClassSyntheticChildrenFrontEnd() override = default; + +    size_t +    CalculateNumChildren() override +    { +        return 0; +    } +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        return lldb::ValueObjectSP(); +    } +     +    bool +    Update() override +    { +        return false; +    } +     +    bool +    MightHaveChildren() override +    { +        return false; +    } +     +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        return UINT32_MAX; +    } +}; + +SyntheticChildrenFrontEnd* +lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp); +} + +template<bool needs_at> +bool +lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    bool is_64bit = (process_sp->GetAddressByteSize() == 8); +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint64_t value = 0; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"NSConcreteData") || +        !strcmp(class_name,"NSConcreteMutableData") || +        !strcmp(class_name,"__NSCFData")) +    { +        uint32_t offset = (is_64bit ? 16 : 8); +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error); +        if (error.Fail()) +            return false; +    } +    else +    { +        if (!ExtractValueFromObjCExpression(valobj, "int", "length", value)) +            return false; +    } +     +    stream.Printf("%s%" PRIu64 " byte%s%s", +                  (needs_at ? "@\"" : ""), +                  value, +                  (value != 1 ? "s" : ""), +                  (needs_at ? "\"" : "")); +     +    return true; +} + +bool +lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo(); +     +    ValueObjectSP real_guy_sp = valobj.GetSP(); +     +    if (type_info & eTypeIsPointer) +    { +        Error err; +        real_guy_sp = valobj.Dereference(err); +        if (err.Fail() || !real_guy_sp) +            return false; +    } +    else if (type_info & eTypeIsReference) +    { +        real_guy_sp =  valobj.GetChildAtIndex(0, true); +        if (!real_guy_sp) +            return false; +    } +    uint64_t value = real_guy_sp->GetValueAsUnsigned(0); +    if (value == 0) +    { +        stream.Printf("NO"); +        return true; +    } +    stream.Printf("YES"); +    return true; +} + +template <bool is_sel_ptr> +bool +lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    lldb::ValueObjectSP valobj_sp; +     +    CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType()); +     +    if (!charstar) +        return false; +     +    ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); +     +    if (is_sel_ptr) +    { +        lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +        if (data_address == LLDB_INVALID_ADDRESS) +            return false; +        valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar); +    } +    else +    { +        DataExtractor data; +        Error error; +        valobj.GetData(data, error); +        if (error.Fail()) +            return false; +        valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar); +    } +     +    if (!valobj_sp) +        return false; +     +    stream.Printf("%s",valobj_sp->GetSummaryAsCString()); +    return true; +} + +// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001 +// this call gives the POSIX equivalent of the Cocoa epoch +time_t +lldb_private::formatters::GetOSXEpoch () +{ +    static time_t epoch = 0; +    if (!epoch) +    { +#ifndef _WIN32 +        tzset(); +        tm tm_epoch; +        tm_epoch.tm_sec = 0; +        tm_epoch.tm_hour = 0; +        tm_epoch.tm_min = 0; +        tm_epoch.tm_mon = 0; +        tm_epoch.tm_mday = 1; +        tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why. +        tm_epoch.tm_isdst = -1; +        tm_epoch.tm_gmtoff = 0; +        tm_epoch.tm_zone = NULL; +        epoch = timegm(&tm_epoch); +#endif +    } +    return epoch; +} + +bool +lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    if (const char* description = valobj.GetObjectDescription()) +    { +        stream.Printf("%s", description); +        return true; +    } +    else +        return false; +} + +template bool +lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&); + +template bool +lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&); + +template bool +lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&); + +template bool +lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&); diff --git a/source/Plugins/Language/ObjC/Cocoa.h b/source/Plugins/Language/ObjC/Cocoa.h new file mode 100644 index 0000000000000..0caacf3453d4a --- /dev/null +++ b/source/Plugins/Language/ObjC/Cocoa.h @@ -0,0 +1,97 @@ +//===-- Cocoa.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Cocoa_h_ +#define liblldb_Cocoa_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Target/ObjCLanguageRuntime.h" + +namespace lldb_private { +    namespace formatters +    { +        bool +        NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        template<bool needs_at> +        bool +        NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        extern template bool +        NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ; +         +        extern template bool +        NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ; +         +        SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        bool +        ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        bool +        ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        template <bool is_sel_ptr> +        bool +        ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        extern template bool +        ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&); +         +        extern template bool +        ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&); +         +        bool +        RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        SyntheticChildrenFrontEnd* +        NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp); +         +        SyntheticChildrenFrontEnd* +        NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp); +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_Cocoa_h_ diff --git a/source/Plugins/Language/ObjC/CoreMedia.cpp b/source/Plugins/Language/ObjC/CoreMedia.cpp new file mode 100644 index 0000000000000..4103067b8d582 --- /dev/null +++ b/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -0,0 +1,89 @@ +//===-- CoreMedia.cpp --------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "CoreMedia.h" + +#include "lldb/Core/Flags.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/Target.h" +#include <inttypes.h> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    CompilerType type = valobj.GetCompilerType(); +    if (!type.IsValid()) +        return false; + +    TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC); +    if (!type_system) +        return false; +     +    // fetch children by offset to compensate for potential lack of debug info +    auto int64_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64); +    auto int32_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32); +     +    auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true)); +    auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true)); +    auto flags_sp(valobj.GetSyntheticChildAtOffset(12, int32_ty, true)); +     +    if (!value_sp || !timescale_sp || !flags_sp) +        return false; +     +    auto value = value_sp->GetValueAsUnsigned(0); +    auto timescale = (int32_t)timescale_sp->GetValueAsUnsigned(0); // the timescale specifies the fraction of a second each unit in the numerator occupies +    auto flags = Flags(flags_sp->GetValueAsUnsigned(0) & 0x00000000000000FF); // the flags I need sit in the LSB +     +    const unsigned int FlagPositiveInf = 4; +    const unsigned int FlagNegativeInf = 8; +    const unsigned int FlagIndefinite = 16; +     +    if (flags.AnySet(FlagIndefinite)) +    { +        stream.Printf("indefinite"); +        return true; +    } +     +    if (flags.AnySet(FlagPositiveInf)) +    { +        stream.Printf("+oo"); +        return true; +    } +     +    if (flags.AnySet(FlagNegativeInf)) +    { +        stream.Printf("-oo"); +        return true; +    } +     +    if (timescale == 0) +        return false; +     +    switch (timescale) +    { +        case 0: +            return false; +        case 1: +            stream.Printf("%" PRId64 " seconds", value); +            return true; +        case 2: +            stream.Printf("%" PRId64 " half seconds", value); +            return true; +        case 3: +            stream.Printf("%" PRId64 " third%sof a second", value, value == 1 ? " " : "s "); +            return true; +        default: +            stream.Printf("%" PRId64 " %" PRId32 "th%sof a second", value, timescale, value == 1 ? " " : "s "); +            return true; +    } +} diff --git a/source/Plugins/Language/ObjC/CoreMedia.h b/source/Plugins/Language/ObjC/CoreMedia.h new file mode 100644 index 0000000000000..2ffabaadccf58 --- /dev/null +++ b/source/Plugins/Language/ObjC/CoreMedia.h @@ -0,0 +1,26 @@ +//===-- CoreMedia.h -----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CoreMedia_h_ +#define liblldb_CoreMedia_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" + +namespace lldb_private { +    namespace formatters +    { +         +        bool +        CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CF_h_ diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp new file mode 100644 index 0000000000000..ccc82ab95ecc7 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -0,0 +1,792 @@ +//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" + +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace  lldb_private { +    namespace formatters { +        class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSArrayMSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override = 0; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +             +        protected: +            virtual lldb::addr_t +            GetDataAddress () = 0; +             +            virtual uint64_t +            GetUsedCount () = 0; +             +            virtual uint64_t +            GetOffset () = 0; +             +            virtual uint64_t +            GetSize () = 0; +             +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            CompilerType m_id_type; +            std::vector<lldb::ValueObjectSP> m_children; +        }; +         +        class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd +        { +        public: +            NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp); + +            ~NSArrayMSyntheticFrontEnd_109() override; + +            bool +            Update() override; +             +        protected: +            lldb::addr_t +            GetDataAddress() override; +             +            uint64_t +            GetUsedCount() override; +             +            uint64_t +            GetOffset() override; +             +            uint64_t +            GetSize() override; +             +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used; +                uint32_t _priv1 : 2 ; +                uint32_t _size : 30; +                uint32_t _priv2 : 2; +                uint32_t _offset : 30; +                uint32_t _priv3; +                uint32_t _data; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used; +                uint64_t _priv1 : 2 ; +                uint64_t _size : 62; +                uint64_t _priv2 : 2; +                uint64_t _offset : 62; +                uint32_t _priv3; +                uint64_t _data; +            }; + +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +        }; +         +        class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd +        { +        public: +            NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp); + +            ~NSArrayMSyntheticFrontEnd_1010() override; + +            bool +            Update() override; +             +        protected: +            lldb::addr_t +            GetDataAddress() override; +             +            uint64_t +            GetUsedCount() override; +             +            uint64_t +            GetOffset() override; +             +            uint64_t +            GetSize() override; +             +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used; +                uint32_t _offset; +                uint32_t _size : 28; +                uint64_t _priv1 : 4; +                uint32_t _priv2; +                uint32_t _data; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used; +                uint64_t _offset; +                uint64_t _size : 60; +                uint64_t _priv1 : 4; +                uint32_t _priv2; +                uint64_t _data; +            }; + +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +        }; +         +        class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSArrayISyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            uint64_t m_items; +            lldb::addr_t m_data_ptr; +            CompilerType m_id_type; +            std::vector<lldb::ValueObjectSP> m_children; +        }; +         +        class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSArray0SyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +        }; +         +        class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSArrayCodeRunningSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +        }; +    } // namespace formatters +} // namespace lldb_private + +bool +lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    static ConstString g_TypeHint("NSArray"); +     +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint64_t value = 0; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"__NSArrayI")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +    } +    else if (!strcmp(class_name,"__NSArrayM")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +    } +    else if (!strcmp(class_name,"__NSArray0")) +    { +        value = 0; +    } +    else if (!strcmp(class_name,"__NSCFArray")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +    } +    else +    { +        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) +            return false; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%" PRIu64 " %s%s%s", +                  prefix.c_str(), +                  value, +                  "element", +                  value == 1 ? "" : "s", +                  suffix.c_str()); +    return true; +} + +lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp), +m_exe_ctx_ref(), +m_ptr_size(8), +m_id_type(), +m_children() +{ +    if (valobj_sp) +    { +        clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext(); +        if (ast) +            m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy); +        if (valobj_sp->GetProcessSP()) +            m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize(); +    } +} + +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) : +NSArrayMSyntheticFrontEnd(valobj_sp), +m_data_32(NULL), +m_data_64(NULL) +{ +} + +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) : +NSArrayMSyntheticFrontEnd(valobj_sp), +m_data_32(NULL), +m_data_64(NULL) +{ +} + +size_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren () +{ +    return GetUsedCount(); +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (idx >= CalculateNumChildren()) +        return lldb::ValueObjectSP(); +    lldb::addr_t object_at_idx = GetDataAddress(); +    size_t pyhs_idx = idx; +    pyhs_idx += GetOffset(); +    if (GetSize() <= pyhs_idx) +        pyhs_idx -= GetSize(); +    object_at_idx += (pyhs_idx * m_ptr_size); +    StreamString idx_name; +    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), +                                                                 object_at_idx, +                                                                 m_exe_ctx_ref, +                                                                 m_id_type); +    m_children.push_back(retval_sp); +    return retval_sp; +} + +bool +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() +{ +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    m_ptr_size = 0; +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    return false; +} + +bool +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update() +{ +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    m_ptr_size = 0; +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    return false; +} + +bool +lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109() +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +lldb::addr_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress () +{ +    if (!m_data_32 && !m_data_64) +        return LLDB_INVALID_ADDRESS; +    return m_data_32 ? m_data_32->_data : +    m_data_64->_data; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_used : +    m_data_64->_used; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_offset : +    m_data_64->_offset; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_size : +    m_data_64->_size; +} + +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010() +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +lldb::addr_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress () +{ +    if (!m_data_32 && !m_data_64) +        return LLDB_INVALID_ADDRESS; +    return m_data_32 ? m_data_32->_data : +    m_data_64->_data; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_used : +    m_data_64->_used; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_offset : +    m_data_64->_offset; +} + +uint64_t +lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return m_data_32 ? m_data_32->_size : +    m_data_64->_size; +} + +lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd (*valobj_sp.get()), +m_exe_ctx_ref (), +m_ptr_size (8), +m_items (0), +m_data_ptr (0) +{ +    if (valobj_sp) +    { +        CompilerType type = valobj_sp->GetCompilerType(); +        if (type) +        { +            ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext(); +            if (ast) +                m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy); +        } +    } +} + +size_t +lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +size_t +lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren () +{ +    return m_items; +} + +bool +lldb_private::formatters::NSArrayISyntheticFrontEnd::Update() +{ +    m_ptr_size = 0; +    m_items = 0; +    m_data_ptr = 0; +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; +    m_items = process_sp->ReadPointerFromMemory(data_location, error); +    if (error.Fail()) +        return false; +    m_data_ptr = data_location+m_ptr_size; +    return false; +} + +bool +lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    if (idx >= CalculateNumChildren()) +        return lldb::ValueObjectSP(); +    lldb::addr_t object_at_idx = m_data_ptr; +    object_at_idx += (idx * m_ptr_size); +    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); +    if (!process_sp) +        return lldb::ValueObjectSP(); +    Error error; +    if (error.Fail()) +        return lldb::ValueObjectSP(); +    StreamString idx_name; +    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(), +                                                                 object_at_idx, +                                                                 m_exe_ctx_ref, +                                                                 m_id_type); +    m_children.push_back(retval_sp); +    return retval_sp; +} + +lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd (*valobj_sp.get()) +{ +} + +size_t +lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return UINT32_MAX; +} + +size_t +lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren () +{ +    return 0; +} + +bool +lldb_private::formatters::NSArray0SyntheticFrontEnd::Update() +{ +    return false; +} + +bool +lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren () +{ +    return false; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    return lldb::ValueObjectSP(); +} + +SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return nullptr; +     +    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); +    if (!process_sp) +        return NULL; +    AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime()); +    if (!runtime) +        return NULL; +     +    CompilerType valobj_type(valobj_sp->GetCompilerType()); +    Flags flags(valobj_type.GetTypeInfo()); +     +    if (flags.IsClear(eTypeIsPointer)) +    { +        Error error; +        valobj_sp = valobj_sp->AddressOf(error); +        if (error.Fail() || !valobj_sp) +            return NULL; +    } +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return NULL; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return NULL; +     +    if (!strcmp(class_name,"__NSArrayI")) +    { +        return (new NSArrayISyntheticFrontEnd(valobj_sp)); +    } +    else if (!strcmp(class_name,"__NSArray0")) +    { +        return (new NSArray0SyntheticFrontEnd(valobj_sp)); +    } +    else if (!strcmp(class_name,"__NSArrayM")) +    { +        if (runtime->GetFoundationVersion() >= 1100) +            return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); +        else +            return (new NSArrayMSyntheticFrontEnd_109(valobj_sp)); +    } +    else +    { +        return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp)); +    } +} + +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()) +{} + +size_t +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren () +{ +    uint64_t count = 0; +    if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) +        return count; +    return 0; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    StreamString idx_name; +    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx); +    if (valobj_sp) +    { +        valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage()); +        valobj_sp->SetName(ConstString(idx_name.GetData())); +    } +    return valobj_sp; +} + +bool +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update() +{ +    return false; +} + +bool +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return 0; +} diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp new file mode 100644 index 0000000000000..e4a7425329f58 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -0,0 +1,749 @@ +//===-- NSDictionary.cpp ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <mutex> + +// Other libraries and framework includes +#include "clang/AST/DeclCXX.h" + +// Project includes +#include "NSDictionary.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +NSDictionary_Additionals::GetAdditionalSummaries () +{ +    static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; +    return g_map; +} + +std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>& +NSDictionary_Additionals::GetAdditionalSynthetics () +{ +    static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map; +    return g_map; +} + +static CompilerType +GetLLDBNSPairType (TargetSP target_sp) +{ +    CompilerType compiler_type; +     +    ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext(); +     +    if (target_ast_context) +    { +        ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair"); +         +        compiler_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair); +         +        if (!compiler_type) +        { +            compiler_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); +             +            if (compiler_type) +            { +                ClangASTContext::StartTagDeclarationDefinition(compiler_type); +                CompilerType id_compiler_type = target_ast_context->GetBasicType (eBasicTypeObjCID); +                ClangASTContext::AddFieldToRecordType(compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0); +                ClangASTContext::AddFieldToRecordType(compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0); +                ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); +            } +        } +    } +    return compiler_type; +} + +namespace lldb_private { +    namespace  formatters { +        class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSDictionaryISyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used : 26; +                uint32_t _szidx : 6; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used : 58; +                uint32_t _szidx : 6; +            }; + +            struct DictionaryItemDescriptor +            { +                lldb::addr_t key_ptr; +                lldb::addr_t val_ptr; +                lldb::ValueObjectSP valobj_sp; +            }; + +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            lldb::ByteOrder m_order; +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +            lldb::addr_t m_data_ptr; +            CompilerType m_pair_type; +            std::vector<DictionaryItemDescriptor> m_children; +        }; +         +        class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSDictionaryMSyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used : 26; +                uint32_t _kvo : 1; +                uint32_t _size; +                uint32_t _mutations; +                uint32_t _objs_addr; +                uint32_t _keys_addr; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used : 58; +                uint32_t _kvo : 1; +                uint64_t _size; +                uint64_t _mutations; +                uint64_t _objs_addr; +                uint64_t _keys_addr; +            }; + +            struct DictionaryItemDescriptor +            { +                lldb::addr_t key_ptr; +                lldb::addr_t val_ptr; +                lldb::ValueObjectSP valobj_sp; +            }; + +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            lldb::ByteOrder m_order; +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +            CompilerType m_pair_type; +            std::vector<DictionaryItemDescriptor> m_children; +        }; +         +        class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSDictionaryCodeRunningSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +        }; +    } // namespace formatters +} // namespace lldb_private + +template<bool name_entries> +bool +lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    static ConstString g_TypeHint("NSDictionary"); +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +    bool is_64bit = (ptr_size == 8); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint64_t value = 0; +     +    ConstString class_name_cs = descriptor->GetClassName(); +    const char* class_name = class_name_cs.GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"__NSDictionaryI")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); +    } +    else if (!strcmp(class_name,"__NSDictionaryM")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); +    } +    /*else if (!strcmp(class_name,"__NSCFDictionary")) +     { +     Error error; +     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); +     if (error.Fail()) +     return false; +     if (is_64bit) +     value &= ~0x0f1f000000000000UL; +     }*/ +    else +    { +        auto& map(NSDictionary_Additionals::GetAdditionalSummaries()); +        auto iter = map.find(class_name_cs), end = map.end(); +        if (iter != end) +            return iter->second(valobj, stream, options); +        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) +            return false; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%" PRIu64 " %s%s%s", +                  prefix.c_str(), +                  value, +                  "key/value pair", +                  value == 1 ? "" : "s", +                  suffix.c_str()); +    return true; +} + +SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp) +{ +    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); +    if (!process_sp) +        return NULL; +    ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +    if (!runtime) +        return NULL; +     +    CompilerType valobj_type(valobj_sp->GetCompilerType()); +    Flags flags(valobj_type.GetTypeInfo()); +     +    if (flags.IsClear(eTypeIsPointer)) +    { +        Error error; +        valobj_sp = valobj_sp->AddressOf(error); +        if (error.Fail() || !valobj_sp) +            return NULL; +    } +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return NULL; +     +    ConstString class_name_cs = descriptor->GetClassName(); +    const char* class_name = class_name_cs.GetCString(); +     +    if (!class_name || !*class_name) +        return NULL; +     +    if (!strcmp(class_name,"__NSDictionaryI")) +    { +        return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); +    } +    else if (!strcmp(class_name,"__NSDictionaryM")) +    { +        return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); +    } +    else +    { +        auto& map(NSDictionary_Additionals::GetAdditionalSynthetics()); +        auto iter = map.find(class_name_cs), end = map.end(); +        if (iter != end) +            return iter->second(synth, valobj_sp); +        return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp)); +    } +} + +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()) +{} + +size_t +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren () +{ +    uint64_t count = 0; +    if (ExtractValueFromObjCExpression(m_backend, "int", "count", count)) +        return count; +    return 0; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    StreamString idx_name; +    idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +    StreamString key_fetcher_expr; +    key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx); +    StreamString value_fetcher_expr; +    value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData()); +    StreamString object_fetcher_expr; +    object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData()); +    lldb::ValueObjectSP child_sp; +    EvaluateExpressionOptions options; +    options.SetKeepInMemory(true); +    options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus); +    options.SetResultIsInternal(true); +    m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), +                                                GetViableFrame(m_backend.GetTargetSP().get()), +                                                child_sp, +                                                options); +    if (child_sp) +        child_sp->SetName(ConstString(idx_name.GetData())); +    return child_sp; +} + +bool +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update() +{ +    return false; +} + +bool +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    return 0; +} + +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_ptr_size(8), +m_order(lldb::eByteOrderInvalid), +m_data_32(NULL), +m_data_64(NULL), +m_pair_type() +{ +} + +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +size_t +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +size_t +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() +{ +    m_children.clear(); +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    m_ptr_size = 0; +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    m_order = process_sp->GetByteOrder(); +    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    m_data_ptr = data_location + m_ptr_size; +    return false; +} + +bool +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    uint32_t num_children = CalculateNumChildren(); +     +    if (idx >= num_children) +        return lldb::ValueObjectSP(); +     +    if (m_children.empty()) +    { +        // do the scan phase +        lldb::addr_t key_at_idx = 0, val_at_idx = 0; +         +        uint32_t tries = 0; +        uint32_t test_idx = 0; +         +        while(tries < num_children) +        { +            key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size); +            val_at_idx = key_at_idx + m_ptr_size; +            ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); +            if (!process_sp) +                return lldb::ValueObjectSP(); +            Error error; +            key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +            val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +             +            test_idx++; +             +            if (!key_at_idx || !val_at_idx) +                continue; +            tries++; +             +            DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; +             +            m_children.push_back(descriptor); +        } +    } +     +    if (idx >= m_children.size()) // should never happen +        return lldb::ValueObjectSP(); +     +    DictionaryItemDescriptor &dict_item = m_children[idx]; +    if (!dict_item.valobj_sp) +    { +        if (!m_pair_type.IsValid()) +        { +            TargetSP target_sp(m_backend.GetTargetSP()); +            if (!target_sp) +                return ValueObjectSP(); +            m_pair_type = GetLLDBNSPairType(target_sp); +        } +        if (!m_pair_type.IsValid()) +            return ValueObjectSP(); +         +        DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); +         +        if (m_ptr_size == 8) +        { +            uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); +            *data_ptr = dict_item.key_ptr; +            *(data_ptr+1) = dict_item.val_ptr; +        } +        else +        { +            uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); +            *data_ptr = dict_item.key_ptr; +            *(data_ptr+1) = dict_item.val_ptr; +        } +         +        StreamString idx_name; +        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +        DataExtractor data(buffer_sp, m_order, m_ptr_size); +        dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), +                                                        data, +                                                        m_exe_ctx_ref, +                                                        m_pair_type); +    } +    return dict_item.valobj_sp; +} + +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_ptr_size(8), +m_order(lldb::eByteOrderInvalid), +m_data_32(NULL), +m_data_64(NULL), +m_pair_type() +{ +} + +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +size_t +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +size_t +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() +{ +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    m_ptr_size = 0; +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    m_order = process_sp->GetByteOrder(); +    uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    return false; +} + +bool +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr); +    lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); +     +    uint32_t num_children = CalculateNumChildren(); +     +    if (idx >= num_children) +        return lldb::ValueObjectSP(); +     +    if (m_children.empty()) +    { +        // do the scan phase +        lldb::addr_t key_at_idx = 0, val_at_idx = 0; +         +        uint32_t tries = 0; +        uint32_t test_idx = 0; +         +        while(tries < num_children) +        { +            key_at_idx = m_keys_ptr + (test_idx * m_ptr_size); +            val_at_idx = m_values_ptr + (test_idx * m_ptr_size);; +            ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); +            if (!process_sp) +                return lldb::ValueObjectSP(); +            Error error; +            key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +            val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +             +            test_idx++; +             +            if (!key_at_idx || !val_at_idx) +                continue; +            tries++; +             +            DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()}; +             +            m_children.push_back(descriptor); +        } +    } +     +    if (idx >= m_children.size()) // should never happen +        return lldb::ValueObjectSP(); +     +    DictionaryItemDescriptor &dict_item = m_children[idx]; +    if (!dict_item.valobj_sp) +    { +        if (!m_pair_type.IsValid()) +        { +            TargetSP target_sp(m_backend.GetTargetSP()); +            if (!target_sp) +                return ValueObjectSP(); +            m_pair_type = GetLLDBNSPairType(target_sp); +        } +        if (!m_pair_type.IsValid()) +            return ValueObjectSP(); +         +        DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0)); +         +        if (m_ptr_size == 8) +        { +            uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); +            *data_ptr = dict_item.key_ptr; +            *(data_ptr+1) = dict_item.val_ptr; +        } +        else +        { +            uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); +            *data_ptr = dict_item.key_ptr; +            *(data_ptr+1) = dict_item.val_ptr; +        } +         +        StreamString idx_name; +        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +        DataExtractor data(buffer_sp, m_order, m_ptr_size); +        dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(), +                                                        data, +                                                        m_exe_ctx_ref, +                                                        m_pair_type); +    } +    return dict_item.valobj_sp; +} + +template bool +lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&); + +template bool +lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&); diff --git a/source/Plugins/Language/ObjC/NSDictionary.h b/source/Plugins/Language/ObjC/NSDictionary.h new file mode 100644 index 0000000000000..e96c25a97b2b4 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSDictionary.h @@ -0,0 +1,48 @@ +//===-- NSDictionary.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NSDictionary_h_ +#define liblldb_NSDictionary_h_ + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +#include <map> + +namespace lldb_private { +    namespace formatters +    { +        template<bool name_entries> +        bool +        NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); + +        extern template bool +        NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ; +         +        extern template bool +        NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ; +         +        SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        class NSDictionary_Additionals +        { +        public: +            static std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +            GetAdditionalSummaries (); +             +            static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>& +            GetAdditionalSynthetics (); +        }; +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_NSDictionary_h_ diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp new file mode 100644 index 0000000000000..c627cd0319264 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSError.cpp @@ -0,0 +1,218 @@ +//===-- NSError.cpp ---------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/DeclCXX.h" + +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +#include "lldb/Utility/ProcessStructReader.h" + +#include "Plugins/Language/ObjC/NSString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp(valobj.GetProcessSP()); +    if (!process_sp) +        return false; +     +    lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS; +     +    CompilerType valobj_type(valobj.GetCompilerType()); +    Flags type_flags(valobj_type.GetTypeInfo()); +    if (type_flags.AllClear(eTypeHasValue)) +    { +        if (valobj.IsBaseClass() && valobj.GetParent()) +            ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +    } +    else +        ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + +    if (ptr_value == LLDB_INVALID_ADDRESS) +        return false; +    size_t ptr_size = process_sp->GetAddressByteSize(); +    lldb::addr_t code_location = ptr_value + 2 * ptr_size; +    lldb::addr_t domain_location = ptr_value + 3 * ptr_size; +     +    Error error; +    uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error); +    if (error.Fail()) +        return false; +     +    lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error); +    if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS) +        return false; +     +    if (!domain_str_value) +    { +        stream.Printf("domain: nil - code: %" PRIu64, code); +        return true; +    } +     +    InferiorSizedWord isw(domain_str_value, *process_sp); +     +    ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()); +     +    if (!domain_str_sp) +        return false; +     +    StreamString domain_str_summary; +    if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty()) +    { +        stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code); +        return true; +    } +    else +    { +        stream.Printf("domain: nil - code: %" PRIu64, code); +        return true; +    } +} + +class NSErrorSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    NSErrorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd(*valobj_sp) +    {} + +    ~NSErrorSyntheticFrontEnd() override = default; +    // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf + +    size_t +    CalculateNumChildren() override +    { +        if (m_child_ptr) +            return 1; +        if (m_child_sp) +            return 1; +        return 0; +    } +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        if (idx != 0) +            return lldb::ValueObjectSP(); +         +        if (m_child_ptr) +            return m_child_ptr->GetSP(); +        return m_child_sp; +    } +     +    bool +    Update() override +    { +        m_child_ptr = nullptr; +        m_child_sp.reset(); +         +        ProcessSP process_sp(m_backend.GetProcessSP()); +        if (!process_sp) +            return false; +         +        lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS; +         +        CompilerType valobj_type(m_backend.GetCompilerType()); +        Flags type_flags(valobj_type.GetTypeInfo()); +        if (type_flags.AllClear(eTypeHasValue)) +        { +            if (m_backend.IsBaseClass() && m_backend.GetParent()) +                userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +        } +        else +            userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + +        if (userinfo_location == LLDB_INVALID_ADDRESS) +            return false; +         +        size_t ptr_size = process_sp->GetAddressByteSize(); + +        userinfo_location += 4 * ptr_size; +        Error error; +        lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error); +        if (userinfo == LLDB_INVALID_ADDRESS || error.Fail()) +            return false; +        InferiorSizedWord isw(userinfo,*process_sp); +        m_child_sp = ValueObject::CreateValueObjectFromData("_userInfo", +                                                            isw.GetAsData(process_sp->GetByteOrder()), +                                                            m_backend.GetExecutionContextRef(), +                                                            process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); +        return false; +    } +     +    bool +    MightHaveChildren() override +    { +        return true; +    } +     +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        static ConstString g___userInfo("_userInfo"); +        if (name == g___userInfo) +            return 0; +        return UINT32_MAX; +    } + +private: +    // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory +    // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak +    // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away +    // oh joy! +    ValueObject* m_child_ptr; +    ValueObjectSP m_child_sp; +}; + +SyntheticChildrenFrontEnd* +lldb_private::formatters::NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); +    if (!process_sp) +        return nullptr; +    ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +    if (!runtime) +        return nullptr; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return nullptr; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return nullptr; +     +    if (!strcmp(class_name,"NSError")) +        return (new NSErrorSyntheticFrontEnd(valobj_sp)); +    else if (!strcmp(class_name,"__NSCFError")) +        return (new NSErrorSyntheticFrontEnd(valobj_sp)); +     +    return nullptr; +} diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp new file mode 100644 index 0000000000000..e58223a4d461e --- /dev/null +++ b/source/Plugins/Language/ObjC/NSException.cpp @@ -0,0 +1,219 @@ +//===-- NSException.cpp -----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/DeclCXX.h" + +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +#include "lldb/Utility/ProcessStructReader.h" + +#include "Plugins/Language/ObjC/NSString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    ProcessSP process_sp(valobj.GetProcessSP()); +    if (!process_sp) +        return false; +     +    lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS; +     +    CompilerType valobj_type(valobj.GetCompilerType()); +    Flags type_flags(valobj_type.GetTypeInfo()); +    if (type_flags.AllClear(eTypeHasValue)) +    { +        if (valobj.IsBaseClass() && valobj.GetParent()) +            ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +    } +    else +        ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +     +    if (ptr_value == LLDB_INVALID_ADDRESS) +        return false; +    size_t ptr_size = process_sp->GetAddressByteSize(); +    lldb::addr_t name_location = ptr_value + 1 * ptr_size; +    lldb::addr_t reason_location = ptr_value + 2 * ptr_size; +     +    Error error; +    lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error); +    if (error.Fail() || name == LLDB_INVALID_ADDRESS) +        return false; +     +    lldb::addr_t reason = process_sp->ReadPointerFromMemory(reason_location, error); +    if (error.Fail() || reason == LLDB_INVALID_ADDRESS) +        return false; +     +    InferiorSizedWord name_isw(name, *process_sp); +    InferiorSizedWord reason_isw(reason, *process_sp); +     +    CompilerType voidstar = process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); +     +    ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData("name_str", name_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); +    ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData("reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar); +     +    if (!name_sp || !reason_sp) +        return false; +     +    StreamString name_str_summary; +    StreamString reason_str_summary; +    if (NSStringSummaryProvider(*name_sp, name_str_summary, options) && +        NSStringSummaryProvider(*reason_sp, reason_str_summary, options) && +        !name_str_summary.Empty() && +        !reason_str_summary.Empty()) +    { +        stream.Printf("name: %s - reason: %s", name_str_summary.GetData(), reason_str_summary.GetData()); +        return true; +    } +    else +        return false; +} + +class NSExceptionSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    NSExceptionSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd(*valobj_sp) +    {} + +    ~NSExceptionSyntheticFrontEnd() override = default; +    // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf + +    size_t +    CalculateNumChildren() override +    { +        if (m_child_ptr) +            return 1; +        if (m_child_sp) +            return 1; +        return 0; +    } +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        if (idx != 0) +            return lldb::ValueObjectSP(); +         +        if (m_child_ptr) +            return m_child_ptr->GetSP(); +        return m_child_sp; +    } +     +    bool +    Update() override +    { +        m_child_ptr = nullptr; +        m_child_sp.reset(); +         +        ProcessSP process_sp(m_backend.GetProcessSP()); +        if (!process_sp) +            return false; +         +        lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS; +         +        CompilerType valobj_type(m_backend.GetCompilerType()); +        Flags type_flags(valobj_type.GetTypeInfo()); +        if (type_flags.AllClear(eTypeHasValue)) +        { +            if (m_backend.IsBaseClass() && m_backend.GetParent()) +                userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +        } +        else +            userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); +         +        if (userinfo_location == LLDB_INVALID_ADDRESS) +            return false; +         +        size_t ptr_size = process_sp->GetAddressByteSize(); +         +        userinfo_location += 3 * ptr_size; +        Error error; +        lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error); +        if (userinfo == LLDB_INVALID_ADDRESS || error.Fail()) +            return false; +        InferiorSizedWord isw(userinfo,*process_sp); +        m_child_sp = ValueObject::CreateValueObjectFromData("userInfo", +                                                            isw.GetAsData(process_sp->GetByteOrder()), +                                                            m_backend.GetExecutionContextRef(), +                                                            process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); +        return false; +    } +     +    bool +    MightHaveChildren() override +    { +        return true; +    } +     +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        static ConstString g___userInfo("userInfo"); +        if (name == g___userInfo) +            return 0; +        return UINT32_MAX; +    } + +private: +    // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory +    // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak +    // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away +    // oh joy! +    ValueObject* m_child_ptr; +    ValueObjectSP m_child_sp; +}; + +SyntheticChildrenFrontEnd* +lldb_private::formatters::NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ +    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); +    if (!process_sp) +        return nullptr; +    ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +    if (!runtime) +        return nullptr; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return nullptr; +     +    const char* class_name = descriptor->GetClassName().GetCString(); +     +    if (!class_name || !*class_name) +        return nullptr; +     +    if (!strcmp(class_name,"NSException")) +        return (new NSExceptionSyntheticFrontEnd(valobj_sp)); +    else if (!strcmp(class_name,"NSCFException")) +        return (new NSExceptionSyntheticFrontEnd(valobj_sp)); +    else if (!strcmp(class_name,"__NSCFException")) +        return (new NSExceptionSyntheticFrontEnd(valobj_sp)); +     +    return nullptr; +} diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp new file mode 100644 index 0000000000000..245f6da80c7f1 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp @@ -0,0 +1,349 @@ +//===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "Cocoa.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/TypeSynthetic.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: +    NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +    SyntheticChildrenFrontEnd (*valobj_sp.get()), +    m_ptr_size(0), +    m_uint_star_type() +    { +        m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize(); +    } + +    ~NSIndexPathSyntheticFrontEnd() override = default; + +    size_t +    CalculateNumChildren() override +    { +        return m_impl.GetNumIndexes(); +    } +     +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        return m_impl.GetIndexAtIndex(idx, m_uint_star_type); +    } +     +    bool +    Update() override +    { +        m_impl.Clear(); +         +        TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem(); +        if (!type_system) +            return false; + +        ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext(); +        if (!ast) +            return false; + +        m_uint_star_type = ast->GetPointerSizedIntType(false); +         +        static ConstString g__indexes("_indexes"); +        static ConstString g__length("_length"); + +        ProcessSP process_sp = m_backend.GetProcessSP(); +        if (!process_sp) +            return false; +         +        ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +         +        if (!runtime) +            return false; +         +        ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend)); +         +        if (!descriptor.get() || !descriptor->IsValid()) +            return false; +         +        uint64_t info_bits(0),value_bits(0),payload(0); +         +        if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) +        { +            m_impl.m_inlined.SetIndexes(payload, *process_sp); +            m_impl.m_mode = Mode::Inlined; +        } +        else +        { +            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id; +            ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id; +             +            bool has_indexes(false),has_length(false); +             +            for (size_t x = 0; +                 x < descriptor->GetNumIVars(); +                 x++) +            { +                const auto& ivar = descriptor->GetIVarAtIndex(x); +                if (ivar.m_name == g__indexes) +                { +                    _indexes_id = ivar; +                    has_indexes = true; +                } +                else if (ivar.m_name == g__length) +                { +                    _length_id = ivar; +                    has_length = true; +                } +                 +                if (has_length && has_indexes) +                    break; +            } +             +            if (has_length && has_indexes) +            { +                m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset, +                                                                                    m_uint_star_type.GetPointerType(), +                                                                                    true).get(); +                ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset, +                                                                            m_uint_star_type, +                                                                            true)); +                if (length_sp) +                { +                    m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0); +                    if (m_impl.m_outsourced.m_indexes) +                        m_impl.m_mode = Mode::Outsourced; +                } +            } +        } +        return false; +    } +     +    bool +    MightHaveChildren() override +    { +        if (m_impl.m_mode == Mode::Invalid) +            return false; +        return true; +    } +     +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        const char* item_name = name.GetCString(); +        uint32_t idx = ExtractIndexFromString(item_name); +        if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +            return UINT32_MAX; +        return idx; +    } +     +    lldb::ValueObjectSP +    GetSyntheticValue() override +    { +        return nullptr; +    } + +protected: +    ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp; +     +    enum class Mode { +        Inlined, +        Outsourced, +        Invalid +    }; +     +    struct Impl { +        Mode m_mode; + +        size_t +        GetNumIndexes () +        { +            switch (m_mode) +            { +                case Mode::Inlined: +                    return m_inlined.GetNumIndexes(); +                case Mode::Outsourced: +                    return m_outsourced.m_count; +                default: +                    return 0; +            } +        } +         +        lldb::ValueObjectSP +        GetIndexAtIndex (size_t idx, const CompilerType& desired_type) +        { +            if (idx >= GetNumIndexes()) +                return nullptr; +            switch (m_mode) +            { +                default: return nullptr; +                case Mode::Inlined: +                    return m_inlined.GetIndexAtIndex (idx, desired_type); +                case Mode::Outsourced: +                    return m_outsourced.GetIndexAtIndex (idx); +            } +        } + +        struct InlinedIndexes { +        public: +          void SetIndexes(uint64_t value, Process& p) +          { +              m_indexes = value; +              _lengthForInlinePayload(p.GetAddressByteSize()); +              m_process = &p; +          } +               +          size_t +          GetNumIndexes () +          { +              return m_count; +          } + +          lldb::ValueObjectSP +          GetIndexAtIndex (size_t idx, const CompilerType& desired_type) +          { +              std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx)); +              if (!value.second) +                  return nullptr; +               +              Value v; +              if (m_ptr_size == 8) +              { +                  Scalar scalar( (unsigned long long)value.first ); +                  v = Value(scalar); +              } +              else +              { +                  Scalar scalar( (unsigned int)value.first ); +                  v = Value(scalar); +              } + +              v.SetCompilerType(desired_type); + +              StreamString idx_name; +              idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); + +              return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); +          } +             +            void +            Clear () +            { +                m_indexes = 0; +                m_count = 0; +                m_ptr_size = 0; +                m_process = nullptr; +            } +                     +        private: +          uint64_t m_indexes; +          size_t m_count; +          uint32_t m_ptr_size; +          Process *m_process; +                     +          // cfr. Foundation for the details of this code +          size_t _lengthForInlinePayload(uint32_t ptr_size) { +              m_ptr_size = ptr_size; +              if (m_ptr_size == 8) +              m_count = ((m_indexes >> 3) & 0x7); +              else +              m_count = ((m_indexes >> 3) & 0x3); +              return m_count; +          } +                     +          std::pair<uint64_t, bool> +          _indexAtPositionForInlinePayload(size_t pos) +          { +              if (m_ptr_size == 8) +              { +                switch (pos) { +                    case 5: return {((m_indexes >> 51) & 0x1ff),true}; +                    case 4: return {((m_indexes >> 42) & 0x1ff),true}; +                    case 3: return {((m_indexes >> 33) & 0x1ff),true}; +                    case 2: return {((m_indexes >> 24) & 0x1ff),true}; +                    case 1: return {((m_indexes >> 15) & 0x1ff),true}; +                    case 0: return {((m_indexes >>  6) & 0x1ff),true}; +                } +              } +              else +                  { +                  switch (pos) { +                      case 2: return {((m_indexes >> 23) & 0x1ff),true}; +                      case 1: return {((m_indexes >> 14) & 0x1ff),true}; +                      case 0: return {((m_indexes >>  5) & 0x1ff),true}; +                  } +              } +              return {0,false}; +          } + +        }; +        struct OutsourcedIndexes { +            ValueObject *m_indexes; +            size_t m_count; +                     +            lldb::ValueObjectSP +            GetIndexAtIndex (size_t idx) +            { +                if (m_indexes) +                { +                    ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true)); +                    return index_sp; +                } +                return nullptr; +            } +             +            void +            Clear () +            { +                m_indexes = nullptr; +                m_count = 0; +            } +        }; + +        union { +            struct InlinedIndexes m_inlined; +            struct OutsourcedIndexes m_outsourced; +        }; +         +        void +        Clear () +        { +            m_mode = Mode::Invalid; +            m_inlined.Clear(); +            m_outsourced.Clear(); +        } +    } m_impl; +     +    uint32_t m_ptr_size; +    CompilerType m_uint_star_type; +}; + +namespace lldb_private { +    namespace formatters { +         +        SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +        { +            if (valobj_sp) +                return new NSIndexPathSyntheticFrontEnd(valobj_sp); +            return nullptr; +        } + +    } // namespace formatters +} // namespace lldb_private diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp new file mode 100644 index 0000000000000..93115957e329a --- /dev/null +++ b/source/Plugins/Language/ObjC/NSSet.cpp @@ -0,0 +1,758 @@ +//===-- NSSet.cpp -----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "NSSet.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +NSSet_Additionals::GetAdditionalSummaries () +{ +    static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; +    return g_map; +} + +std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>& +NSSet_Additionals::GetAdditionalSynthetics () +{ +    static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map; +    return g_map; +} + +namespace lldb_private { +    namespace formatters { +        class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSSetISyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used : 26; +                uint32_t _szidx : 6; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used : 58; +                uint32_t _szidx : 6; +            }; + +            struct SetItemDescriptor +            { +                lldb::addr_t item_ptr; +                lldb::ValueObjectSP valobj_sp; +            }; + +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +            lldb::addr_t m_data_ptr; +            std::vector<SetItemDescriptor> m_children; +        }; +         +        class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSOrderedSetSyntheticFrontEnd() override = default; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            uint32_t m_count; +            std::map<uint32_t,lldb::ValueObjectSP> m_children; +        }; +         +        class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSSetMSyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; + +        private: +            struct DataDescriptor_32 +            { +                uint32_t _used : 26; +                uint32_t _size; +                uint32_t _mutations; +                uint32_t _objs_addr; +            }; + +            struct DataDescriptor_64 +            { +                uint64_t _used : 58; +                uint64_t _size; +                uint64_t _mutations; +                uint64_t _objs_addr; +            }; + +            struct SetItemDescriptor +            { +                lldb::addr_t item_ptr; +                lldb::ValueObjectSP valobj_sp; +            }; + +            ExecutionContextRef m_exe_ctx_ref; +            uint8_t m_ptr_size; +            DataDescriptor_32 *m_data_32; +            DataDescriptor_64 *m_data_64; +            std::vector<SetItemDescriptor> m_children; +        }; +         +        class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd +        { +        public: +            NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + +            ~NSSetCodeRunningSyntheticFrontEnd() override; + +            size_t +            CalculateNumChildren() override; +             +            lldb::ValueObjectSP +            GetChildAtIndex(size_t idx) override; +             +            bool +            Update() override; +             +            bool +            MightHaveChildren() override; +             +            size_t +            GetIndexOfChildWithName(const ConstString &name) override; +        }; +    } // namespace formatters +} // namespace lldb_private + +template<bool cf_style> +bool +lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    static ConstString g_TypeHint("NSSet"); +     +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +    bool is_64bit = (ptr_size == 8); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    uint64_t value = 0; +     +    ConstString class_name_cs = descriptor->GetClassName(); +    const char* class_name = class_name_cs.GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    if (!strcmp(class_name,"__NSSetI")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); +    } +    else if (!strcmp(class_name,"__NSSetM")) +    { +        Error error; +        value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +        if (error.Fail()) +            return false; +        value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); +    } +    /*else if (!strcmp(class_name,"__NSCFSet")) +     { +     Error error; +     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error); +     if (error.Fail()) +     return false; +     if (is_64bit) +     value &= ~0x1fff000000000000UL; +     } +     else if (!strcmp(class_name,"NSCountedSet")) +     { +     Error error; +     value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); +     if (error.Fail()) +     return false; +     value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error); +     if (error.Fail()) +     return false; +     if (is_64bit) +     value &= ~0x1fff000000000000UL; +     }*/ +    else +    { +        auto& map(NSSet_Additionals::GetAdditionalSummaries()); +        auto iter = map.find(class_name_cs), end = map.end(); +        if (iter != end) +            return iter->second(valobj, stream, options); +        if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) +            return false; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    stream.Printf("%s%" PRIu64 " %s%s%s", +                  prefix.c_str(), +                  value, +                  "element", +                  value == 1 ? "" : "s", +                  suffix.c_str()); +    return true; +} + +SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp) +{ +    lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); +    if (!process_sp) +        return NULL; +    ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +    if (!runtime) +        return NULL; +     +    CompilerType valobj_type(valobj_sp->GetCompilerType()); +    Flags flags(valobj_type.GetTypeInfo()); +     +    if (flags.IsClear(eTypeIsPointer)) +    { +        Error error; +        valobj_sp = valobj_sp->AddressOf(error); +        if (error.Fail() || !valobj_sp) +            return NULL; +    } +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return NULL; +     +    ConstString class_name_cs = descriptor->GetClassName(); +    const char* class_name = class_name_cs.GetCString(); +     +    if (!class_name || !*class_name) +        return NULL; +     +    if (!strcmp(class_name,"__NSSetI")) +    { +        return (new NSSetISyntheticFrontEnd(valobj_sp)); +    } +    else if (!strcmp(class_name,"__NSSetM")) +    { +        return (new NSSetMSyntheticFrontEnd(valobj_sp)); +    } +    else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM"))) +    { +        return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code +    } +    else +    { +        auto& map(NSSet_Additionals::GetAdditionalSynthetics()); +        auto iter = map.find(class_name_cs), end = map.end(); +        if (iter != end) +            return iter->second(synth, valobj_sp); +        return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL; +    } +} + +lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_ptr_size(8), +m_data_32(NULL), +m_data_64(NULL) +{ +    if (valobj_sp) +        Update(); +} + +lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd () +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +size_t +lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +size_t +lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSSetISyntheticFrontEnd::Update() +{ +    m_children.clear(); +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    m_ptr_size = 0; +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    if (!valobj_sp) +        return false; +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    if (valobj_sp->IsPointerType()) +    { +        valobj_sp = valobj_sp->Dereference(error); +        if (error.Fail() || !valobj_sp) +            return false; +    } +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    m_data_ptr = data_location + m_ptr_size; +    return false; +} + +bool +lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    uint32_t num_children = CalculateNumChildren(); +     +    if (idx >= num_children) +        return lldb::ValueObjectSP(); +     +    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); +    if (!process_sp) +        return lldb::ValueObjectSP(); +     +    if (m_children.empty()) +    { +        // do the scan phase +        lldb::addr_t obj_at_idx = 0; +         +        uint32_t tries = 0; +        uint32_t test_idx = 0; +         +        while(tries < num_children) +        { +            obj_at_idx = m_data_ptr + (test_idx * m_ptr_size); +            if (!process_sp) +                return lldb::ValueObjectSP(); +            Error error; +            obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +             +            test_idx++; +             +            if (!obj_at_idx) +                continue; +            tries++; +             +            SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; +             +            m_children.push_back(descriptor); +        } +    } +     +    if (idx >= m_children.size()) // should never happen +        return lldb::ValueObjectSP(); +     +    SetItemDescriptor &set_item = m_children[idx]; +    if (!set_item.valobj_sp) +    { +        auto ptr_size = process_sp->GetAddressByteSize(); +        DataBufferHeap buffer(ptr_size,0); +        switch (ptr_size) +        { +            case 0: // architecture has no clue?? - fail +                return lldb::ValueObjectSP(); +            case 4: +                *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; +                break; +            case 8: +                *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; +                break; +            default: +                assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); +        } +        StreamString idx_name; +        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +         +        DataExtractor data(buffer.GetBytes(), +                           buffer.GetByteSize(), +                           process_sp->GetByteOrder(), +                           process_sp->GetAddressByteSize()); +         +        set_item.valobj_sp = +        CreateValueObjectFromData(idx_name.GetData(), +                                  data, +                                  m_exe_ctx_ref, +                                  m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); +    } +    return set_item.valobj_sp; +} + +lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_exe_ctx_ref(), +m_ptr_size(8), +m_data_32(NULL), +m_data_64(NULL) +{ +    if (valobj_sp) +        Update (); +} + +lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd () +{ +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +} + +size_t +lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +size_t +lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren () +{ +    if (!m_data_32 && !m_data_64) +        return 0; +    return (m_data_32 ? m_data_32->_used : m_data_64->_used); +} + +bool +lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() +{ +    m_children.clear(); +    ValueObjectSP valobj_sp = m_backend.GetSP(); +    m_ptr_size = 0; +    delete m_data_32; +    m_data_32 = NULL; +    delete m_data_64; +    m_data_64 = NULL; +    if (!valobj_sp) +        return false; +    if (!valobj_sp) +        return false; +    m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); +    Error error; +    if (valobj_sp->IsPointerType()) +    { +        valobj_sp = valobj_sp->Dereference(error); +        if (error.Fail() || !valobj_sp) +            return false; +    } +    error.Clear(); +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return false; +    m_ptr_size = process_sp->GetAddressByteSize(); +    uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size; +    if (m_ptr_size == 4) +    { +        m_data_32 = new DataDescriptor_32(); +        process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error); +    } +    else +    { +        m_data_64 = new DataDescriptor_64(); +        process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error); +    } +    if (error.Fail()) +        return false; +    return false; +} + +bool +lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr); +     +    uint32_t num_children = CalculateNumChildren(); +     +    if (idx >= num_children) +        return lldb::ValueObjectSP(); +     +    ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP(); +    if (!process_sp) +        return lldb::ValueObjectSP(); +     +    if (m_children.empty()) +    { +        // do the scan phase +        lldb::addr_t obj_at_idx = 0; +         +        uint32_t tries = 0; +        uint32_t test_idx = 0; +         +        while(tries < num_children) +        { +            obj_at_idx = m_objs_addr + (test_idx * m_ptr_size); +            if (!process_sp) +                return lldb::ValueObjectSP(); +            Error error; +            obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error); +            if (error.Fail()) +                return lldb::ValueObjectSP(); +             +            test_idx++; +             +            if (!obj_at_idx) +                continue; +            tries++; +             +            SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()}; +             +            m_children.push_back(descriptor); +        } +    } +     +    if (idx >= m_children.size()) // should never happen +        return lldb::ValueObjectSP(); +     +    SetItemDescriptor &set_item = m_children[idx]; +    if (!set_item.valobj_sp) +    { +        auto ptr_size = process_sp->GetAddressByteSize(); +        DataBufferHeap buffer(ptr_size,0); +        switch (ptr_size) +        { +            case 0: // architecture has no clue?? - fail +                return lldb::ValueObjectSP(); +            case 4: +                *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr; +                break; +            case 8: +                *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr; +                break; +            default: +                assert(false && "pointer size is not 4 nor 8 - get out of here ASAP"); +        } +        StreamString idx_name; +        idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +         +        DataExtractor data(buffer.GetBytes(), +                           buffer.GetByteSize(), +                           process_sp->GetByteOrder(), +                           process_sp->GetAddressByteSize()); +         +        set_item.valobj_sp = +        CreateValueObjectFromData(idx_name.GetData(), +                                  data, +                                  m_exe_ctx_ref, +                                  m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID)); +    } +    return set_item.valobj_sp; +} + +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd(*valobj_sp.get()), +m_count(UINT32_MAX), +m_children() +{} + +size_t +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren () +{ +    if (m_count != UINT32_MAX) +        return m_count; +    uint64_t count_temp; +    if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp)) +        return (m_count = count_temp); +    return (m_count = 0); +} + +lldb::ValueObjectSP +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ +    auto iter = m_children.find(idx); +    if (iter == m_children.end()) +    { +        lldb::ValueObjectSP retval_sp; +        if (idx <= m_count) +        { +            retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx); +            if (retval_sp) +            { +                StreamString idx_name; +                idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +                retval_sp->SetName(ConstString(idx_name.GetData())); +            } +            m_children[idx] = retval_sp; +        } +        return retval_sp; +    } +    else +        return iter->second; +} + +bool +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update() +{ +    return false; +} + +bool +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren () +{ +    return true; +} + +size_t +lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ +    const char* item_name = name.GetCString(); +    uint32_t idx = ExtractIndexFromString(item_name); +    if (idx < UINT32_MAX && idx >= CalculateNumChildren()) +        return UINT32_MAX; +    return idx; +} + +template bool +lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); + +template bool +lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); diff --git a/source/Plugins/Language/ObjC/NSSet.h b/source/Plugins/Language/ObjC/NSSet.h new file mode 100644 index 0000000000000..c8622706e860d --- /dev/null +++ b/source/Plugins/Language/ObjC/NSSet.h @@ -0,0 +1,40 @@ +//===-- NSSet.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NSSet_h_ +#define liblldb_NSSet_h_ + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +namespace lldb_private { +    namespace formatters +    { +        template<bool cf_style> +        bool +        NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); +         +        class NSSet_Additionals +        { +        public: +            static std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +            GetAdditionalSummaries (); +             +            static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>& +            GetAdditionalSynthetics (); +        }; +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_NSSet_h_ diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp new file mode 100644 index 0000000000000..80896631baf3c --- /dev/null +++ b/source/Plugins/Language/ObjC/NSString.cpp @@ -0,0 +1,405 @@ +//===-- NSString.cpp ----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NSString.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Target/Language.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ProcessStructReader.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +NSString_Additionals::GetAdditionalSummaries () +{ +    static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map; +    return g_map; +} + +static CompilerType +GetNSPathStore2Type (Target &target) +{ +    static ConstString g_type_name("__lldb_autogen_nspathstore2"); +     +    ClangASTContext *ast_ctx = target.GetScratchClangASTContext(); +     +    if (!ast_ctx) +        return CompilerType(); +     +    CompilerType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); +    CompilerType uint32 = ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); +     +    return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, { +        {"isa",voidstar}, +        {"lengthAndRef",uint32}, +        {"buffer",voidstar} +    }); +} + +bool +lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) +{ +    static ConstString g_TypeHint("NSString"); +     +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; +     +    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); +     +    if (!runtime) +        return false; +     +    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); +     +    if (!descriptor.get() || !descriptor->IsValid()) +        return false; +     +    uint32_t ptr_size = process_sp->GetAddressByteSize(); +     +    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0); +     +    if (!valobj_addr) +        return false; +     +    ConstString class_name_cs = descriptor->GetClassName(); +    const char* class_name = class_name_cs.GetCString(); +     +    if (!class_name || !*class_name) +        return false; +     +    bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo(); +    // for a tagged pointer, the descriptor has everything we need +    if (is_tagged_ptr) +        return NSTaggedString_SummaryProvider(valobj, descriptor, stream, summary_options); +     +    auto& additionals_map(NSString_Additionals::GetAdditionalSummaries()); +    auto iter = additionals_map.find(class_name_cs), end = additionals_map.end(); +    if (iter != end) +        return iter->second(valobj, stream, summary_options); +     +    // if not a tagged pointer that we know about, try the normal route +    uint64_t info_bits_location = valobj_addr + ptr_size; +    if (process_sp->GetByteOrder() != lldb::eByteOrderLittle) +        info_bits_location += 3; +     +    Error error; +     +    uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error); +    if (error.Fail()) +        return false; +     +    bool is_mutable = (info_bits & 1) == 1; +    bool is_inline = (info_bits & 0x60) == 0; +    bool has_explicit_length = (info_bits & (1 | 4)) != 4; +    bool is_unicode = (info_bits & 0x10) == 0x10; +    bool is_path_store = strcmp(class_name,"NSPathStore2") == 0; +    bool has_null = (info_bits & 8) == 8; +     +    size_t explicit_length = 0; +    if (!has_null && has_explicit_length && !is_path_store) +    { +        lldb::addr_t explicit_length_offset = 2*ptr_size; +        if (is_mutable && !is_inline) +            explicit_length_offset = explicit_length_offset + ptr_size; //  notInlineMutable.length; +        else if (is_inline) +            explicit_length = explicit_length + 0; // inline1.length; +        else if (!is_inline && !is_mutable) +            explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length; +        else +            explicit_length_offset = 0; +         +        if (explicit_length_offset) +        { +            explicit_length_offset = valobj_addr + explicit_length_offset; +            explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error); +        } +    } +     +    if (strcmp(class_name,"NSString") && +        strcmp(class_name,"CFStringRef") && +        strcmp(class_name,"CFMutableStringRef") && +        strcmp(class_name,"__NSCFConstantString") && +        strcmp(class_name,"__NSCFString") && +        strcmp(class_name,"NSCFConstantString") && +        strcmp(class_name,"NSCFString") && +        strcmp(class_name,"NSPathStore2")) +    { +        // not one of us - but tell me class name +        stream.Printf("class name = %s",class_name); +        return true; +    } +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(summary_options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetPrefixToken(prefix); +    options.SetSuffixToken(suffix); +     +    if (is_mutable) +    { +        uint64_t location = 2 * ptr_size + valobj_addr; +        location = process_sp->ReadPointerFromMemory(location, error); +        if (error.Fail()) +            return false; +        if (has_explicit_length && is_unicode) +        { +            options.SetLocation(location); +            options.SetProcessSP(process_sp); +            options.SetStream(&stream); +            options.SetQuote('"'); +            options.SetSourceSize(explicit_length); +            options.SetNeedsZeroTermination(false); +            options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +            options.SetBinaryZeroIsTerminator(false); +            options.SetLanguage(summary_options.GetLanguage()); +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options); +        } +        else +        { +            options.SetLocation(location+1); +            options.SetProcessSP(process_sp); +            options.SetStream(&stream); +            options.SetSourceSize(explicit_length); +            options.SetNeedsZeroTermination(false); +            options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +            options.SetBinaryZeroIsTerminator(false); +            options.SetLanguage(summary_options.GetLanguage()); +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options); +        } +    } +    else if (is_inline && has_explicit_length && !is_unicode && !is_path_store && !is_mutable) +    { +        uint64_t location = 3 * ptr_size + valobj_addr; +         +        options.SetLocation(location); +        options.SetProcessSP(process_sp); +        options.SetStream(&stream); +        options.SetQuote('"'); +        options.SetSourceSize(explicit_length); +        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +        options.SetLanguage(summary_options.GetLanguage()); +        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (options); +    } +    else if (is_unicode) +    { +        uint64_t location = valobj_addr + 2*ptr_size; +        if (is_inline) +        { +            if (!has_explicit_length) +            { +                stream.Printf("found new combo"); +                return true; +            } +            else +                location += ptr_size; +        } +        else +        { +            location = process_sp->ReadPointerFromMemory(location, error); +            if (error.Fail()) +                return false; +        } +        options.SetLocation(location); +        options.SetProcessSP(process_sp); +        options.SetStream(&stream); +        options.SetQuote('"'); +        options.SetSourceSize(explicit_length); +        options.SetNeedsZeroTermination(has_explicit_length == false); +        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +        options.SetBinaryZeroIsTerminator(has_explicit_length == false); +        options.SetLanguage(summary_options.GetLanguage()); +        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options); +    } +    else if (is_path_store) +    { +        ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP())); +        explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20; +        lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4; +         +        options.SetLocation(location); +        options.SetProcessSP(process_sp); +        options.SetStream(&stream); +        options.SetQuote('"'); +        options.SetSourceSize(explicit_length); +        options.SetNeedsZeroTermination(has_explicit_length == false); +        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +        options.SetBinaryZeroIsTerminator(has_explicit_length == false); +        options.SetLanguage(summary_options.GetLanguage()); +        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options); +    } +    else if (is_inline) +    { +        uint64_t location = valobj_addr + 2*ptr_size; +        if (!has_explicit_length) +        { +            // in this kind of string, the byte before the string content is a length byte +            // so let's try and use it to handle the embedded NUL case +            Error error; +            explicit_length = process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error); +            if (error.Fail() || explicit_length == 0) +                has_explicit_length = false; +            else +                has_explicit_length = true; +            location++; +        } +        options.SetLocation(location); +        options.SetProcessSP(process_sp); +        options.SetStream(&stream); +        options.SetSourceSize(explicit_length); +        options.SetNeedsZeroTermination(!has_explicit_length); +        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +        options.SetBinaryZeroIsTerminator(!has_explicit_length); +        options.SetLanguage(summary_options.GetLanguage()); +        if (has_explicit_length) +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options); +        else +            return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options); +    } +    else +    { +        uint64_t location = valobj_addr + 2*ptr_size; +        location = process_sp->ReadPointerFromMemory(location, error); +        if (error.Fail()) +            return false; +        if (has_explicit_length && !has_null) +            explicit_length++; // account for the fact that there is no NULL and we need to have one added +        options.SetLocation(location); +        options.SetProcessSP(process_sp); +        options.SetStream(&stream); +        options.SetSourceSize(explicit_length); +        options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped); +        options.SetLanguage(summary_options.GetLanguage()); +        return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options); +    } +} + +bool +lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    TargetSP target_sp(valobj.GetTargetSP()); +    if (!target_sp) +        return false; +    uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize(); +    uint64_t pointer_value = valobj.GetValueAsUnsigned(0); +    if (!pointer_value) +        return false; +    pointer_value += addr_size; +    CompilerType type(valobj.GetCompilerType()); +    ExecutionContext exe_ctx(target_sp,false); +    ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type)); +    if (!child_ptr_sp) +        return false; +    DataExtractor data; +    Error error; +    child_ptr_sp->GetData(data, error); +    if (error.Fail()) +        return false; +    ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type)); +    child_sp->GetValueAsUnsigned(0); +    if (child_sp) +        return NSStringSummaryProvider(*child_sp, stream, options); +    return false; +} + +bool +lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ +    return NSAttributedStringSummaryProvider(valobj, stream, options); +} + +bool +lldb_private::formatters::NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options) +{ +    static ConstString g_TypeHint("NSString"); +     +    if (!descriptor) +        return false; +    uint64_t len_bits = 0, data_bits = 0; +    if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr)) +        return false; +     +    static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN +    static const int g_SixbitMaxLen = 9; +    static const int g_fiveBitMaxLen = 11; +     +    static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX"; +     +    if (len_bits > g_fiveBitMaxLen) +        return false; +     +    std::string prefix,suffix; +    if (Language* language = Language::FindPlugin(summary_options.GetLanguage())) +    { +        if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix)) +        { +            prefix.clear(); +            suffix.clear(); +        } +    } +     +    // this is a fairly ugly trick - pretend that the numeric value is actually a char* +    // this works under a few assumptions: +    // little endian architecture +    // sizeof(uint64_t) > g_MaxNonBitmaskedLen +    if (len_bits <= g_MaxNonBitmaskedLen) +    { +        stream.Printf("%s",prefix.c_str()); +        stream.Printf("\"%s\"",(const char*)&data_bits); +        stream.Printf("%s",suffix.c_str()); +        return true; +    } +     +    // if the data is bitmasked, we need to actually process the bytes +    uint8_t bitmask = 0; +    uint8_t shift_offset = 0; +     +    if (len_bits <= g_SixbitMaxLen) +    { +        bitmask = 0x03f; +        shift_offset = 6; +    } +    else +    { +        bitmask = 0x01f; +        shift_offset = 5; +    } +     +    std::vector<uint8_t> bytes; +    bytes.resize(len_bits); +    for (; len_bits > 0; data_bits >>= shift_offset, --len_bits) +    { +        uint8_t packed = data_bits & bitmask; +        bytes.insert(bytes.begin(), sixBitToCharLookup[packed]); +    } +     +    stream.Printf("%s",prefix.c_str()); +    stream.Printf("\"%s\"",&bytes[0]); +    stream.Printf("%s",suffix.c_str()); +    return true; +} diff --git a/source/Plugins/Language/ObjC/NSString.h b/source/Plugins/Language/ObjC/NSString.h new file mode 100644 index 0000000000000..6a767a55e0098 --- /dev/null +++ b/source/Plugins/Language/ObjC/NSString.h @@ -0,0 +1,42 @@ +//===-- NSString.h ---------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NSString_h_ +#define liblldb_NSString_h_ + +#include "lldb/Core/Stream.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Target/ObjCLanguageRuntime.h" + +namespace lldb_private { +    namespace formatters +    { +        bool +        NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options); +         +        bool +        NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        bool +        NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); +         +        class NSString_Additionals +        { +        public: +            static std::map<ConstString, CXXFunctionSummaryFormat::Callback>& +            GetAdditionalSummaries (); +        }; +    } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CF_h_ diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp new file mode 100644 index 0000000000000..91a3a0fb42999 --- /dev/null +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -0,0 +1,877 @@ +//===-- ObjCLanguage.cpp ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <mutex> + +// Other libraries and framework includes +// Project includes +#include "ObjCLanguage.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Symbol/ClangASTContext.h" + +#include "CF.h" +#include "Cocoa.h" +#include "CoreMedia.h" +#include "NSDictionary.h" +#include "NSSet.h" +#include "NSString.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +ObjCLanguage::Initialize() +{ +    PluginManager::RegisterPlugin (GetPluginNameStatic(), +                                   "Objective-C Language", +                                   CreateInstance); +} + +void +ObjCLanguage::Terminate() +{ +    PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +ObjCLanguage::GetPluginNameStatic() +{ +    static ConstString g_name("objc"); +    return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +ObjCLanguage::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +ObjCLanguage::GetPluginVersion() +{ +    return 1; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +Language * +ObjCLanguage::CreateInstance (lldb::LanguageType language) +{ +    switch (language) +    { +        case lldb::eLanguageTypeObjC: +            return new ObjCLanguage(); +        default: +            return nullptr; +    } +} + +void +ObjCLanguage::MethodName::Clear() +{ +    m_full.Clear(); +    m_class.Clear(); +    m_category.Clear(); +    m_selector.Clear(); +    m_type = eTypeUnspecified; +    m_category_is_valid = false; +} + +bool +ObjCLanguage::MethodName::SetName (const char *name, bool strict) +{ +    Clear(); +    if (name && name[0]) +    { +        // If "strict" is true. then the method must be specified with a +        // '+' or '-' at the beginning. If "strict" is false, then the '+' +        // or '-' can be omitted +        bool valid_prefix = false; +         +        if (name[0] == '+' || name[0] == '-') +        { +            valid_prefix = name[1] == '['; +            if (name[0] == '+') +                m_type = eTypeClassMethod; +            else +                m_type = eTypeInstanceMethod; +        } +        else if (!strict) +        { +            // "strict" is false, the name just needs to start with '[' +            valid_prefix = name[0] == '['; +        } +         +        if (valid_prefix) +        { +            int name_len = strlen (name); +            // Objective C methods must have at least: +            //      "-[" or "+[" prefix +            //      One character for a class name +            //      One character for the space between the class name +            //      One character for the method name +            //      "]" suffix +            if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']') +            { +                m_full.SetCStringWithLength(name, name_len); +            } +        } +    } +    return IsValid(strict); +} + +const ConstString & +ObjCLanguage::MethodName::GetClassName () +{ +    if (!m_class) +    { +        if (IsValid(false)) +        { +            const char *full = m_full.GetCString(); +            const char *class_start = (full[0] == '[' ? full + 1 : full + 2); +            const char *paren_pos = strchr (class_start, '('); +            if (paren_pos) +            { +                m_class.SetCStringWithLength (class_start, paren_pos - class_start); +            } +            else +            { +                // No '(' was found in the full name, we can definitively say +                // that our category was valid (and empty). +                m_category_is_valid = true; +                const char *space_pos = strchr (full, ' '); +                if (space_pos) +                { +                    m_class.SetCStringWithLength (class_start, space_pos - class_start); +                    if (!m_class_category) +                    { +                        // No category in name, so we can also fill in the m_class_category +                        m_class_category = m_class; +                    } +                } +            } +        } +    } +    return m_class; +} + +const ConstString & +ObjCLanguage::MethodName::GetClassNameWithCategory ()  +{ +    if (!m_class_category) +    { +        if (IsValid(false)) +        { +            const char *full = m_full.GetCString(); +            const char *class_start = (full[0] == '[' ? full + 1 : full + 2); +            const char *space_pos = strchr (full, ' '); +            if (space_pos) +            { +                m_class_category.SetCStringWithLength (class_start, space_pos - class_start); +                // If m_class hasn't been filled in and the class with category doesn't +                // contain a '(', then we can also fill in the m_class +                if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL) +                { +                    m_class = m_class_category; +                    // No '(' was found in the full name, we can definitively say +                    // that our category was valid (and empty). +                    m_category_is_valid = true; + +                } +            } +        } +    } +    return m_class_category; +} + +const ConstString & +ObjCLanguage::MethodName::GetSelector () +{ +    if (!m_selector) +    { +        if (IsValid(false)) +        { +            const char *full = m_full.GetCString(); +            const char *space_pos = strchr (full, ' '); +            if (space_pos) +            { +                ++space_pos; // skip the space +                m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1); +            } +        } +    } +    return m_selector; +} + +const ConstString & +ObjCLanguage::MethodName::GetCategory () +{ +    if (!m_category_is_valid && !m_category) +    { +        if (IsValid(false)) +        { +            m_category_is_valid = true; +            const char *full = m_full.GetCString(); +            const char *class_start = (full[0] == '[' ? full + 1 : full + 2); +            const char *open_paren_pos = strchr (class_start, '('); +            if (open_paren_pos) +            { +                ++open_paren_pos; // Skip the open paren +                const char *close_paren_pos = strchr (open_paren_pos, ')'); +                if (close_paren_pos) +                    m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos); +            } +        } +    } +    return m_category; +} + +ConstString +ObjCLanguage::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category) +{ +    if (IsValid(false)) +    { +        if (HasCategory()) +        { +            StreamString strm; +            if (m_type == eTypeClassMethod) +                strm.PutChar('+'); +            else if (m_type == eTypeInstanceMethod) +                strm.PutChar('-'); +            strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString()); +            return ConstString(strm.GetString().c_str()); +        } +         +        if (!empty_if_no_category) +        { +            // Just return the full name since it doesn't have a category +            return GetFullName(); +        } +    } +    return ConstString(); +} + +size_t +ObjCLanguage::MethodName::GetFullNames (std::vector<ConstString> &names, bool append) +{ +    if (!append) +        names.clear(); +    if (IsValid(false)) +    { +        StreamString strm; +        const bool is_class_method = m_type == eTypeClassMethod; +        const bool is_instance_method = m_type == eTypeInstanceMethod; +        const ConstString &category = GetCategory(); +        if (is_class_method || is_instance_method) +        { +            names.push_back (m_full); +            if (category) +            { +                strm.Printf("%c[%s %s]", +                            is_class_method ? '+' : '-', +                            GetClassName().GetCString(), +                            GetSelector().GetCString()); +                names.push_back(ConstString(strm.GetString().c_str())); +            } +        } +        else +        { +            const ConstString &class_name = GetClassName(); +            const ConstString &selector = GetSelector(); +            strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString()); +            names.push_back(ConstString(strm.GetString().c_str())); +            strm.Clear(); +            strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString()); +            names.push_back(ConstString(strm.GetString().c_str())); +            strm.Clear(); +            if (category) +            { +                strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); +                names.push_back(ConstString(strm.GetString().c_str())); +                strm.Clear(); +                strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString()); +                names.push_back(ConstString(strm.GetString().c_str())); +            } +        } +    } +    return names.size(); +} + +static void +LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) +{ +    if (!objc_category_sp) +        return; +     +    TypeSummaryImpl::Flags objc_flags; +    objc_flags.SetCascades(false) +    .SetSkipPointers(true) +    .SetSkipReferences(true) +    .SetDontShowChildren(true) +    .SetDontShowValue(true) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +    lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,"")); +    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"), +                                                       ObjC_BOOL_summary); +    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"), +                                                       ObjC_BOOL_summary); +    objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"), +                                                       ObjC_BOOL_summary); +     +#ifndef LLDB_DISABLE_PYTHON +    // we need to skip pointers here since we are special casing a SEL* when retrieving its value +    objc_flags.SetSkipPointers(true); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("SEL"), objc_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("struct objc_selector"), objc_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("objc_selector"), objc_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("objc_selector *"), objc_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("SEL *"), objc_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags); +     +    SyntheticChildren::Flags class_synth_flags; +    class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags); +#endif // LLDB_DISABLE_PYTHON +     +    objc_flags.SetSkipPointers(false); +    objc_flags.SetCascades(true); +    objc_flags.SetSkipReferences(false); +     +    AddStringSummary (objc_category_sp, +                      "${var.__FuncPtr%A}", +                      ConstString("__block_literal_generic"), +                      objc_flags); +     +    AddStringSummary(objc_category_sp, +                     "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds", +                     ConstString("CFGregorianUnits"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "location=${var.location} length=${var.length}", +                     ConstString("CFRange"), +                     objc_flags); +     +    AddStringSummary(objc_category_sp, +                     "location=${var.location}, length=${var.length}", +                     ConstString("NSRange"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "(${var.origin}, ${var.size}), ...", +                     ConstString("NSRectArray"), +                     objc_flags); +     +    AddOneLineSummary (objc_category_sp, +                       ConstString("NSPoint"), +                       objc_flags); +    AddOneLineSummary (objc_category_sp, +                       ConstString("NSSize"), +                       objc_flags); +    AddOneLineSummary (objc_category_sp, +                       ConstString("NSRect"), +                       objc_flags); +     +    AddOneLineSummary (objc_category_sp, +                       ConstString("CGSize"), +                       objc_flags); +    AddOneLineSummary (objc_category_sp, +                       ConstString("CGPoint"), +                       objc_flags); +    AddOneLineSummary (objc_category_sp, +                       ConstString("CGRect"), +                       objc_flags); +     +    AddStringSummary(objc_category_sp, +                     "red=${var.red} green=${var.green} blue=${var.blue}", +                     ConstString("RGBColor"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})", +                     ConstString("Rect"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "{(v=${var.v}, h=${var.h})}", +                     ConstString("Point"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "${var.month}/${var.day}/${var.year}  ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}", +                     ConstString("DateTimeRect *"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}", +                     ConstString("LongDateRect"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "(x=${var.x}, y=${var.y})", +                     ConstString("HIPoint"), +                     objc_flags); +    AddStringSummary(objc_category_sp, +                     "origin=${var.origin} size=${var.size}", +                     ConstString("HIRect"), +                     objc_flags); +     +    TypeSummaryImpl::Flags appkit_flags; +    appkit_flags.SetCascades(true) +    .SetSkipPointers(false) +    .SetSkipReferences(false) +    .SetDontShowChildren(true) +    .SetDontShowValue(false) +    .SetShowMembersOneLiner(false) +    .SetHideItemNames(false); +     +    appkit_flags.SetDontShowChildren(false); +     +#ifndef LLDB_DISABLE_PYTHON +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArray0"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSError_SummaryProvider, "NSError summary provider", ConstString("NSError"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSException_SummaryProvider, "NSException summary provider", ConstString("NSException"), appkit_flags); +     +    // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags); +     +    appkit_flags.SetDontShowChildren(true); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArray0"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags()); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags()); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSErrorSyntheticFrontEndCreator, "NSError synthetic children", ConstString("NSError"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, "NSException synthetic children", ConstString("NSException"), ScriptedSyntheticChildren::Flags()); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags()); +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags()); +     +    AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags()); +     +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags); +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags); +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags); +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags); +     +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags); +    AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags); +     +    AddStringSummary(objc_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags); +    AddStringSummary(objc_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags); +     +    // CFAbsoluteTime is actually a double rather than a pointer to an object +    // we do not care about the numeric value, since it is probably meaningless to users +    appkit_flags.SetDontShowValue(true); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags); +    appkit_flags.SetDontShowValue(false); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags); +     +    AddStringSummary(objc_category_sp, +                     "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"", +                     ConstString("CFGregorianDate"), +                     appkit_flags); +     +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags); +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags); +#endif // LLDB_DISABLE_PYTHON +} + +static void +LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp) +{ +    if (!objc_category_sp) +        return; + +    TypeSummaryImpl::Flags cm_flags; +    cm_flags.SetCascades(true) +    .SetDontShowChildren(false) +    .SetDontShowValue(false) +    .SetHideItemNames(false) +    .SetShowMembersOneLiner(false) +    .SetSkipPointers(false) +    .SetSkipReferences(false); +     +#ifndef LLDB_DISABLE_PYTHON +    AddCXXSummary(objc_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags); +#endif // LLDB_DISABLE_PYTHON +} + +lldb::TypeCategoryImplSP +ObjCLanguage::GetFormatters () +{ +    static std::once_flag g_initialize; +    static TypeCategoryImplSP g_category; +     +    std::call_once(g_initialize, [this] () -> void { +        DataVisualization::Categories::GetCategory(GetPluginName(), g_category); +        if (g_category) +        { +            LoadCoreMediaFormatters(g_category); +            LoadObjCFormatters(g_category); +        } +    }); +    return g_category; +} + +std::vector<ConstString> +ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) +{ +    std::vector<ConstString> result; +     +    if (use_dynamic == lldb::eNoDynamicValues) +        return result; +     +    CompilerType compiler_type(valobj.GetCompilerType()); +     +    const bool check_cpp = false; +    const bool check_objc = true; +    bool canBeObjCDynamic = compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc); +     +    if (canBeObjCDynamic) +    { +        do { +            lldb::ProcessSP process_sp = valobj.GetProcessSP(); +            if (!process_sp) +                break; +            ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); +            if (runtime == nullptr) +                break; +            ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj)); +            if (!objc_class_sp) +                break; +            if (ConstString name = objc_class_sp->GetClassName()) +                result.push_back(name); +        } while (false); +    } +     +    return result; +} + +std::unique_ptr<Language::TypeScavenger> +ObjCLanguage::GetTypeScavenger () +{ +    class ObjCTypeScavenger : public Language::TypeScavenger +    { +    private: +        class ObjCScavengerResult : public Language::TypeScavenger::Result +        { +        public: +            ObjCScavengerResult (CompilerType type) : +                Language::TypeScavenger::Result(), +                m_compiler_type(type) +            { +            } +             +            bool +            IsValid () override +            { +                return m_compiler_type.IsValid(); +            } +             +            bool +            DumpToStream (Stream& stream, +                          bool print_help_if_available) override +            { +                if (IsValid()) +                { +                    m_compiler_type.DumpTypeDescription(&stream); +                    stream.EOL(); +                    return true; +                } +                return false; +            } + +            ~ObjCScavengerResult() override = default; + +        private: +            CompilerType m_compiler_type; +        }; +         +    protected: +        ObjCTypeScavenger() = default; +         +        ~ObjCTypeScavenger() override = default; +         +        bool +        Find_Impl (ExecutionContextScope *exe_scope, +                   const char *key, +                   ResultSet &results) override +        { +            bool result = false; +             +            Target* target = exe_scope->CalculateTarget().get(); +            if (target) +            { +                if (auto clang_modules_decl_vendor = target->GetClangModulesDeclVendor()) +                { +                    std::vector <clang::NamedDecl*> decls; +                    ConstString key_cs(key); +                     +                    if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, decls) > 0 && +                        decls.size() > 0) +                    { +                        CompilerType module_type = ClangASTContext::GetTypeForDecl(decls.front()); +                        result = true; +                        std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(module_type)); +                        results.insert(std::move(result)); +                    } +                } +            } +             +            if (!result) +            { +                Process* process = exe_scope->CalculateProcess().get(); +                if (process) +                { +                    const bool create_on_demand = false; +                    auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand); +                    if (objc_runtime) +                    { +                        auto decl_vendor = objc_runtime->GetDeclVendor(); +                        if (decl_vendor) +                        { +                            std::vector<clang::NamedDecl *> decls; +                            ConstString name(key); +                            decl_vendor->FindDecls(name, true, UINT32_MAX, decls); +                            for (auto decl : decls) +                            { +                                if (decl) +                                { +                                    if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl)) +                                    { +                                        result = true; +                                        std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate)); +                                        results.insert(std::move(result)); +                                    } +                                } +                            } +                        } +                    } +                } +            } + +            return result; +        } + +        friend class lldb_private::ObjCLanguage; +    }; +     +    return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger()); +} + +bool +ObjCLanguage::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint, +                                        std::string& prefix, std::string& suffix) +{ +    static ConstString g_CFBag("CFBag"); +    static ConstString g_CFBinaryHeap("CFBinaryHeap"); +     +    static ConstString g_NSNumberChar("NSNumber:char"); +    static ConstString g_NSNumberShort("NSNumber:short"); +    static ConstString g_NSNumberInt("NSNumber:int"); +    static ConstString g_NSNumberLong("NSNumber:long"); +    static ConstString g_NSNumberFloat("NSNumber:float"); +    static ConstString g_NSNumberDouble("NSNumber:double"); +     +    static ConstString g_NSData("NSData"); +    static ConstString g_NSArray("NSArray"); +    static ConstString g_NSString("NSString"); +    static ConstString g_NSStringStar("NSString*"); +     +    if (type_hint.IsEmpty()) +        return false; +     +    prefix.clear(); +    suffix.clear(); +     +    if (type_hint == g_CFBag || +        type_hint == g_CFBinaryHeap) +    { +        prefix = "@"; +        return true; +    } +     +    if (type_hint == g_NSNumberChar) +    { +        prefix = "(char)"; +        return true; +    } +    if (type_hint == g_NSNumberShort) +    { +        prefix = "(short)"; +        return true; +    } +    if (type_hint == g_NSNumberInt) +    { +        prefix = "(int)"; +        return true; +    } +    if (type_hint == g_NSNumberLong) +    { +        prefix = "(long)"; +        return true; +    } +    if (type_hint == g_NSNumberFloat) +    { +        prefix = "(float)"; +        return true; +    } +    if (type_hint == g_NSNumberDouble) +    { +        prefix = "(double)"; +        return true; +    } +     +    if (type_hint == g_NSData || +        type_hint == g_NSArray) +    { +        prefix = "@\""; +        suffix = "\""; +        return true; +    } +     +    if (type_hint == g_NSString || +        type_hint == g_NSStringStar) +    { +        prefix = "@"; +        return true; +    } +     +    return false; +} + +bool +ObjCLanguage::IsNilReference (ValueObject& valobj) +{ +    const uint32_t mask = eTypeIsObjC | eTypeIsPointer; +    bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask); +    if (!isObjCpointer) +        return false; +    bool canReadValue = true; +    bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0; +    return canReadValue && isZero; +} diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.h b/source/Plugins/Language/ObjC/ObjCLanguage.h new file mode 100644 index 0000000000000..e30aa18c0443d --- /dev/null +++ b/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -0,0 +1,210 @@ +//===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ObjCLanguage_h_ +#define liblldb_ObjCLanguage_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Target/Language.h" + +namespace lldb_private { +     +class ObjCLanguage : +    public Language +{ +public: +    class MethodName +    { +    public: +        enum Type +        { +            eTypeUnspecified, +            eTypeClassMethod, +            eTypeInstanceMethod +        }; +         +        MethodName () : +            m_full(), +            m_class(), +            m_category(), +            m_selector(), +            m_type (eTypeUnspecified), +            m_category_is_valid (false) +        { +        } + +        MethodName (const char *name, bool strict) : +            m_full(), +            m_class(), +            m_category(), +            m_selector(), +            m_type (eTypeUnspecified), +            m_category_is_valid (false) +        { +            SetName (name, strict); +        } + +        void +        Clear(); + +        bool +        IsValid (bool strict) const +        { +            // If "strict" is true, the name must have everything specified including +            // the leading "+" or "-" on the method name +            if (strict && m_type == eTypeUnspecified) +                return false; +            // Other than that, m_full will only be filled in if the objective C +            // name is valid. +            return (bool)m_full; +        } +         +        bool +        HasCategory() +        { +            return !GetCategory().IsEmpty(); +        } + +        Type +        GetType () const +        { +            return m_type; +        } +         +        const ConstString & +        GetFullName () const +        { +            return m_full; +        } +         +        ConstString +        GetFullNameWithoutCategory (bool empty_if_no_category); + +        bool +        SetName (const char *name, bool strict); + +        const ConstString & +        GetClassName (); + +        const ConstString & +        GetClassNameWithCategory (); + +        const ConstString & +        GetCategory (); +         +        const ConstString & +        GetSelector (); + +        // Get all possible names for a method. Examples: +        // If name is "+[NSString(my_additions) myStringWithCString:]" +        //  names[0] => "+[NSString(my_additions) myStringWithCString:]" +        //  names[1] => "+[NSString myStringWithCString:]" +        // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]" +        //  names[0] => "+[NSString(my_additions) myStringWithCString:]" +        //  names[1] => "-[NSString(my_additions) myStringWithCString:]" +        //  names[2] => "+[NSString myStringWithCString:]" +        //  names[3] => "-[NSString myStringWithCString:]" +        size_t +        GetFullNames (std::vector<ConstString> &names, bool append); + +    protected: +        ConstString m_full;     // Full name:   "+[NSString(my_additions) myStringWithCString:]" +        ConstString m_class;    // Class name:  "NSString" +        ConstString m_class_category; // Class with category: "NSString(my_additions)" +        ConstString m_category; // Category:    "my_additions" +        ConstString m_selector; // Selector:    "myStringWithCString:" +        Type m_type; +        bool m_category_is_valid; +    }; + +    ObjCLanguage() = default; + +    ~ObjCLanguage() override = default; + +    lldb::LanguageType +    GetLanguageType () const override +    { +        return lldb::eLanguageTypeObjC; +    } +     +    lldb::TypeCategoryImplSP +    GetFormatters () override; +     +    std::vector<ConstString> +    GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override; +     +    std::unique_ptr<TypeScavenger> +    GetTypeScavenger () override; +     +    bool +    GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint, +                              std::string& prefix, std::string& suffix) override; +     +    bool +    IsNilReference (ValueObject& valobj) override; +     +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void +    Initialize(); +     +    static void +    Terminate(); +     +    static lldb_private::Language * +    CreateInstance (lldb::LanguageType language); +     +    static lldb_private::ConstString +    GetPluginNameStatic(); +     +    static bool +    IsPossibleObjCMethodName (const char *name) +    { +        if (!name) +            return false; +        bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; +        bool ends_right = (name[strlen(name) - 1] == ']'); +        return (starts_right && ends_right); +    } +     +    static bool +    IsPossibleObjCSelector (const char *name) +    { +        if (!name) +            return false; +             +        if (strchr(name, ':') == NULL) +            return true; +        else if (name[strlen(name) - 1] == ':') +            return true; +        else +            return false; +    } +     +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    ConstString +    GetPluginName() override; +     +    uint32_t +    GetPluginVersion() override; +}; +     +} // namespace lldb_private + +#endif // liblldb_ObjCLanguage_h_ diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp new file mode 100644 index 0000000000000..62ddafefad97d --- /dev/null +++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp @@ -0,0 +1,68 @@ +//===-- ObjCPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ObjCPlusPlusLanguage.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" + +using namespace lldb; +using namespace lldb_private; + +void +ObjCPlusPlusLanguage::Initialize() +{ +    PluginManager::RegisterPlugin (GetPluginNameStatic(), +                                   "Objective-C++ Language", +                                   CreateInstance); +} + +void +ObjCPlusPlusLanguage::Terminate() +{ +    PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +ObjCPlusPlusLanguage::GetPluginNameStatic() +{ +    static ConstString g_name("objcplusplus"); +    return g_name; +} + + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +ObjCPlusPlusLanguage::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +ObjCPlusPlusLanguage::GetPluginVersion() +{ +    return 1; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +Language * +ObjCPlusPlusLanguage::CreateInstance (lldb::LanguageType language) +{ +    switch (language) +    { +        case lldb::eLanguageTypeObjC_plus_plus: +            return new ObjCPlusPlusLanguage(); +        default: +            return nullptr; +    } +} diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h new file mode 100644 index 0000000000000..0e1db66b08995 --- /dev/null +++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h @@ -0,0 +1,63 @@ +//===-- ObjCPlusPlusLanguage.h ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ObjCPlusPlusLanguage_h_ +#define liblldb_ObjCPlusPlusLanguage_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/Language.h" + +namespace lldb_private { +     +class ObjCPlusPlusLanguage : +    public Language +{ +public: +    ObjCPlusPlusLanguage() = default; + +    ~ObjCPlusPlusLanguage() override = default; + +    lldb::LanguageType +    GetLanguageType() const override +    { +        return lldb::eLanguageTypeObjC_plus_plus; +    } +     +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void +    Initialize(); +     +    static void +    Terminate(); +     +    static lldb_private::Language * +    CreateInstance (lldb::LanguageType language); +     +    static lldb_private::ConstString +    GetPluginNameStatic(); +     +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    ConstString +    GetPluginName() override; +     +    uint32_t +    GetPluginVersion() override; +}; +     +} // namespace lldb_private + +#endif // liblldb_CPlusPlusLanguage_h_ diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 3a3878ef09a1a..a5fa004493a2a 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -40,14 +40,15 @@ ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)  {      const bool check_cxx = true;      const bool check_objc = false; -    return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc); +    return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);  }  bool  ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,                                                        lldb::DynamicValueType use_dynamic,                                                        TypeAndOrName &class_type_or_name,  -                                                     Address &dynamic_address) +                                                     Address &dynamic_address, +                                                     Value::ValueType &value_type)  {      // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0      // in the object.  That will point to the "address point" within the vtable (not the beginning of the @@ -58,6 +59,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,      //      class_type_or_name.Clear(); +    value_type = Value::ValueType::eValueTypeScalar;      // Only a pointer or reference type can have a different dynamic and static type:      if (CouldHaveDynamicValue (in_value)) @@ -189,7 +191,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,                                  type_sp = class_types.GetTypeAtIndex(i);                                  if (type_sp)                                  { -                                    if (type_sp->GetClangFullType().IsCXXClassType()) +                                    if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ()))                                      {                                          if (log)                                              log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n", @@ -221,8 +223,8 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,                          // the value we were handed.                          if (type_sp)                          { -                            if (ClangASTContext::AreTypesSame (in_value.GetClangType(), -                                                               type_sp->GetClangFullType())) +                            if (ClangASTContext::AreTypesSame (in_value.GetCompilerType(), +                                                               type_sp->GetFullCompilerType ()))                              {                                  // The dynamic type we found was the same type,                                  // so we don't have a dynamic type here... @@ -268,6 +270,42 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,      return class_type_or_name.IsEmpty() == false;  } +TypeAndOrName +ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name, +                                            ValueObject& static_value) +{ +    CompilerType static_type(static_value.GetCompilerType()); +    Flags static_type_flags(static_type.GetTypeInfo()); +     +    TypeAndOrName ret(type_and_or_name); +    if (type_and_or_name.HasType()) +    { +        // The type will always be the type of the dynamic object.  If our parent's type was a pointer, +        // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type +        // should be okay... +        CompilerType orig_type = type_and_or_name.GetCompilerType(); +        CompilerType corrected_type = orig_type; +        if (static_type_flags.AllSet(eTypeIsPointer)) +            corrected_type = orig_type.GetPointerType (); +        else if (static_type_flags.AllSet(eTypeIsReference)) +            corrected_type = orig_type.GetLValueReferenceType(); +        ret.SetCompilerType(corrected_type); +    } +    else +    { +        // If we are here we need to adjust our dynamic type name to include the correct & or * symbol +        std::string corrected_name (type_and_or_name.GetName().GetCString()); +        if (static_type_flags.AllSet(eTypeIsPointer)) +            corrected_name.append(" *"); +        else if (static_type_flags.AllSet(eTypeIsReference)) +            corrected_name.append(" &"); +        // the parent type should be a correctly pointer'ed or referenc'ed type +        ret.SetCompilerType(static_type); +        ret.SetName(corrected_name.c_str()); +    } +    return ret; +} +  bool  ItaniumABILanguageRuntime::IsVTableName (const char *name)  { @@ -420,6 +458,7 @@ ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch                                                                    exception_names.data(),                                                                    exception_names.size(),                                                                    eFunctionNameTypeBase, +                                                                  eLanguageTypeUnknown,                                                                    eLazyBoolNo));      return resolver_sp; diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index bc5d83be4bf57..519a3cee36d6a 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -1,4 +1,4 @@ -//===-- ItaniumABILanguageRuntime.h ----------------------------------------*- C++ -*-===// +//===-- ItaniumABILanguageRuntime.h -----------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -12,6 +12,8 @@  // C Includes  // C++ Includes +#include <vector> +  // Other libraries and framework includes  // Project includes  #include "lldb/lldb-private.h" @@ -20,28 +22,13 @@  #include "lldb/Target/CPPLanguageRuntime.h"  #include "lldb/Core/Value.h" -#include <map> -#include <vector> -  namespace lldb_private {      class ItaniumABILanguageRuntime :      public lldb_private::CPPLanguageRuntime      {      public: -        ~ItaniumABILanguageRuntime() { } -         -        virtual bool -        IsVTableName (const char *name); -         -        virtual bool -        GetDynamicTypeAndAddress (ValueObject &in_value,  -                                  lldb::DynamicValueType use_dynamic,  -                                  TypeAndOrName &class_type_or_name,  -                                  Address &address); -         -        virtual bool -        CouldHaveDynamicValue (ValueObject &in_value); +        ~ItaniumABILanguageRuntime() override = default;          //------------------------------------------------------------------          // Static Functions @@ -58,38 +45,54 @@ namespace lldb_private {          static lldb_private::ConstString          GetPluginNameStatic(); -        //------------------------------------------------------------------ -        // PluginInterface protocol -        //------------------------------------------------------------------ -        virtual lldb_private::ConstString -        GetPluginName(); +        bool +        IsVTableName(const char *name) override; -        virtual uint32_t -        GetPluginVersion(); +        bool +        GetDynamicTypeAndAddress(ValueObject &in_value, +                                 lldb::DynamicValueType use_dynamic, +                                 TypeAndOrName &class_type_or_name, +                                 Address &address, +                                 Value::ValueType &value_type) override; -        virtual void -        SetExceptionBreakpoints (); +        TypeAndOrName +        FixUpDynamicType(const TypeAndOrName& type_and_or_name, +                         ValueObject& static_value) override; -        virtual void -        ClearExceptionBreakpoints (); +        bool +        CouldHaveDynamicValue(ValueObject &in_value) override; -        virtual bool -        ExceptionBreakpointsAreSet (); +        void +        SetExceptionBreakpoints() override; -        virtual bool -        ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason); +        void +        ClearExceptionBreakpoints() override; +         +        bool +        ExceptionBreakpointsAreSet() override; +         +        bool +        ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override; -        virtual lldb::BreakpointResolverSP -        CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp); +        lldb::BreakpointResolverSP +        CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override; -        virtual lldb::SearchFilterSP -        CreateExceptionSearchFilter (); +        lldb::SearchFilterSP +        CreateExceptionSearchFilter() override; -        virtual size_t -        GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates); +        size_t +        GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override; -    protected: +        //------------------------------------------------------------------ +        // PluginInterface protocol +        //------------------------------------------------------------------ +        lldb_private::ConstString +        GetPluginName() override; +         +        uint32_t +        GetPluginVersion() override; +    protected:          lldb::BreakpointResolverSP          CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions); @@ -107,4 +110,4 @@ namespace lldb_private {  } // namespace lldb_private -#endif  // liblldb_ItaniumABILanguageRuntime_h_ +#endif // liblldb_ItaniumABILanguageRuntime_h_ diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp new file mode 100644 index 0000000000000..d59f292e7a08c --- /dev/null +++ b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp @@ -0,0 +1,238 @@ +//===-- GoLanguageRuntime.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "GoLanguageRuntime.h" + +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "llvm/ADT/Twine.h" + +#include <vector> + +using namespace lldb; +using namespace lldb_private; + +namespace { +ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) { +    ConstString name_const_str(name); +    ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true); +    if (dereference && result && result->IsPointerType()) { +        Error err; +        result = result->Dereference(err); +        if (err.Fail()) +            result.reset(); +    } +    return result; +} + +ConstString ReadString(ValueObject& str, Process* process) { +    ConstString result; +    ValueObjectSP data = GetChild(str, "str", false); +    ValueObjectSP len = GetChild(str, "len"); +    if (len && data) +    { +        Error err; +        lldb::addr_t addr = data->GetPointerValue(); +        if (addr == LLDB_INVALID_ADDRESS) +            return result; +        uint64_t byte_size = len->GetValueAsUnsigned(0); +        char* buf = new char[byte_size + 1]; +        buf[byte_size] = 0; +        size_t bytes_read = process->ReadMemory (addr, +                                                 buf, +                                                 byte_size, +                                                 err); +        if (!(err.Fail() || bytes_read != byte_size)) +            result = ConstString(buf, bytes_read); +        delete[] buf; +    } +    return result; +} + +ConstString +ReadTypeName(ValueObjectSP type, Process* process) +{ +    if (ValueObjectSP uncommon = GetChild(*type, "x")) +    { +        ValueObjectSP name = GetChild(*uncommon, "name"); +        ValueObjectSP package = GetChild(*uncommon, "pkgpath"); +        if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0) +        { +            ConstString package_const_str = ReadString(*package, process); +            ConstString name_const_str = ReadString(*name, process); +            if (package_const_str.GetLength() == 0) +                return name_const_str; +            return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str()); +        } +    } +    ValueObjectSP name = GetChild(*type, "_string"); +    if (name) +        return ReadString(*name, process); +    return ConstString(""); +} + +CompilerType +LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct) +{ +    uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0); +    *is_direct = GoASTContext::IsDirectIface(kind); +    if (GoASTContext::IsPointerKind(kind)) +    { +        CompilerType type_ptr = type->GetCompilerType().GetPointerType(); +        Error err; +        ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err); +        if (err.Fail()) +            return CompilerType(); +        bool tmp_direct; +        return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType(); +    } +    Target *target = exe_ctx->GetTargetPtr(); +    Process *process = exe_ctx->GetProcessPtr(); +     +    ConstString const_typename = ReadTypeName(type, process); +    if (const_typename.GetLength() == 0) +        return CompilerType(); +     +    SymbolContext sc; +    TypeList type_list; +    uint32_t num_matches = target->GetImages().FindTypes (sc, +                                                          const_typename, +                                                          false, +                                                          2, +                                                          type_list); +    if (num_matches > 0) { +        return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); +    } +    return CompilerType(); +} + +} + +bool +GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) +{ +    return GoASTContext::IsGoInterface(in_value.GetCompilerType()); +} + +bool +GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, +                                            TypeAndOrName &class_type_or_name, Address &dynamic_address, +                                            Value::ValueType &value_type) +{ +    value_type = Value::eValueTypeScalar; +    class_type_or_name.Clear(); +    if (CouldHaveDynamicValue (in_value)) +    { +        Error err; +        ValueObjectSP iface = in_value.GetStaticValue(); +        ValueObjectSP data_sp = GetChild(*iface, "data", false); +        if (!data_sp) +            return false; + +        if (ValueObjectSP tab = GetChild(*iface, "tab")) +            iface = tab; +        ValueObjectSP type = GetChild(*iface, "_type"); +        if (!type) +        { +            return false; +        } +         +        bool direct; +        ExecutionContext exe_ctx (in_value.GetExecutionContextRef()); +        CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct); +        if (!final_type) +            return false; +        if (direct) +        { +            class_type_or_name.SetCompilerType(final_type); +        } +        else +        { +            // TODO: implement reference types or fix caller to support dynamic types that aren't pointers +            // so we don't have to introduce this extra pointer. +            class_type_or_name.SetCompilerType(final_type.GetPointerType()); +        } + +        dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr()); + +        return true; +    } +    return false; +} + +TypeAndOrName +GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) +{ +    return type_and_or_name; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ +LanguageRuntime * +GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) +{ +    if (language == eLanguageTypeGo) +        return new GoLanguageRuntime (process); +    else +        return NULL; +} + +void +GoLanguageRuntime::Initialize() +{ +    PluginManager::RegisterPlugin (GetPluginNameStatic(), +                                   "Go Language Runtime", +                                   CreateInstance); +} + +void +GoLanguageRuntime::Terminate() +{ +    PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +GoLanguageRuntime::GetPluginNameStatic() +{ +    static ConstString g_name("golang"); +    return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +lldb_private::ConstString +GoLanguageRuntime::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +GoLanguageRuntime::GetPluginVersion() +{ +    return 1; +} + diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h new file mode 100644 index 0000000000000..596d2888dc856 --- /dev/null +++ b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h @@ -0,0 +1,93 @@ +//===-- GoLanguageRuntime.h -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoLanguageRuntime_h_ +#define liblldb_GoLanguageRuntime_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/Core/Value.h" + +namespace lldb_private { +     +    class GoLanguageRuntime : +    public lldb_private::LanguageRuntime +    { +    public: +        ~GoLanguageRuntime() override = default; + +        //------------------------------------------------------------------ +        // Static Functions +        //------------------------------------------------------------------ +        static void +        Initialize(); +         +        static void +        Terminate(); +         +        static lldb_private::LanguageRuntime * +        CreateInstance(Process *process, lldb::LanguageType language); +         +        static lldb_private::ConstString +        GetPluginNameStatic(); + +        lldb::LanguageType +        GetLanguageType() const override +        { +            return lldb::eLanguageTypeGo; +        } + +        bool +        GetObjectDescription(Stream &str, ValueObject &object) override +        { +            // TODO(ribrdb): Maybe call String() method? +            return false; +        } + +        bool +        GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override +        { +            return false; +        } + +        bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, +                                      TypeAndOrName &class_type_or_name, Address &address, +                                      Value::ValueType &value_type) override; + +        bool CouldHaveDynamicValue(ValueObject &in_value) override; + +        lldb::BreakpointResolverSP +        CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override +        { +            return lldb::BreakpointResolverSP(); +        } + +        TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override; + +        //------------------------------------------------------------------ +        // PluginInterface protocol +        //------------------------------------------------------------------ +        lldb_private::ConstString +        GetPluginName() override; +         +        uint32_t +        GetPluginVersion() override; +         +    private: +        GoLanguageRuntime(Process *process) : lldb_private::LanguageRuntime(process) { } // Call CreateInstance instead. +    }; +     +} // namespace lldb_private + +#endif // liblldb_GoLanguageRuntime_h_ diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 2490cf31409b6..149244df30c22 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -7,6 +7,10 @@  //  //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "RenderScriptRuntime.h"  #include "lldb/Core/ConstString.h" @@ -14,10 +18,15 @@  #include "lldb/Core/Error.h"  #include "lldb/Core/Log.h"  #include "lldb/Core/PluginManager.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/DataFormatters/DumpValueObjectOptions.h" +#include "lldb/Host/StringConvert.h"  #include "lldb/Symbol/Symbol.h"  #include "lldb/Symbol/Type.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h"  #include "lldb/Interpreter/Args.h"  #include "lldb/Interpreter/Options.h"  #include "lldb/Interpreter/CommandInterpreter.h" @@ -25,11 +34,350 @@  #include "lldb/Interpreter/CommandObjectMultiword.h"  #include "lldb/Breakpoint/StoppointCallbackContext.h"  #include "lldb/Target/RegisterContext.h" - +#include "lldb/Expression/UserExpression.h"  #include "lldb/Symbol/VariableList.h"  using namespace lldb;  using namespace lldb_private; +using namespace lldb_renderscript; + +namespace { + +// The empirical_type adds a basic level of validation to arbitrary data +// allowing us to track if data has been discovered and stored or not. +// An empirical_type will be marked as valid only if it has been explicitly assigned to. +template <typename type_t> +class empirical_type +{ +public: +    // Ctor. Contents is invalid when constructed. +    empirical_type() +        : valid(false) +    {} + +    // Return true and copy contents to out if valid, else return false. +    bool get(type_t& out) const +    { +        if (valid) +            out = data; +        return valid; +    } + +    // Return a pointer to the contents or nullptr if it was not valid. +    const type_t* get() const +    { +        return valid ? &data : nullptr; +    } + +    // Assign data explicitly. +    void set(const type_t in) +    { +        data = in; +        valid = true; +    } + +    // Mark contents as invalid. +    void invalidate() +    { +        valid = false; +    } + +    // Returns true if this type contains valid data. +    bool isValid() const +    { +        return valid; +    } + +    // Assignment operator. +    empirical_type<type_t>& operator = (const type_t in) +    { +        set(in); +        return *this; +    } + +    // Dereference operator returns contents. +    // Warning: Will assert if not valid so use only when you know data is valid. +    const type_t& operator * () const +    { +        assert(valid); +        return data; +    } + +protected: +    bool valid; +    type_t data; +}; + +} // anonymous namespace + +// The ScriptDetails class collects data associated with a single script instance. +struct RenderScriptRuntime::ScriptDetails +{ +    ~ScriptDetails() = default; + +    enum ScriptType +    { +        eScript, +        eScriptC +    }; + +    // The derived type of the script. +    empirical_type<ScriptType> type; +    // The name of the original source file. +    empirical_type<std::string> resName; +    // Path to script .so file on the device. +    empirical_type<std::string> scriptDyLib; +    // Directory where kernel objects are cached on device. +    empirical_type<std::string> cacheDir; +    // Pointer to the context which owns this script. +    empirical_type<lldb::addr_t> context; +    // Pointer to the script object itself. +    empirical_type<lldb::addr_t> script; +}; + +// This Element class represents the Element object in RS, +// defining the type associated with an Allocation. +struct RenderScriptRuntime::Element +{ +    // Taken from rsDefines.h +    enum DataKind +    { +        RS_KIND_USER, +        RS_KIND_PIXEL_L = 7, +        RS_KIND_PIXEL_A, +        RS_KIND_PIXEL_LA, +        RS_KIND_PIXEL_RGB, +        RS_KIND_PIXEL_RGBA, +        RS_KIND_PIXEL_DEPTH, +        RS_KIND_PIXEL_YUV, +        RS_KIND_INVALID = 100 +    }; + +    // Taken from rsDefines.h +    enum DataType +    { +        RS_TYPE_NONE = 0, +        RS_TYPE_FLOAT_16, +        RS_TYPE_FLOAT_32, +        RS_TYPE_FLOAT_64, +        RS_TYPE_SIGNED_8, +        RS_TYPE_SIGNED_16, +        RS_TYPE_SIGNED_32, +        RS_TYPE_SIGNED_64, +        RS_TYPE_UNSIGNED_8, +        RS_TYPE_UNSIGNED_16, +        RS_TYPE_UNSIGNED_32, +        RS_TYPE_UNSIGNED_64, +        RS_TYPE_BOOLEAN, + +        RS_TYPE_UNSIGNED_5_6_5, +        RS_TYPE_UNSIGNED_5_5_5_1, +        RS_TYPE_UNSIGNED_4_4_4_4, + +        RS_TYPE_MATRIX_4X4, +        RS_TYPE_MATRIX_3X3, +        RS_TYPE_MATRIX_2X2, + +        RS_TYPE_ELEMENT = 1000, +        RS_TYPE_TYPE, +        RS_TYPE_ALLOCATION, +        RS_TYPE_SAMPLER, +        RS_TYPE_SCRIPT, +        RS_TYPE_MESH, +        RS_TYPE_PROGRAM_FRAGMENT, +        RS_TYPE_PROGRAM_VERTEX, +        RS_TYPE_PROGRAM_RASTER, +        RS_TYPE_PROGRAM_STORE, +        RS_TYPE_FONT, + +        RS_TYPE_INVALID = 10000 +    }; + +    std::vector<Element> children;                       // Child Element fields for structs +    empirical_type<lldb::addr_t> element_ptr;            // Pointer to the RS Element of the Type +    empirical_type<DataType> type;                       // Type of each data pointer stored by the allocation +    empirical_type<DataKind> type_kind;                  // Defines pixel type if Allocation is created from an image +    empirical_type<uint32_t> type_vec_size;              // Vector size of each data point, e.g '4' for uchar4 +    empirical_type<uint32_t> field_count;                // Number of Subelements +    empirical_type<uint32_t> datum_size;                 // Size of a single Element with padding +    empirical_type<uint32_t> padding;                    // Number of padding bytes +    empirical_type<uint32_t> array_size;                 // Number of items in array, only needed for strucrs +    ConstString type_name;                               // Name of type, only needed for structs + +    static const ConstString &GetFallbackStructName();   // Print this as the type name of a struct Element +                                                         // If we can't resolve the actual struct name + +    bool shouldRefresh() const +    { +        const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0; +        const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid(); +        return !valid_ptr || !valid_type || !datum_size.isValid(); +    } +}; + +// This AllocationDetails class collects data associated with a single +// allocation instance. +struct RenderScriptRuntime::AllocationDetails +{ +    struct Dimension +    { +        uint32_t dim_1; +        uint32_t dim_2; +        uint32_t dim_3; +        uint32_t cubeMap; + +        Dimension() +        { +             dim_1 = 0; +             dim_2 = 0; +             dim_3 = 0; +             cubeMap = 0; +        } +    }; + +    // Header for reading and writing allocation contents +    // to a binary file. +    struct FileHeader +    { +        uint8_t ident[4];      // ASCII 'RSAD' identifying the file +        uint16_t hdr_size;     // Header size in bytes, for backwards compatability +        uint16_t type;         // DataType enum +        uint32_t kind;         // DataKind enum +        uint32_t dims[3];      // Dimensions +        uint32_t element_size; // Size of a single element, including padding +    }; + +    // Monotonically increasing from 1 +    static unsigned int ID; + +    // Maps Allocation DataType enum and vector size to printable strings +    // using mapping from RenderScript numerical types summary documentation +    static const char* RsDataTypeToString[][4]; + +    // Maps Allocation DataKind enum to printable strings +    static const char* RsDataKindToString[]; + +    // Maps allocation types to format sizes for printing. +    static const unsigned int RSTypeToFormat[][3]; + +    // Give each allocation an ID as a way +    // for commands to reference it. +    const unsigned int id; + +    RenderScriptRuntime::Element element;     // Allocation Element type +    empirical_type<Dimension> dimension;      // Dimensions of the Allocation +    empirical_type<lldb::addr_t> address;     // Pointer to address of the RS Allocation +    empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held by the Allocation +    empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type of the Allocation +    empirical_type<lldb::addr_t> context;     // Pointer to the RS Context of the Allocation +    empirical_type<uint32_t> size;            // Size of the allocation +    empirical_type<uint32_t> stride;          // Stride between rows of the allocation + +    // Give each allocation an id, so we can reference it in user commands. +    AllocationDetails(): id(ID++) +    { +    } + +    bool shouldRefresh() const +    { +        bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0; +        valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0; +        return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh(); +    } +}; + + +const ConstString & +RenderScriptRuntime::Element::GetFallbackStructName() +{ +    static const ConstString FallbackStructName("struct"); +    return FallbackStructName; +} + +unsigned int RenderScriptRuntime::AllocationDetails::ID = 1; + +const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = +{ +   "User", +   "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 +   "Undefined", "Undefined", "Undefined", +   "L Pixel", +   "A Pixel", +   "LA Pixel", +   "RGB Pixel", +   "RGBA Pixel", +   "Pixel Depth", +   "YUV Pixel" +}; + +const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = +{ +    {"None", "None", "None", "None"}, +    {"half", "half2", "half3", "half4"}, +    {"float", "float2", "float3", "float4"}, +    {"double", "double2", "double3", "double4"}, +    {"char", "char2", "char3", "char4"}, +    {"short", "short2", "short3", "short4"}, +    {"int", "int2", "int3", "int4"}, +    {"long", "long2", "long3", "long4"}, +    {"uchar", "uchar2", "uchar3", "uchar4"}, +    {"ushort", "ushort2", "ushort3", "ushort4"}, +    {"uint", "uint2", "uint3", "uint4"}, +    {"ulong", "ulong2", "ulong3", "ulong4"}, +    {"bool", "bool2", "bool3", "bool4"}, +    {"packed_565", "packed_565", "packed_565", "packed_565"}, +    {"packed_5551", "packed_5551", "packed_5551", "packed_5551"}, +    {"packed_4444", "packed_4444", "packed_4444", "packed_4444"}, +    {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"}, +    {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"}, +    {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"}, + +    // Handlers +    {"RS Element", "RS Element", "RS Element", "RS Element"}, +    {"RS Type", "RS Type", "RS Type", "RS Type"}, +    {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"}, +    {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"}, +    {"RS Script", "RS Script", "RS Script", "RS Script"}, + +    // Deprecated +    {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"}, +    {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"}, +    {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"}, +    {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"}, +    {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"}, +    {"RS Font", "RS Font", "RS Font", "RS Font"} +}; + +// Used as an index into the RSTypeToFormat array elements +enum TypeToFormatIndex { +   eFormatSingle = 0, +   eFormatVector, +   eElementSize +}; + +// { format enum of single element, format enum of element vector, size of element} +const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = +{ +    {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE +    {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16 +    {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32 +    {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64 +    {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8 +    {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16 +    {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32 +    {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64 +    {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8 +    {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16 +    {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32 +    {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64 +    {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL +    {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5 +    {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1 +    {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4 +    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4 +    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3 +    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2 +};  //------------------------------------------------------------------  // Static Functions @@ -44,6 +392,47 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag          return NULL;  } +// Callback with a module to search for matching symbols. +// We first check that the module contains RS kernels. +// Then look for a symbol which matches our kernel name. +// The breakpoint address is finally set using the address of this symbol. +Searcher::CallbackReturn +RSBreakpointResolver::SearchCallback(SearchFilter &filter, +                                     SymbolContext &context, +                                     Address*, +                                     bool) +{ +    ModuleSP module = context.module_sp; + +    if (!module) +        return Searcher::eCallbackReturnContinue; + +    // Is this a module containing renderscript kernels? +    if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData)) +        return Searcher::eCallbackReturnContinue; + +    // Attempt to set a breakpoint on the kernel name symbol within the module library. +    // If it's not found, it's likely debug info is unavailable - try to set a +    // breakpoint on <name>.expand. + +    const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); +    if (!kernel_sym) +    { +        std::string kernel_name_expanded(m_kernel_name.AsCString()); +        kernel_name_expanded.append(".expand"); +        kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); +    } + +    if (kernel_sym) +    { +        Address bp_addr = kernel_sym->GetAddress(); +        if (filter.AddressPasses(bp_addr)) +            m_breakpoint->AddLocation(bp_addr); +    } + +    return Searcher::eCallbackReturnContinue; +} +  void  RenderScriptRuntime::Initialize()  { @@ -88,7 +477,7 @@ RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)              return eModuleKindDriver;          } -        const ConstString rs_cpureflib("libRSCPURef.so"); +        const ConstString rs_cpureflib("libRSCpuRef.so");          if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)          {              return eModuleKindImpl; @@ -104,7 +493,6 @@ RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)      return GetModuleKind(module_sp) != eModuleKindIgnored;  } -  void   RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )  { @@ -121,7 +509,6 @@ RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )      }  } -  //------------------------------------------------------------------  // PluginInterface protocol  //------------------------------------------------------------------ @@ -145,11 +532,19 @@ RenderScriptRuntime::IsVTableName(const char *name)  bool  RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, -                                              TypeAndOrName &class_type_or_name, Address &address) +                                              TypeAndOrName &class_type_or_name, Address &address, +                                              Value::ValueType &value_type)  {      return false;  } +TypeAndOrName +RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name, +                                       ValueObject& static_value) +{ +    return type_and_or_name; +} +  bool  RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)  { @@ -163,22 +558,78 @@ RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bo      return resolver_sp;  } -  const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =  {      //rsdScript -    {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureScriptInit1}, -    {"rsdScriptInvokeForEach", "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr}, -    {"rsdScriptInvokeForEachMulti", "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr}, -    {"rsdScriptInvokeFunction", "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr}, -    {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1}, +    { +        "rsdScriptInit", //name +        "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit +        "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler +    }, +    { +        "rsdScriptInvokeForEach", // name +        "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit +        "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        nullptr // handler +    }, +    { +        "rsdScriptInvokeForEachMulti", // name +        "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit +        "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        nullptr // handler +    }, +    { +        "rsdScriptInvokeFunction", // name +        "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit +        "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        nullptr // handler +    }, +    { +        "rsdScriptSetGlobalVar", // name +        "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit +        "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler +    },      //rsdAllocation -    {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureAllocationInit1}, -    {"rsdAllocationRead2D", "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr}, +    { +        "rsdAllocationInit", // name +        "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit +        "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler +    }, +    { +        "rsdAllocationRead2D", //name +        "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit +        "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        nullptr // handler +    }, +    { +        "rsdAllocationDestroy", // name +        "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 32bit +        "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 64bit +        0, // version +        RenderScriptRuntime::eModuleKindDriver, // type +        &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy // handler +    },  }; -const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]); +const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);  bool  RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) @@ -193,13 +644,12 @@ RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, ll      return false;  } -  void   RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)  {      Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); -    if(log) +    if (log)          log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);      if (hook_info->defn->grabber)  @@ -208,56 +658,241 @@ RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& cont      }  } -  bool -RenderScriptRuntime::GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data) +RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)  { -    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); +    // Get a positional integer argument. +    // Given an ExecutionContext, ``context`` which should be a RenderScript +    // frame, get the value of the positional argument ``arg`` and save its value +    // to the address pointed to by ``data``. +    // returns true on success, false otherwise. +    // If unsuccessful, the value pointed to by ``data`` is undefined. Otherwise, +    // ``data`` will be set to the value of the the given ``arg``. +    // NOTE: only natural width integer arguments for the machine are supported. +    // Behaviour with non primitive arguments is undefined.      if (!data)          return false; +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));      Error error;      RegisterContext* reg_ctx = context.GetRegisterContext();      Process* process = context.GetProcessPtr(); +    bool success = false; // return value -    if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86)  +    if (!context.GetTargetPtr())      { -        uint64_t sp = reg_ctx->GetSP(); +        if (log) +            log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target"); + +        return false; +    } + +    switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) +    { +        case llvm::Triple::ArchType::x86:          { +            uint64_t sp = reg_ctx->GetSP();              uint32_t offset = (1 + arg) * sizeof(uint32_t); -            process->ReadMemory(sp + offset, data, sizeof(uint32_t), error); -            if(error.Fail()) +            uint32_t result = 0; +            process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error); +            if (error.Fail())              { -                if(log) -                    log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading X86 stack: %s.", error.AsCString());      +                if (log) +                    log->Printf("RenderScriptRuntime::GetArgSimple - error reading X86 stack: %s.", error.AsCString());              } +            else +            { +                *data = result; +                success = true; +            } + +            break;          } -    } -    else if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::arm)  -    { -        if (arg < 4) +        case llvm::Triple::ArchType::x86_64:          { -            const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); +            // amd64 has 6 integer registers, and 8 XMM registers for parameter passing. +            // Surplus args are spilled onto the stack. +            // rdi, rsi, rdx, rcx, r8, r9, (zmm0 - 7 for vectors) +            // ref: AMD64 ABI Draft 0.99.6 – October 7, 2013 – 10:35; Figure 3.4. Retrieved from +            // http://www.x86-64.org/documentation/abi.pdf +            if (arg > 5) +            { +                if (log) +                    log->Warning("X86_64 register spill is not supported."); +                break; +            } +            const char * regnames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}; +            assert((sizeof(regnames) / sizeof(const char *)) > arg); +            const RegisterInfo *rArg = reg_ctx->GetRegisterInfoByName(regnames[arg]);              RegisterValue rVal; -            reg_ctx->ReadRegister(rArg, rVal); -            (*data) = rVal.GetAsUInt32(); +            success = reg_ctx->ReadRegister(rArg, rVal); +            if (success) +            { +                *data = rVal.GetAsUInt64(0u, &success); +            } +            else +            { +                if (log) +                    log->Printf("RenderScriptRuntime::GetArgSimple - error reading x86_64 register: %d.", arg); +            } +            break;          } -        else +        case llvm::Triple::ArchType::arm:          { -            uint64_t sp = reg_ctx->GetSP(); +            // arm 32 bit +            if (arg < 4)              { +                const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); +                RegisterValue rVal; +                success = reg_ctx->ReadRegister(rArg, rVal); +                if (success) +                { +                    (*data) = rVal.GetAsUInt32(0u, &success); +                } +                else +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM register: %d.", arg); +                } +            } +            else +            { +                uint64_t sp = reg_ctx->GetSP();                  uint32_t offset = (arg-4) * sizeof(uint32_t);                  process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error); -                if(error.Fail()) +                if (error.Fail()) +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString()); +                } +                else                  { -                    if(log) -                        log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading ARM stack: %s.", error.AsCString());      +                    success = true;                  }              } -        }    + +            break; +        } +        case llvm::Triple::ArchType::aarch64: +        { +            // arm 64 bit +            // first 8 arguments are in the registers +            if (arg < 8) +            { +                const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); +                RegisterValue rVal; +                success = reg_ctx->ReadRegister(rArg, rVal); +                if (success) +                { +                    *data = rVal.GetAsUInt64(0u, &success); +                } +                else +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg); +                } +            } +            else +            { +                // @TODO: need to find the argument in the stack +                if (log) +                    log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg); +            } +            break; +        } +        case llvm::Triple::ArchType::mipsel: +        { + +            // read from the registers +            if (arg < 4){ +                const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4); +                RegisterValue rVal; +                success = reg_ctx->ReadRegister(rArg, rVal); +                if (success) +                { +                    *data = rVal.GetAsUInt64(0u, &success); +                } +                else +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple() - Mips - Error while reading the argument #%d", arg); +                } + +            } + +            // read from the stack +            else +            { +                uint64_t sp = reg_ctx->GetSP(); +                uint32_t offset = arg * sizeof(uint32_t); +                process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString()); +                } +                else +                { +                    success = true; +                } +            } + +            break; +        } +        case llvm::Triple::ArchType::mips64el: +        { +            // read from the registers +            if (arg < 8) +            { +                const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4); +                RegisterValue rVal; +                success = reg_ctx->ReadRegister(rArg, rVal); +                if (success) +                { +                    (*data) = rVal.GetAsUInt64(0u, &success); +                } +                else +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg); +                } +            } + +            // read from the stack +            else +            { +                uint64_t sp = reg_ctx->GetSP(); +                uint32_t offset = (arg - 8) * sizeof(uint64_t); +                process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString()); +                } +                else +                { +                    success = true; +                } +            } + +            break; +        } +        default: +        { +            // invalid architecture +            if (log) +                log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported"); + +        }      } -    return true; + +    if (!success) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg); +    } +    return success;  }  void  @@ -267,35 +902,38 @@ RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionConte      //Context, Script, int, data, length -    Error error; -     -    uint32_t rs_context_u32 = 0U; -    uint32_t rs_script_u32 = 0U; -    uint32_t rs_id_u32 = 0U; -    uint32_t rs_data_u32 = 0U; -    uint32_t rs_length_u32 = 0U; +    uint64_t rs_context_u64 = 0U; +    uint64_t rs_script_u64 = 0U; +    uint64_t rs_id_u64 = 0U; +    uint64_t rs_data_u64 = 0U; +    uint64_t rs_length_u64 = 0U; -    std::string resname; -    std::string cachedir; +    bool success = +        GetArgSimple(context, 0, &rs_context_u64) && +        GetArgSimple(context, 1, &rs_script_u64) && +        GetArgSimple(context, 2, &rs_id_u64) && +        GetArgSimple(context, 3, &rs_data_u64) && +        GetArgSimple(context, 4, &rs_length_u64); -    GetArg32Simple(context, 0, &rs_context_u32); -    GetArg32Simple(context, 1, &rs_script_u32); -    GetArg32Simple(context, 2, &rs_id_u32); -    GetArg32Simple(context, 3, &rs_data_u32); -    GetArg32Simple(context, 4, &rs_length_u32); +    if (!success) +    { +        if (log) +            log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters"); +        return; +    } -    if(log) +    if (log)      {          log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", -                        (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, (uint64_t)rs_id_u32, (uint64_t)rs_data_u32, (uint64_t)rs_length_u32); +                        rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64); -        addr_t script_addr =  (addr_t)rs_script_u32; +        addr_t script_addr =  (addr_t)rs_script_u64;          if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())          {              auto rsm = m_scriptMappings[script_addr]; -            if (rs_id_u32 < rsm->m_globals.size()) +            if (rs_id_u64 < rsm->m_globals.size())              { -                auto rsg = rsm->m_globals[rs_id_u32]; +                auto rsg = rsm->m_globals[rs_id_u64];                  log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),                                   rsm->m_module->GetFileSpec().GetFilename().AsCString());              } @@ -310,19 +948,65 @@ RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionCon      //Context, Alloc, bool -    Error error; -     -    uint32_t rs_context_u32 = 0U; -    uint32_t rs_alloc_u32 = 0U; -    uint32_t rs_forceZero_u32 = 0U; - -    GetArg32Simple(context, 0, &rs_context_u32); -    GetArg32Simple(context, 1, &rs_alloc_u32); -    GetArg32Simple(context, 2, &rs_forceZero_u32); -         -    if(log) +    uint64_t rs_context_u64 = 0U; +    uint64_t rs_alloc_u64 = 0U; +    uint64_t rs_forceZero_u64 = 0U; + +    bool success = +        GetArgSimple(context, 0, &rs_context_u64) && +        GetArgSimple(context, 1, &rs_alloc_u64) && +        GetArgSimple(context, 2, &rs_forceZero_u64); +    if (!success) // error case +    { +        if (log) +            log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters"); +        return; // abort +    } + +    if (log)          log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", -                        (uint64_t)rs_context_u32, (uint64_t)rs_alloc_u32, (uint64_t)rs_forceZero_u32); +                        rs_context_u64, rs_alloc_u64, rs_forceZero_u64); + +    AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true); +    if (alloc) +        alloc->context = rs_context_u64; +} + +void +RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    // Context, Alloc +    uint64_t rs_context_u64 = 0U; +    uint64_t rs_alloc_u64 = 0U; + +    bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64); +    if (!success) // error case +    { +        if (log) +            log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters"); +        return; // abort +    } + +    if (log) +        log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".", +                    rs_context_u64, rs_alloc_u64); + +    for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) +    { +        auto& allocation_ap = *iter; // get the unique pointer +        if (allocation_ap->address.isValid() && *allocation_ap->address.get() == rs_alloc_u64) +        { +            m_allocations.erase(iter); +            if (log) +                log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry"); +            return; +        } +    } + +    if (log) +        log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation");  }  void  @@ -334,64 +1018,72 @@ RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext      Error error;      Process* process = context.GetProcessPtr(); -    uint32_t rs_context_u32 = 0U; -    uint32_t rs_script_u32 = 0U; -    uint32_t rs_resnameptr_u32 = 0U; -    uint32_t rs_cachedirptr_u32 = 0U; +    uint64_t rs_context_u64 = 0U; +    uint64_t rs_script_u64 = 0U; +    uint64_t rs_resnameptr_u64 = 0U; +    uint64_t rs_cachedirptr_u64 = 0U;      std::string resname;      std::string cachedir; -    GetArg32Simple(context, 0, &rs_context_u32); -    GetArg32Simple(context, 1, &rs_script_u32); -    GetArg32Simple(context, 2, &rs_resnameptr_u32); -    GetArg32Simple(context, 3, &rs_cachedirptr_u32); +    // read the function parameters +    bool success = +        GetArgSimple(context, 0, &rs_context_u64) && +        GetArgSimple(context, 1, &rs_script_u64) && +        GetArgSimple(context, 2, &rs_resnameptr_u64) && +        GetArgSimple(context, 3, &rs_cachedirptr_u64); -    process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u32, resname, error); +    if (!success) +    { +        if (log) +            log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters"); +        return; +    } + +    process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);      if (error.Fail())      { -        if(log) +        if (log)              log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());      } -    process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u32, cachedir, error); +    process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);      if (error.Fail())      { -        if(log) +        if (log)              log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());           }      if (log)          log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", -                     (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, resname.c_str(), cachedir.c_str()); +                     rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());      if (resname.size() > 0)      {          StreamString strm;          strm.Printf("librs.%s.so", resname.c_str()); -        ScriptDetails script; -        script.cachedir = cachedir; -        script.resname = resname; -        script.scriptDyLib.assign(strm.GetData()); -        script.script = rs_script_u32; -        script.context = rs_context_u32; - -        m_scripts.push_back(script); +        ScriptDetails* script = LookUpScript(rs_script_u64, true); +        if (script) +        { +            script->type = ScriptDetails::eScriptC; +            script->cacheDir = cachedir; +            script->resName = resname; +            script->scriptDyLib = strm.GetData(); +            script->context = addr_t(rs_context_u64); +        }          if (log)              log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", -                         strm.GetData(), (uint64_t)rs_context_u32, (uint64_t)rs_script_u32); +                         strm.GetData(), rs_context_u64, rs_script_u64);      }       else if (log)      {          log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");      } -  } -  void  RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)  { @@ -402,16 +1094,24 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)          return;      } -    if ((GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::x86) -        && (GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::arm)) +    Target &target = GetProcess()->GetTarget(); +    llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine(); + +    if (targetArchType != llvm::Triple::ArchType::x86 +        && targetArchType != llvm::Triple::ArchType::arm +        && targetArchType != llvm::Triple::ArchType::aarch64 +        && targetArchType != llvm::Triple::ArchType::mipsel +        && targetArchType != llvm::Triple::ArchType::mips64el +        && targetArchType != llvm::Triple::ArchType::x86_64 +    )      {          if (log) -            log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently."); +            log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently.");          return;      } -    Target &target = GetProcess()->GetTarget(); +    uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();      for (size_t idx = 0; idx < s_runtimeHookCount; idx++)      { @@ -420,16 +1120,29 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)              continue;          } -        const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(hook_defn->symbol_name), eSymbolTypeCode); +        const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64; + +        const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode); +        if (!sym){ +            if (log){ +                log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name); +            } +            continue; +        }          addr_t addr = sym->GetLoadAddress(&target);          if (addr == LLDB_INVALID_ADDRESS)          { -            if(log) +            if (log)                  log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",  -                             hook_defn->name, hook_defn->symbol_name); +                             hook_defn->name, symbol_name);              continue;          } +        else +        { +            if (log) +                log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr); +        }          RuntimeHookSP hook(new RuntimeHook());          hook->address = addr; @@ -455,35 +1168,1082 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)      const ModuleSP module = rsmodule_sp->m_module;      const FileSpec& file = module->GetPlatformFileSpec(); -     -    for (const auto &rs_script : m_scripts) + +    // Iterate over all of the scripts that we currently know of. +    // Note: We cant push or pop to m_scripts here or it may invalidate rs_script. +    for (const auto & rs_script : m_scripts) +    { +        // Extract the expected .so file path for this script. +        std::string dylib; +        if (!rs_script->scriptDyLib.get(dylib)) +            continue; + +        // Only proceed if the module that has loaded corresponds to this script. +        if (file.GetFilename() != ConstString(dylib.c_str())) +            continue; + +        // Obtain the script address which we use as a key. +        lldb::addr_t script; +        if (!rs_script->script.get(script)) +            continue; + +        // If we have a script mapping for the current script. +        if (m_scriptMappings.find(script) != m_scriptMappings.end()) +        { +            // if the module we have stored is different to the one we just received. +            if (m_scriptMappings[script] != rsmodule_sp) +            { +                if (log) +                    log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.", +                                    (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); +            } +        } +        // We don't have a script mapping for the current script. +        else +        { +            // Obtain the script resource name. +            std::string resName; +            if (rs_script->resName.get(resName)) +                // Set the modules resource name. +                rsmodule_sp->m_resname = resName; +            // Add Script/Module pair to map. +            m_scriptMappings[script] = rsmodule_sp; +            if (log) +                log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.", +                                (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); +        } +    } +} + +// Uses the Target API to evaluate the expression passed as a parameter to the function +// The result of that expression is returned an unsigned 64 bit int, via the result* paramter. +// Function returns true on success, and false on failure +bool +RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); +    if (log) +        log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); + +    ValueObjectSP expr_result; +    // Perform the actual expression evaluation +    GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); + +    if (!expr_result) +    { +       if (log) +           log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression"); +       return false; +    } + +    // The result of the expression is invalid +    if (!expr_result->GetError().Success()) +    { +        Error err = expr_result->GetError(); +        if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success +        { +            if (log) +                log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); + +            result = nullptr; +            return true; +        } + +        if (log) +            log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); +        return false; +    } + +    bool success = false; +    *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. + +    if (!success) +    { +       if (log) +           log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int"); +       return false; +    } + +    return true; +} + +namespace // anonymous +{ +    // max length of an expanded expression +    const int jit_max_expr_size = 768; + +    // Format strings containing the expressions we may need to evaluate. +    const char runtimeExpressions[][256] = +    { +     // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) +     "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", + +     // Type* rsaAllocationGetType(Context*, Allocation*) +     "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", + +     // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) +     // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; +     // mHal.state.lodCount; mHal.state.faces; mElement; into typeData +     // Need to specify 32 or 64 bit for uint_t since this differs between devices +     "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim +     "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim +     "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim +     "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr + +     // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) +     // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData +     "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type +     "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind +     "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size +     "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count + +      // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, +      // size_t *arraySizes, uint32_t dataSize) +      // Needed for Allocations of structs to gather details about fields/Subelements +     "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +     "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]",     // Element* of field + +     "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +     "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]",   // Name of field + +     "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +     "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field +    }; + + +    // Temporary workaround for MIPS, until the compiler emits the JAL instruction when invoking directly the function. +    // At the moment, when evaluating an expression involving a function call, the LLVM codegen for Mips  emits a JAL +    // instruction, which is able to jump in the range +/- 128MB with respect to the current program counter ($pc). If +    // the requested function happens to reside outside the above region, the function address will be truncated and the +    // function invocation will fail. This is a problem in the RS plugin as we rely on the RS API to probe the number and +    // the nature of allocations. A proper solution in the MIPS compiler is currently being investigated. As temporary +    // work around for this context, we'll invoke the RS API through function pointers, which cause the compiler to emit a +    // register based JALR instruction. +    const char runtimeExpressions_mips[][512] = +    { +    // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) +    "int* (*f) (void*, int, int, int, int, int) = (int* (*) (void*, int, int, int, int, int)) " +        "_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace; " +        "(int*) f((void*) 0x%lx, %u, %u, %u, 0, 0)", + +    // Type* rsaAllocationGetType(Context*, Allocation*) +    "void* (*f) (void*, void*) = (void* (*) (void*, void*)) rsaAllocationGetType; (void*) f((void*) 0x%lx, (void*) 0x%lx)", + +    // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) +    // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; +    // mHal.state.lodCount; mHal.state.faces; mElement; into typeData +    // Need to specify 32 or 64 bit for uint_t since this differs between devices +    "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " +        "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[0]", +    "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " +        "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[1]", +    "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " +        "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[2]", +    "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " +        "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[5]", + +    // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) +    // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData +    "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " +        "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[0]", // Type +    "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " +        "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[1]", // Kind +    "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " +        "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[3]", // Vector size +    "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " +        "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[4]", // Field count + +    // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, +    // size_t *arraySizes, uint32_t dataSize) +    // Needed for Allocations of structs to gather details about fields/Subelements +   "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +        "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " +        "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" +        "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" +        "ids[%u]", // Element* of field +   "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +        "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " +        "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" +        "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" +        "names[%u]", // Name of field +   "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" +        "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " +        "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" +        "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" +        "arr_size[%u]" // Array size of field +    }; + +} // end of the anonymous namespace + + +// Retrieve the string to JIT for the given expression +const char* +RenderScriptRuntime::JITTemplate(ExpressionStrings e) +{ +    // be nice to your Mips friend when adding new expression strings +    static_assert(sizeof(runtimeExpressions)/sizeof(runtimeExpressions[0]) == +            sizeof(runtimeExpressions_mips)/sizeof(runtimeExpressions_mips[0]), +            "#runtimeExpressions != #runtimeExpressions_mips"); + +    assert((e >= eExprGetOffsetPtr && e <= eExprSubelementsArrSize) && +           "Expression string out of bounds"); + +    llvm::Triple::ArchType arch = GetTargetRef().GetArchitecture().GetMachine(); + +    // mips JAL workaround +    if(arch == llvm::Triple::ArchType::mips64el || arch == llvm::Triple::ArchType::mipsel) +        return runtimeExpressions_mips[e]; +    else +        return runtimeExpressions[e]; +} + + +// JITs the RS runtime for the internal data pointer of an allocation. +// Is passed x,y,z coordinates for the pointer to a specific element. +// Then sets the data_ptr member in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, +                                    unsigned int x, unsigned int y, unsigned int z) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!allocation->address.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); +        return false; +    } + +    const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); +    char buffer[jit_max_expr_size]; + +    int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); +    if (chars_written < 0) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); +        return false; +    } +    else if (chars_written >= jit_max_expr_size) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); +        return false; +    } + +    uint64_t result = 0; +    if (!EvalRSExpression(buffer, frame_ptr, &result)) +        return false; + +    addr_t mem_ptr = static_cast<lldb::addr_t>(result); +    allocation->data_ptr = mem_ptr; + +    return true; +} + +// JITs the RS runtime for the internal pointer to the RS Type of an allocation +// Then sets the type_ptr member in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!allocation->address.isValid() || !allocation->context.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); +        return false; +    } + +    const char* expr_cstr = JITTemplate(eExprAllocGetType); +    char buffer[jit_max_expr_size]; + +    int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); +    if (chars_written < 0) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); +        return false; +    } +    else if (chars_written >= jit_max_expr_size) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); +        return false; +    } + +    uint64_t result = 0; +    if (!EvalRSExpression(buffer, frame_ptr, &result)) +        return false; + +    addr_t type_ptr = static_cast<lldb::addr_t>(result); +    allocation->type_ptr = type_ptr; + +    return true; +} + +// JITs the RS runtime for information about the dimensions and type of an allocation +// Then sets dimension and element_ptr members in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!allocation->type_ptr.isValid() || !allocation->context.isValid())      { -        if (file.GetFilename() == ConstString(rs_script.scriptDyLib.c_str())) +        if (log) +            log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); +        return false; +    } + +    // Expression is different depending on if device is 32 or 64 bit +    uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); +    const unsigned int bits = archByteSize == 4 ? 32 : 64; + +    // We want 4 elements from packed data +    const unsigned int num_exprs = 4; +    assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); + +    char buffer[num_exprs][jit_max_expr_size]; +    uint64_t results[num_exprs]; + +    for (unsigned int i = 0; i < num_exprs; ++i) +    { +        const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprTypeDimX + i)); +        int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits, +                                     *allocation->context.get(), *allocation->type_ptr.get()); +        if (chars_written < 0) +        { +            if (log) +                log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); +            return false; +        } +        else if (chars_written >= jit_max_expr_size) +        { +            if (log) +                log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); +            return false; +        } + +        // Perform expression evaluation +        if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) +            return false; +    } + +    // Assign results to allocation members +    AllocationDetails::Dimension dims; +    dims.dim_1 = static_cast<uint32_t>(results[0]); +    dims.dim_2 = static_cast<uint32_t>(results[1]); +    dims.dim_3 = static_cast<uint32_t>(results[2]); +    allocation->dimension = dims; + +    addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]); +    allocation->element.element_ptr = elem_ptr; + +    if (log) +        log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, +                    dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); + +    return true; +} + +// JITs the RS runtime for information about the Element of an allocation +// Then sets type, type_vec_size, field_count and type_kind members in Element with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!elem.element_ptr.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); +        return false; +    } + +    // We want 4 elements from packed data +    const unsigned int num_exprs = 4; +    assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions"); + +    char buffer[num_exprs][jit_max_expr_size]; +    uint64_t results[num_exprs]; + +    for (unsigned int i = 0; i < num_exprs; i++) +    { +        const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + i)); +        int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get()); +        if (chars_written < 0)          { -            if (m_scriptMappings.find( rs_script.script ) != m_scriptMappings.end()) +            if (log) +                log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()"); +            return false; +        } +        else if (chars_written >= jit_max_expr_size) +        { +            if (log) +                log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); +            return false; +        } + +        // Perform expression evaluation +        if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) +            return false; +    } + +    // Assign results to allocation members +    elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]); +    elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]); +    elem.type_vec_size = static_cast<uint32_t>(results[2]); +    elem.field_count = static_cast<uint32_t>(results[3]); + +    if (log) +        log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u", +                    *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get()); + +    // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields +    if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr)) +        return false; + +    return true; +} + +// JITs the RS runtime for information about the subelements/fields of a struct allocation +// This is necessary for infering the struct type so we can pretty print the allocation's contents. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details"); +        return false; +    } + +    const short num_exprs = 3; +    assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions"); + +    char expr_buffer[jit_max_expr_size]; +    uint64_t results; + +    // Iterate over struct fields. +    const uint32_t field_count = *elem.field_count.get(); +    for (unsigned int field_index = 0; field_index < field_count; ++field_index) +    { +        Element child; +        for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index) +        { +            const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + expr_index)); +            int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr, +                                         field_count, field_count, field_count, +                                         context, *elem.element_ptr.get(), field_count, field_index); +            if (chars_written < 0) +            { +                if (log) +                    log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()"); +                return false; +            } +            else if (chars_written >= jit_max_expr_size)              { -                if (m_scriptMappings[rs_script.script] != rsmodule_sp) +                if (log) +                    log->Printf("RenderScriptRuntime::JITSubelements - Expression too long"); +                return false; +            } + +            // Perform expression evaluation +            if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) +                return false; + +            if (log) +                log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results); + +            switch(expr_index) +            { +                case 0: // Element* of child +                    child.element_ptr = static_cast<addr_t>(results); +                    break; +                case 1: // Name of child                  { -                    if (log) +                    lldb::addr_t address = static_cast<addr_t>(results); +                    Error err; +                    std::string name; +                    GetProcess()->ReadCStringFromMemory(address, name, err); +                    if (!err.Fail()) +                        child.type_name = ConstString(name); +                    else                      { -                        log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",  -                                     (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); +                        if (log) +                            log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name");                      } +                    break;                  } +                case 2: // Array size of child +                    child.array_size = static_cast<uint32_t>(results); +                    break;              } -            else +        } + +        // We need to recursively JIT each Element field of the struct since +        // structs can be nested inside structs. +        if (!JITElementPacked(child, context, frame_ptr)) +            return false; +        elem.children.push_back(child); +    } + +    // Try to infer the name of the struct type so we can pretty print the allocation contents. +    FindStructTypeName(elem, frame_ptr); + +    return true; +} + +// JITs the RS runtime for the address of the last element in the allocation. +// The `elem_size` paramter represents the size of a single element, including padding. +// Which is needed as an offset from the last element pointer. +// Using this offset minus the starting address we can calculate the size of the allocation. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!allocation->address.isValid() || !allocation->dimension.isValid() +        || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details"); +        return false; +    } + +    // Find dimensions +    unsigned int dim_x = allocation->dimension.get()->dim_1; +    unsigned int dim_y = allocation->dimension.get()->dim_2; +    unsigned int dim_z = allocation->dimension.get()->dim_3; + +    // Our plan of jitting the last element address doesn't seem to work for struct Allocations +    // Instead try to infer the size ourselves without any inter element padding. +    if (allocation->element.children.size() > 0) +    { +        if (dim_x == 0) dim_x = 1; +        if (dim_y == 0) dim_y = 1; +        if (dim_z == 0) dim_z = 1; + +        allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get(); + +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get()); + +        return true; +    } + +    const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); +    char buffer[jit_max_expr_size]; + +    // Calculate last element +    dim_x = dim_x == 0 ? 0 : dim_x - 1; +    dim_y = dim_y == 0 ? 0 : dim_y - 1; +    dim_z = dim_z == 0 ? 0 : dim_z - 1; + +    int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), +                                 dim_x, dim_y, dim_z); +    if (chars_written < 0) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()"); +        return false; +    } +    else if (chars_written >= jit_max_expr_size) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); +        return false; +    } + +    uint64_t result = 0; +    if (!EvalRSExpression(buffer, frame_ptr, &result)) +        return false; + +    addr_t mem_ptr = static_cast<lldb::addr_t>(result); +    // Find pointer to last element and add on size of an element +    allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); + +    return true; +} + +// JITs the RS runtime for information about the stride between rows in the allocation. +// This is done to detect padding, since allocated memory is 16-byte aligned. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details"); +        return false; +    } + +    const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); +    char buffer[jit_max_expr_size]; + +    int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), +                                 0, 1, 0); +    if (chars_written < 0) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()"); +        return false; +    } +    else if (chars_written >= jit_max_expr_size) +    { +        if (log) +            log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); +        return false; +    } + +    uint64_t result = 0; +    if (!EvalRSExpression(buffer, frame_ptr, &result)) +        return false; + +    addr_t mem_ptr = static_cast<lldb::addr_t>(result); +    allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()); + +    return true; +} + +// JIT all the current runtime info regarding an allocation +bool +RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    // GetOffsetPointer() +    if (!JITDataPointer(allocation, frame_ptr)) +        return false; + +    // rsaAllocationGetType() +    if (!JITTypePointer(allocation, frame_ptr)) +        return false; + +    // rsaTypeGetNativeData() +    if (!JITTypePacked(allocation, frame_ptr)) +        return false; + +    // rsaElementGetNativeData() +    if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr)) +        return false; + +    // Sets the datum_size member in Element +    SetElementSize(allocation->element); + +    // Use GetOffsetPointer() to infer size of the allocation +    if (!JITAllocationSize(allocation, frame_ptr)) +        return false; + +    return true; +} + +// Function attempts to set the type_name member of the paramaterised Element object. +// This string should be the name of the struct type the Element represents. +// We need this string for pretty printing the Element to users. +void +RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    if (!elem.type_name.IsEmpty()) // Name already set +        return; +    else +        elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed + +    // Find all the global variables from the script rs modules +    VariableList variable_list; +    for (auto module_sp : m_rsmodules) +        module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list); + +    // Iterate over all the global variables looking for one with a matching type to the Element. +    // We make the assumption a match exists since there needs to be a global variable to reflect the +    // struct type back into java host code. +    for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index) +    { +        const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index)); +        if (!var_sp) +           continue; + +        ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); +        if (!valobj_sp) +            continue; + +        // Find the number of variable fields. +        // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for. +        // Don't check for equality since RS can add extra struct members for padding. +        size_t num_children = valobj_sp->GetNumChildren(); +        if (num_children > elem.children.size() || num_children == 0) +            continue; + +        // Iterate over children looking for members with matching field names. +        // If all the field names match, this is likely the struct we want. +        // +        //   TODO: This could be made more robust by also checking children data sizes, or array size +        bool found = true; +        for (size_t child_index = 0; child_index < num_children; ++child_index) +        { +            ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true); +            if (!child || (child->GetName() != elem.children[child_index].type_name))              { -                m_scriptMappings[rs_script.script] = rsmodule_sp; -                rsmodule_sp->m_resname = rs_script.resname; -                if (log) -                { -                    log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",  -                                    (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); -                } +                found = false; +                break; +            } +        } + +        // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+' +        if (found && num_children < elem.children.size()) +        { +            const unsigned int size_diff = elem.children.size() - num_children; +            if (log) +                log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff); + +            for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index) +            { +                const ConstString& name = elem.children[num_children + padding_index].type_name; +                if (strcmp(name.AsCString(), "#rs_padding") < 0) +                    found = false;              }          } + +        // We've found a global var with matching type +        if (found) +        { +            // Dereference since our Element type isn't a pointer. +            if (valobj_sp->IsPointerType()) +            { +                Error err; +                ValueObjectSP deref_valobj = valobj_sp->Dereference(err); +                if (!err.Fail()) +                    valobj_sp = deref_valobj; +            } + +            // Save name of variable in Element. +            elem.type_name = valobj_sp->GetTypeName(); +            if (log) +                log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString()); + +            return; +        }      } -     +} + +// Function sets the datum_size member of Element. Representing the size of a single instance including padding. +// Assumes the relevant allocation information has already been jitted. +void +RenderScriptRuntime::SetElementSize(Element& elem) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); +    const Element::DataType type = *elem.type.get(); +    assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT +                                                   && "Invalid allocation type"); + +    const unsigned int vec_size = *elem.type_vec_size.get(); +    unsigned int data_size = 0; +    unsigned int padding = 0; + +    // Element is of a struct type, calculate size recursively. +    if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) +    { +        for (Element& child : elem.children) +        { +            SetElementSize(child); +            const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1; +            data_size += *child.datum_size.get() * array_size; +        } +    } +    else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 || +             type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already +    { +        data_size = AllocationDetails::RSTypeToFormat[type][eElementSize]; +    } +    else if (type < Element::RS_TYPE_ELEMENT) +    { +        data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; +        if (vec_size == 3) +            padding = AllocationDetails::RSTypeToFormat[type][eElementSize]; +    } +    else +        data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); + +    elem.padding = padding; +    elem.datum_size = data_size + padding; +    if (log) +        log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding); +} + +// Given an allocation, this function copies the allocation contents from device into a buffer on the heap. +// Returning a shared pointer to the buffer containing the data. +std::shared_ptr<uint8_t> +RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    // JIT all the allocation details +    if (allocation->shouldRefresh()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info"); + +        if (!RefreshAllocation(allocation, frame_ptr)) +        { +            if (log) +                log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details"); +            return nullptr; +        } +    } + +    assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid() +           && allocation->size.isValid() && "Allocation information not available"); + +    // Allocate a buffer to copy data into +    const unsigned int size = *allocation->size.get(); +    std::shared_ptr<uint8_t> buffer(new uint8_t[size]); +    if (!buffer) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size); +        return nullptr; +    } + +    // Read the inferior memory +    Error error; +    lldb::addr_t data_ptr = *allocation->data_ptr.get(); +    GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error); +    if (error.Fail()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64, +                        error.AsCString(), size, data_ptr); +        return nullptr; +    } + +    return buffer; +} + +// Function copies data from a binary file into an allocation. +// There is a header at the start of the file, FileHeader, before the data content itself. +// Information from this header is used to display warnings to the user about incompatabilities +bool +RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    // Find allocation with the given id +    AllocationDetails* alloc = FindAllocByID(strm, alloc_id); +    if (!alloc) +        return false; + +    if (log) +        log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); + +    // JIT all the allocation details +    if (alloc->shouldRefresh()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info"); + +        if (!RefreshAllocation(alloc, frame_ptr)) +        { +            if (log) +                log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details"); +            return false; +        } +    } + +    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() +           && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available"); + +    // Check we can read from file +    FileSpec file(filename, true); +    if (!file.Exists()) +    { +        strm.Printf("Error: File %s does not exist", filename); +        strm.EOL(); +        return false; +    } + +    if (!file.Readable()) +    { +        strm.Printf("Error: File %s does not have readable permissions", filename); +        strm.EOL(); +        return false; +    } + +    // Read file into data buffer +    DataBufferSP data_sp(file.ReadFileContents()); + +    // Cast start of buffer to FileHeader and use pointer to read metadata +    void* file_buffer = data_sp->GetBytes(); +    const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer); + +    // Advance buffer past header +    file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size; + +    if (log) +        log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u", +                    head->type, head->element_size); + +    // Check if the target allocation and file both have the same number of bytes for an Element +    if (*alloc->element.datum_size.get() != head->element_size) +    { +        strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes", +                    head->element_size, *alloc->element.datum_size.get()); +        strm.EOL(); +    } + +    // Check if the target allocation and file both have the same integral type +    const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get()); +    if (type != head->type) +    { +        // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array +        unsigned int printable_target_type_index = type; +        unsigned int printable_head_type_index = head->type; +        if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) +            printable_target_type_index = static_cast<Element::DataType>( +                                         (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); + +        if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT) +            printable_head_type_index = static_cast<Element::DataType>( +                                        (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); + +        const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0]; +        const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0]; + +        strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", +                    file_type_cstr, target_type_cstr); +        strm.EOL(); +    } + +    // Calculate size of allocation data in file +    size_t length = data_sp->GetByteSize() - head->hdr_size; + +    // Check if the target allocation and file both have the same total data size. +    const unsigned int alloc_size = *alloc->size.get(); +    if (alloc_size != length) +    { +        strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes", +                    (uint64_t) length, alloc_size); +        strm.EOL(); +        length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum +    } + +    // Copy file data from our buffer into the target allocation. +    lldb::addr_t alloc_data = *alloc->data_ptr.get(); +    Error error; +    size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error); +    if (!error.Success() || bytes_written != length) +    { +        strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString()); +        strm.EOL(); +        return false; +    } + +    strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id); +    strm.EOL(); + +    return true; +} + +// Function copies allocation contents into a binary file. +// This file can then be loaded later into a different allocation. +// There is a header, FileHeader, before the allocation data containing meta-data. +bool +RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    // Find allocation with the given id +    AllocationDetails* alloc = FindAllocByID(strm, alloc_id); +    if (!alloc) +        return false; + +    if (log) +        log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); + +     // JIT all the allocation details +    if (alloc->shouldRefresh()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info"); + +        if (!RefreshAllocation(alloc, frame_ptr)) +        { +            if (log) +                log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details"); +            return false; +        } +    } + +    assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get() +           && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available"); + +    // Check we can create writable file +    FileSpec file_spec(filename, true); +    File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate); +    if (!file) +    { +        strm.Printf("Error: Failed to open '%s' for writing", filename); +        strm.EOL(); +        return false; +    } + +    // Read allocation into buffer of heap memory +    const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); +    if (!buffer) +    { +        strm.Printf("Error: Couldn't read allocation data into buffer"); +        strm.EOL(); +        return false; +    } + +    // Create the file header +    AllocationDetails::FileHeader head; +    head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D'; +    head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader)); +    head.type = static_cast<uint16_t>(*alloc->element.type.get()); +    head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get()); +    head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1); +    head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2); +    head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3); +    head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get()); + +    // Write the file header +    size_t num_bytes = sizeof(AllocationDetails::FileHeader); +    Error err = file.Write(static_cast<const void*>(&head), num_bytes); +    if (!err.Success()) +    { +        strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); +        strm.EOL(); +        return false; +    } + +    // Write allocation data to file +    num_bytes = static_cast<size_t>(*alloc->size.get()); +    if (log) +        log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, buffer.get()); + +    err = file.Write(buffer.get(), num_bytes); +    if (!err.Success()) +    { +        strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); +        strm.EOL(); +        return false; +    } + +    strm.Printf("Allocation written to file '%s'", filename); +    strm.EOL(); +    return true;  }  bool @@ -496,7 +2256,14 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)          for (const auto &rs_module : m_rsmodules)          {              if (rs_module->m_module == module_sp) +            { +                // Check if the user has enabled automatically breaking on +                // all RS kernels. +                if (m_breakAllKernels) +                    BreakOnModuleKernels(rs_module); +                  return false; +            }          }          bool module_loaded = false;          switch (GetModuleKind(module_sp)) @@ -585,7 +2352,6 @@ RenderScriptRuntime::Update()      }  } -  // The maximum line length of an .rs.info packet  #define MAXLINE 500 @@ -609,12 +2375,12 @@ RSModuleDescriptor::ParseRSInfo()          std::string info((const char *)buffer->GetBytes());          std::vector<std::string> info_lines; -        size_t lpos = info.find_first_of("\n"); +        size_t lpos = info.find('\n');          while (lpos != std::string::npos)          {              info_lines.push_back(info.substr(0, lpos));              info = info.substr(lpos + 1); -            lpos = info.find_first_of("\n"); +            lpos = info.find('\n');          }          size_t offset = 0;          while (offset < info_lines.size()) @@ -710,7 +2476,6 @@ RenderScriptRuntime::Status(Stream &strm) const              strm.Indent(b.second->defn->name);              strm.EOL();          } -        strm.EOL();      }       else      { @@ -728,15 +2493,21 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const      std::map<addr_t, uint64_t> contextReferences; -    for (const auto &script : m_scripts) +    // Iterate over all of the currently discovered scripts. +    // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script. +    for (const auto & script : m_scripts)      { -        if (contextReferences.find(script.context) != contextReferences.end()) +        if (!script->context.isValid()) +            continue; +        lldb::addr_t context = *script->context; + +        if (contextReferences.find(context) != contextReferences.end())          { -            contextReferences[script.context]++; +            contextReferences[context]++;          }          else          { -            contextReferences[script.context] = 1; +            contextReferences[context] = 1;          }      } @@ -767,69 +2538,502 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const      strm.IndentLess();  } -void  -RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error) +RenderScriptRuntime::AllocationDetails* +RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)  { -    if (!name)  +    AllocationDetails* alloc = nullptr; + +    // See if we can find allocation using id as an index; +    if (alloc_id <= m_allocations.size() && alloc_id != 0 +        && m_allocations[alloc_id-1]->id == alloc_id)      { -        error.SetErrorString("invalid kernel name"); -        return; +        alloc = m_allocations[alloc_id-1].get(); +        return alloc;      } -    bool kernels_found; -    ConstString kernel_name(name); -    for (const auto &module : m_rsmodules) +    // Fallback to searching +    for (const auto & a : m_allocations)      { -        for (const auto &kernel : module->m_kernels) +       if (a->id == alloc_id) +       { +           alloc = a.get(); +           break; +       } +    } + +    if (alloc == nullptr) +    { +        strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id); +        strm.EOL(); +    } + +    return alloc; +} + +// Prints the contents of an allocation to the output stream, which may be a file +bool +RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id) +{ +    Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + +    // Check we can find the desired allocation +    AllocationDetails* alloc = FindAllocByID(strm, id); +    if (!alloc) +        return false; // FindAllocByID() will print error message for us here + +    if (log) +        log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); + +    // Check we have information about the allocation, if not calculate it +    if (alloc->shouldRefresh()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info"); + +        // JIT all the allocation information +        if (!RefreshAllocation(alloc, frame_ptr))          { -            if (kernel.m_name == kernel_name) -            { -                //Attempt to set a breakpoint on this symbol, within the module library -                //If it's not found, it's likely debug info is unavailable - set a -                //breakpoint on <name>.expand and emit a warning. +            strm.Printf("Error: Couldn't JIT allocation details"); +            strm.EOL(); +            return false; +        } +    } + +    // Establish format and size of each data element +    const unsigned int vec_size = *alloc->element.type_vec_size.get(); +    const Element::DataType type = *alloc->element.type.get(); + +    assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT +                                                   && "Invalid allocation type"); + +    lldb::Format format; +    if (type >= Element::RS_TYPE_ELEMENT) +        format = eFormatHex; +    else +        format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) +                               : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]); + +    const unsigned int data_size = *alloc->element.datum_size.get(); + +    if (log) +        log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size); + +    // Allocate a buffer to copy data into +    std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); +    if (!buffer) +    { +        strm.Printf("Error: Couldn't read allocation data"); +        strm.EOL(); +        return false; +    } + +    // Calculate stride between rows as there may be padding at end of rows since +    // allocated memory is 16-byte aligned +    if (!alloc->stride.isValid()) +    { +        if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension +            alloc->stride = 0; +        else if (!JITAllocationStride(alloc, frame_ptr)) +        { +            strm.Printf("Error: Couldn't calculate allocation row stride"); +            strm.EOL(); +            return false; +        } +    } +    const unsigned int stride = *alloc->stride.get(); +    const unsigned int size = *alloc->size.get(); // Size of whole allocation +    const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; +    if (log) +        log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding); + +    // Find dimensions used to index loops, so need to be non-zero +    unsigned int dim_x = alloc->dimension.get()->dim_1; +    dim_x = dim_x == 0 ? 1 : dim_x; -                const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode); +    unsigned int dim_y = alloc->dimension.get()->dim_2; +    dim_y = dim_y == 0 ? 1 : dim_y; -                if (!kernel_sym) +    unsigned int dim_z = alloc->dimension.get()->dim_3; +    dim_z = dim_z == 0 ? 1 : dim_z; + +    // Use data extractor to format output +    const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); +    DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize); + +    unsigned int offset = 0;   // Offset in buffer to next element to be printed +    unsigned int prev_row = 0; // Offset to the start of the previous row + +    // Iterate over allocation dimensions, printing results to user +    strm.Printf("Data (X, Y, Z):"); +    for (unsigned int z = 0; z < dim_z; ++z) +    { +        for (unsigned int y = 0; y < dim_y; ++y) +        { +            // Use stride to index start of next row. +            if (!(y==0 && z==0)) +                offset = prev_row + stride; +            prev_row = offset; + +            // Print each element in the row individually +            for (unsigned int x = 0; x < dim_x; ++x) +            { +                strm.Printf("\n(%u, %u, %u) = ", x, y, z); +                if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) && +                    (alloc->element.type_name != Element::GetFallbackStructName()))                  { -                    std::string kernel_name_expanded(name); -                    kernel_name_expanded.append(".expand"); -                    kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); +                    // Here we are dumping an Element of struct type. +                    // This is done using expression evaluation with the name of the struct type and pointer to element. -                    if (kernel_sym) -                    { -                        strm.Printf("Kernel '%s' could not be found, but expansion exists. ", name);  -                        strm.Printf("Breakpoint placed on expanded kernel. Have you compiled in debug mode?"); -                        strm.EOL(); -                    } -                    else +                    // Don't print the name of the resulting expression, since this will be '$[0-9]+' +                    DumpValueObjectOptions expr_options; +                    expr_options.SetHideName(true); + +                    // Setup expression as derefrencing a pointer cast to element address. +                    char expr_char_buffer[jit_max_expr_size]; +                    int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64, +                                        alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset); + +                    if (chars_written < 0 || chars_written >= jit_max_expr_size)                      { -                        error.SetErrorStringWithFormat("Could not locate symbols for loaded kernel '%s'.", name); -                        return; +                        if (log) +                            log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()"); +                        continue;                      } -                } -                addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget()); -                if (bp_addr == LLDB_INVALID_ADDRESS) +                    // Evaluate expression +                    ValueObjectSP expr_result; +                    GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result); + +                    // Print the results to our stream. +                    expr_result->Dump(strm, expr_options); +                } +                else                  { -                    error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name); -                    return; +                    alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);                  } +                offset += data_size; +            } +        } +    } +    strm.EOL(); + +    return true; +} + +// Prints infomation regarding all the currently loaded allocations. +// These details are gathered by jitting the runtime, which has as latency. +void +RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) +{ +    strm.Printf("RenderScript Allocations:"); +    strm.EOL(); +    strm.IndentMore(); + +    for (auto &alloc : m_allocations) +    { +        // JIT the allocation info if we haven't done it, or the user forces us to. +        bool do_refresh = alloc->shouldRefresh() || recompute; + +        // JIT current allocation information +        if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) +        { +            strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); +            continue; +        } -                BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(bp_addr, false, false); -                strm.Printf("Breakpoint %" PRIu64 ": kernel '%s' within script '%s'", (uint64_t)bp->GetID(), name, module->m_resname.c_str()); -                strm.EOL(); +        strm.Printf("%u:\n",alloc->id); +        strm.IndentMore(); -                kernels_found = true; +        strm.Indent("Context: "); +        if (!alloc->context.isValid()) +            strm.Printf("unknown\n"); +        else +            strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); + +        strm.Indent("Address: "); +        if (!alloc->address.isValid()) +            strm.Printf("unknown\n"); +        else +            strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); + +        strm.Indent("Data pointer: "); +        if (!alloc->data_ptr.isValid()) +            strm.Printf("unknown\n"); +        else +            strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); + +        strm.Indent("Dimensions: "); +        if (!alloc->dimension.isValid()) +            strm.Printf("unknown\n"); +        else +            strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, +                                          alloc->dimension.get()->dim_2, +                                          alloc->dimension.get()->dim_3); + +        strm.Indent("Data Type: "); +        if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid()) +            strm.Printf("unknown\n"); +        else +        { +            const int vector_size = *alloc->element.type_vec_size.get(); +            Element::DataType type = *alloc->element.type.get(); + +            if (!alloc->element.type_name.IsEmpty()) +                strm.Printf("%s\n", alloc->element.type_name.AsCString()); +            else +            { +                // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array +                if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) +                    type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +  Element::RS_TYPE_MATRIX_2X2 + 1); + +                if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0])) +                    || vector_size > 4 || vector_size < 1) +                    strm.Printf("invalid type\n"); +                else +                    strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);              }          } + +        strm.Indent("Data Kind: "); +        if (!alloc->element.type_kind.isValid()) +            strm.Printf("unknown\n"); +        else +        { +            const Element::DataKind kind = *alloc->element.type_kind.get(); +            if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV) +                strm.Printf("invalid kind\n"); +            else +                strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]); +        } + +        strm.EOL(); +        strm.IndentLess();      } +    strm.IndentLess(); +} -    if (!kernels_found) +// Set breakpoints on every kernel found in RS module +void +RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) +{ +    for (const auto &kernel : rsmodule_sp->m_kernels)      { -        error.SetErrorString("kernel name not found"); +        // Don't set breakpoint on 'root' kernel +        if (strcmp(kernel.m_name.AsCString(), "root") == 0) +            continue; + +        CreateKernelBreakpoint(kernel.m_name);      } -    return; +} + +// Method is internally called by the 'kernel breakpoint all' command to +// enable or disable breaking on all kernels. +// +// When do_break is true we want to enable this functionality. +// When do_break is false we want to disable it. +void +RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) +{ +    Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); + +    InitSearchFilter(target); + +    // Set breakpoints on all the kernels +    if (do_break && !m_breakAllKernels) +    { +        m_breakAllKernels = true; + +        for (const auto &module : m_rsmodules) +            BreakOnModuleKernels(module); + +        if (log) +            log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" +                        "- breakpoints set on all currently loaded kernels"); +    } +    else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. +    { +        m_breakAllKernels = false; + +        if (log) +            log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set"); +    } +} + +// Given the name of a kernel this function creates a breakpoint using our +// own breakpoint resolver, and returns the Breakpoint shared pointer. +BreakpointSP +RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) +{ +    Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); + +    if (!m_filtersp) +    { +        if (log) +            log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); +        return nullptr; +    } + +    BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); +    BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false); + +    // Give RS breakpoints a specific name, so the user can manipulate them as a group. +    Error err; +    if (!bp->AddName("RenderScriptKernel", err) && log) +        log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString()); + +    return bp; +} + +// Given an expression for a variable this function tries to calculate the variable's value. +// If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value. +// Otherwise function returns false. +bool +RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val) +{ +    Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); +    Error error; +    VariableSP var_sp; + +    // Find variable in stack frame +    ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name, +                                                                       eNoDynamicValues, +                                                                       StackFrame::eExpressionPathOptionCheckPtrVsMember | +                                                                       StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, +                                                                       var_sp, +                                                                       error)); +    if (!error.Success()) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name); + +        return false; +    } + +    // Find the unsigned int value for the variable +    bool success = false; +    val = value_sp->GetValueAsUnsigned(0, &success); +    if (!success) +    { +        if (log) +            log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name); + +        return false; +    } + +    return true; +} + +// Callback when a kernel breakpoint hits and we're looking for a specific coordinate. +// Baton parameter contains a pointer to the target coordinate we want to break on. +// Function then checks the .expand frame for the current coordinate and breaks to user if it matches. +// Parameter 'break_id' is the id of the Breakpoint which made the callback. +// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit, +// a single logical breakpoint can have multiple addresses. +bool +RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, +                                         user_id_t break_id, user_id_t break_loc_id) +{ +    Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); + +    assert(baton && "Error: null baton in conditional kernel breakpoint callback"); + +    // Coordinate we want to stop on +    const int* target_coord = static_cast<const int*>(baton); + +    if (log) +        log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)", +                    break_id, target_coord[0], target_coord[1], target_coord[2]); + +    // Go up one stack frame to .expand kernel +    ExecutionContext context(ctx->exe_ctx_ref); +    ThreadSP thread_sp = context.GetThreadSP(); +    if (!thread_sp->SetSelectedFrameByIndex(1)) +    { +        if (log) +            log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame"); + +       return false; +    } + +    StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); +    if (!frame_sp) +    { +        if (log) +            log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame"); + +        return false; +    } + +    // Get values for variables in .expand frame that tell us the current kernel invocation +    const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"}; +    uint64_t current_coord[3] = {0, 0, 0}; + +    for(int i = 0; i < 3; ++i) +    { +        if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i])) +            return false; + +        if (log) +            log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]); +    } + +    // Check if the current kernel invocation coordinate matches our target coordinate +    if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) && +        current_coord[1] == static_cast<uint64_t>(target_coord[1]) && +        current_coord[2] == static_cast<uint64_t>(target_coord[2])) +    { +        if (log) +             log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64, +                         current_coord[0], current_coord[1], current_coord[2]); + +        BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); +        assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback"); +        breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once. +        return true; +    } + +    // No match on coordinate +    return false; +} + +// Tries to set a breakpoint on the start of a kernel, resolved using the kernel name. +// Argument 'coords', represents a three dimensional coordinate which can be used to specify +// a single kernel instance to break on. If this is set then we add a callback to the breakpoint. +void +RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords, +                                             Error& error, TargetSP target) +{ +    if (!name) +    { +        error.SetErrorString("invalid kernel name"); +        return; +    } + +    InitSearchFilter(target); + +    ConstString kernel_name(name); +    BreakpointSP bp = CreateKernelBreakpoint(kernel_name); + +    // We have a conditional breakpoint on a specific coordinate +    if (coords[0] != -1) +    { +        strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]); +        strm.EOL(); + +        // Allocate memory for the baton, and copy over coordinate +        int* baton = new int[3]; +        baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2]; + +        // Create a callback that will be invoked everytime the breakpoint is hit. +        // The baton object passed to the handler is the target coordinate we want to break on. +        bp->SetCallback(KernelBreakpointHit, baton, true); + +        // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction +        m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton); +    } + +    if (bp) +        bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);  }  void @@ -845,12 +3049,49 @@ RenderScriptRuntime::DumpModules(Stream &strm) const      strm.IndentLess();  } +RenderScriptRuntime::ScriptDetails* +RenderScriptRuntime::LookUpScript(addr_t address, bool create) +{ +    for (const auto & s : m_scripts) +    { +        if (s->script.isValid()) +            if (*s->script == address) +                return s.get(); +    } +    if (create) +    { +        std::unique_ptr<ScriptDetails> s(new ScriptDetails); +        s->script = address; +        m_scripts.push_back(std::move(s)); +        return m_scripts.back().get(); +    } +    return nullptr; +} + +RenderScriptRuntime::AllocationDetails* +RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) +{ +    for (const auto & a : m_allocations) +    { +        if (a->address.isValid()) +            if (*a->address == address) +                return a.get(); +    } +    if (create) +    { +        std::unique_ptr<AllocationDetails> a(new AllocationDetails); +        a->address = address; +        m_allocations.push_back(std::move(a)); +        return m_allocations.back().get(); +    } +    return nullptr; +} +  void  RSModuleDescriptor::Dump(Stream &strm) const  {      strm.Indent();      m_module->GetFileSpec().Dump(&strm); -    m_module->ParseAllDebugSymbols();      if(m_module->GetNumCompileUnits())      {          strm.Indent("Debug info loaded."); @@ -931,8 +3172,7 @@ RSKernelDescriptor::Dump(Stream &strm) const  class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)          : CommandObjectParsed(interpreter, "renderscript module probe",                                "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", @@ -941,10 +3181,10 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed      {      } -    ~CommandObjectRenderScriptRuntimeModuleProbe() {} +    ~CommandObjectRenderScriptRuntimeModuleProbe() override = default;      bool -    DoExecute(Args &command, CommandReturnObject &result) +    DoExecute(Args &command, CommandReturnObject &result) override      {          const size_t argc = command.GetArgumentCount();          if (argc == 0) @@ -970,8 +3210,7 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed  class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)          : CommandObjectParsed(interpreter, "renderscript module dump",                                "Dumps renderscript specific information for all modules.", "renderscript module dump", @@ -979,10 +3218,10 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed      {      } -    ~CommandObjectRenderScriptRuntimeModuleDump() {} +    ~CommandObjectRenderScriptRuntimeModuleDump() override = default;      bool -    DoExecute(Args &command, CommandReturnObject &result) +    DoExecute(Args &command, CommandReturnObject &result) override      {          RenderScriptRuntime *runtime =              (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); @@ -994,8 +3233,7 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed  class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)          : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",                                   NULL) @@ -1004,13 +3242,12 @@ class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword          LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));      } -    ~CommandObjectRenderScriptRuntimeModule() {} +    ~CommandObjectRenderScriptRuntimeModule() override = default;  };  class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)          : CommandObjectParsed(interpreter, "renderscript kernel list",                                "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", @@ -1018,10 +3255,10 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed      {      } -    ~CommandObjectRenderScriptRuntimeKernelList() {} +    ~CommandObjectRenderScriptRuntimeKernelList() override = default;      bool -    DoExecute(Args &command, CommandReturnObject &result) +    DoExecute(Args &command, CommandReturnObject &result) override      {          RenderScriptRuntime *runtime =              (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); @@ -1031,52 +3268,213 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed      }  }; -class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectParsed +class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed  { -  private: -  public: -    CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) -        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint", -                              "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint", -                              eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) +public: +    CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", +                              "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter)      {      } -    ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {} +    ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; -    bool -    DoExecute(Args &command, CommandReturnObject &result) +    Options* +    GetOptions() override      { -        const size_t argc = command.GetArgumentCount(); -        if (argc == 1) +        return &m_options; +    } + +    class CommandOptions : public Options +    { +    public: +        CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)          { -            RenderScriptRuntime *runtime = -                (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); +        } + +        ~CommandOptions() override = default; +        Error +        SetOptionValue(uint32_t option_idx, const char *option_arg) override +        {              Error error; -            runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), error); +            const int short_option = m_getopt_table[option_idx].val; -            if (error.Success()) +            switch (short_option)              { -                result.AppendMessage("Breakpoint(s) created"); -                result.SetStatus(eReturnStatusSuccessFinishResult); -                return true; +                case 'c': +                    if (!ParseCoordinate(option_arg)) +                        error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg); +                    break; +                default: +                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); +                    break;              } +            return error; +        } + +        // -c takes an argument of the form 'num[,num][,num]'. +        // Where 'id_cstr' is this argument with the whitespace trimmed. +        // Missing coordinates are defaulted to zero. +        bool +        ParseCoordinate(const char* id_cstr) +        { +            RegularExpression regex; +            RegularExpression::Match regex_match(3); + +            bool matched = false; +            if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) +                matched = true; +            else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) +                matched = true; +            else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) +                matched = true; +            for(uint32_t i = 0; i < 3; i++) +            { +                std::string group; +                if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group)) +                    m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0); +                else +                    m_coord[i] = 0; +            } +            return matched; +        } + +        void +        OptionParsingStarting() override +        { +            // -1 means the -c option hasn't been set +            m_coord[0] = -1; +            m_coord[1] = -1; +            m_coord[2] = -1; +        } + +        const OptionDefinition* +        GetDefinitions() override +        { +            return g_option_table; +        } + +        static OptionDefinition g_option_table[]; +        std::array<int,3> m_coord; +    }; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        const size_t argc = command.GetArgumentCount(); +        if (argc < 1) +        { +            result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str());              result.SetStatus(eReturnStatusFailed); -            result.AppendErrorWithFormat("Error: %s", error.AsCString());              return false;          } -        result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str()); +        RenderScriptRuntime *runtime = +                (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); + +        Error error; +        runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord, +                                         error, m_exe_ctx.GetTargetSP()); + +        if (error.Success()) +        { +            result.AppendMessage("Breakpoint(s) created"); +            result.SetStatus(eReturnStatusSuccessFinishResult); +            return true; +        }          result.SetStatus(eReturnStatusFailed); +        result.AppendErrorWithFormat("Error: %s", error.AsCString());          return false;      } + +private: +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = +{ +    { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, +      "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n" +      "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. " +      "Any unset dimensions will be defaulted to zero."}, +    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed +{ +public: +    CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all", +                              "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n" +                              "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, " +                              "but does not remove currently set breakpoints.", +                              "renderscript kernel breakpoint all <enable/disable>", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) +    { +    } + +    ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        const size_t argc = command.GetArgumentCount(); +        if (argc != 1) +        { +            result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        RenderScriptRuntime *runtime = +          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + +        bool do_break = false; +        const char* argument = command.GetArgumentAtIndex(0); +        if (strcmp(argument, "enable") == 0) +        { +            do_break = true; +            result.AppendMessage("Breakpoints will be set on all kernels."); +        } +        else if (strcmp(argument, "disable") == 0) +        { +            do_break = false; +            result.AppendMessage("Breakpoints will not be set on any new kernels."); +        } +        else +        { +            result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'"); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); + +        result.SetStatus(eReturnStatusSuccessFinishResult); +        return true; +    } +}; + +class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword +{ +public: +    CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) +        : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", +                                 nullptr) +    { +        LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); +        LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); +    } + +    ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;  };  class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)          : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",                                   NULL) @@ -1085,13 +3483,12 @@ class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword          LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));      } -    ~CommandObjectRenderScriptRuntimeKernel() {} +    ~CommandObjectRenderScriptRuntimeKernel() override = default;  };  class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)          : CommandObjectParsed(interpreter, "renderscript context dump",                                "Dumps renderscript context information.", "renderscript context dump", @@ -1099,10 +3496,10 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed      {      } -    ~CommandObjectRenderScriptRuntimeContextDump() {} +    ~CommandObjectRenderScriptRuntimeContextDump() override = default;      bool -    DoExecute(Args &command, CommandReturnObject &result) +    DoExecute(Args &command, CommandReturnObject &result) override      {          RenderScriptRuntime *runtime =              (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); @@ -1114,8 +3511,7 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed  class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)          : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",                                   NULL) @@ -1123,13 +3519,345 @@ class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword          LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));      } -    ~CommandObjectRenderScriptRuntimeContext() {} +    ~CommandObjectRenderScriptRuntimeContext() override = default; +}; + +class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed +{ +public: +    CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript allocation dump", +                              "Displays the contents of a particular allocation", "renderscript allocation dump <ID>", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) +    { +    } + +    ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; + +    Options* +    GetOptions() override +    { +        return &m_options; +    } + +    class CommandOptions : public Options +    { +    public: +        CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) +        { +        } + +        ~CommandOptions() override = default; + +        Error +        SetOptionValue(uint32_t option_idx, const char *option_arg) override +        { +            Error error; +            const int short_option = m_getopt_table[option_idx].val; + +            switch (short_option) +            { +                case 'f': +                    m_outfile.SetFile(option_arg, true); +                    if (m_outfile.Exists()) +                    { +                        m_outfile.Clear(); +                        error.SetErrorStringWithFormat("file already exists: '%s'", option_arg); +                    } +                    break; +                default: +                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); +                    break; +            } +            return error; +        } + +        void +        OptionParsingStarting() override +        { +            m_outfile.Clear(); +        } + +        const OptionDefinition* +        GetDefinitions() override +        { +            return g_option_table; +        } + +        static OptionDefinition g_option_table[]; +        FileSpec m_outfile; +    }; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        const size_t argc = command.GetArgumentCount(); +        if (argc < 1) +        { +            result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument", +                                         m_cmd_name.c_str()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        RenderScriptRuntime *runtime = +          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + +        const char* id_cstr = command.GetArgumentAtIndex(0); +        bool convert_complete = false; +        const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); +        if (!convert_complete) +        { +            result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        Stream* output_strm = nullptr; +        StreamFile outfile_stream; +        const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead +        if (outfile_spec) +        { +            // Open output file +            char path[256]; +            outfile_spec.GetPath(path, sizeof(path)); +            if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) +            { +                output_strm = &outfile_stream; +                result.GetOutputStream().Printf("Results written to '%s'", path); +                result.GetOutputStream().EOL(); +            } +            else +            { +                result.AppendErrorWithFormat("Couldn't open file '%s'", path); +                result.SetStatus(eReturnStatusFailed); +                return false; +            } +        } +        else +            output_strm = &result.GetOutputStream(); + +        assert(output_strm != nullptr); +        bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); + +        if (success) +            result.SetStatus(eReturnStatusSuccessFinishResult); +        else +            result.SetStatus(eReturnStatusFailed); + +        return true; +    } + +private: +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = +{ +    { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, +      "Print results to specified file instead of command line."}, +    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed +{ +public: +    CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript allocation list", +                              "List renderscript allocations and their information.", "renderscript allocation list", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) +    { +    } + +    ~CommandObjectRenderScriptRuntimeAllocationList() override = default; + +    Options* +    GetOptions() override +    { +        return &m_options; +    } + +    class CommandOptions : public Options +    { +    public: +        CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) +        { +        } + +        ~CommandOptions() override = default; + +        Error +        SetOptionValue(uint32_t option_idx, const char *option_arg) override +        { +            Error error; +            const int short_option = m_getopt_table[option_idx].val; + +            switch (short_option) +            { +                case 'r': +                    m_refresh = true; +                    break; +                default: +                    error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); +                    break; +            } +            return error; +        } + +        void +        OptionParsingStarting() override +        { +            m_refresh = false; +        } + +        const OptionDefinition* +        GetDefinitions() override +        { +            return g_option_table; +        } + +        static OptionDefinition g_option_table[]; +        bool m_refresh; +    }; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        RenderScriptRuntime *runtime = +          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); +        runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); +        result.SetStatus(eReturnStatusSuccessFinishResult); +        return true; +    } + +private: +    CommandOptions m_options; +}; + +OptionDefinition +CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = +{ +    { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, +      "Recompute allocation details."}, +    { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + +class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed +{ +public: +    CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript allocation load", +                              "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched) +    { +    } + +    ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        const size_t argc = command.GetArgumentCount(); +        if (argc != 2) +        { +            result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        RenderScriptRuntime *runtime = +          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + +        const char* id_cstr = command.GetArgumentAtIndex(0); +        bool convert_complete = false; +        const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); +        if (!convert_complete) +        { +            result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        const char* filename = command.GetArgumentAtIndex(1); +        bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); + +        if (success) +            result.SetStatus(eReturnStatusSuccessFinishResult); +        else +            result.SetStatus(eReturnStatusFailed); + +        return true; +    } +}; + +class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed +{ +public: +    CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter) +        : CommandObjectParsed(interpreter, "renderscript allocation save", +                              "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>", +                              eCommandRequiresProcess | eCommandProcessMustBeLaunched) +    { +    } + +    ~CommandObjectRenderScriptRuntimeAllocationSave() override = default; + +    bool +    DoExecute(Args &command, CommandReturnObject &result) override +    { +        const size_t argc = command.GetArgumentCount(); +        if (argc != 2) +        { +            result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); +            result.SetStatus(eReturnStatusFailed); +            return false; +        } + +        RenderScriptRuntime *runtime = +          static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + +        const char* id_cstr = command.GetArgumentAtIndex(0); +        bool convert_complete = false; +        const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); +        if (!convert_complete) +        { +            result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); +            result.SetStatus (eReturnStatusFailed); +            return false; +        } + +        const char* filename = command.GetArgumentAtIndex(1); +        bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); + +        if (success) +            result.SetStatus(eReturnStatusSuccessFinishResult); +        else +            result.SetStatus(eReturnStatusFailed); + +        return true; +    } +}; + +class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword +{ +public: +    CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) +        : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", +                                 NULL) +    { +        LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); +        LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); +        LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); +        LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); +    } + +    ~CommandObjectRenderScriptRuntimeAllocation() override = default;  };  class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed  { -  private: -  public: +public:      CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)          : CommandObjectParsed(interpreter, "renderscript status",                                "Displays current renderscript runtime status.", "renderscript status", @@ -1137,10 +3865,10 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed      {      } -    ~CommandObjectRenderScriptRuntimeStatus() {} +    ~CommandObjectRenderScriptRuntimeStatus() override = default;      bool -    DoExecute(Args &command, CommandReturnObject &result) +    DoExecute(Args &command, CommandReturnObject &result) override      {          RenderScriptRuntime *runtime =              (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); @@ -1152,7 +3880,7 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed  class CommandObjectRenderScriptRuntime : public CommandObjectMultiword  { -  public: +public:      CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)          : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",                                   "renderscript <subcommand> [<subcommand-options>]") @@ -1161,9 +3889,10 @@ class CommandObjectRenderScriptRuntime : public CommandObjectMultiword          LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));          LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));          LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); +        LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));      } -    ~CommandObjectRenderScriptRuntime() {} +    ~CommandObjectRenderScriptRuntime() override = default;  };  void @@ -1173,7 +3902,8 @@ RenderScriptRuntime::Initiate()  }  RenderScriptRuntime::RenderScriptRuntime(Process *process) -    : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false) +    : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false), +      m_breakAllKernels(false)  {      ModulesDidLoad(process->GetTarget().GetImages());  } @@ -1189,3 +3919,4 @@ RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpre      return command_object;  } +RenderScriptRuntime::~RenderScriptRuntime() = default; diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 2a01e744e9768..0ca268c93b007 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -12,6 +12,12 @@  // C Includes  // C++ Includes +#include <array> +#include <map> +#include <memory> +#include <string> +#include <vector> +  // Other libraries and framework includes  // Project includes  #include "lldb/lldb-private.h" @@ -19,8 +25,8 @@  #include "lldb/Target/CPPLanguageRuntime.h"  #include "lldb/Core/Module.h" -namespace lldb_private -{ +namespace lldb_private { +namespace lldb_renderscript {  typedef uint32_t RSSlot;  class RSModuleDescriptor; @@ -31,11 +37,56 @@ typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;  typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;  typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP; +// Breakpoint Resolvers decide where a breakpoint is placed, +// so having our own allows us to limit the search scope to RS kernel modules. +// As well as check for .expand kernels as a fallback. +class RSBreakpointResolver : public BreakpointResolver +{ +public: +    RSBreakpointResolver(Breakpoint *bkpt, ConstString name): +                         BreakpointResolver (bkpt, BreakpointResolver::NameResolver), +                         m_kernel_name(name) +    { +    } + +    void +    GetDescription(Stream *strm) override +    { +        if (strm) +            strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString()); +    } + +    void +    Dump(Stream *s) const override +    { +    } + +    Searcher::CallbackReturn +    SearchCallback(SearchFilter &filter, +                   SymbolContext &context, +                   Address *addr, +                   bool containing) override; + +    Searcher::Depth +    GetDepth() override +    { +        return Searcher::eDepthModule; +    } + +    lldb::BreakpointResolverSP +    CopyForBreakpoint(Breakpoint &breakpoint) override +    { +        lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name)); +        return ret_sp; +    } +protected: +    ConstString m_kernel_name; +};  struct RSKernelDescriptor  { -  public: +public:      RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)          : m_module(module)          , m_name(name) @@ -52,7 +103,7 @@ struct RSKernelDescriptor  struct RSGlobalDescriptor  { -  public: +public:      RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )          : m_module(module)          , m_name(name) @@ -67,13 +118,13 @@ struct RSGlobalDescriptor  class RSModuleDescriptor  { -  public: +public:      RSModuleDescriptor(const lldb::ModuleSP &module)          : m_module(module)      {      } -    ~RSModuleDescriptor() {} +    ~RSModuleDescriptor() = default;      bool ParseRSInfo(); @@ -86,10 +137,11 @@ class RSModuleDescriptor      std::string m_resname;  }; +} // namespace lldb_renderscript +  class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime  { -  public: - +public:      enum ModuleKind      {          eModuleKindIgnored, @@ -99,8 +151,7 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime          eModuleKindKernelObj      }; - -    ~RenderScriptRuntime() {} +    ~RenderScriptRuntime() override;      //------------------------------------------------------------------      // Static Functions @@ -121,21 +172,19 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime      static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list ); -    //------------------------------------------------------------------ -    // PluginInterface protocol -    //------------------------------------------------------------------ -    virtual lldb_private::ConstString GetPluginName(); - -    virtual uint32_t GetPluginVersion(); +    bool IsVTableName(const char *name) override; -    virtual bool IsVTableName(const char *name); - -    virtual bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, -                                          TypeAndOrName &class_type_or_name, Address &address); +    bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, +                                  TypeAndOrName &class_type_or_name, Address &address, +                                  Value::ValueType &value_type) override; +     +    TypeAndOrName +    FixUpDynamicType(const TypeAndOrName& type_and_or_name, +                     ValueObject& static_value) override; -    virtual bool CouldHaveDynamicValue(ValueObject &in_value); +    bool CouldHaveDynamicValue(ValueObject &in_value) override; -    virtual lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp); +    lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;      bool LoadModule(const lldb::ModuleSP &module_sp); @@ -147,25 +196,60 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime      void DumpKernels(Stream &strm) const; -    void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error); +    bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id); + +    void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute); + +    void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int,3> coords, +                                 Error &error, lldb::TargetSP target); + +    void SetBreakAllKernels(bool do_break, lldb::TargetSP target);      void Status(Stream &strm) const; -    virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) { +    size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override {          return static_cast<size_t>(0);      } -    virtual void ModulesDidLoad(const ModuleList &module_list ); +    void ModulesDidLoad(const ModuleList &module_list) override; + +    bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr); + +    bool SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);      void Update();      void Initiate(); + +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    lldb_private::ConstString GetPluginName() override; + +    uint32_t GetPluginVersion() override; + +protected: +    struct ScriptDetails; +    struct AllocationDetails; +    struct Element; + +    void InitSearchFilter(lldb::TargetSP target) +    { +        if (!m_filtersp) +            m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target)); +    } -  protected: -     -    void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp); +    void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);      void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); + +    bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr); + +    bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result); + +    lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name); + +    void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);      struct RuntimeHook;      typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context);  // Please do this! @@ -173,7 +257,8 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime      struct HookDefn      {          const char * name; -        const char * symbol_name; +        const char * symbol_name_m32; // mangled name for the 32 bit architectures +        const char * symbol_name_m64; // mangled name for the 64 bit archs          uint32_t version;          ModuleKind kind;          CaptureStateFn grabber; @@ -185,46 +270,102 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime          const HookDefn  *defn;          lldb::BreakpointSP bp_sp;      }; -     -    typedef std::shared_ptr<RuntimeHook> RuntimeHookSP; -    struct ScriptDetails -    { -        std::string resname; -        std::string scriptDyLib; -        std::string cachedir; -        lldb::addr_t context; -        lldb::addr_t script; -    }; +    typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;      lldb::ModuleSP m_libRS;      lldb::ModuleSP m_libRSDriver;      lldb::ModuleSP m_libRSCpuRef; -    std::vector<RSModuleDescriptorSP> m_rsmodules; -    std::vector<ScriptDetails> m_scripts; +    std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules; + +    std::vector<std::unique_ptr<ScriptDetails>> m_scripts; +    std::vector<std::unique_ptr<AllocationDetails>> m_allocations; -    std::map<lldb::addr_t, RSModuleDescriptorSP> m_scriptMappings; +    std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;      std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks; +    std::map<lldb::user_id_t, std::shared_ptr<int>> m_conditional_breaks; + +    lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API      bool m_initiated;      bool m_debuggerPresentFlagged; +    bool m_breakAllKernels;      static const HookDefn s_runtimeHookDefns[];      static const size_t s_runtimeHookCount; -  private: +private: +    // Used to index expression format strings +    enum ExpressionStrings +    { +       eExprGetOffsetPtr = 0, +       eExprAllocGetType, +       eExprTypeDimX, +       eExprTypeDimY, +       eExprTypeDimZ, +       eExprTypeElemPtr, +       eExprElementType, +       eExprElementKind, +       eExprElementVec, +       eExprElementFieldCount, +       eExprSubelementsId, +       eExprSubelementsName, +       eExprSubelementsArrSize +    }; +      RenderScriptRuntime(Process *process); // Call CreateInstance instead.      static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,                               lldb::user_id_t break_loc_id); +    static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, +                                    lldb::user_id_t break_id, lldb::user_id_t break_loc_id); +      void HookCallback(RuntimeHook* hook_info, ExecutionContext& context); -    bool GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data); +    bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data);      void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);      void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context); +    void CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context);      void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context); +    AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id); +    std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr); +    void SetElementSize(Element& elem); +    static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val); +    void FindStructTypeName(Element& elem, StackFrame* frame_ptr); + +    // +    // Helper functions for jitting the runtime +    // +    const char* JITTemplate(ExpressionStrings e); + +    bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, +                        unsigned int x = 0, unsigned int y = 0, unsigned int z = 0); + +    bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr); + +    bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr); + +    bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr); + +    bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr); + +    bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr); + +    bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr); + +    // Search for a script detail object using a target address. +    // If a script does not currently exist this function will return nullptr. +    // If 'create' is true and there is no previous script with this address, +    // then a new Script detail object will be created for this address and returned. +    ScriptDetails* LookUpScript(lldb::addr_t address, bool create); + +    // Search for a previously saved allocation detail object using a target address. +    // If an allocation does not exist for this address then nullptr will be returned. +    // If 'create' is true and there is no previous allocation then a new allocation +    // detail object will be created for this address and returned. +    AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);  };  } // namespace lldb_private diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp index c7c64ed54d87e..c575198716241 100644 --- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -30,36 +30,25 @@ MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)  {      if (!process_sp.get())          return NULL; -     +      Target & target = process_sp->GetTarget(); -     -    bool found_asan_runtime = false; -     +      const ModuleList &target_modules = target.GetImages();      Mutex::Locker modules_locker(target_modules.GetMutex());      const size_t num_modules = target_modules.GetSize();      for (size_t i = 0; i < num_modules; ++i)      {          Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i); -         -        SymbolContextList sc_list; -        const bool include_symbols = true; -        const bool append = true; -        const bool include_inlines = true; -        size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list); -         -        if (num_matches) -        { -            found_asan_runtime = true; -            break; -        } +        const Symbol* symbol = module_pointer->FindFirstSymbolWithNameAndType( +                ConstString("__asan_get_alloc_stack"), +                lldb::eSymbolTypeAny); + +        if (symbol != nullptr) +            return MemoryHistorySP(new MemoryHistoryASan(process_sp));              } -     -    if (! found_asan_runtime) -        return MemoryHistorySP(); -    return MemoryHistorySP(new MemoryHistoryASan(process_sp)); +    return MemoryHistorySP();  }  void @@ -86,7 +75,8 @@ MemoryHistoryASan::GetPluginNameStatic()  MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)  { -    this->m_process_sp = process_sp; +    if (process_sp) +        m_process_wp = process_sp;  }  const char * @@ -112,14 +102,23 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject      std::string count_path = "." + std::string(type) + "_count";      std::string tid_path = "." + std::string(type) + "_tid";      std::string trace_path = "." + std::string(type) + "_trace"; +     +    ValueObjectSP count_sp = return_value_sp->GetValueForExpressionPath(count_path.c_str()); +    ValueObjectSP tid_sp = return_value_sp->GetValueForExpressionPath(tid_path.c_str()); +     +    if (!count_sp || !tid_sp) +        return; -    int count = return_value_sp->GetValueForExpressionPath(count_path.c_str())->GetValueAsUnsigned(0); -    tid_t tid = return_value_sp->GetValueForExpressionPath(tid_path.c_str())->GetValueAsUnsigned(0); +    int count = count_sp->GetValueAsUnsigned(0); +    tid_t tid = tid_sp->GetValueAsUnsigned(0);      if (count <= 0)          return;      ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str()); +     +    if (!trace_sp) +        return;      std::vector<lldb::addr_t> pcs;      for (int i = 0; i < count; i++) @@ -144,40 +143,41 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject  HistoryThreads  MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)  { -    ProcessSP process_sp = m_process_sp; -    ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread(); -    StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); +    HistoryThreads result; -    if (!frame_sp) +    ProcessSP process_sp = m_process_wp.lock(); +    if (process_sp)      { -        return HistoryThreads(); -    } +        ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); -    ExecutionContext exe_ctx (frame_sp); -    ValueObjectSP return_value_sp; -    StreamString expr; -    expr.Printf(memory_history_asan_command_format, address, address); -     -    EvaluateExpressionOptions options; -    options.SetUnwindOnError(true); -    options.SetTryAllThreads(true); -    options.SetStopOthers(true); -    options.SetIgnoreBreakpoints(true); -    options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC); - -    if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted) -    { -        return HistoryThreads(); -    } -    if (!return_value_sp) -    { -        return HistoryThreads(); +        if (thread_sp) +        { +            StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + +            if (frame_sp) +            { +                ExecutionContext exe_ctx (frame_sp); +                ValueObjectSP return_value_sp; +                StreamString expr; +                expr.Printf(memory_history_asan_command_format, address, address); +                 +                EvaluateExpressionOptions options; +                options.SetUnwindOnError(true); +                options.SetTryAllThreads(true); +                options.SetStopOthers(true); +                options.SetIgnoreBreakpoints(true); +                options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC); + +                if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) == eExpressionCompleted) +                { +                    if (return_value_sp) +                    { +                        CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result); +                        CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result); +                    } +                } +            } +        }      } -     -    HistoryThreads result; - -    CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result); -    CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result); -          return result;  } diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h index 5307e0b340818..b38f95ed744ea 100644 --- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h +++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h @@ -1,4 +1,4 @@ -//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===// +//===-- MemoryHistoryASan.h -------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -24,7 +24,8 @@ namespace lldb_private {  class MemoryHistoryASan : public lldb_private::MemoryHistory  {  public: -     +    ~MemoryHistoryASan() override = default; +      static lldb::MemoryHistorySP      CreateInstance (const lldb::ProcessSP &process_sp); @@ -36,27 +37,28 @@ public:      static lldb_private::ConstString      GetPluginNameStatic(); + +    lldb_private::ConstString +    GetPluginName() override +    { +        return GetPluginNameStatic(); +    } -    virtual -    ~MemoryHistoryASan () {} -     -    virtual lldb_private::ConstString -    GetPluginName() { return GetPluginNameStatic(); } -     -    virtual uint32_t -    GetPluginVersion() { return 1; } +    uint32_t +    GetPluginVersion() override +    { +        return 1; +    } -    virtual lldb_private::HistoryThreads -    GetHistoryThreads(lldb::addr_t address); +    lldb_private::HistoryThreads +    GetHistoryThreads(lldb::addr_t address) override;  private: -          MemoryHistoryASan(const lldb::ProcessSP &process_sp); -    lldb::ProcessSP m_process_sp; -     +    lldb::ProcessWP m_process_wp;  };  } // namespace lldb_private -#endif  // liblldb_MemoryHistoryASan_h_ +#endif // liblldb_MemoryHistoryASan_h_ diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 8209d23c0aee6..f2a74b05fe265 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -103,9 +103,13 @@ ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::off      }      else      { -        // Strip off any spaces (if the object file name contains spaces it -        // will use the extended format above). -        str.erase (str.find(' ')); +        // Strip off any trailing spaces. +        const size_t last_pos = str.find_last_not_of(' '); +        if (last_pos != std::string::npos) +        { +            if (last_pos + 1 < 16) +                str.erase (last_pos + 1); +        }          ar_name.SetCString(str.c_str());      } diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index 8093c580ff970..cbb3848dc7cd2 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -10,8 +10,11 @@  #ifndef liblldb_ObjectContainerBSDArchive_h_  #define liblldb_ObjectContainerBSDArchive_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Symbol/ObjectContainer.h" -  #include "lldb/Core/ArchSpec.h"  #include "lldb/Core/ConstString.h"  #include "lldb/Host/FileSpec.h" @@ -22,6 +25,14 @@ class ObjectContainerBSDArchive :      public lldb_private::ObjectContainer  {  public: +    ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp, +                              lldb::DataBufferSP& data_sp, +                              lldb::offset_t data_offset, +                              const lldb_private::FileSpec *file, +                              lldb::offset_t offset, +                              lldb::offset_t length); + +    ~ObjectContainerBSDArchive() override;      //------------------------------------------------------------------      // Static Functions @@ -60,43 +71,33 @@ public:      //------------------------------------------------------------------      // Member Functions      //------------------------------------------------------------------ -    ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp, -                               lldb::DataBufferSP& data_sp, -                               lldb::offset_t data_offset, -                               const lldb_private::FileSpec *file, -                               lldb::offset_t offset, -                               lldb::offset_t length); - -    virtual -    ~ObjectContainerBSDArchive(); +    bool +    ParseHeader() override; -    virtual bool -    ParseHeader (); - -    virtual size_t -    GetNumObjects () const +    size_t +    GetNumObjects() const override      {          if (m_archive_sp)              return m_archive_sp->GetNumObjects();          return 0;      } -    virtual void -    Dump (lldb_private::Stream *s) const; -    virtual lldb::ObjectFileSP -    GetObjectFile (const lldb_private::FileSpec *file); +    void +    Dump(lldb_private::Stream *s) const override; + +    lldb::ObjectFileSP +    GetObjectFile(const lldb_private::FileSpec *file) override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  protected: -      struct Object      {          Object(); @@ -127,6 +128,13 @@ protected:          typedef std::shared_ptr<Archive> shared_ptr;          typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map; +        Archive(const lldb_private::ArchSpec &arch, +                const lldb_private::TimeValue &mod_time, +                lldb::offset_t file_offset, +                lldb_private::DataExtractor &data); + +        ~Archive(); +          static Map &          GetArchiveCache (); @@ -146,13 +154,6 @@ protected:                                       lldb::offset_t file_offset,                                       lldb_private::DataExtractor &data); -        Archive (const lldb_private::ArchSpec &arch, -                 const lldb_private::TimeValue &mod_time, -                 lldb::offset_t file_offset, -                 lldb_private::DataExtractor &data); - -        ~Archive (); -          size_t          GetNumObjects () const          { @@ -226,4 +227,4 @@ protected:      Archive::shared_ptr m_archive_sp;  }; -#endif  // liblldb_ObjectContainerBSDArchive_h_ +#endif // liblldb_ObjectContainerBSDArchive_h_ diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 789fd49133019..44fe6615a3618 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -11,6 +11,7 @@  #include <cassert>  #include <algorithm> +#include <unordered_map>  #include "lldb/Core/ArchSpec.h"  #include "lldb/Core/DataBuffer.h" @@ -48,6 +49,8 @@ const char *const LLDB_NT_OWNER_GNU     = "GNU";  const char *const LLDB_NT_OWNER_NETBSD  = "NetBSD";  const char *const LLDB_NT_OWNER_CSR     = "csr";  const char *const LLDB_NT_OWNER_ANDROID = "Android"; +const char *const LLDB_NT_OWNER_CORE    = "CORE"; +const char *const LLDB_NT_OWNER_LINUX   = "LINUX";  // ELF note type definitions  const elf_word LLDB_NT_FREEBSD_ABI_TAG  = 0x01; @@ -66,6 +69,41 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX   = 0x00;  const elf_word LLDB_NT_GNU_ABI_OS_HURD    = 0x01;  const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02; +// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants +#define NT_PRSTATUS             1 +#define NT_PRFPREG              2 +#define NT_PRPSINFO             3 +#define NT_TASKSTRUCT           4 +#define NT_AUXV                 6 +#define NT_SIGINFO              0x53494749 +#define NT_FILE                 0x46494c45 +#define NT_PRXFPREG             0x46e62b7f +#define NT_PPC_VMX              0x100 +#define NT_PPC_SPE              0x101 +#define NT_PPC_VSX              0x102 +#define NT_386_TLS              0x200 +#define NT_386_IOPERM           0x201 +#define NT_X86_XSTATE           0x202 +#define NT_S390_HIGH_GPRS       0x300 +#define NT_S390_TIMER           0x301 +#define NT_S390_TODCMP          0x302 +#define NT_S390_TODPREG         0x303 +#define NT_S390_CTRS            0x304 +#define NT_S390_PREFIX          0x305 +#define NT_S390_LAST_BREAK      0x306 +#define NT_S390_SYSTEM_CALL     0x307 +#define NT_S390_TDB             0x308 +#define NT_S390_VXRS_LOW        0x309 +#define NT_S390_VXRS_HIGH       0x30a +#define NT_ARM_VFP              0x400 +#define NT_ARM_TLS              0x401 +#define NT_ARM_HW_BREAK         0x402 +#define NT_ARM_HW_WATCH         0x403 +#define NT_ARM_SYSTEM_CALL      0x404 +#define NT_METAG_CBUF           0x500 +#define NT_METAG_RPIPE          0x501 +#define NT_METAG_TLS            0x502 +  //===----------------------------------------------------------------------===//  /// @class ELFRelocation  /// @brief Generic wrapper for ELFRel and ELFRela. @@ -290,6 +328,11 @@ mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian)      switch (mips_arch)      { +        case llvm::ELF::EF_MIPS_ARCH_1: +        case llvm::ELF::EF_MIPS_ARCH_2: +        case llvm::ELF::EF_MIPS_ARCH_3: +        case llvm::ELF::EF_MIPS_ARCH_4: +        case llvm::ELF::EF_MIPS_ARCH_5:          case llvm::ELF::EF_MIPS_ARCH_32:              return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32;          case llvm::ELF::EF_MIPS_ARCH_32R2: @@ -847,40 +890,52 @@ ObjectFileELF::SetLoadAddress (Target &target,          SectionList *section_list = GetSectionList ();          if (section_list)          { -            if (value_is_offset) +            if (!value_is_offset)              { -                const size_t num_sections = section_list->GetSize(); -                size_t sect_idx = 0; - -                for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) +                bool found_offset = false; +                for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)                  { -                    // Iterate through the object file sections to find all -                    // of the sections that have SHF_ALLOC in their flag bits. -                    SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); -                    // if (section_sp && !section_sp->IsThreadSpecific()) -                    if (section_sp && section_sp->Test(SHF_ALLOC)) -                    { -                        lldb::addr_t load_addr = section_sp->GetFileAddress() + value; -                         -                        // On 32-bit systems the load address have to fit into 4 bytes. The rest of -                        // the bytes are the overflow from the addition. -                        if (GetAddressByteSize() == 4) -                            load_addr &= 0xFFFFFFFF; - -                        if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr)) -                            ++num_loaded_sections; -                    } +                    const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i); +                    if (header == nullptr) +                        continue; + +                    if (header->p_type != PT_LOAD || header->p_offset != 0) +                        continue; +                     +                    value = value - header->p_vaddr; +                    found_offset = true; +                    break;                  } -                return num_loaded_sections > 0; +                if (!found_offset) +                    return false;              } -            else + +            const size_t num_sections = section_list->GetSize(); +            size_t sect_idx = 0; + +            for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)              { -                // Not sure how to slide an ELF file given the base address -                // of the ELF file in memory +                // Iterate through the object file sections to find all +                // of the sections that have SHF_ALLOC in their flag bits. +                SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); +                // if (section_sp && !section_sp->IsThreadSpecific()) +                if (section_sp && section_sp->Test(SHF_ALLOC)) +                { +                    lldb::addr_t load_addr = section_sp->GetFileAddress() + value; + +                    // On 32-bit systems the load address have to fit into 4 bytes. The rest of +                    // the bytes are the overflow from the addition. +                    if (GetAddressByteSize() == 4) +                        load_addr &= 0xFFFFFFFF; + +                    if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr)) +                        ++num_loaded_sections; +                }              } +            return num_loaded_sections > 0;          }      } -    return false; // If it changed +    return false;  }  ByteOrder @@ -905,8 +960,17 @@ ObjectFileELF::GetAddressByteSize() const  AddressClass  ObjectFileELF::GetAddressClass (addr_t file_addr)  { -    auto res = ObjectFile::GetAddressClass (file_addr); +    Symtab* symtab = GetSymtab(); +    if (!symtab) +        return eAddressClassUnknown; + +    // The address class is determined based on the symtab. Ask it from the object file what +    // contains the symtab information. +    ObjectFile* symtab_objfile = symtab->GetObjectFile(); +    if (symtab_objfile != nullptr && symtab_objfile != this) +        return symtab_objfile->GetAddressClass(file_addr); +    auto res = ObjectFile::GetAddressClass (file_addr);      if (res != eAddressClassCode)          return res; @@ -1076,16 +1140,35 @@ ObjectFileELF::GetImageInfoAddress(Target *target)              addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();              return Address(dynsym_section_sp, offset);          } -        else if (symbol.d_tag == DT_MIPS_RLD_MAP && target) +        // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP exists in non-PIE. +        else if ((symbol.d_tag == DT_MIPS_RLD_MAP || symbol.d_tag == DT_MIPS_RLD_MAP_REL) && target)          {              addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();              addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);              if (dyn_base == LLDB_INVALID_ADDRESS)                  return Address(); -            Address addr; +              Error error; -            if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr)) -                return addr; +            if (symbol.d_tag == DT_MIPS_RLD_MAP) +            { +                // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer. +                Address addr; +                if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr)) +                    return addr; +            } +            if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) +            { +                // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, relative to the address of the tag. +                uint64_t rel_offset; +                rel_offset = target->ReadUnsignedIntegerFromMemory(dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error); +                if (error.Success() && rel_offset != UINT64_MAX) +                { +                    Address addr; +                    addr_t debug_ptr_address = dyn_base + (offset - GetAddressByteSize()) + rel_offset; +                    addr.SetOffset (debug_ptr_address); +                    return addr; +                } +            }          }      } @@ -1232,6 +1315,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l      while (true)      {          // Parse the note header.  If this fails, bail out. +        const lldb::offset_t note_offset = offset;          ELFNote note = ELFNote();          if (!note.Parse(data, &offset))          { @@ -1239,11 +1323,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l              return error;          } -        // If a tag processor handles the tag, it should set processed to true, and -        // the loop will assume the tag processing has moved entirely past the note's payload. -        // Otherwise, leave it false and the end of the loop will handle the offset properly. -        bool processed = false; -          if (log)              log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type); @@ -1252,9 +1331,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l              (note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&              (note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))          { -            // We'll consume the payload below. -            processed = true; -              // Pull out the min version info.              uint32_t version_info;              if (data.GetU32 (&offset, &version_info, 1) == nullptr) @@ -1285,9 +1361,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l                  case LLDB_NT_GNU_ABI_TAG:                      if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)                      { -                        // We'll consume the payload below. -                        processed = true; -                          // Pull out the min OS version supporting the ABI.                          uint32_t version_info[4];                          if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr) @@ -1330,9 +1403,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l                      // Only bother processing this if we don't already have the uuid set.                      if (!uuid.IsValid())                      { -                        // We'll consume the payload below. -                        processed = true; -                          // 16 bytes is UUID|MD5, 20 bytes is SHA1                          if ((note.n_descsz == 16 || note.n_descsz == 20))                          { @@ -1355,10 +1425,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l                   (note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&                   (note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))          { - -            // We'll consume the payload below. -            processed = true; -              // Pull out the min version info.              uint32_t version_info;              if (data.GetU32 (&offset, &version_info, 1) == nullptr) @@ -1378,8 +1444,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l          else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&                  (note.n_name == LLDB_NT_OWNER_CSR))          { -            // We'll consume the payload below. -            processed = true;              arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);              arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR); @@ -1397,9 +1461,48 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l              arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);              arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android);          } +        else if (note.n_name == LLDB_NT_OWNER_LINUX) +        { +            // This is sometimes found in core files and usually contains extended register info +            arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); +        } +        else if (note.n_name == LLDB_NT_OWNER_CORE) +        { +            // Parse the NT_FILE to look for stuff in paths to shared libraries +            // As the contents look like: +            // count     = 0x000000000000000a (10) +            // page_size = 0x0000000000001000 (4096) +            // Index start              end                file_ofs           path +            // ===== ------------------ ------------------ ------------------ ------------------------------------- +            // [  0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out +            // [  1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out +            // [  2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out +            // [  3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so +            // [  4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so +            // [  5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so +            // [  6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so +            // [  7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so +            // [  8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so +            // [  9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so +            if (note.n_type == NT_FILE) +            { +                uint64_t count = data.GetU64(&offset); +                offset += 8 + 3*8*count; // Skip page size and all start/end/file_ofs +                for (size_t i=0; i<count; ++i) +                { +                    llvm::StringRef path(data.GetCStr(&offset)); +                    if (path.startswith("/lib/x86_64-linux-gnu")) +                    { +                        arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); +                        break; +                    } +                } +            } +        } -        if (!processed) -            offset += llvm::RoundUpToAlignment(note.n_descsz, 4); +        // Calculate the offset of the next note just in case "offset" has been used +        // to poke at the contents of the note data +        offset = note_offset + note.GetByteSize();      }      return error; @@ -1496,8 +1599,8 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                   I != section_headers.end(); ++I)              {                  static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink"); -                const ELFSectionHeaderInfo &header = *I; -                const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size; +                const ELFSectionHeaderInfo &sheader = *I; +                const uint64_t section_size = sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;                  ConstString name(shstr_data.PeekCStr(I->sh_name));                  I->section_name = name; @@ -1505,23 +1608,33 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                  if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel                      || arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el)                  { -                    if (header.sh_type == SHT_MIPS_ABIFLAGS) +                    uint32_t arch_flags = arch_spec.GetFlags (); +                    DataExtractor data; +                    if (sheader.sh_type == SHT_MIPS_ABIFLAGS)                      { -                        DataExtractor data; -                        if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) +                         +                        if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))                          {                              lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0 -                            uint32_t arch_flags = arch_spec.GetFlags ();                              arch_flags |= data.GetU32 (&ase_offset); -                            arch_spec.SetFlags (arch_flags);                          }                      } +                    // Settings appropriate ArchSpec ABI Flags +                    if (header.e_flags & llvm::ELF::EF_MIPS_ABI2) +                    {    +                        arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32; +                    } +                    else if (header.e_flags & llvm::ELF::EF_MIPS_ABI_O32) +                    { +                         arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;        +                    } +                    arch_spec.SetFlags (arch_flags);                  }                  if (name == g_sect_name_gnu_debuglink)                  {                      DataExtractor data; -                    if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) +                    if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))                      {                          lldb::offset_t gnu_debuglink_offset = 0;                          gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset); @@ -1531,7 +1644,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                  }                  // Process ELF note section entries. -                bool is_note_header = (header.sh_type == SHT_NOTE); +                bool is_note_header = (sheader.sh_type == SHT_NOTE);                  // The section header ".note.android.ident" is stored as a                  // PROGBITS type header but it is actually a note header. @@ -1543,7 +1656,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                  {                      // Allow notes to refine module info.                      DataExtractor data; -                    if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size)) +                    if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))                      {                          Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);                          if (error.Fail ()) @@ -1555,6 +1668,12 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers,                  }              } +            // Make any unknown triple components to be unspecified unknowns. +            if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor) +                arch_spec.GetTriple().setVendorName (llvm::StringRef()); +            if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS) +                arch_spec.GetTriple().setOSName (llvm::StringRef()); +              return section_headers.size();          }      } @@ -1651,17 +1770,30 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)              static ConstString g_sect_name_tdata (".tdata");              static ConstString g_sect_name_tbss (".tbss");              static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev"); +            static ConstString g_sect_name_dwarf_debug_addr (".debug_addr");              static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");              static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");              static ConstString g_sect_name_dwarf_debug_info (".debug_info");              static ConstString g_sect_name_dwarf_debug_line (".debug_line");              static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");              static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo"); +            static ConstString g_sect_name_dwarf_debug_macro (".debug_macro");              static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");              static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");              static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");              static ConstString g_sect_name_dwarf_debug_str (".debug_str"); +            static ConstString g_sect_name_dwarf_debug_str_offsets (".debug_str_offsets"); +            static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo"); +            static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo"); +            static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo"); +            static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo"); +            static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo"); +            static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo"); +            static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");              static ConstString g_sect_name_eh_frame (".eh_frame"); +            static ConstString g_sect_name_arm_exidx (".ARM.exidx"); +            static ConstString g_sect_name_arm_extab (".ARM.extab"); +            static ConstString g_sect_name_go_symtab (".gosymtab");              SectionType sect_type = eSectionTypeOther; @@ -1694,18 +1826,31 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)              // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html              // MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644              // MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo -            else if (name == g_sect_name_dwarf_debug_abbrev)    sect_type = eSectionTypeDWARFDebugAbbrev; -            else if (name == g_sect_name_dwarf_debug_aranges)   sect_type = eSectionTypeDWARFDebugAranges; -            else if (name == g_sect_name_dwarf_debug_frame)     sect_type = eSectionTypeDWARFDebugFrame; -            else if (name == g_sect_name_dwarf_debug_info)      sect_type = eSectionTypeDWARFDebugInfo; -            else if (name == g_sect_name_dwarf_debug_line)      sect_type = eSectionTypeDWARFDebugLine; -            else if (name == g_sect_name_dwarf_debug_loc)       sect_type = eSectionTypeDWARFDebugLoc; -            else if (name == g_sect_name_dwarf_debug_macinfo)   sect_type = eSectionTypeDWARFDebugMacInfo; -            else if (name == g_sect_name_dwarf_debug_pubnames)  sect_type = eSectionTypeDWARFDebugPubNames; -            else if (name == g_sect_name_dwarf_debug_pubtypes)  sect_type = eSectionTypeDWARFDebugPubTypes; -            else if (name == g_sect_name_dwarf_debug_ranges)    sect_type = eSectionTypeDWARFDebugRanges; -            else if (name == g_sect_name_dwarf_debug_str)       sect_type = eSectionTypeDWARFDebugStr; -            else if (name == g_sect_name_eh_frame)              sect_type = eSectionTypeEHFrame; +            else if (name == g_sect_name_dwarf_debug_abbrev)          sect_type = eSectionTypeDWARFDebugAbbrev; +            else if (name == g_sect_name_dwarf_debug_addr)            sect_type = eSectionTypeDWARFDebugAddr; +            else if (name == g_sect_name_dwarf_debug_aranges)         sect_type = eSectionTypeDWARFDebugAranges; +            else if (name == g_sect_name_dwarf_debug_frame)           sect_type = eSectionTypeDWARFDebugFrame; +            else if (name == g_sect_name_dwarf_debug_info)            sect_type = eSectionTypeDWARFDebugInfo; +            else if (name == g_sect_name_dwarf_debug_line)            sect_type = eSectionTypeDWARFDebugLine; +            else if (name == g_sect_name_dwarf_debug_loc)             sect_type = eSectionTypeDWARFDebugLoc; +            else if (name == g_sect_name_dwarf_debug_macinfo)         sect_type = eSectionTypeDWARFDebugMacInfo; +            else if (name == g_sect_name_dwarf_debug_macro)           sect_type = eSectionTypeDWARFDebugMacro; +            else if (name == g_sect_name_dwarf_debug_pubnames)        sect_type = eSectionTypeDWARFDebugPubNames; +            else if (name == g_sect_name_dwarf_debug_pubtypes)        sect_type = eSectionTypeDWARFDebugPubTypes; +            else if (name == g_sect_name_dwarf_debug_ranges)          sect_type = eSectionTypeDWARFDebugRanges; +            else if (name == g_sect_name_dwarf_debug_str)             sect_type = eSectionTypeDWARFDebugStr; +            else if (name == g_sect_name_dwarf_debug_str_offsets)     sect_type = eSectionTypeDWARFDebugStrOffsets; +            else if (name == g_sect_name_dwarf_debug_abbrev_dwo)      sect_type = eSectionTypeDWARFDebugAbbrev; +            else if (name == g_sect_name_dwarf_debug_info_dwo)        sect_type = eSectionTypeDWARFDebugInfo; +            else if (name == g_sect_name_dwarf_debug_line_dwo)        sect_type = eSectionTypeDWARFDebugLine; +            else if (name == g_sect_name_dwarf_debug_macro_dwo)       sect_type = eSectionTypeDWARFDebugMacro; +            else if (name == g_sect_name_dwarf_debug_loc_dwo)         sect_type = eSectionTypeDWARFDebugLoc; +            else if (name == g_sect_name_dwarf_debug_str_dwo)         sect_type = eSectionTypeDWARFDebugStr; +            else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets; +            else if (name == g_sect_name_eh_frame)                    sect_type = eSectionTypeEHFrame; +            else if (name == g_sect_name_arm_exidx)                   sect_type = eSectionTypeARMexidx; +            else if (name == g_sect_name_arm_extab)                   sect_type = eSectionTypeARMextab; +            else if (name == g_sect_name_go_symtab)                   sect_type = eSectionTypeGoSymtab;              switch (header.sh_type)              { @@ -1731,7 +1876,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)              if (eSectionTypeOther == sect_type)              {                  // the kalimba toolchain assumes that ELF section names are free-form. It does -                // supports linkscripts which (can) give rise to various arbitarily named +                // support linkscripts which (can) give rise to various arbitrarily named                  // sections being "Code" or "Data".                   sect_type = kalimbaSectionType(m_header, header);              } @@ -1770,17 +1915,19 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)          {              static const SectionType g_sections[] =              { -                eSectionTypeDWARFDebugAranges, -                eSectionTypeDWARFDebugInfo,                  eSectionTypeDWARFDebugAbbrev, +                eSectionTypeDWARFDebugAddr, +                eSectionTypeDWARFDebugAranges,                  eSectionTypeDWARFDebugFrame, +                eSectionTypeDWARFDebugInfo,                  eSectionTypeDWARFDebugLine, -                eSectionTypeDWARFDebugStr,                  eSectionTypeDWARFDebugLoc,                  eSectionTypeDWARFDebugMacInfo,                  eSectionTypeDWARFDebugPubNames,                  eSectionTypeDWARFDebugPubTypes,                  eSectionTypeDWARFDebugRanges, +                eSectionTypeDWARFDebugStr, +                eSectionTypeDWARFDebugStrOffsets,                  eSectionTypeELFSymbolTable,              };              SectionList *elf_section_list = m_sections_ap.get(); @@ -1805,6 +1952,29 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)      }  } +// Find the arm/aarch64 mapping symbol character in the given symbol name. Mapping symbols have the +// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping symbol prefixed by +// an arbitrary string because if a symbol prefix added to each symbol in the object file with +// objcopy then the mapping symbols are also prefixed. +static char +FindArmAarch64MappingSymbol(const char* symbol_name) +{ +    if (!symbol_name) +        return '\0'; + +    const char* dollar_pos = ::strchr(symbol_name, '$'); +    if (!dollar_pos || dollar_pos[1] == '\0') +        return '\0'; + +    if (dollar_pos[2] == '\0' || dollar_pos[2] == '.') +        return dollar_pos[1]; +    return '\0'; +} + +#define STO_MIPS_ISA            (3 << 6) +#define STO_MICROMIPS           (2 << 6) +#define IS_MICROMIPS(ST_OTHER)  (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS) +  // private  unsigned  ObjectFileELF::ParseSymbols (Symtab *symtab, @@ -1840,6 +2010,13 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,      // makes it highly unlikely that this will collide with anything else.      bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat"); +    ArchSpec arch; +    GetArchitecture(arch); + +    // Local cache to avoid doing a FindSectionByName for each symbol. The "const char*" key must +    // came from a ConstString object so they can be compared by pointer +    std::unordered_map<const char*, lldb::SectionSP> section_name_to_section; +      unsigned i;      for (i = 0; i < num_symbols; ++i)      { @@ -1945,64 +2122,58 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,          int64_t symbol_value_offset = 0;          uint32_t additional_flags = 0; -        ArchSpec arch; -        if (GetArchitecture(arch)) +        if (arch.IsValid())          {              if (arch.GetMachine() == llvm::Triple::arm)              { -                if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') +                if (symbol.getBinding() == STB_LOCAL)                  { -                    // These are reserved for the specification (e.g.: mapping -                    // symbols). We don't want to add them to the symbol table. - +                    char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);                      if (symbol_type == eSymbolTypeCode)                      { -                        llvm::StringRef symbol_name_ref(symbol_name); -                        if (symbol_name_ref == "$a" || symbol_name_ref.startswith("$a.")) -                        { -                            // $a[.<any>]* - marks an ARM instruction sequence -                            m_address_class_map[symbol.st_value] = eAddressClassCode; -                        } -                        else if (symbol_name_ref == "$b" || symbol_name_ref.startswith("$b.") || -                                 symbol_name_ref == "$t" || symbol_name_ref.startswith("$t.")) +                        switch (mapping_symbol)                          { -                            // $b[.<any>]* - marks a THUMB BL instruction sequence -                            // $t[.<any>]* - marks a THUMB instruction sequence -                            m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; -                        } -                        else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d.")) -                        { -                            // $d[.<any>]* - marks a data item sequence (e.g. lit pool) -                            m_address_class_map[symbol.st_value] = eAddressClassData; +                            case 'a': +                                // $a[.<any>]* - marks an ARM instruction sequence +                                m_address_class_map[symbol.st_value] = eAddressClassCode; +                                break; +                            case 'b': +                            case 't': +                                // $b[.<any>]* - marks a THUMB BL instruction sequence +                                // $t[.<any>]* - marks a THUMB instruction sequence +                                m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; +                                break; +                            case 'd': +                                // $d[.<any>]* - marks a data item sequence (e.g. lit pool) +                                m_address_class_map[symbol.st_value] = eAddressClassData; +                                break;                          }                      } - -                    continue; +                    if (mapping_symbol) +                        continue;                  }              }              else if (arch.GetMachine() == llvm::Triple::aarch64)              { -                if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$') +                if (symbol.getBinding() == STB_LOCAL)                  { -                    // These are reserved for the specification (e.g.: mapping -                    // symbols). We don't want to add them to the symbol table. - +                    char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);                      if (symbol_type == eSymbolTypeCode)                      { -                        llvm::StringRef symbol_name_ref(symbol_name); -                        if (symbol_name_ref == "$x" || symbol_name_ref.startswith("$x.")) +                        switch (mapping_symbol)                          { -                            // $x[.<any>]* - marks an A64 instruction sequence -                            m_address_class_map[symbol.st_value] = eAddressClassCode; -                        } -                        else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d.")) -                        { -                            // $d[.<any>]* - marks a data item sequence (e.g. lit pool) -                            m_address_class_map[symbol.st_value] = eAddressClassData; +                            case 'x': +                                // $x[.<any>]* - marks an A64 instruction sequence +                                m_address_class_map[symbol.st_value] = eAddressClassCode; +                                break; +                            case 'd': +                                // $d[.<any>]* - marks a data item sequence (e.g. lit pool) +                                m_address_class_map[symbol.st_value] = eAddressClassData; +                                break;                          }                      } - -                    continue; +                    if (mapping_symbol) +                        continue;                  }              } @@ -2029,11 +2200,46 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,                      }                  }              } + +            /* +             * MIPS: +             * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS). +             * This allows processer to switch between microMIPS and MIPS without any need +             * for special mode-control register. However, apart from .debug_line, none of +             * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other +             * flag to check whether the symbol is microMIPS and then set the address class +             * accordingly. +            */ +            const llvm::Triple::ArchType llvm_arch = arch.GetMachine(); +            if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel +                || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) +            { +                if (IS_MICROMIPS(symbol.st_other)) +                    m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; +                else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) +                { +                    symbol.st_value = symbol.st_value & (~1ull); +                    m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; +                } +                else +                { +                    if (symbol_type == eSymbolTypeCode) +                        m_address_class_map[symbol.st_value] = eAddressClassCode; +                    else if (symbol_type == eSymbolTypeData) +                        m_address_class_map[symbol.st_value] = eAddressClassData; +                    else +                        m_address_class_map[symbol.st_value] = eAddressClassUnknown; +                } +            }          } -        // If the symbol section we've found has no data (SHT_NOBITS), then check the module section -        // list. This can happen if we're parsing the debug file and it has no .text section, for example. -        if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0)) +        // symbol_value_offset may contain 0 for ARM symbols or -1 for +        // THUMB symbols. See above for more details. +        uint64_t symbol_value = symbol.st_value + symbol_value_offset; +        if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) +            symbol_value -= symbol_section_sp->GetFileAddress(); + +        if (symbol_section_sp)          {              ModuleSP module_sp(GetModule());              if (module_sp) @@ -2042,20 +2248,17 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,                  if (module_section_list && module_section_list != section_list)                  {                      const ConstString §_name = symbol_section_sp->GetName(); -                    lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name)); -                    if (section_sp && section_sp->GetFileSize()) -                    { -                        symbol_section_sp = section_sp; -                    } +                    auto section_it = section_name_to_section.find(sect_name.GetCString()); +                    if (section_it == section_name_to_section.end()) +                        section_it = section_name_to_section.emplace( +                            sect_name.GetCString(), +                            module_section_list->FindSectionByName (sect_name)).first; +                    if (section_it->second && section_it->second->GetFileSize()) +                        symbol_section_sp = section_it->second;                  }              }          } -        // symbol_value_offset may contain 0 for ARM symbols or -1 for -        // THUMB symbols. See above for more details. -        uint64_t symbol_value = symbol.st_value + symbol_value_offset; -        if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) -            symbol_value -= symbol_section_sp->GetFileAddress();          bool is_global = symbol.getBinding() == STB_GLOBAL;          uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;          bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false; @@ -2069,7 +2272,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,          Mangled mangled(ConstString(symbol_bare), is_mangled);          // Now append the suffix back to mangled and unmangled names. Only do it if the -        // demangling was sucessful (string is not empty). +        // demangling was successful (string is not empty).          if (has_suffix)          {              llvm::StringRef suffix = symbol_ref.substr(version_pos); @@ -2221,7 +2424,7 @@ ObjectFileELF::PLTRelocationType()  }  // Returns the size of the normal plt entries and the offset of the first normal plt entry. The -// 0th entry in the plt table is ususally a resolution entry which have different size in some +// 0th entry in the plt table is usually a resolution entry which have different size in some  // architectures then the rest of the plt entries.  static std::pair<uint64_t, uint64_t>  GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr) @@ -2237,8 +2440,8 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader      {          // The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt          // entries based on the number of entries and the size of the plt section with the -        // asumption that the size of the 0th entry is at least as big as the size of the normal -        // entries and it isn't mutch bigger then that. +        // assumption that the size of the 0th entry is at least as big as the size of the normal +        // entries and it isn't much bigger then that.          if (plt_hdr->sh_addralign)              plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign;          else @@ -2563,8 +2766,6 @@ ObjectFileELF::GetSymtab()          uint64_t symbol_id = 0;          lldb_private::Mutex::Locker locker(module_sp->GetMutex()); -        m_symtab_ap.reset(new Symtab(this)); -          // Sharable objects and dynamic executables usually have 2 distinct symbol          // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller          // version of the symtab that only contains global symbols. The information found @@ -2578,7 +2779,10 @@ ObjectFileELF::GetSymtab()              symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();          }          if (symtab) +        { +            m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));              symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab); +        }          // DT_JMPREL          //      If present, this entry's d_ptr member holds the address of relocation @@ -2598,10 +2802,19 @@ ObjectFileELF::GetSymtab()                  user_id_t reloc_id = reloc_section->GetID();                  const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);                  assert(reloc_header); +                 +                if (m_symtab_ap == nullptr) +                    m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));                  ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);              }          } +         +        // If we still don't have any symtab then create an empty instance to avoid do the section +        // lookup next time. +        if (m_symtab_ap == nullptr) +            m_symtab_ap.reset(new Symtab(this)); +                      m_symtab_ap->CalculateSymbolSizes();      } @@ -3000,6 +3213,27 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch)          ParseSectionHeaders();      } +    if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown()) +    { +        // Core files don't have section headers yet they have PT_NOTE program headers +        // that might shed more light on the architecture +        if (ParseProgramHeaders()) +        { +            for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) +            { +                const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i); +                if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0) +                { +                    DataExtractor data; +                    if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz) +                    { +                        lldb_private::UUID uuid; +                        RefineModuleDetailsFromNote (data, m_arch_spec, uuid); +                    } +                } +            } +        } +    }      arch = m_arch_spec;      return true;  } diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 99088d166b12a..4b97f92c6c5c8 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -10,9 +10,14 @@  #ifndef liblldb_ObjectFileELF_h_  #define liblldb_ObjectFileELF_h_ +// C Includes  #include <stdint.h> + +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Host/FileSpec.h"  #include "lldb/Symbol/ObjectFile.h" @@ -47,6 +52,12 @@ struct ELFNote      ///    True if the ELFRel entry was successfully read and false otherwise.      bool      Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset); + +    size_t +    GetByteSize() const +    { +        return 12 + llvm::RoundUpToAlignment (n_namesz, 4) + llvm::RoundUpToAlignment (n_descsz, 4); +    }  };  //------------------------------------------------------------------------------ @@ -59,6 +70,8 @@ class ObjectFileELF :      public lldb_private::ObjectFile  {  public: +    ~ObjectFileELF() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -113,9 +126,6 @@ public:      //------------------------------------------------------------------      // ObjectFile Protocol.      //------------------------------------------------------------------ -    virtual -    ~ObjectFileELF(); -      bool      ParseHeader() override; @@ -211,6 +221,7 @@ private:      {          lldb_private::ConstString section_name;      }; +      typedef std::vector<ELFSectionHeaderInfo>   SectionHeaderColl;      typedef SectionHeaderColl::iterator         SectionHeaderCollIter;      typedef SectionHeaderColl::const_iterator   SectionHeaderCollConstIter; @@ -428,4 +439,4 @@ private:      RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);  }; -#endif // #ifndef liblldb_ObjectFileELF_h_ +#endif // liblldb_ObjectFileELF_h_ diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h index 47140f5bcaff2..39dbb3fb047b4 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -10,10 +10,13 @@  #ifndef liblldb_ObjectFileJIT_h_  #define liblldb_ObjectFileJIT_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Address.h"  #include "lldb/Symbol/ObjectFile.h" -  //----------------------------------------------------------------------  // This class needs to be hidden as eventually belongs in a plugin that  // will export the ObjectFile protocol @@ -22,6 +25,11 @@ class ObjectFileJIT :      public lldb_private::ObjectFile  {  public: +    ObjectFileJIT(const lldb::ModuleSP &module_sp, +                  const lldb::ObjectFileJITDelegateSP &delegate_sp); + +    ~ObjectFileJIT() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -62,81 +70,77 @@ public:      //------------------------------------------------------------------      // Member Functions      //------------------------------------------------------------------ -    ObjectFileJIT (const lldb::ModuleSP &module_sp, -                   const lldb::ObjectFileJITDelegateSP &delegate_sp); -     -    virtual -    ~ObjectFileJIT(); - -    virtual bool -    ParseHeader (); +    bool +    ParseHeader() override; -    virtual bool +    bool      SetLoadAddress(lldb_private::Target &target,                     lldb::addr_t value, -                   bool value_is_offset); +                   bool value_is_offset) override; -    virtual lldb::ByteOrder -    GetByteOrder () const; +    lldb::ByteOrder +    GetByteOrder() const override; -    virtual bool -    IsExecutable () const; +    bool +    IsExecutable() const override; -    virtual uint32_t -    GetAddressByteSize ()  const; +    uint32_t +    GetAddressByteSize() const override; -    virtual lldb_private::Symtab * -    GetSymtab(); +    lldb_private::Symtab * +    GetSymtab() override; -    virtual bool -    IsStripped (); +    bool +    IsStripped() override; -    virtual void -    CreateSections (lldb_private::SectionList &unified_section_list); +    void +    CreateSections(lldb_private::SectionList &unified_section_list) override; -    virtual void -    Dump (lldb_private::Stream *s); +    void +    Dump(lldb_private::Stream *s) override; -    virtual bool -    GetArchitecture (lldb_private::ArchSpec &arch); +    bool +    GetArchitecture(lldb_private::ArchSpec &arch) override; -    virtual bool -    GetUUID (lldb_private::UUID* uuid); +    bool +    GetUUID(lldb_private::UUID* uuid) override; -    virtual uint32_t -    GetDependentModules (lldb_private::FileSpecList& files); +    uint32_t +    GetDependentModules(lldb_private::FileSpecList& files) override; +     +    size_t +    ReadSectionData(const lldb_private::Section *section, +                    lldb::offset_t section_offset, +                    void *dst, +                    size_t dst_len) const override; + +    size_t +    ReadSectionData(const lldb_private::Section *section, +                    lldb_private::DataExtractor& section_data) const override; -    virtual size_t -    ReadSectionData (const lldb_private::Section *section, -                     lldb::offset_t section_offset, -                     void *dst, -                     size_t dst_len) const; -    virtual size_t -    ReadSectionData (const lldb_private::Section *section, -                     lldb_private::DataExtractor& section_data) const; +    lldb_private::Address +    GetEntryPointAddress() override; +    lldb_private::Address +    GetHeaderAddress() override; +     +    ObjectFile::Type +    CalculateType() override; +     +    ObjectFile::Strata +    CalculateStrata() override; +      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override; -    virtual lldb_private::Address -    GetEntryPointAddress (); -     -    virtual lldb_private::Address -    GetHeaderAddress (); -     -    virtual ObjectFile::Type -    CalculateType(); -     -    virtual ObjectFile::Strata -    CalculateStrata();  protected:      lldb::ObjectFileJITDelegateWP m_delegate_wp;  }; -#endif  // liblldb_ObjectFileJIT_h_ +#endif // liblldb_ObjectFileJIT_h_ diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp new file mode 100644 index 0000000000000..86c574f2776c2 --- /dev/null +++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp @@ -0,0 +1,559 @@ +//===-- OperatingSystemGo.cpp -----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <unordered_map> + +// Other libraries and framework includes +// Project includes +#include "OperatingSystemGo.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionGroupBoolean.h" +#include "lldb/Interpreter/OptionGroupUInt64.h" +#include "lldb/Interpreter/Property.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadList.h" +#include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/DynamicRegisterInfo.h" +#include "Plugins/Process/Utility/RegisterContextMemory.h" +#include "Plugins/Process/Utility/ThreadMemory.h" + +using namespace lldb; +using namespace lldb_private; + +namespace +{ + +static PropertyDefinition g_properties[] = {{"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, +                                             "Specify whether goroutines should be treated as threads."}, +                                            {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; + +enum +{ +    ePropertyEnableGoroutines, +}; + +class PluginProperties : public Properties +{ +public: +    PluginProperties() +        : Properties() +    { +        m_collection_sp.reset(new OptionValueProperties(GetSettingName())); +        m_collection_sp->Initialize(g_properties); +    } + +    ~PluginProperties() override = default; + +    static ConstString +    GetSettingName() +    { +        return OperatingSystemGo::GetPluginNameStatic(); +    } + +    bool +    GetEnableGoroutines() +    { +        const uint32_t idx = ePropertyEnableGoroutines; +        return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value); +    } + +    bool +    SetEnableGoroutines(bool enable) +    { +        const uint32_t idx = ePropertyEnableGoroutines; +        return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, enable); +    } +}; + +typedef std::shared_ptr<PluginProperties> OperatingSystemGoPropertiesSP; + +static const OperatingSystemGoPropertiesSP & +GetGlobalPluginProperties() +{ +    static OperatingSystemGoPropertiesSP g_settings_sp; +    if (!g_settings_sp) +        g_settings_sp.reset(new PluginProperties()); +    return g_settings_sp; +} + +class RegisterContextGo : public RegisterContextMemory +{ +public: +    RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx, DynamicRegisterInfo ®_info, +                      lldb::addr_t reg_data_addr) +        : RegisterContextMemory(thread, concrete_frame_idx, reg_info, reg_data_addr) +    { +        const RegisterInfo *sp = reg_info.GetRegisterInfoAtIndex( +            reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP)); +        const RegisterInfo *pc = reg_info.GetRegisterInfoAtIndex( +            reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC)); +        size_t byte_size = std::max(sp->byte_offset + sp->byte_size, pc->byte_offset + pc->byte_size); + +        DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0)); +        m_reg_data.SetData(reg_data_sp); +    } + +    ~RegisterContextGo() override = default; + +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue ®_value) override +    { +        switch (reg_info->kinds[eRegisterKindGeneric]) +        { +            case LLDB_REGNUM_GENERIC_SP: +            case LLDB_REGNUM_GENERIC_PC: +                return RegisterContextMemory::ReadRegister(reg_info, reg_value); +            default: +                reg_value.SetValueToInvalid(); +                return true; +        } +    } + +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue ®_value) override +    { +        switch (reg_info->kinds[eRegisterKindGeneric]) +        { +            case LLDB_REGNUM_GENERIC_SP: +            case LLDB_REGNUM_GENERIC_PC: +                return RegisterContextMemory::WriteRegister(reg_info, reg_value); +            default: +                return false; +        } +    } + +private: +    DISALLOW_COPY_AND_ASSIGN(RegisterContextGo); +}; + +} // anonymous namespace + +struct OperatingSystemGo::Goroutine +{ +    uint64_t m_lostack; +    uint64_t m_histack; +    uint64_t m_goid; +    addr_t m_gobuf; +    uint32_t m_status; +}; + +void +OperatingSystemGo::Initialize() +{ +    PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, +                                  DebuggerInitialize); +} + +void +OperatingSystemGo::DebuggerInitialize(Debugger &debugger) +{ +    if (!PluginManager::GetSettingForOperatingSystemPlugin(debugger, PluginProperties::GetSettingName())) +    { +        const bool is_global_setting = true; +        PluginManager::CreateSettingForOperatingSystemPlugin( +            debugger, GetGlobalPluginProperties()->GetValueProperties(), +            ConstString("Properties for the goroutine thread plug-in."), is_global_setting); +    } +} + +void +OperatingSystemGo::Terminate() +{ +    PluginManager::UnregisterPlugin(CreateInstance); +} + +OperatingSystem * +OperatingSystemGo::CreateInstance(Process *process, bool force) +{ +    if (!force) +    { +        TargetSP target_sp = process->CalculateTarget(); +        if (!target_sp) +            return nullptr; +        ModuleList &module_list = target_sp->GetImages(); +        Mutex::Locker modules_locker(module_list.GetMutex()); +        const size_t num_modules = module_list.GetSize(); +        bool found_go_runtime = false; +        for (size_t i = 0; i < num_modules; ++i) +        { +            Module *module = module_list.GetModulePointerAtIndexUnlocked(i); +            const SectionList *section_list = module->GetSectionList(); +            if (section_list) +            { +                SectionSP section_sp(section_list->FindSectionByType(eSectionTypeGoSymtab, true)); +                if (section_sp) +                { +                    found_go_runtime = true; +                    break; +                } +            } +        } +        if (!found_go_runtime) +            return nullptr; +    } +    return new OperatingSystemGo(process); +} + +OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process) +    : OperatingSystem(process) +    , m_reginfo(new DynamicRegisterInfo) +{ +} + +OperatingSystemGo::~OperatingSystemGo() = default; + +ConstString +OperatingSystemGo::GetPluginNameStatic() +{ +    static ConstString g_name("goroutines"); +    return g_name; +} + +const char * +OperatingSystemGo::GetPluginDescriptionStatic() +{ +    return "Operating system plug-in that reads runtime data-structures for goroutines."; +} + +bool +OperatingSystemGo::Init(ThreadList &threads) +{ +    if (threads.GetSize(false) < 1) +        return false; +    TargetSP target_sp = m_process->CalculateTarget(); +    if (!target_sp) +        return false; +    m_allg_sp = FindGlobal(target_sp, "runtime.allg"); +    m_allglen_sp = FindGlobal(target_sp, "runtime.allglen"); + +    if (m_allg_sp && !m_allglen_sp) +    { +        StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream(); +        error_sp->Printf("Unsupported Go runtime version detected."); +        return false; +    } + +    if (!m_allg_sp) +        return false; + +    RegisterContextSP real_registers_sp = threads.GetThreadAtIndex(0, false)->GetRegisterContext(); + +    std::unordered_map<size_t, ConstString> register_sets; +    for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount(); ++set_idx) +    { +        const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx); +        ConstString name(set->name); +        for (size_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx) +        { +            register_sets[reg_idx] = name; +        } +    } +    TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf"); +    if (!gobuf_sp) +    { +        Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + +        if (log) +            log->Printf("OperatingSystemGo unable to find struct Gobuf"); +        return false; +    } +    CompilerType gobuf_type(gobuf_sp->GetLayoutCompilerType()); +    for (size_t idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx) +    { +        RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx); +        int field_index = -1; +        if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) +        { +            field_index = 0; +        } +        else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC) +        { +            field_index = 1; +        } +        if (field_index == -1) +        { +            reg.byte_offset = ~0; +        } +        else +        { +            std::string field_name; +            uint64_t bit_offset = 0; +            CompilerType field_type = +                gobuf_type.GetFieldAtIndex(field_index, field_name, &bit_offset, nullptr, nullptr); +            reg.byte_size = field_type.GetByteSize(nullptr); +            reg.byte_offset = bit_offset / 8; +        } +        ConstString name(reg.name); +        ConstString alt_name(reg.alt_name); +        m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]); +    } +    return true; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +ConstString +OperatingSystemGo::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +OperatingSystemGo::GetPluginVersion() +{ +    return 1; +} + +bool +OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list, ThreadList &real_thread_list, +                                    ThreadList &new_thread_list) +{ +    new_thread_list = real_thread_list; +    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + +    if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) || +        !GetGlobalPluginProperties()->GetEnableGoroutines()) +    { +        return new_thread_list.GetSize(false) > 0; +    } + +    if (log) +        log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching thread data from Go for pid %" PRIu64, +                    old_thread_list.GetSize(false), real_thread_list.GetSize(false), new_thread_list.GetSize(0), +                    m_process->GetID()); +    uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0); +    if (allglen == 0) +    { +        return new_thread_list.GetSize(false) > 0; +    } +    std::vector<Goroutine> goroutines; +    // The threads that are in "new_thread_list" upon entry are the threads from the +    // lldb_private::Process subclass, no memory threads will be in this list. + +    Error err; +    for (uint64_t i = 0; i < allglen; ++i) +    { +        goroutines.push_back(CreateGoroutineAtIndex(i, err)); +        if (err.Fail()) +        { +            err.PutToLog(log, "OperatingSystemGo::UpdateThreadList"); +            return new_thread_list.GetSize(false) > 0; +        } +    } +    // Make a map so we can match goroutines with backing threads. +    std::map<uint64_t, ThreadSP> stack_map; +    for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i) +    { +        ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false); +        stack_map[thread->GetRegisterContext()->GetSP()] = thread; +    } +    for (const Goroutine &goroutine : goroutines) +    { +        if (0 /* Gidle */ == goroutine.m_status || 6 /* Gdead */ == goroutine.m_status) +        { +            continue; +        } +        ThreadSP memory_thread = old_thread_list.FindThreadByID(goroutine.m_goid, false); +        if (memory_thread && IsOperatingSystemPluginThread(memory_thread) && memory_thread->IsValid()) +        { +            memory_thread->ClearBackingThread(); +        } +        else +        { +            memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, nullptr, nullptr, goroutine.m_gobuf)); +        } +        // Search for the backing thread if the goroutine is running. +        if (2 == (goroutine.m_status & 0xfff)) +        { +            auto backing_it = stack_map.lower_bound(goroutine.m_lostack); +            if (backing_it != stack_map.end()) +            { +                if (goroutine.m_histack >= backing_it->first) +                { +                    if (log) +                        log->Printf("OperatingSystemGo::UpdateThreadList found backing thread %" PRIx64 " (%" PRIx64 +                                    ") for thread %" PRIx64 "", +                                    backing_it->second->GetID(), backing_it->second->GetProtocolID(), +                                    memory_thread->GetID()); +                    memory_thread->SetBackingThread(backing_it->second); +                    new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false); +                } +            } +        } +        new_thread_list.AddThread(memory_thread); +    } + +    return new_thread_list.GetSize(false) > 0; +} + +void +OperatingSystemGo::ThreadWasSelected(Thread *thread) +{ +} + +RegisterContextSP +OperatingSystemGo::CreateRegisterContextForThread(Thread *thread, addr_t reg_data_addr) +{ +    RegisterContextSP reg_ctx_sp; +    if (!thread) +        return reg_ctx_sp; + +    if (!IsOperatingSystemPluginThread(thread->shared_from_this())) +        return reg_ctx_sp; + +    reg_ctx_sp.reset(new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr)); +    return reg_ctx_sp; +} + +StopInfoSP +OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread) +{ +    StopInfoSP stop_info_sp; +    return stop_info_sp; +} + +lldb::ThreadSP +OperatingSystemGo::CreateThread(lldb::tid_t tid, addr_t context) +{ +    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + +    if (log) +        log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") not implemented", +                    tid, context); + +    return ThreadSP(); +} + +ValueObjectSP +OperatingSystemGo::FindGlobal(TargetSP target, const char *name) +{ +    VariableList variable_list; +    const bool append = true; + +    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + +    if (log) +    { +        log->Printf("exe: %s", target->GetExecutableModule()->GetSpecificationDescription().c_str()); +        log->Printf("modules: %zu", target->GetImages().GetSize()); +    } + +    uint32_t match_count = target->GetImages().FindGlobalVariables(ConstString(name), append, 1, variable_list); +    if (match_count > 0) +    { +        ExecutionContextScope *exe_scope = target->GetProcessSP().get(); +        if (exe_scope == NULL) +            exe_scope = target.get(); +        return ValueObjectVariable::Create(exe_scope, variable_list.GetVariableAtIndex(0)); +    } +    return ValueObjectSP(); +} + +TypeSP +OperatingSystemGo::FindType(TargetSP target_sp, const char *name) +{ +    ConstString const_typename(name); +    SymbolContext sc; +    const bool exact_match = false; + +    const ModuleList &module_list = target_sp->GetImages(); +    size_t count = module_list.GetSize(); +    for (size_t idx = 0; idx < count; idx++) +    { +        ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); +        if (module_sp) +        { +            TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match)); +            if (type_sp) +                return type_sp; +        } +    } +    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS)); + +    if (log) +        log->Printf("OperatingSystemGo::FindType(%s): not found", name); +    return TypeSP(); +} + +OperatingSystemGo::Goroutine +OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err) +{ +    err.Clear(); +    Goroutine result; +    ValueObjectSP g = m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err); +    if (err.Fail()) +    { +        return result; +    } + +    ConstString name("goid"); +    ValueObjectSP val = g->GetChildMemberWithName(name, true); +    bool success = false; +    result.m_goid = val->GetValueAsUnsigned(0, &success); +    if (!success) +    { +        err.SetErrorToGenericError(); +        err.SetErrorString("unable to read goid"); +        return result; +    } +    name.SetCString("atomicstatus"); +    val = g->GetChildMemberWithName(name, true); +    result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success); +    if (!success) +    { +        err.SetErrorToGenericError(); +        err.SetErrorString("unable to read atomicstatus"); +        return result; +    } +    name.SetCString("sched"); +    val = g->GetChildMemberWithName(name, true); +    result.m_gobuf = val->GetAddressOf(false); +    name.SetCString("stack"); +    val = g->GetChildMemberWithName(name, true); +    name.SetCString("lo"); +    ValueObjectSP child = val->GetChildMemberWithName(name, true); +    result.m_lostack = child->GetValueAsUnsigned(0, &success); +    if (!success) +    { +        err.SetErrorToGenericError(); +        err.SetErrorString("unable to read stack.lo"); +        return result; +    } +    name.SetCString("hi"); +    child = val->GetChildMemberWithName(name, true); +    result.m_histack = child->GetValueAsUnsigned(0, &success); +    if (!success) +    { +        err.SetErrorToGenericError(); +        err.SetErrorString("unable to read stack.hi"); +        return result; +    } +    return result; +} diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h new file mode 100644 index 0000000000000..d3391d907dfe5 --- /dev/null +++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h @@ -0,0 +1,87 @@ +//===-- OperatingSystemGo.h -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _liblldb_OperatingSystemGo_h_ +#define _liblldb_OperatingSystemGo_h_ + +// C Includes +// C++ Includes +#include <memory> + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/OperatingSystem.h" + +class DynamicRegisterInfo; + +class OperatingSystemGo : public lldb_private::OperatingSystem +{ +public: +    OperatingSystemGo(lldb_private::Process *process); + +    ~OperatingSystemGo() override; + +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static lldb_private::OperatingSystem *CreateInstance(lldb_private::Process *process, bool force); + +    static void Initialize(); + +    static void DebuggerInitialize(lldb_private::Debugger &debugger); + +    static void Terminate(); + +    static lldb_private::ConstString GetPluginNameStatic(); + +    static const char *GetPluginDescriptionStatic(); + +    //------------------------------------------------------------------ +    // lldb_private::PluginInterface Methods +    //------------------------------------------------------------------ +    lldb_private::ConstString GetPluginName() override; + +    uint32_t GetPluginVersion() override; + +    //------------------------------------------------------------------ +    // lldb_private::OperatingSystem Methods +    //------------------------------------------------------------------ +    bool UpdateThreadList(lldb_private::ThreadList &old_thread_list, +                          lldb_private::ThreadList &real_thread_list, +                          lldb_private::ThreadList &new_thread_list) override; + +    void ThreadWasSelected(lldb_private::Thread *thread) override; + +    lldb::RegisterContextSP CreateRegisterContextForThread(lldb_private::Thread *thread, +                                                           lldb::addr_t reg_data_addr) override; + +    lldb::StopInfoSP CreateThreadStopReason(lldb_private::Thread *thread) override; + +    //------------------------------------------------------------------ +    // Method for lazy creation of threads on demand +    //------------------------------------------------------------------ +    lldb::ThreadSP CreateThread(lldb::tid_t tid, lldb::addr_t context) override; + +private: +    struct Goroutine; + +    static lldb::ValueObjectSP FindGlobal(lldb::TargetSP target, const char *name); + +    static lldb::TypeSP FindType(lldb::TargetSP target_sp, const char *name); + +    bool Init(lldb_private::ThreadList &threads); + +    Goroutine CreateGoroutineAtIndex(uint64_t idx, lldb_private::Error &err); + +    std::unique_ptr<DynamicRegisterInfo> m_reginfo; +    lldb::ValueObjectSP m_allg_sp; +    lldb::ValueObjectSP m_allglen_sp; +}; + +#endif // liblldb_OperatingSystemGo_h_ diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index e744d13deec1a..a556b0e84e83b 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -24,7 +24,6 @@  #include "lldb/Core/ValueObjectVariable.h"  #include "lldb/Interpreter/CommandInterpreter.h"  #include "lldb/Interpreter/ScriptInterpreter.h" -#include "lldb/Symbol/ClangNamespaceDecl.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Symbol/VariableList.h"  #include "lldb/Target/Process.h" @@ -43,9 +42,7 @@ using namespace lldb_private;  void  OperatingSystemPython::Initialize()  { -    PluginManager::RegisterPlugin (GetPluginNameStatic(), -                                   GetPluginDescriptionStatic(), -                                   CreateInstance); +    PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, nullptr);  }  void diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h index e29bf8054f6c0..1b33c42cf0fef 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h @@ -1,4 +1,4 @@ -//===-- OperatingSystemPython.h ---------------------------*- C++ -*-===// +//===-- OperatingSystemPython.h ---------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -6,14 +6,16 @@  // License. See LICENSE.TXT for details.  //  //===----------------------------------------------------------------------===// -#ifndef LLDB_DISABLE_PYTHON  #ifndef liblldb_OperatingSystemPython_h_  #define liblldb_OperatingSystemPython_h_ +#ifndef LLDB_DISABLE_PYTHON +  // C Includes  // C++ Includes  // Other libraries and framework includes +// Project includes  #include "lldb/Core/StructuredData.h"  #include "lldb/Target/OperatingSystem.h" @@ -27,6 +29,11 @@ class ScriptInterpreter;  class OperatingSystemPython : public lldb_private::OperatingSystem  {  public: +    OperatingSystemPython(lldb_private::Process *process, +                          const lldb_private::FileSpec &python_module_path); + +    ~OperatingSystemPython() override; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -46,49 +53,39 @@ public:      GetPluginDescriptionStatic();      //------------------------------------------------------------------ -    // Class Methods -    //------------------------------------------------------------------ -    OperatingSystemPython (lldb_private::Process *process, -                           const lldb_private::FileSpec &python_module_path); -     -    virtual -    ~OperatingSystemPython (); -     -    //------------------------------------------------------------------      // lldb_private::PluginInterface Methods      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;      //------------------------------------------------------------------      // lldb_private::OperatingSystem Methods      //------------------------------------------------------------------ -    virtual bool -    UpdateThreadList (lldb_private::ThreadList &old_thread_list, -                      lldb_private::ThreadList &real_thread_list, -                      lldb_private::ThreadList &new_thread_list); +    bool +    UpdateThreadList(lldb_private::ThreadList &old_thread_list, +                     lldb_private::ThreadList &real_thread_list, +                     lldb_private::ThreadList &new_thread_list) override; -    virtual void -    ThreadWasSelected (lldb_private::Thread *thread); +    void +    ThreadWasSelected(lldb_private::Thread *thread) override; -    virtual lldb::RegisterContextSP -    CreateRegisterContextForThread (lldb_private::Thread *thread, -                                    lldb::addr_t reg_data_addr); +    lldb::RegisterContextSP +    CreateRegisterContextForThread(lldb_private::Thread *thread, +                                   lldb::addr_t reg_data_addr) override; -    virtual lldb::StopInfoSP -    CreateThreadStopReason (lldb_private::Thread *thread); +    lldb::StopInfoSP +    CreateThreadStopReason(lldb_private::Thread *thread) override;      //------------------------------------------------------------------      // Method for lazy creation of threads on demand      //------------------------------------------------------------------ -    virtual lldb::ThreadSP -    CreateThread (lldb::tid_t tid, lldb::addr_t context); +    lldb::ThreadSP +    CreateThread(lldb::tid_t tid, lldb::addr_t context) override;  protected: -          bool IsValid() const      {          return m_python_object_sp && m_python_object_sp->IsValid(); @@ -107,5 +104,6 @@ protected:      lldb_private::StructuredData::ObjectSP m_python_object_sp;  }; -#endif // #ifndef liblldb_OperatingSystemPython_h_ -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif // LLDB_DISABLE_PYTHON + +#endif // liblldb_OperatingSystemPython_h_ diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h index 67156e6ae37b6..d1bfc438a3419 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h @@ -22,6 +22,9 @@ namespace platform_freebsd {      class PlatformFreeBSD : public Platform      {      public: +        PlatformFreeBSD(bool is_host); + +        ~PlatformFreeBSD() override;          //------------------------------------------------------------          // Class functions @@ -42,14 +45,6 @@ namespace platform_freebsd {          GetDescriptionStatic (bool is_host);          //------------------------------------------------------------ -        // Class Methods -        //------------------------------------------------------------ -        PlatformFreeBSD (bool is_host); - -        virtual -        ~PlatformFreeBSD(); - -        //------------------------------------------------------------          // lldb_private::PluginInterface functions          //------------------------------------------------------------          ConstString @@ -179,4 +174,4 @@ namespace platform_freebsd {  } // namespace platform_freebsd  } // namespace lldb_private -#endif  // liblldb_PlatformFreeBSD_h_ +#endif // liblldb_PlatformFreeBSD_h_ diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp new file mode 100644 index 0000000000000..2979d1e438b77 --- /dev/null +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -0,0 +1,685 @@ +//===-- PlatformNetBSD.cpp -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PlatformNetBSD.h" +#include "lldb/Host/Config.h" + +// C Includes +#include <stdio.h> +#ifndef LLDB_DISABLE_POSIX +#include <sys/utsname.h> +#endif + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/BreakpointSite.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Process.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_netbsd; + +PlatformSP +PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) +{ +    // The only time we create an instance is when we are creating a remote +    // netbsd platform +    const bool is_host = false; + +    bool create = force; +    if (create == false && arch && arch->IsValid()) +    { +        const llvm::Triple &triple = arch->GetTriple(); +        switch (triple.getOS()) +        { +            case llvm::Triple::NetBSD: +                create = true; +                break; + +            default: +                break; +        } +    } +    if (create) +        return PlatformSP(new PlatformNetBSD (is_host)); +    return PlatformSP(); + +} + +ConstString +PlatformNetBSD::GetPluginNameStatic(bool is_host) +{ +    if (is_host) +    { +        static ConstString g_host_name(Platform::GetHostPlatformName ()); +        return g_host_name; +    } +    else +    { +        static ConstString g_remote_name("remote-netbsd"); +        return g_remote_name; +    } +} + +const char * +PlatformNetBSD::GetDescriptionStatic (bool is_host) +{ +    if (is_host) +        return "Local NetBSD user platform plug-in."; +    else +        return "Remote NetBSD user platform plug-in."; +} + +static uint32_t g_initialize_count = 0; + +void +PlatformNetBSD::Initialize () +{ +    Platform::Initialize (); + +    if (g_initialize_count++ == 0) +    { +#if defined(__NetBSD__) +        // Force a host flag to true for the default platform object. +        PlatformSP default_platform_sp (new PlatformNetBSD(true)); +        default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); +        Platform::SetHostPlatform (default_platform_sp); +#endif +        PluginManager::RegisterPlugin(PlatformNetBSD::GetPluginNameStatic(false), +                                      PlatformNetBSD::GetDescriptionStatic(false), +                                      PlatformNetBSD::CreateInstance); +    } +} + +void +PlatformNetBSD::Terminate () +{ +    if (g_initialize_count > 0 && --g_initialize_count == 0) +        PluginManager::UnregisterPlugin (PlatformNetBSD::CreateInstance); + +    Platform::Terminate (); +} + +bool +PlatformNetBSD::GetModuleSpec (const FileSpec& module_file_spec, +                               const ArchSpec& arch, +                               ModuleSpec &module_spec) +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec); + +    return Platform::GetModuleSpec (module_file_spec, arch, module_spec); +} + +Error +PlatformNetBSD::RunShellCommand(const char *command, +                                const FileSpec &working_dir, +                                int *status_ptr, +                                int *signo_ptr, +                                std::string *command_output, +                                uint32_t timeout_sec) +{ +    if (IsHost()) +        return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); +    else +    { +        if (m_remote_platform_sp) +            return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec); +        else +            return Error("unable to run a remote command without a platform"); +    } +} + +Error +PlatformNetBSD::ResolveExecutable (const ModuleSpec &module_spec, +                                   lldb::ModuleSP &exe_module_sp, +                                   const FileSpecList *module_search_paths_ptr) +{ +    Error error; +    // Nothing special to do here, just use the actual file and architecture + +    char exe_path[PATH_MAX]; +    ModuleSpec resolved_module_spec(module_spec); + +    if (IsHost()) +    { +        // If we have "ls" as the module_spec's file, resolve the executable location based on +        // the current path variables +        if (!resolved_module_spec.GetFileSpec().Exists()) +        { +            module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path)); +            resolved_module_spec.GetFileSpec().SetFile(exe_path, true); +        } + +        if (!resolved_module_spec.GetFileSpec().Exists()) +            resolved_module_spec.GetFileSpec().ResolveExecutableLocation (); + +        if (resolved_module_spec.GetFileSpec().Exists()) +            error.Clear(); +        else +        { +            error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str()); +        } +    } +    else +    { +        if (m_remote_platform_sp) +        { +            error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp); +        } +        else +        { +            // We may connect to a process and use the provided executable (Don't use local $PATH). + +            // Resolve any executable within a bundle on MacOSX +            Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec()); + +            if (resolved_module_spec.GetFileSpec().Exists()) +            { +                error.Clear(); +            } +            else +            { +                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str()); +            } +        } +    } + +    if (error.Success()) +    { +        if (resolved_module_spec.GetArchitecture().IsValid()) +        { +            error = ModuleList::GetSharedModule (resolved_module_spec, +                                                 exe_module_sp, +                                                 module_search_paths_ptr, +                                                 NULL, +                                                 NULL); + +            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) +            { +                exe_module_sp.reset(); +                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", +                                                resolved_module_spec.GetFileSpec().GetPath().c_str(), +                                                resolved_module_spec.GetArchitecture().GetArchitectureName()); +            } +        } +        else +        { +            // No valid architecture was specified, ask the platform for +            // the architectures that we should be using (in the correct order) +            // and see if we can find a match that way +            StreamString arch_names; +            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx) +            { +                error = ModuleList::GetSharedModule (resolved_module_spec, +                                                     exe_module_sp, +                                                     module_search_paths_ptr, +                                                     NULL, +                                                     NULL); +                // Did we find an executable using one of the +                if (error.Success()) +                { +                    if (exe_module_sp && exe_module_sp->GetObjectFile()) +                        break; +                    else +                        error.SetErrorToGenericError(); +                } + +                if (idx > 0) +                    arch_names.PutCString (", "); +                arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName()); +            } + +            if (error.Fail() || !exe_module_sp) +            { +                if (resolved_module_spec.GetFileSpec().Readable()) +                { +                    error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", +                                                    resolved_module_spec.GetFileSpec().GetPath().c_str(), +                                                    GetPluginName().GetCString(), +                                                    arch_names.GetString().c_str()); +                } +                else +                { +                    error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str()); +                } +            } +        } +    } + +    return error; +} + +// From PlatformMacOSX only +Error +PlatformNetBSD::GetFileWithUUID (const FileSpec &platform_file, +                                 const UUID *uuid_ptr, +                                 FileSpec &local_file) +{ +    if (IsRemote()) +    { +        if (m_remote_platform_sp) +            return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file); +    } + +    // Default to the local case +    local_file = platform_file; +    return Error(); +} + + +//------------------------------------------------------------------ +/// Default Constructor +//------------------------------------------------------------------ +PlatformNetBSD::PlatformNetBSD (bool is_host) : +    Platform(is_host), +    m_remote_platform_sp() +{ +} + +bool +PlatformNetBSD::GetRemoteOSVersion () +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetOSVersion (m_major_os_version, +                                                   m_minor_os_version, +                                                   m_update_os_version); +    return false; +} + +bool +PlatformNetBSD::GetRemoteOSBuildString (std::string &s) +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetRemoteOSBuildString (s); +    s.clear(); +    return false; +} + +bool +PlatformNetBSD::GetRemoteOSKernelDescription (std::string &s) +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetRemoteOSKernelDescription (s); +    s.clear(); +    return false; +} + +// Remote Platform subclasses need to override this function +ArchSpec +PlatformNetBSD::GetRemoteSystemArchitecture () +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetRemoteSystemArchitecture (); +    return ArchSpec(); +} + + +const char * +PlatformNetBSD::GetHostname () +{ +    if (IsHost()) +        return Platform::GetHostname(); + +    if (m_remote_platform_sp) +        return m_remote_platform_sp->GetHostname (); +    return NULL; +} + +bool +PlatformNetBSD::IsConnected () const +{ +    if (IsHost()) +        return true; +    else if (m_remote_platform_sp) +        return m_remote_platform_sp->IsConnected(); +    return false; +} + +Error +PlatformNetBSD::ConnectRemote (Args& args) +{ +    Error error; +    if (IsHost()) +    { +        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); +    } +    else +    { +        if (!m_remote_platform_sp) +            m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error); + +        if (m_remote_platform_sp) +        { +            if (error.Success()) +            { +                if (m_remote_platform_sp) +                { +                    error = m_remote_platform_sp->ConnectRemote (args); +                } +                else +                { +                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>"); +                } +            } +        } +        else +            error.SetErrorString ("failed to create a 'remote-gdb-server' platform"); + +        if (error.Fail()) +            m_remote_platform_sp.reset(); +    } + +    return error; +} + +Error +PlatformNetBSD::DisconnectRemote () +{ +    Error error; + +    if (IsHost()) +    { +        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString()); +    } +    else +    { +        if (m_remote_platform_sp) +            error = m_remote_platform_sp->DisconnectRemote (); +        else +            error.SetErrorString ("the platform is not currently connected"); +    } +    return error; +} + +bool +PlatformNetBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) +{ +    bool success = false; +    if (IsHost()) +    { +        success = Platform::GetProcessInfo (pid, process_info); +    } +    else if (m_remote_platform_sp) +    { +        success = m_remote_platform_sp->GetProcessInfo (pid, process_info); +    } +    return success; +} + +uint32_t +PlatformNetBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info, +                               ProcessInstanceInfoList &process_infos) +{ +    uint32_t match_count = 0; +    if (IsHost()) +    { +        // Let the base class figure out the host details +        match_count = Platform::FindProcesses (match_info, process_infos); +    } +    else +    { +        // If we are remote, we can only return results if we are connected +        if (m_remote_platform_sp) +            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos); +    } +    return match_count; +} + +const char * +PlatformNetBSD::GetUserName (uint32_t uid) +{ +    // Check the cache in Platform in case we have already looked this uid up +    const char *user_name = Platform::GetUserName(uid); +    if (user_name) +        return user_name; + +    if (IsRemote() && m_remote_platform_sp) +        return m_remote_platform_sp->GetUserName(uid); +    return NULL; +} + +const char * +PlatformNetBSD::GetGroupName (uint32_t gid) +{ +    const char *group_name = Platform::GetGroupName(gid); +    if (group_name) +        return group_name; + +    if (IsRemote() && m_remote_platform_sp) +        return m_remote_platform_sp->GetGroupName(gid); +    return NULL; +} + + +Error +PlatformNetBSD::GetSharedModule (const ModuleSpec &module_spec, +                                 Process* process, +                                 ModuleSP &module_sp, +                                 const FileSpecList *module_search_paths_ptr, +                                 ModuleSP *old_module_sp_ptr, +                                 bool *did_create_ptr) +{ +    Error error; +    module_sp.reset(); + +    if (IsRemote()) +    { +        // If we have a remote platform always, let it try and locate +        // the shared module first. +        if (m_remote_platform_sp) +        { +            error = m_remote_platform_sp->GetSharedModule (module_spec, +                                                           process, +                                                           module_sp, +                                                           module_search_paths_ptr, +                                                           old_module_sp_ptr, +                                                           did_create_ptr); +        } +    } + +    if (!module_sp) +    { +        // Fall back to the local platform and find the file locally +        error = Platform::GetSharedModule (module_spec, +                                           process, +                                           module_sp, +                                           module_search_paths_ptr, +                                           old_module_sp_ptr, +                                           did_create_ptr); +    } +    if (module_sp) +        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec()); +    return error; +} + + +bool +PlatformNetBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) +{ +    if (IsHost()) +    { +        ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); +        if (hostArch.GetTriple().isOSNetBSD()) +        { +            if (idx == 0) +            { +                arch = hostArch; +                return arch.IsValid(); +            } +            else if (idx == 1) +            { +                // If the default host architecture is 64-bit, look for a 32-bit variant +                if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) +                { +                    arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); +                    return arch.IsValid(); +                } +            } +        } +    } +    else +    { +        if (m_remote_platform_sp) +            return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); + +        llvm::Triple triple; +        // Set the OS to NetBSD +        triple.setOS(llvm::Triple::NetBSD); +        // Set the architecture +        switch (idx) +        { +            case 0: triple.setArchName("x86_64"); break; +            case 1: triple.setArchName("i386"); break; +            default: return false; +        } +        // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by +        // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown". +        // This means when someone calls triple.GetVendorName() it will return an empty string +        // which indicates that the vendor can be set when two architectures are merged + +        // Now set the triple into "arch" and return true +        arch.SetTriple(triple); +        return true; +    } +    return false; +} + +void +PlatformNetBSD::GetStatus (Stream &strm) +{ +#ifndef LLDB_DISABLE_POSIX +    struct ::utsname un; + +    strm << "      Host: "; + +    ::memset(&un, 0, sizeof(utsname)); +    if (::uname(&un) == -1) { +        strm << "NetBSD" << '\n'; +    } else { +        strm << un.sysname << ' ' << un.release; +        if (un.nodename[0] != '\0') +            strm << " (" << un.nodename << ')'; +        strm << '\n'; + +        // Dump a common information about the platform status. +        strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n'; +    } +#endif + +    Platform::GetStatus(strm); +} + +size_t +PlatformNetBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) +{ +    ArchSpec arch = target.GetArchitecture(); +    const uint8_t *trap_opcode = NULL; +    size_t trap_opcode_size = 0; + +    switch (arch.GetMachine()) +    { +    default: +        assert(false && "Unhandled architecture in PlatformNetBSD::GetSoftwareBreakpointTrapOpcode()"); +        break; +    case llvm::Triple::x86: +    case llvm::Triple::x86_64: +        { +            static const uint8_t g_i386_opcode[] = { 0xCC }; +            trap_opcode = g_i386_opcode; +            trap_opcode_size = sizeof(g_i386_opcode); +        } +        break; +    } + +    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) +        return trap_opcode_size; +    return 0; +} + + +void +PlatformNetBSD::CalculateTrapHandlerSymbolNames () +{ +    m_trap_handlers.push_back (ConstString ("_sigtramp")); +} + +Error +PlatformNetBSD::LaunchProcess (ProcessLaunchInfo &launch_info) +{ +    Error error; +    if (IsHost()) +    { +        error = Platform::LaunchProcess (launch_info); +    } +    else +    { +        if (m_remote_platform_sp) +            error = m_remote_platform_sp->LaunchProcess (launch_info); +        else +            error.SetErrorString ("the platform is not currently connected"); +    } +    return error; +} + +lldb::ProcessSP +PlatformNetBSD::Attach(ProcessAttachInfo &attach_info, +                       Debugger &debugger, +                       Target *target, +                       Error &error) +{ +    lldb::ProcessSP process_sp; +    if (IsHost()) +    { +        if (target == NULL) +        { +            TargetSP new_target_sp; +            ArchSpec emptyArchSpec; + +            error = debugger.GetTargetList().CreateTarget (debugger, +                                                           NULL, +                                                           emptyArchSpec, +                                                           false, +                                                           m_remote_platform_sp, +                                                           new_target_sp); +            target = new_target_sp.get(); +        } +        else +            error.Clear(); + +        if (target && error.Success()) +        { +            debugger.GetTargetList().SetSelectedTarget(target); +            // The netbsd always currently uses the GDB remote debugger plug-in +            // so even when debugging locally we are debugging remotely! +            // Just like the darwin plugin. +            process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); + +            if (process_sp) +                error = process_sp->Attach (attach_info); +        } +    } +    else +    { +        if (m_remote_platform_sp) +            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error); +        else +            error.SetErrorString ("the platform is not currently connected"); +    } +    return process_sp; +} diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h new file mode 100644 index 0000000000000..b0187be99b059 --- /dev/null +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -0,0 +1,177 @@ +//===-- PlatformNetBSD.h ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformNetBSD_h_ +#define liblldb_PlatformNetBSD_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Platform.h" + +namespace lldb_private { +namespace platform_netbsd { + +    class PlatformNetBSD : public Platform +    { +    public: +        PlatformNetBSD (bool is_host); + +        ~PlatformNetBSD() override = default; + +        //------------------------------------------------------------ +        // Class functions +        //------------------------------------------------------------ +        static lldb::PlatformSP +        CreateInstance(bool force, const ArchSpec *arch); + +        static void +        Initialize (); + +        static void +        Terminate (); + +        static ConstString +        GetPluginNameStatic (bool is_host); + +        static const char * +        GetDescriptionStatic (bool is_host); + +        //------------------------------------------------------------ +        // lldb_private::PluginInterface functions +        //------------------------------------------------------------ +        ConstString +        GetPluginName() override +        { +            return GetPluginNameStatic (IsHost()); +        } + +        uint32_t +        GetPluginVersion() override +        { +            return 1; +        } + +        const char * +        GetDescription () override +        { +            return GetDescriptionStatic(IsHost()); +        } + +        //------------------------------------------------------------ +        // lldb_private::Platform functions +        //------------------------------------------------------------ +        bool +        GetModuleSpec(const FileSpec& module_file_spec, +                      const ArchSpec& arch, +                      ModuleSpec &module_spec) override; + +        Error +        RunShellCommand(const char *command, +                        const FileSpec &working_dir, +                        int *status_ptr, +                        int *signo_ptr, +                        std::string *command_output, +                        uint32_t timeout_sec) override; + +        Error +        ResolveExecutable(const ModuleSpec &module_spec, +                          lldb::ModuleSP &module_sp, +                          const FileSpecList *module_search_paths_ptr) override; + +        size_t +        GetSoftwareBreakpointTrapOpcode(Target &target, +                                        BreakpointSite *bp_site) override; + +        bool +        GetRemoteOSVersion () override; + +        bool +        GetRemoteOSBuildString (std::string &s) override; + +        bool +        GetRemoteOSKernelDescription (std::string &s) override; + +        // Remote Platform subclasses need to override this function +        ArchSpec +        GetRemoteSystemArchitecture() override; + +        bool +        IsConnected () const override; + +        Error +        ConnectRemote(Args& args) override; + +        Error +        DisconnectRemote() override; + +        const char * +        GetHostname () override; + +        const char * +        GetUserName (uint32_t uid) override; + +        const char * +        GetGroupName (uint32_t gid) override; + +        bool +        GetProcessInfo(lldb::pid_t pid, +                       ProcessInstanceInfo &proc_info) override; + +        uint32_t +        FindProcesses(const ProcessInstanceInfoMatch &match_info, +                      ProcessInstanceInfoList &process_infos) override; + +        Error +        LaunchProcess(ProcessLaunchInfo &launch_info) override; + +        lldb::ProcessSP +        Attach(ProcessAttachInfo &attach_info, +               Debugger &debugger, +               Target *target, +               Error &error) override; + +        // NetBSD processes can not be launched by spawning and attaching. +        bool +        CanDebugProcess () override { return false; } + +        // Only on PlatformMacOSX: +        Error +        GetFileWithUUID(const FileSpec &platform_file, +                        const UUID* uuid, FileSpec &local_file) override; + +        Error +        GetSharedModule(const ModuleSpec &module_spec, +                        Process* process, +                        lldb::ModuleSP &module_sp, +                        const FileSpecList *module_search_paths_ptr, +                        lldb::ModuleSP *old_module_sp_ptr, +                        bool *did_create_ptr) override; + +        bool +        GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override; + +        void +        GetStatus(Stream &strm) override; + +        void +        CalculateTrapHandlerSymbolNames () override; + +    protected: +        lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote netbsd OS + +    private: +        DISALLOW_COPY_AND_ASSIGN (PlatformNetBSD); +    }; + +} // namespace platform_netbsd +} // namespace lldb_private + +#endif // liblldb_PlatformNetBSD_h_ diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index b4f841a16dec4..c7564655a11b5 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -19,13 +19,18 @@  #include "lldb/Core/Log.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/UserExpression.h"  #include "lldb/Host/File.h"  #include "lldb/Host/FileCache.h"  #include "lldb/Host/FileSpec.h"  #include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/ExecutionContext.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/ProcessLaunchInfo.h" +#include "lldb/Target/Thread.h"  using namespace lldb;  using namespace lldb_private; @@ -673,9 +678,12 @@ PlatformPOSIX::ConnectRemote (Args& args)          if (m_options.get())          {              OptionGroupOptions* options = m_options.get(); -            const OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r'); -            const OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s'); -            const OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c'); +            const OptionGroupPlatformRSync *m_rsync_options = +                static_cast<const OptionGroupPlatformRSync *>(options->GetGroupWithOption('r')); +            const OptionGroupPlatformSSH *m_ssh_options = +                static_cast<const OptionGroupPlatformSSH *>(options->GetGroupWithOption('s')); +            const OptionGroupPlatformCaching *m_cache_options = +                static_cast<const OptionGroupPlatformCaching *>(options->GetGroupWithOption('c'));              if (m_rsync_options->m_rsync)              { @@ -843,6 +851,175 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,  void  PlatformPOSIX::CalculateTrapHandlerSymbolNames () -{    +{      m_trap_handlers.push_back (ConstString ("_sigtramp")); +} + +Error +PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process, +                                       const char* expr_cstr, +                                       const char* expr_prefix, +                                       lldb::ValueObjectSP& result_valobj_sp) +{ +    DynamicLoader *loader = process->GetDynamicLoader(); +    if (loader) +    { +        Error error = loader->CanLoadImage(); +        if (error.Fail()) +            return error; +    } + +    ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); +    if (!thread_sp) +        return Error("Selected thread isn't valid"); + +    StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); +    if (!frame_sp) +        return Error("Frame 0 isn't valid"); + +    ExecutionContext exe_ctx; +    frame_sp->CalculateExecutionContext(exe_ctx); +    EvaluateExpressionOptions expr_options; +    expr_options.SetUnwindOnError(true); +    expr_options.SetIgnoreBreakpoints(true); +    expr_options.SetExecutionPolicy(eExecutionPolicyAlways); +    expr_options.SetLanguage(eLanguageTypeC_plus_plus); + +    Error expr_error; +    UserExpression::Evaluate(exe_ctx, +                             expr_options, +                             expr_cstr, +                             expr_prefix, +                             result_valobj_sp, +                             expr_error); +    if (result_valobj_sp->GetError().Fail()) +        return result_valobj_sp->GetError(); +    return Error(); +} + +uint32_t +PlatformPOSIX::DoLoadImage(lldb_private::Process* process, +                           const lldb_private::FileSpec& remote_file, +                           lldb_private::Error& error) +{ +    char path[PATH_MAX]; +    remote_file.GetPath(path, sizeof(path)); + +    StreamString expr; +    expr.Printf(R"( +                   struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result; +                   the_result.image_ptr = dlopen ("%s", 2); +                   if (the_result.image_ptr == (void *) 0x0) +                   { +                       the_result.error_str = dlerror(); +                   } +                   else +                   { +                       the_result.error_str = (const char *) 0x0; +                   } +                   the_result; +                  )", +                  path); +    const char *prefix = GetLibdlFunctionDeclarations(); +    lldb::ValueObjectSP result_valobj_sp; +    error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); +    if (error.Fail()) +        return LLDB_INVALID_IMAGE_TOKEN; + +    error = result_valobj_sp->GetError(); +    if (error.Fail()) +        return LLDB_INVALID_IMAGE_TOKEN; + +    Scalar scalar; +    ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true); +    if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) +    { +        error.SetErrorStringWithFormat("unable to load '%s'", path); +        return LLDB_INVALID_IMAGE_TOKEN; +    } + +    addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS); +    if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS) +        return process->AddImageToken(image_ptr); + +    if (image_ptr == 0) +    { +        ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); +        if (error_str_sp && error_str_sp->IsCStringContainer(true)) +        { +            DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); +            size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first; +            if (error.Success() && num_chars > 0) +                error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes()); +            else +                error.SetErrorStringWithFormat("dlopen failed for unknown reasons."); +            return LLDB_INVALID_IMAGE_TOKEN; +        } +    } +    error.SetErrorStringWithFormat("unable to load '%s'", path); +    return LLDB_INVALID_IMAGE_TOKEN; +} + +Error +PlatformPOSIX::UnloadImage (lldb_private::Process* process, uint32_t image_token) +{ +    const addr_t image_addr = process->GetImagePtrFromToken(image_token); +    if (image_addr == LLDB_INVALID_ADDRESS) +        return Error("Invalid image token"); + +    StreamString expr; +    expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr); +    const char *prefix = GetLibdlFunctionDeclarations(); +    lldb::ValueObjectSP result_valobj_sp; +    Error error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp); +    if (error.Fail()) +        return error; + +    if (result_valobj_sp->GetError().Fail()) +        return result_valobj_sp->GetError(); + +    Scalar scalar; +    if (result_valobj_sp->ResolveValue(scalar)) +    { +        if (scalar.UInt(1)) +            return Error("expression failed: \"%s\"", expr.GetData()); +        process->ResetImageToken(image_token); +    } +    return Error();  }    + +lldb::ProcessSP +PlatformPOSIX::ConnectProcess (const char* connect_url, +                               const char* plugin_name, +                               lldb_private::Debugger &debugger, +                               lldb_private::Target *target, +                               lldb_private::Error &error) +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->ConnectProcess(connect_url, +                                                    plugin_name, +                                                    debugger, +                                                    target, +                                                    error); + +    return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); +} + +const char* +PlatformPOSIX::GetLibdlFunctionDeclarations() const +{ +    return R"( +              extern "C" void* dlopen(const char*, int); +              extern "C" void* dlsym(void*, const char*); +              extern "C" int   dlclose(void*); +              extern "C" char* dlerror(void); +             )"; +} + +size_t +PlatformPOSIX::ConnectToWaitingProcesses(Debugger& debugger, Error& error) +{ +    if (m_remote_platform_sp) +        return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error); +    return Platform::ConnectToWaitingProcesses(debugger, error); +} diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 82686dcef6b0a..60f6207d140bc 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -12,7 +12,6 @@  // C Includes  // C++ Includes -  #include <memory>  // Other libraries and framework includes @@ -23,11 +22,10 @@  class PlatformPOSIX : public lldb_private::Platform  {  public: -    PlatformPOSIX (bool is_host); -     -    virtual -    ~PlatformPOSIX(); -     +    PlatformPOSIX(bool is_host); + +    ~PlatformPOSIX() override; +      //------------------------------------------------------------      // lldb_private::Platform functions      //------------------------------------------------------------ @@ -37,9 +35,8 @@ public:                     const lldb_private::ArchSpec& arch,                     lldb_private::ModuleSpec &module_spec) override; -    lldb_private::OptionGroupOptions -    *GetConnectionOptions( -        lldb_private::CommandInterpreter &interpreter) override; +    lldb_private::OptionGroupOptions* +    GetConnectionOptions(lldb_private::CommandInterpreter &interpreter) override;      const char *      GetHostname () override; @@ -119,11 +116,11 @@ public:      IsConnected () const override;      lldb_private::Error -    RunShellCommand(const char *command,                       // Shouldn't be NULL +    RunShellCommand(const char *command,                       // Shouldn't be nullptr                      const lldb_private::FileSpec &working_dir, // Pass empty FileSpec to use the current working directory -                    int *status_ptr,                           // Pass NULL if you don't want the process exit status -                    int *signo_ptr,                            // Pass NULL if you don't want the signal that caused the process to exit -                    std::string *command_output,               // Pass NULL if you don't want the command output +                    int *status_ptr,                           // Pass nullptr if you don't want the process exit status +                    int *signo_ptr,                            // Pass nullptr if you don't want the signal that caused the process to exit +                    std::string *command_output,               // Pass nullptr if you don't want the command output                      uint32_t timeout_sec) override;            // Timeout in seconds to wait for shell program to finish      lldb_private::Error @@ -150,13 +147,13 @@ public:      lldb::ProcessSP      Attach (lldb_private::ProcessAttachInfo &attach_info,              lldb_private::Debugger &debugger, -            lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one +            lldb_private::Target *target,       // Can be nullptr, if nullptr create a new target, else use existing one              lldb_private::Error &error) override;      lldb::ProcessSP      DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,                    lldb_private::Debugger &debugger, -                  lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one +                  lldb_private::Target *target,       // Can be nullptr, if nullptr create a new target, else use existing one                    lldb_private::Error &error) override;      std::string @@ -176,14 +173,39 @@ public:      lldb_private::Error      DisconnectRemote () override; +    uint32_t +    DoLoadImage (lldb_private::Process* process, +                 const lldb_private::FileSpec& remote_file, +                 lldb_private::Error& error) override; + +    lldb_private::Error +    UnloadImage (lldb_private::Process* process, uint32_t image_token) override; + +    lldb::ProcessSP +    ConnectProcess (const char* connect_url, +                    const char* plugin_name, +                    lldb_private::Debugger &debugger, +                    lldb_private::Target *target, +                    lldb_private::Error &error) override; +                     +    size_t +    ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override; +  protected:      std::unique_ptr<lldb_private::OptionGroupOptions> m_options; -              lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS -     + +    lldb_private::Error +    EvaluateLibdlExpression(lldb_private::Process* process, +                            const char *expr_cstr, +                            const char *expr_prefix, +                            lldb::ValueObjectSP& result_valobj_sp); + +    virtual const char* +    GetLibdlFunctionDeclarations() const; +  private:      DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX); -      }; -#endif  // liblldb_PlatformPOSIX_h_ +#endif // liblldb_PlatformPOSIX_h_ diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index b0e75d4f34576..f16ea017676f5 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -21,6 +21,7 @@  #include "lldb/Core/ModuleList.h"  #include "lldb/Core/ModuleSpec.h"  #include "lldb/Core/PluginManager.h" +#include "lldb/Core/StreamFile.h"  #include "lldb/Core/StreamString.h"  #include "lldb/Host/ConnectionFileDescriptor.h"  #include "lldb/Host/FileSpec.h" @@ -40,23 +41,6 @@ using namespace lldb_private::platform_gdb_server;  static bool g_initialized = false; -static std::string MakeGdbServerUrl( -        const std::string &platform_scheme, -        const std::string &platform_hostname, -        uint16_t port) -{ -    const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); -    const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); -    const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); -    int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; -    StreamString result; -    result.Printf("%s://%s:%u", -            override_scheme ? override_scheme : platform_scheme.c_str(), -            override_hostname ? override_hostname : platform_hostname.c_str(), -            port + port_offset); -    return result.GetString(); -} -  void  PlatformRemoteGDBServer::Initialize ()  { @@ -590,9 +574,8 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,          if (IsConnected())          {              lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; -            uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); - -            if (port == 0) +            std::string connect_url; +            if (!LaunchGDBServer(debugserver_pid, connect_url))              {                  error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());              } @@ -623,8 +606,6 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,                      if (process_sp)                      { -                        std::string connect_url = -                            MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);                          error = process_sp->ConnectRemote (nullptr, connect_url.c_str());                          // Retry the connect remote one time...                          if (error.Fail()) @@ -649,23 +630,36 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,  } -uint16_t -PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid) +bool +PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)  {      ArchSpec remote_arch = GetRemoteSystemArchitecture ();      llvm::Triple &remote_triple = remote_arch.GetTriple (); + +    uint16_t port = 0; +    std::string socket_name; +    bool launch_result = false;      if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)      {          // When remote debugging to iOS, we use a USB mux that always talks          // to localhost, so we will need the remote debugserver to accept connections          // only from localhost, no matter what our current hostname is -        return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1"); +        launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name);      }      else      {          // All other hosts should use their actual hostname -        return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL); +        launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name);      } + +    if (!launch_result) +        return false; + +    connect_url = MakeGdbServerUrl(m_platform_scheme, +                                   m_platform_hostname, +                                   port, +                                   (socket_name.empty()) ? nullptr : socket_name.c_str()); +    return true;  }  bool @@ -686,9 +680,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,          if (IsConnected())          {              lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; -            uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid); - -            if (port == 0) +            std::string connect_url; +            if (!LaunchGDBServer(debugserver_pid, connect_url))              {                  error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());              } @@ -716,11 +709,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,                      // The darwin always currently uses the GDB remote debugger plug-in                      // so even when debugging locally we are debugging remotely!                      process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL); -                                          if (process_sp)                      { -                        std::string connect_url = -                            MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);                          error = process_sp->ConnectRemote(nullptr, connect_url.c_str());                          if (error.Success())                          { @@ -931,13 +921,8 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()                  return false;              // We can live without short_name, description, etc. -            std::string short_name{""}; -            auto object_sp = dict->GetValueForKey("short_name"); -            if (object_sp && object_sp->IsValid()) -                short_name = object_sp->GetStringValue(); -              bool suppress{false}; -            object_sp = dict->GetValueForKey("suppress"); +            auto object_sp = dict->GetValueForKey("suppress");              if (object_sp && object_sp->IsValid())                  suppress = object_sp->GetBooleanValue(); @@ -958,7 +943,6 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()              remote_signals_sp->AddSignal(signo,                                           name.c_str(), -                                         short_name.c_str(),                                           suppress, stop, notify,                                           description.c_str());              return true; @@ -969,3 +953,66 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()      return m_remote_signals_sp;  } + +std::string +PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme, +                                          const std::string &platform_hostname, +                                          uint16_t port, +                                          const char* socket_name) +{ +    const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME"); +    const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME"); +    const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET"); +    int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0; + +    return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(), +                   override_hostname ? override_hostname : platform_hostname.c_str(), +                   port + port_offset, +                   socket_name); +} + +std::string +PlatformRemoteGDBServer::MakeUrl(const char* scheme, +                                 const char* hostname, +                                 uint16_t port, +                                 const char* path) +{ +    StreamString result; +    result.Printf("%s://%s", scheme, hostname); +    if (port != 0) +        result.Printf(":%u", port); +    if (path) +        result.Write(path, strlen(path)); +    return result.GetString(); +} + +lldb::ProcessSP +PlatformRemoteGDBServer::ConnectProcess(const char* connect_url, +                                        const char* plugin_name, +                                        lldb_private::Debugger &debugger, +                                        lldb_private::Target *target, +                                        lldb_private::Error &error) +{ +    if (!IsRemote() || !IsConnected()) +    { +        error.SetErrorString("Not connected to remote gdb server"); +        return nullptr; +    } +    return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); +} + +size_t +PlatformRemoteGDBServer::GetPendingGdbServerList(std::vector<std::string>& connection_urls) +{ +    std::vector<std::pair<uint16_t, std::string>> remote_servers; +    m_gdb_client.QueryGDBServer(remote_servers); +    for (const auto& gdbserver : remote_servers) +    { +        const char* socket_name_cstr = gdbserver.second.empty() ? nullptr : gdbserver.second.c_str(); +        connection_urls.emplace_back(MakeGdbServerUrl(m_platform_scheme, +                                                      m_platform_hostname, +                                                      gdbserver.first, +                                                      socket_name_cstr)); +    } +    return connection_urls.size(); +} diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 0bf013fdfb68e..61136f1185e66 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -217,6 +217,16 @@ public:      const lldb::UnixSignalsSP &      GetRemoteUnixSignals() override; +    lldb::ProcessSP +    ConnectProcess (const char* connect_url, +                    const char* plugin_name, +                    lldb_private::Debugger &debugger, +                    lldb_private::Target *target, +                    lldb_private::Error &error) override; + +    virtual size_t +    GetPendingGdbServerList(std::vector<std::string>& connection_urls); +  protected:      process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client;      std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to @@ -225,16 +235,29 @@ protected:      lldb::UnixSignalsSP m_remote_signals_sp; -    // Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on -    // failure. Subclasses should override this method if they want to do extra actions before or -    // after launching the lldb-gdbserver. -    virtual uint16_t -    LaunchGDBserverAndGetPort (lldb::pid_t &pid); +    // Launch the debug server on the remote host - caller connects to launched +    // debug server using connect_url. +    // Subclasses should override this method if they want to do extra actions before or +    // after launching the debug server. +    virtual bool +    LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url);      virtual bool      KillSpawnedProcess (lldb::pid_t pid); +    virtual std::string +    MakeUrl(const char* scheme, +            const char* hostname, +            uint16_t port, +            const char* path); +  private: +    std::string +    MakeGdbServerUrl(const std::string &platform_scheme, +                     const std::string &platform_hostname, +                     uint16_t port, +                     const char* socket_name); +      DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);  }; diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 5e46c836beac6..2b292442399ff 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -8,33 +8,288 @@  //===----------------------------------------------------------------------===//  // C Includes +#include <errno.h> +  // C++ Includes  // Other libraries and framework includes  #include "lldb/Core/State.h"  #include "lldb/Target/UnixSignals.h"  // Project includes +#include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadSpec.h" +#include "llvm/ADT/SmallString.h" +#include "POSIXStopInfo.h"  #include "FreeBSDThread.h"  #include "ProcessFreeBSD.h"  #include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContextPOSIXProcessMonitor_arm.h" +#include "RegisterContextPOSIXProcessMonitor_arm64.h" +#include "RegisterContextPOSIXProcessMonitor_mips64.h" +#include "RegisterContextPOSIXProcessMonitor_powerpc.h" +#include "RegisterContextPOSIXProcessMonitor_x86.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" +#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" +#include "Plugins/Process/Utility/UnwindLLDB.h"  using namespace lldb;  using namespace lldb_private; -//------------------------------------------------------------------------------ -// Constructors and destructors. -  FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid) -    : POSIXThread(process, tid) +    : Thread(process, tid), +      m_frame_ap (), +      m_breakpoint (), +      m_thread_name_valid (false), +      m_thread_name (), +      m_posix_thread(NULL)  { +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); + +    // Set the current watchpoints for this thread. +    Target &target = GetProcess()->GetTarget(); +    const WatchpointList &wp_list = target.GetWatchpointList(); +    size_t wp_size = wp_list.GetSize(); + +    for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) +    { +        lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); +        if (wp.get() && wp->IsEnabled()) +        { +            // This watchpoint as been enabled; obviously this "new" thread +            // has been created since that watchpoint was enabled.  Since +            // the POSIXBreakpointProtocol has yet to be initialized, its +            // m_watchpoints_initialized member will be FALSE.  Attempting to +            // read the debug status register to determine if a watchpoint +            // has been hit would result in the zeroing of that register. +            // Since the active debug registers would have been cloned when +            // this thread was created, simply force the m_watchpoints_initized +            // member to TRUE and avoid resetting dr6 and dr7. +            GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); +        } +    }  }  FreeBSDThread::~FreeBSDThread()  { +    DestroyThread(); +} + +ProcessMonitor & +FreeBSDThread::GetMonitor() +{ +    ProcessSP base = GetProcess(); +    ProcessFreeBSD &process = static_cast<ProcessFreeBSD&>(*base); +    return process.GetMonitor(); +} + +void +FreeBSDThread::RefreshStateAfterStop() +{ +    // Invalidate all registers in our register context. We don't set "force" to +    // true because the stop reply packet might have had some register values +    // that were expedited and these will already be copied into the register +    // context by the time this function gets called. The KDPRegisterContext +    // class has been made smart enough to detect when it needs to invalidate +    // which registers are valid by putting hooks in the register read and  +    // register supply functions where they check the process stop ID and do +    // the right thing. +    //if (StateIsStoppedState(GetState()) +    { +        const bool force = false; +        GetRegisterContext()->InvalidateIfNeeded (force); +    }  } -//------------------------------------------------------------------------------ -// ProcessInterface protocol. +const char * +FreeBSDThread::GetInfo() +{ +    return NULL; +} + +void +FreeBSDThread::SetName (const char *name) +{ +    m_thread_name_valid = (name && name[0]); +    if (m_thread_name_valid) +        m_thread_name.assign (name); +    else +        m_thread_name.clear(); +} + +const char * +FreeBSDThread::GetName () +{ +    if (!m_thread_name_valid) +    { +        llvm::SmallString<32> thread_name; +        HostNativeThread::GetName(GetID(), thread_name); +        m_thread_name = thread_name.c_str(); +        m_thread_name_valid = true; +    } + +    if (m_thread_name.empty()) +        return NULL; +    return m_thread_name.c_str(); +} + +lldb::RegisterContextSP +FreeBSDThread::GetRegisterContext() +{ +    if (!m_reg_context_sp) +    { +        m_posix_thread = NULL; + +        RegisterInfoInterface *reg_interface = NULL; +        const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); + +        assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD); +        switch (target_arch.GetMachine()) +        { +            case llvm::Triple::aarch64: +                reg_interface = new RegisterContextFreeBSD_arm64(target_arch); +                break; +            case llvm::Triple::arm: +                reg_interface = new RegisterContextFreeBSD_arm(target_arch); +                break; +            case llvm::Triple::ppc: +#ifndef __powerpc64__ +                reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); +                break; +#endif +            case llvm::Triple::ppc64: +                reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); +                break; +            case llvm::Triple::mips64: +                reg_interface = new RegisterContextFreeBSD_mips64(target_arch); +                break; +            case llvm::Triple::x86: +                reg_interface = new RegisterContextFreeBSD_i386(target_arch); +                break; +            case llvm::Triple::x86_64: +                reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); +                break; +            default: +                llvm_unreachable("CPU not supported"); +        } + +        switch (target_arch.GetMachine()) +        { +            case llvm::Triple::aarch64: +                { +                    RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); +                    m_posix_thread = reg_ctx; +                    m_reg_context_sp.reset(reg_ctx); +                    break; +                } +            case llvm::Triple::arm: +                { +                    RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface); +                    m_posix_thread = reg_ctx; +                    m_reg_context_sp.reset(reg_ctx); +                    break; +                } +            case llvm::Triple::mips64: +                { +                    RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); +                    m_posix_thread = reg_ctx; +                    m_reg_context_sp.reset(reg_ctx); +                    break; +                } +            case llvm::Triple::ppc: +            case llvm::Triple::ppc64: +                { +                    RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface); +                    m_posix_thread = reg_ctx; +                    m_reg_context_sp.reset(reg_ctx); +                    break; +                } +            case llvm::Triple::x86: +            case llvm::Triple::x86_64: +                { +                    RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface); +                    m_posix_thread = reg_ctx; +                    m_reg_context_sp.reset(reg_ctx); +                    break; +                } +            default: +                break; +        } +    } +    return m_reg_context_sp; +} + +lldb::RegisterContextSP +FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) +{ +    lldb::RegisterContextSP reg_ctx_sp; +    uint32_t concrete_frame_idx = 0; + +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("FreeBSDThread::%s ()", __FUNCTION__); + +    if (frame) +        concrete_frame_idx = frame->GetConcreteFrameIndex(); + +    if (concrete_frame_idx == 0) +        reg_ctx_sp = GetRegisterContext(); +    else +    { +        assert(GetUnwinder()); +        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); +    } + +    return reg_ctx_sp; +} + +lldb::addr_t +FreeBSDThread::GetThreadPointer () +{ +    ProcessMonitor &monitor = GetMonitor(); +    addr_t addr; +    if (monitor.ReadThreadPointer (GetID(), addr)) +        return addr; +    else +        return LLDB_INVALID_ADDRESS; +} + +bool +FreeBSDThread::CalculateStopInfo() +{ +    SetStopInfo (m_stop_info_sp); +    return true; +} + +Unwind * +FreeBSDThread::GetUnwinder() +{ +    if (m_unwinder_ap.get() == NULL) +        m_unwinder_ap.reset(new UnwindLLDB(*this)); + +    return m_unwinder_ap.get(); +} + +void +FreeBSDThread::DidStop() +{ +    // Don't set the thread state to stopped unless we really stopped. +}  void  FreeBSDThread::WillResume(lldb::StateType resume_state) @@ -68,3 +323,359 @@ FreeBSDThread::WillResume(lldb::StateType resume_state)          break;      }  } + +bool +FreeBSDThread::Resume() +{ +    lldb::StateType resume_state = GetResumeState(); +    ProcessMonitor &monitor = GetMonitor(); +    bool status; + +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log) +        log->Printf ("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__, +                         StateAsCString(resume_state)); + +    switch (resume_state) +    { +    default: +        assert(false && "Unexpected state for resume!"); +        status = false; +        break; + +    case lldb::eStateRunning: +        SetState(resume_state); +        status = monitor.Resume(GetID(), GetResumeSignal()); +        break; + +    case lldb::eStateStepping: +        SetState(resume_state); +        status = monitor.SingleStep(GetID(), GetResumeSignal()); +        break; +    case lldb::eStateStopped: +    case lldb::eStateSuspended: +        status = true; +        break; +    } + +    return status; +} + +void +FreeBSDThread::Notify(const ProcessMessage &message) +{ +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log) +        log->Printf ("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64, +                     __FUNCTION__, message.PrintKind(), GetID()); + +    switch (message.GetKind()) +    { +    default: +        assert(false && "Unexpected message kind!"); +        break; + +    case ProcessMessage::eExitMessage: +        // Nothing to be done. +        break; + +    case ProcessMessage::eLimboMessage: +        LimboNotify(message); +        break; + +    case ProcessMessage::eSignalMessage: +        SignalNotify(message); +        break; + +    case ProcessMessage::eSignalDeliveredMessage: +        SignalDeliveredNotify(message); +        break; + +    case ProcessMessage::eTraceMessage: +        TraceNotify(message); +        break; + +    case ProcessMessage::eBreakpointMessage: +        BreakNotify(message); +        break; + +    case ProcessMessage::eWatchpointMessage: +        WatchNotify(message); +        break; + +    case ProcessMessage::eCrashMessage: +        CrashNotify(message); +        break; + +    case ProcessMessage::eExecMessage: +        ExecNotify(message); +        break; +    } +} + +bool +FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp) +{ +    bool wp_set = false; +    if (wp) +    { +        addr_t wp_addr = wp->GetLoadAddress(); +        size_t wp_size = wp->GetByteSize(); +        bool wp_read = wp->WatchpointRead(); +        bool wp_write = wp->WatchpointWrite(); +        uint32_t wp_hw_index = wp->GetHardwareIndex(); +        POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); +        if (reg_ctx) +            wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, +                                                             wp_read, wp_write, +                                                             wp_hw_index); +    } +    return wp_set; +} + +bool +FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp) +{ +    bool result = false; +    if (wp) +    { +        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); +        if (reg_ctx_sp.get()) +            result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); +    } +    return result; +} + +uint32_t +FreeBSDThread::NumSupportedHardwareWatchpoints() +{ +    lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); +    if (reg_ctx_sp.get()) +        return reg_ctx_sp->NumSupportedHardwareWatchpoints(); +    return 0; +} + +uint32_t +FreeBSDThread::FindVacantWatchpointIndex() +{ +    uint32_t hw_index = LLDB_INVALID_INDEX32; +    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); +    uint32_t wp_idx; +    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); +    if (reg_ctx) +    { +        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) +        { +            if (reg_ctx->IsWatchpointVacant(wp_idx)) +            { +                hw_index = wp_idx; +                break; +            } +        } +    } +    return hw_index; +} + +void +FreeBSDThread::BreakNotify(const ProcessMessage &message) +{ +    bool status; +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + +    assert(GetRegisterContext()); +    status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); +    assert(status && "Breakpoint update failed!"); + +    // With our register state restored, resolve the breakpoint object +    // corresponding to our current PC. +    assert(GetRegisterContext()); +    lldb::addr_t pc = GetRegisterContext()->GetPC(); +    if (log) +        log->Printf ("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); +    lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); + +    // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, +    // we create a stop reason with should_stop=false.  If there is no breakpoint location, then report +    // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will +    // be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +    if (bp_site) +    { +        lldb::break_id_t bp_id = bp_site->GetID(); +        // If we have an operating system plug-in, we might have set a thread specific breakpoint using the +        // operating system thread ID, so we can't make any assumptions about the thread ID so we must always +        // report the breakpoint regardless of the thread. +        if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL) +            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); +        else +        { +            const bool should_stop = false; +            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); +        } +    } +    else +        SetStopInfo(StopInfoSP()); +} + +void +FreeBSDThread::WatchNotify(const ProcessMessage &message) +{ +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + +    lldb::addr_t halt_addr = message.GetHWAddress(); +    if (log) +        log->Printf ("FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8" +                     PRIx64, __FUNCTION__, halt_addr); + +    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); +    if (reg_ctx) +    { +        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); +        uint32_t wp_idx; +        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) +        { +            if (reg_ctx->IsWatchpointHit(wp_idx)) +            { +                // Clear the watchpoint hit here +                reg_ctx->ClearWatchpointHits(); +                break; +            } +        } + +        if (wp_idx == num_hw_wps) +            return; + +        Target &target = GetProcess()->GetTarget(); +        lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); +        const WatchpointList &wp_list = target.GetWatchpointList(); +        lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); + +        assert(wp_sp.get() && "No watchpoint found"); +        SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this, +                                                                wp_sp->GetID())); +    } +} + +void +FreeBSDThread::TraceNotify(const ProcessMessage &message) +{ +    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); +    if (reg_ctx) +    { +        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); +        uint32_t wp_idx; +        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) +        { +            if (reg_ctx->IsWatchpointHit(wp_idx)) +            { +                WatchNotify(message); +                return; +            } +        } +    } + +    SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); +} + +void +FreeBSDThread::LimboNotify(const ProcessMessage &message) +{ +    SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); +} + +void +FreeBSDThread::SignalNotify(const ProcessMessage &message) +{ +    int signo = message.GetSignal(); +    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +} + +void +FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message) +{ +    int signo = message.GetSignal(); +    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); +} + +void +FreeBSDThread::CrashNotify(const ProcessMessage &message) +{ +    // FIXME: Update stop reason as per bugzilla 14598 +    int signo = message.GetSignal(); + +    assert(message.GetKind() == ProcessMessage::eCrashMessage); + +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log) +        log->Printf ("FreeBSDThread::%s () signo = %i, reason = '%s'", +                     __FUNCTION__, signo, message.PrintCrashReason()); + +    SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, +                                                         message.GetCrashReason(), +                                                         message.GetFaultAddress()))); +} + +unsigned +FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset) +{ +    unsigned reg = LLDB_INVALID_REGNUM; +    ArchSpec arch = HostInfo::GetArchitecture(); + +    switch (arch.GetMachine()) +    { +    default: +        llvm_unreachable("CPU type not supported!"); +        break; + +    case llvm::Triple::aarch64: +    case llvm::Triple::arm: +    case llvm::Triple::mips64: +    case llvm::Triple::ppc: +    case llvm::Triple::ppc64: +    case llvm::Triple::x86: +    case llvm::Triple::x86_64: +        { +            POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); +            reg = reg_ctx->GetRegisterIndexFromOffset(offset); +        } +        break; +    } +    return reg; +} + +void +FreeBSDThread::ExecNotify(const ProcessMessage &message) +{ +    SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); +} + +const char * +FreeBSDThread::GetRegisterName(unsigned reg) +{ +    const char * name = nullptr; +    ArchSpec arch = HostInfo::GetArchitecture(); + +    switch (arch.GetMachine()) +    { +    default: +        assert(false && "CPU type not supported!"); +        break; + +    case llvm::Triple::aarch64: +    case llvm::Triple::arm: +    case llvm::Triple::mips64: +    case llvm::Triple::ppc: +    case llvm::Triple::ppc64: +    case llvm::Triple::x86: +    case llvm::Triple::x86_64: +        name = GetRegisterContext()->GetRegisterName(reg); +        break; +    } +    return name; +} + +const char * +FreeBSDThread::GetRegisterNameFromOffset(unsigned offset) +{ +    return GetRegisterName(GetRegisterIndexFromOffset(offset)); +} + diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h index 8741075cb60be..90c11dbefcb0d 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.h +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h @@ -10,14 +10,23 @@  #ifndef liblldb_FreeBSDThread_H_  #define liblldb_FreeBSDThread_H_ +// C++ Includes +#include <memory> +#include <string> +  // Other libraries and framework includes -#include "POSIXThread.h" +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIX.h" + +class ProcessMessage; +class ProcessMonitor; +class POSIXBreakpointProtocol;  //------------------------------------------------------------------------------  // @class FreeBSDThread  // @brief Abstraction of a FreeBSD thread.  class FreeBSDThread -    : public POSIXThread +    : public lldb_private::Thread  {  public: @@ -28,12 +37,106 @@ public:      virtual ~FreeBSDThread(); +    // POSIXThread +    void +    RefreshStateAfterStop() override; + +    // This notifies the thread when a private stop occurs. +    void +    DidStop () override; + +    const char * +    GetInfo() override; + +    void +    SetName (const char *name) override; + +    const char * +    GetName () override; + +    lldb::RegisterContextSP +    GetRegisterContext() override; + +    lldb::RegisterContextSP +    CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override; + +    lldb::addr_t +    GetThreadPointer () override; + +    //-------------------------------------------------------------------------- +    // These functions provide a mapping from the register offset +    // back to the register index or name for use in debugging or log +    // output. + +    unsigned +    GetRegisterIndexFromOffset(unsigned offset); + +    const char * +    GetRegisterName(unsigned reg); + +    const char * +    GetRegisterNameFromOffset(unsigned offset); + +    //-------------------------------------------------------------------------- +    // These methods form a specialized interface to POSIX threads. +    // +    bool Resume(); + +    void Notify(const ProcessMessage &message); + +    //-------------------------------------------------------------------------- +    // These methods provide an interface to watchpoints +    // +    bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp); + +    bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp); + +    uint32_t NumSupportedHardwareWatchpoints(); + +    uint32_t FindVacantWatchpointIndex(); + +protected: +    POSIXBreakpointProtocol * +    GetPOSIXBreakpointProtocol () +    { +        if (!m_reg_context_sp) +            m_reg_context_sp = GetRegisterContext(); +        return m_posix_thread; +    } +     +    std::unique_ptr<lldb_private::StackFrame> m_frame_ap; + +    lldb::BreakpointSiteSP m_breakpoint; + +    bool m_thread_name_valid; +    std::string m_thread_name; +    POSIXBreakpointProtocol *m_posix_thread; + +    ProcessMonitor & +    GetMonitor(); + +    bool +    CalculateStopInfo() override; + +    void BreakNotify(const ProcessMessage &message); +    void WatchNotify(const ProcessMessage &message); +    virtual void TraceNotify(const ProcessMessage &message); +    void LimboNotify(const ProcessMessage &message); +    void SignalNotify(const ProcessMessage &message); +    void SignalDeliveredNotify(const ProcessMessage &message); +    void CrashNotify(const ProcessMessage &message); +    void ExitNotify(const ProcessMessage &message); +    void ExecNotify(const ProcessMessage &message); + +    lldb_private::Unwind * +    GetUnwinder() override; +      //--------------------------------------------------------------------------      // FreeBSDThread internal API.      // POSIXThread override      virtual void -    WillResume(lldb::StateType resume_state); +    WillResume(lldb::StateType resume_state) override;  };  #endif // #ifndef liblldb_FreeBSDThread_H_ diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp index 3b8cea737bcbd..409cf8c46b030 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp @@ -45,7 +45,7 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)  //===----------------------------------------------------------------------===//  // POSIXCrashStopInfo -POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread, +POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread,                                         uint32_t status,                                         CrashReason reason,                                         lldb::addr_t fault_addr) diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h index a1ee2ea685244..ace6c98017b77 100644 --- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h +++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h @@ -17,7 +17,7 @@  #include "lldb/Target/StopInfo.h"  #include "CrashReason.h" -#include "POSIXThread.h" +#include "FreeBSDThread.h"  #include <string> @@ -42,7 +42,7 @@ class POSIXLimboStopInfo      : public POSIXStopInfo  {  public: -    POSIXLimboStopInfo(POSIXThread &thread) +    POSIXLimboStopInfo(FreeBSDThread &thread)          : POSIXStopInfo(thread, 0)          { } @@ -70,7 +70,7 @@ class POSIXCrashStopInfo      : public POSIXStopInfo  {  public: -    POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, +    POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status,                         CrashReason reason,                         lldb::addr_t fault_addr);      ~POSIXCrashStopInfo(); @@ -88,7 +88,7 @@ class POSIXNewThreadStopInfo      : public POSIXStopInfo  {  public: -    POSIXNewThreadStopInfo (POSIXThread &thread) +    POSIXNewThreadStopInfo (FreeBSDThread &thread)          : POSIXStopInfo (thread, 0)          { } diff --git a/source/Plugins/Process/FreeBSD/POSIXThread.cpp b/source/Plugins/Process/FreeBSD/POSIXThread.cpp deleted file mode 100644 index 854796fb7448c..0000000000000 --- a/source/Plugins/Process/FreeBSD/POSIXThread.cpp +++ /dev/null @@ -1,661 +0,0 @@ -//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include <errno.h> - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/State.h" -#include "lldb/Host/Host.h" -#include "lldb/Host/HostNativeThread.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/ThreadSpec.h" -#include "llvm/ADT/SmallString.h" -#include "POSIXStopInfo.h" -#include "POSIXThread.h" -#include "ProcessPOSIX.h" -#include "ProcessPOSIXLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextPOSIXProcessMonitor_arm.h" -#include "RegisterContextPOSIXProcessMonitor_arm64.h" -#include "RegisterContextPOSIXProcessMonitor_mips64.h" -#include "RegisterContextPOSIXProcessMonitor_powerpc.h" -#include "RegisterContextPOSIXProcessMonitor_x86.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h" -#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h" -#include "Plugins/Process/Utility/UnwindLLDB.h" - -using namespace lldb; -using namespace lldb_private; - - -POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) -    : Thread(process, tid), -      m_frame_ap (), -      m_breakpoint (), -      m_thread_name_valid (false), -      m_thread_name (), -      m_posix_thread(NULL) -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid); - -    // Set the current watchpoints for this thread. -    Target &target = GetProcess()->GetTarget(); -    const WatchpointList &wp_list = target.GetWatchpointList(); -    size_t wp_size = wp_list.GetSize(); - -    for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) -    { -        lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx); -        if (wp.get() && wp->IsEnabled()) -        { -            // This watchpoint as been enabled; obviously this "new" thread -            // has been created since that watchpoint was enabled.  Since -            // the POSIXBreakpointProtocol has yet to be initialized, its -            // m_watchpoints_initialized member will be FALSE.  Attempting to -            // read the debug status register to determine if a watchpoint -            // has been hit would result in the zeroing of that register. -            // Since the active debug registers would have been cloned when -            // this thread was created, simply force the m_watchpoints_initized -            // member to TRUE and avoid resetting dr6 and dr7. -            GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized(); -        } -    } -} - -POSIXThread::~POSIXThread() -{ -    DestroyThread(); -} - -ProcessMonitor & -POSIXThread::GetMonitor() -{ -    ProcessSP base = GetProcess(); -    ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base); -    return process.GetMonitor(); -} - -void -POSIXThread::RefreshStateAfterStop() -{ -    // Invalidate all registers in our register context. We don't set "force" to -    // true because the stop reply packet might have had some register values -    // that were expedited and these will already be copied into the register -    // context by the time this function gets called. The KDPRegisterContext -    // class has been made smart enough to detect when it needs to invalidate -    // which registers are valid by putting hooks in the register read and  -    // register supply functions where they check the process stop ID and do -    // the right thing. -    //if (StateIsStoppedState(GetState()) -    { -        const bool force = false; -        GetRegisterContext()->InvalidateIfNeeded (force); -    } -} - -const char * -POSIXThread::GetInfo() -{ -    return NULL; -} - -void -POSIXThread::SetName (const char *name) -{ -    m_thread_name_valid = (name && name[0]); -    if (m_thread_name_valid) -        m_thread_name.assign (name); -    else -        m_thread_name.clear(); -} - -const char * -POSIXThread::GetName () -{ -    if (!m_thread_name_valid) -    { -        llvm::SmallString<32> thread_name; -        HostNativeThread::GetName(GetID(), thread_name); -        m_thread_name = thread_name.c_str(); -        m_thread_name_valid = true; -    } - -    if (m_thread_name.empty()) -        return NULL; -    return m_thread_name.c_str(); -} - -lldb::RegisterContextSP -POSIXThread::GetRegisterContext() -{ -    if (!m_reg_context_sp) -    { -        m_posix_thread = NULL; - -        RegisterInfoInterface *reg_interface = NULL; -        const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture(); - -        switch (target_arch.GetTriple().getOS()) -        { -            case llvm::Triple::FreeBSD: -                switch (target_arch.GetMachine()) -                { -                    case llvm::Triple::arm: -                        reg_interface = new RegisterContextFreeBSD_arm(target_arch); -                        break; -                    case llvm::Triple::ppc: -#ifndef __powerpc64__ -                        reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch); -                        break; -#endif -                    case llvm::Triple::ppc64: -                        reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch); -                        break; -                    case llvm::Triple::mips64: -                        reg_interface = new RegisterContextFreeBSD_mips64(target_arch); -                        break; -                    case llvm::Triple::x86: -                        reg_interface = new RegisterContextFreeBSD_i386(target_arch); -                        break; -                    case llvm::Triple::x86_64: -                        reg_interface = new RegisterContextFreeBSD_x86_64(target_arch); -                        break; -                    default: -                        break; -                } -                break; - -            default: -                break; -        } - -        assert(reg_interface && "OS or CPU not supported!"); - -        switch (target_arch.GetMachine()) -        { -            case llvm::Triple::aarch64: -                { -                    RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface); -                    m_posix_thread = reg_ctx; -                    m_reg_context_sp.reset(reg_ctx); -                    break; -                } -            case llvm::Triple::arm: -                { -                    RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface); -                    m_posix_thread = reg_ctx; -                    m_reg_context_sp.reset(reg_ctx); -                    break; -                } -            case llvm::Triple::mips64: -                { -                    RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface); -                    m_posix_thread = reg_ctx; -                    m_reg_context_sp.reset(reg_ctx); -                    break; -                } -            case llvm::Triple::ppc: -            case llvm::Triple::ppc64: -                { -                    RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface); -                    m_posix_thread = reg_ctx; -                    m_reg_context_sp.reset(reg_ctx); -                    break; -                } -            case llvm::Triple::x86: -            case llvm::Triple::x86_64: -                { -                    RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface); -                    m_posix_thread = reg_ctx; -                    m_reg_context_sp.reset(reg_ctx); -                    break; -                } -            default: -                break; -        } -    } -    return m_reg_context_sp; -} - -lldb::RegisterContextSP -POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ -    lldb::RegisterContextSP reg_ctx_sp; -    uint32_t concrete_frame_idx = 0; - -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("POSIXThread::%s ()", __FUNCTION__); - -    if (frame) -        concrete_frame_idx = frame->GetConcreteFrameIndex(); - -    if (concrete_frame_idx == 0) -        reg_ctx_sp = GetRegisterContext(); -    else -    { -        assert(GetUnwinder()); -        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); -    } - -    return reg_ctx_sp; -} - -lldb::addr_t -POSIXThread::GetThreadPointer () -{ -    ProcessMonitor &monitor = GetMonitor(); -    addr_t addr; -    if (monitor.ReadThreadPointer (GetID(), addr)) -        return addr; -    else -        return LLDB_INVALID_ADDRESS; -} - -bool -POSIXThread::CalculateStopInfo() -{ -    SetStopInfo (m_stop_info_sp); -    return true; -} - -Unwind * -POSIXThread::GetUnwinder() -{ -    if (m_unwinder_ap.get() == NULL) -        m_unwinder_ap.reset(new UnwindLLDB(*this)); - -    return m_unwinder_ap.get(); -} - -void -POSIXThread::DidStop() -{ -    // Don't set the thread state to stopped unless we really stopped. -} - -bool -POSIXThread::Resume() -{ -    lldb::StateType resume_state = GetResumeState(); -    ProcessMonitor &monitor = GetMonitor(); -    bool status; - -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log) -        log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__, -                         StateAsCString(resume_state)); - -    switch (resume_state) -    { -    default: -        assert(false && "Unexpected state for resume!"); -        status = false; -        break; - -    case lldb::eStateRunning: -        SetState(resume_state); -        status = monitor.Resume(GetID(), GetResumeSignal()); -        break; - -    case lldb::eStateStepping: -        SetState(resume_state); -        status = monitor.SingleStep(GetID(), GetResumeSignal()); -        break; -    case lldb::eStateStopped: -    case lldb::eStateSuspended: -        status = true; -        break; -    } - -    return status; -} - -void -POSIXThread::Notify(const ProcessMessage &message) -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log) -        log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64, -                     __FUNCTION__, message.PrintKind(), GetID()); - -    switch (message.GetKind()) -    { -    default: -        assert(false && "Unexpected message kind!"); -        break; - -    case ProcessMessage::eExitMessage: -        // Nothing to be done. -        break; - -    case ProcessMessage::eLimboMessage: -        LimboNotify(message); -        break; - -    case ProcessMessage::eSignalMessage: -        SignalNotify(message); -        break; - -    case ProcessMessage::eSignalDeliveredMessage: -        SignalDeliveredNotify(message); -        break; - -    case ProcessMessage::eTraceMessage: -        TraceNotify(message); -        break; - -    case ProcessMessage::eBreakpointMessage: -        BreakNotify(message); -        break; - -    case ProcessMessage::eWatchpointMessage: -        WatchNotify(message); -        break; - -    case ProcessMessage::eCrashMessage: -        CrashNotify(message); -        break; - -    case ProcessMessage::eNewThreadMessage: -        ThreadNotify(message); -        break; - -    case ProcessMessage::eExecMessage: -        ExecNotify(message); -        break; -    } -} - -bool -POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp) -{ -    bool wp_set = false; -    if (wp) -    { -        addr_t wp_addr = wp->GetLoadAddress(); -        size_t wp_size = wp->GetByteSize(); -        bool wp_read = wp->WatchpointRead(); -        bool wp_write = wp->WatchpointWrite(); -        uint32_t wp_hw_index = wp->GetHardwareIndex(); -        POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); -        if (reg_ctx) -            wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size, -                                                             wp_read, wp_write, -                                                             wp_hw_index); -    } -    return wp_set; -} - -bool -POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp) -{ -    bool result = false; -    if (wp) -    { -        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); -        if (reg_ctx_sp.get()) -            result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex()); -    } -    return result; -} - -uint32_t -POSIXThread::NumSupportedHardwareWatchpoints() -{ -    lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext(); -    if (reg_ctx_sp.get()) -        return reg_ctx_sp->NumSupportedHardwareWatchpoints(); -    return 0; -} - -uint32_t -POSIXThread::FindVacantWatchpointIndex() -{ -    uint32_t hw_index = LLDB_INVALID_INDEX32; -    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); -    uint32_t wp_idx; -    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); -    if (reg_ctx) -    { -        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) -        { -            if (reg_ctx->IsWatchpointVacant(wp_idx)) -            { -                hw_index = wp_idx; -                break; -            } -        } -    } -    return hw_index; -} - -void -POSIXThread::BreakNotify(const ProcessMessage &message) -{ -    bool status; -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - -    assert(GetRegisterContext()); -    status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint(); -    assert(status && "Breakpoint update failed!"); - -    // With our register state restored, resolve the breakpoint object -    // corresponding to our current PC. -    assert(GetRegisterContext()); -    lldb::addr_t pc = GetRegisterContext()->GetPC(); -    if (log) -        log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc); -    lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc)); - -    // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, -    // we create a stop reason with should_stop=false.  If there is no breakpoint location, then report -    // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will -    // be taken care of when the thread resumes and notices that there's a breakpoint under the pc. -    if (bp_site) -    { -        lldb::break_id_t bp_id = bp_site->GetID(); -        // If we have an operating system plug-in, we might have set a thread specific breakpoint using the -        // operating system thread ID, so we can't make any assumptions about the thread ID so we must always -        // report the breakpoint regardless of the thread. -        if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL) -            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id)); -        else -        { -            const bool should_stop = false; -            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop)); -        } -    } -    else -        SetStopInfo(StopInfoSP()); -} - -void -POSIXThread::WatchNotify(const ProcessMessage &message) -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - -    lldb::addr_t halt_addr = message.GetHWAddress(); -    if (log) -        log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8" -                     PRIx64, __FUNCTION__, halt_addr); - -    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); -    if (reg_ctx) -    { -        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); -        uint32_t wp_idx; -        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) -        { -            if (reg_ctx->IsWatchpointHit(wp_idx)) -            { -                // Clear the watchpoint hit here -                reg_ctx->ClearWatchpointHits(); -                break; -            } -        } - -        if (wp_idx == num_hw_wps) -            return; - -        Target &target = GetProcess()->GetTarget(); -        lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx); -        const WatchpointList &wp_list = target.GetWatchpointList(); -        lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr); - -        assert(wp_sp.get() && "No watchpoint found"); -        SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this, -                                                                wp_sp->GetID())); -    } -} - -void -POSIXThread::TraceNotify(const ProcessMessage &message) -{ -    POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); -    if (reg_ctx) -    { -        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); -        uint32_t wp_idx; -        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) -        { -            if (reg_ctx->IsWatchpointHit(wp_idx)) -            { -                WatchNotify(message); -                return; -            } -        } -    } - -    SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); -} - -void -POSIXThread::LimboNotify(const ProcessMessage &message) -{ -    SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this))); -} - -void -POSIXThread::SignalNotify(const ProcessMessage &message) -{ -    int signo = message.GetSignal(); -    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); -} - -void -POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) -{ -    int signo = message.GetSignal(); -    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo)); -} - -void -POSIXThread::CrashNotify(const ProcessMessage &message) -{ -    // FIXME: Update stop reason as per bugzilla 14598 -    int signo = message.GetSignal(); - -    assert(message.GetKind() == ProcessMessage::eCrashMessage); - -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log) -        log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", -                     __FUNCTION__, signo, message.PrintCrashReason()); - -    SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo, -                                                         message.GetCrashReason(), -                                                         message.GetFaultAddress()))); -} - -void -POSIXThread::ThreadNotify(const ProcessMessage &message) -{ -    SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this))); -} - -unsigned -POSIXThread::GetRegisterIndexFromOffset(unsigned offset) -{ -    unsigned reg = LLDB_INVALID_REGNUM; -    ArchSpec arch = HostInfo::GetArchitecture(); - -    switch (arch.GetMachine()) -    { -    default: -        llvm_unreachable("CPU type not supported!"); -        break; - -    case llvm::Triple::aarch64: -    case llvm::Triple::arm: -    case llvm::Triple::mips64: -    case llvm::Triple::ppc: -    case llvm::Triple::ppc64: -    case llvm::Triple::x86: -    case llvm::Triple::x86_64: -        { -            POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); -            reg = reg_ctx->GetRegisterIndexFromOffset(offset); -        } -        break; -    } -    return reg; -} - -void -POSIXThread::ExecNotify(const ProcessMessage &message) -{ -    SetStopInfo (StopInfo::CreateStopReasonWithExec(*this)); -} - -const char * -POSIXThread::GetRegisterName(unsigned reg) -{ -    const char * name = nullptr; -    ArchSpec arch = HostInfo::GetArchitecture(); - -    switch (arch.GetMachine()) -    { -    default: -        assert(false && "CPU type not supported!"); -        break; - -    case llvm::Triple::aarch64: -    case llvm::Triple::arm: -    case llvm::Triple::mips64: -    case llvm::Triple::ppc: -    case llvm::Triple::ppc64: -    case llvm::Triple::x86: -    case llvm::Triple::x86_64: -        name = GetRegisterContext()->GetRegisterName(reg); -        break; -    } -    return name; -} - -const char * -POSIXThread::GetRegisterNameFromOffset(unsigned offset) -{ -    return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} - diff --git a/source/Plugins/Process/FreeBSD/POSIXThread.h b/source/Plugins/Process/FreeBSD/POSIXThread.h deleted file mode 100644 index c38d194dbd19f..0000000000000 --- a/source/Plugins/Process/FreeBSD/POSIXThread.h +++ /dev/null @@ -1,132 +0,0 @@ -//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_POSIXThread_H_ -#define liblldb_POSIXThread_H_ - -// C Includes -// C++ Includes -#include <memory> -#include <string> - -// Other libraries and framework includes -#include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h" - -class ProcessMessage; -class ProcessMonitor; -class POSIXBreakpointProtocol; - -//------------------------------------------------------------------------------ -// @class POSIXThread -// @brief Abstraction of a POSIX thread. -class POSIXThread -    : public lldb_private::Thread -{ -public: -    POSIXThread(lldb_private::Process &process, lldb::tid_t tid); - -    virtual ~POSIXThread(); - -    void -    RefreshStateAfterStop() override; - -    // This notifies the thread when a private stop occurs. -    void -    DidStop () override; - -    const char * -    GetInfo() override; - -    void -    SetName (const char *name) override; - -    const char * -    GetName () override; - -    lldb::RegisterContextSP -    GetRegisterContext() override; - -    lldb::RegisterContextSP -    CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override; - -    lldb::addr_t -    GetThreadPointer () override; - -    //-------------------------------------------------------------------------- -    // These functions provide a mapping from the register offset -    // back to the register index or name for use in debugging or log -    // output. - -    unsigned -    GetRegisterIndexFromOffset(unsigned offset); - -    const char * -    GetRegisterName(unsigned reg); - -    const char * -    GetRegisterNameFromOffset(unsigned offset); - -    //-------------------------------------------------------------------------- -    // These methods form a specialized interface to POSIX threads. -    // -    bool Resume(); - -    void Notify(const ProcessMessage &message); - -    //-------------------------------------------------------------------------- -    // These methods provide an interface to watchpoints -    // -    bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp); - -    bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp); - -    uint32_t NumSupportedHardwareWatchpoints(); - -    uint32_t FindVacantWatchpointIndex(); - -protected: -    POSIXBreakpointProtocol * -    GetPOSIXBreakpointProtocol () -    { -        if (!m_reg_context_sp) -            m_reg_context_sp = GetRegisterContext(); -        return m_posix_thread; -    } -     -    std::unique_ptr<lldb_private::StackFrame> m_frame_ap; - -    lldb::BreakpointSiteSP m_breakpoint; - -    bool m_thread_name_valid; -    std::string m_thread_name; -    POSIXBreakpointProtocol *m_posix_thread; - -    ProcessMonitor & -    GetMonitor(); - -    bool -    CalculateStopInfo() override; - -    void BreakNotify(const ProcessMessage &message); -    void WatchNotify(const ProcessMessage &message); -    virtual void TraceNotify(const ProcessMessage &message); -    void LimboNotify(const ProcessMessage &message); -    void SignalNotify(const ProcessMessage &message); -    void SignalDeliveredNotify(const ProcessMessage &message); -    void CrashNotify(const ProcessMessage &message); -    void ThreadNotify(const ProcessMessage &message); -    void ExitNotify(const ProcessMessage &message); -    void ExecNotify(const ProcessMessage &message); - -    lldb_private::Unwind * -    GetUnwinder() override; -}; - -#endif // #ifndef liblldb_POSIXThread_H_ diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index a0458f16e558e..769ccd7248ac1 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -28,6 +28,23 @@  #include "ProcessMonitor.h"  #include "FreeBSDThread.h" +// Other libraries and framework includes +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/Watchpoint.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Target.h" + +#include "lldb/Host/posix/Fcntl.h" + +  using namespace lldb;  using namespace lldb_private; @@ -45,13 +62,13 @@ namespace  // Static functions.  lldb::ProcessSP -ProcessFreeBSD::CreateInstance(Target& target, +ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,                                 Listener &listener,                                 const FileSpec *crash_file_path)  {      lldb::ProcessSP process_sp;      if (crash_file_path == NULL) -        process_sp.reset(new ProcessFreeBSD (target, listener)); +        process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals()));      return process_sp;  } @@ -97,32 +114,6 @@ ProcessFreeBSD::GetPluginVersion()  }  void -ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - -Error -ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) -{ -    return Error(1, eErrorTypeGeneric); -} - -Log * -ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) -{ -    return NULL; -} - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) -    : ProcessPOSIX(target, listener, GetFreeBSDSignals ()), -      m_resume_signo(0) -{ -} - -void  ProcessFreeBSD::Terminate()  {  } @@ -232,7 +223,7 @@ ProcessFreeBSD::WillResume()      m_suspend_tids.clear();      m_run_tids.clear();      m_step_tids.clear(); -    return ProcessPOSIX::WillResume(); +    return Process::WillResume();  }  void @@ -264,7 +255,7 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)          break;      case ProcessMessage::eNewThreadMessage: -        assert(0 && "eNewThreadMessage unexpected on FreeBSD"); +        llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");          break;      case ProcessMessage::eExecMessage: @@ -274,3 +265,781 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)      m_message_queue.push(message);  } + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp) +    : Process(target_sp, listener, unix_signals_sp), +      m_byte_order(endian::InlHostByteOrder()), +      m_monitor(NULL), +      m_module(NULL), +      m_message_mutex (Mutex::eMutexTypeRecursive), +      m_exit_now(false), +      m_seen_initial_stop(), +      m_resume_signo(0) +{ +    // FIXME: Putting this code in the ctor and saving the byte order in a +    // member variable is a hack to avoid const qual issues in GetByteOrder. +    lldb::ModuleSP module = GetTarget().GetExecutableModule(); +    if (module && module->GetObjectFile()) +        m_byte_order = module->GetObjectFile()->GetByteOrder(); +} + +ProcessFreeBSD::~ProcessFreeBSD() +{ +    delete m_monitor; +} + +//------------------------------------------------------------------------------ +// Process protocol. +void +ProcessFreeBSD::Finalize() +{ +  Process::Finalize(); + +  if (m_monitor) +    m_monitor->StopMonitor(); +} + +bool +ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) +{ +    // For now we are just making sure the file exists for a given module +    ModuleSP exe_module_sp(target_sp->GetExecutableModule()); +    if (exe_module_sp.get()) +        return exe_module_sp->GetFileSpec().Exists(); +    // If there is no executable module, we return true since we might be preparing to attach. +    return true; +} + +Error +ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info) +{ +    Error error; +    assert(m_monitor == NULL); + +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); + +    m_monitor = new ProcessMonitor(this, pid, error); + +    if (!error.Success()) +        return error; + +    PlatformSP platform_sp (GetTarget().GetPlatform ()); +    assert (platform_sp.get()); +    if (!platform_sp) +        return error;  // FIXME: Detatch? + +    // Find out what we can about this process +    ProcessInstanceInfo process_info; +    platform_sp->GetProcessInfo (pid, process_info); + +    // Resolve the executable module +    ModuleSP exe_module_sp; +    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); +    ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture()); +    error = platform_sp->ResolveExecutable(exe_module_spec, +                                           exe_module_sp, +                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL); +    if (!error.Success()) +        return error; + +    // Fix the target architecture if necessary +    const ArchSpec &module_arch = exe_module_sp->GetArchitecture(); +    if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch)) +        GetTarget().SetArchitecture(module_arch); + +    // Initialize the target module list +    GetTarget().SetExecutableModule (exe_module_sp, true); + +    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); + +    SetID(pid); + +    return error; +} + +Error +ProcessFreeBSD::WillLaunch(Module* module) +{ +    Error error; +    return error; +} + +FileSpec +ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action, +                          const FileSpec &default_file_spec, +                          const FileSpec &dbg_pts_file_spec) +{ +    FileSpec file_spec{}; + +    if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) +    { +        file_spec = file_action->GetFileSpec(); +        // By default the stdio paths passed in will be pseudo-terminal +        // (/dev/pts). If so, convert to using a different default path +        // instead to redirect I/O to the debugger console. This should +        // also handle user overrides to /dev/null or a different file. +        if (!file_spec || file_spec == dbg_pts_file_spec) +            file_spec = default_file_spec; +    } +    return file_spec; +} + +Error +ProcessFreeBSD::DoLaunch (Module *module, +                        ProcessLaunchInfo &launch_info) +{ +    Error error; +    assert(m_monitor == NULL); + +    FileSpec working_dir = launch_info.GetWorkingDirectory(); +    if (working_dir && +            (!working_dir.ResolvePath() || +             working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) +    { +        error.SetErrorStringWithFormat("No such file or directory: %s", +                working_dir.GetCString()); +        return error; +    } + +    SetPrivateState(eStateLaunching); + +    const lldb_private::FileAction *file_action; + +    // Default of empty will mean to use existing open file descriptors +    FileSpec stdin_file_spec{}; +    FileSpec stdout_file_spec{}; +    FileSpec stderr_file_spec{}; + +    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false}; + +    file_action = launch_info.GetFileActionForFD (STDIN_FILENO); +    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec); + +    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); +    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec); + +    file_action = launch_info.GetFileActionForFD (STDERR_FILENO); +    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec); + +    m_monitor = new ProcessMonitor(this, +                                   module, +                                   launch_info.GetArguments().GetConstArgumentVector(), +                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(), +                                   stdin_file_spec, +                                   stdout_file_spec, +                                   stderr_file_spec, +                                   working_dir, +                                   launch_info, +                                   error); + +    m_module = module; + +    if (!error.Success()) +        return error; + +    int terminal = m_monitor->GetTerminalFD(); +    if (terminal >= 0) { +        // The reader thread will close the file descriptor when done, so we pass it a copy. +#ifdef F_DUPFD_CLOEXEC +        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); +        if (stdio == -1) { +            error.SetErrorToErrno(); +            return error; +        } +#else +        // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD) +        int stdio = fcntl(terminal, F_DUPFD, 0); +        if (stdio == -1) { +            error.SetErrorToErrno(); +            return error; +        } +        stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC); +        if (stdio == -1) { +            error.SetErrorToErrno(); +            return error; +        } +#endif +        SetSTDIOFileDescriptor(stdio); +    } + +    SetID(m_monitor->GetPID()); +    return error; +} + +void +ProcessFreeBSD::DidLaunch() +{ +} + +addr_t +ProcessFreeBSD::GetImageInfoAddress() +{ +    Target *target = &GetTarget(); +    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); +    Address addr = obj_file->GetImageInfoAddress(target); + +    if (addr.IsValid()) +        return addr.GetLoadAddress(target); +    return LLDB_INVALID_ADDRESS; +} + +Error +ProcessFreeBSD::DoHalt(bool &caused_stop) +{ +    Error error; + +    if (IsStopped()) +    { +        caused_stop = false; +    } +    else if (kill(GetID(), SIGSTOP)) +    { +        caused_stop = false; +        error.SetErrorToErrno(); +    } +    else +    { +        caused_stop = true; +    } +    return error; +} + +Error +ProcessFreeBSD::DoSignal(int signal) +{ +    Error error; + +    if (kill(GetID(), signal)) +        error.SetErrorToErrno(); + +    return error; +} + +Error +ProcessFreeBSD::DoDestroy() +{ +    Error error; + +    if (!HasExited()) +    { +        assert(m_monitor); +        m_exit_now = true; +        if (GetID() == LLDB_INVALID_PROCESS_ID) +        { +            error.SetErrorString("invalid process id"); +            return error; +        } +        if (!m_monitor->Kill()) +        { +            error.SetErrorToErrno(); +            return error; +        } + +        SetPrivateState(eStateExited); +    } + +    return error; +} + +void +ProcessFreeBSD::DoDidExec() +{ +    Target *target = &GetTarget(); +    if (target) +    { +        PlatformSP platform_sp (target->GetPlatform()); +        assert (platform_sp.get()); +        if (platform_sp) +        { +            ProcessInstanceInfo process_info; +            platform_sp->GetProcessInfo(GetID(), process_info); +            ModuleSP exe_module_sp; +            ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture()); +            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); +            Error error = platform_sp->ResolveExecutable(exe_module_spec, +                                                         exe_module_sp, +                                                         executable_search_paths.GetSize() ? &executable_search_paths : NULL); +            if (!error.Success()) +                return; +            target->SetExecutableModule(exe_module_sp, true); +        } +    } +} + +bool +ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) +{ +    bool added_to_set = false; +    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid); +    if (it == m_seen_initial_stop.end()) +    { +        m_seen_initial_stop.insert(stop_tid); +        added_to_set = true; +    } +    return added_to_set; +} + +bool +ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid) +{ +    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); +} + +FreeBSDThread * +ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid) +{ +    return new FreeBSDThread(process, tid); +} + +void +ProcessFreeBSD::RefreshStateAfterStop() +{ +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size()); + +    Mutex::Locker lock(m_message_mutex); + +    // This method used to only handle one message.  Changing it to loop allows +    // it to handle the case where we hit a breakpoint while handling a different +    // breakpoint. +    while (!m_message_queue.empty()) +    { +        ProcessMessage &message = m_message_queue.front(); + +        // Resolve the thread this message corresponds to and pass it along. +        lldb::tid_t tid = message.GetTID(); +        if (log) +            log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); + +        m_thread_list.RefreshStateAfterStop(); + +        FreeBSDThread *thread = static_cast<FreeBSDThread*>( +            GetThreadList().FindThreadByID(tid, false).get()); +        if (thread) +            thread->Notify(message); + +        if (message.GetKind() == ProcessMessage::eExitMessage) +        { +            // FIXME: We should tell the user about this, but the limbo message is probably better for that. +            if (log) +                log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); + +            Mutex::Locker lock(m_thread_list.GetMutex()); + +            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); +            thread_sp.reset(); +            m_seen_initial_stop.erase(tid); +        } + +        m_message_queue.pop(); +    } +} + +bool +ProcessFreeBSD::IsAlive() +{ +    StateType state = GetPrivateState(); +    return state != eStateDetached +        && state != eStateExited +        && state != eStateInvalid +        && state != eStateUnloaded; +} + +size_t +ProcessFreeBSD::DoReadMemory(addr_t vm_addr, +                           void *buf, size_t size, Error &error) +{ +    assert(m_monitor); +    return m_monitor->ReadMemory(vm_addr, buf, size, error); +} + +size_t +ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, +                            Error &error) +{ +    assert(m_monitor); +    return m_monitor->WriteMemory(vm_addr, buf, size, error); +} + +addr_t +ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, +                               Error &error) +{ +    addr_t allocated_addr = LLDB_INVALID_ADDRESS; + +    unsigned prot = 0; +    if (permissions & lldb::ePermissionsReadable) +        prot |= eMmapProtRead; +    if (permissions & lldb::ePermissionsWritable) +        prot |= eMmapProtWrite; +    if (permissions & lldb::ePermissionsExecutable) +        prot |= eMmapProtExec; + +    if (InferiorCallMmap(this, allocated_addr, 0, size, prot, +                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { +        m_addr_to_mmap_size[allocated_addr] = size; +        error.Clear(); +    } else { +        allocated_addr = LLDB_INVALID_ADDRESS; +        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); +    } + +    return allocated_addr; +} + +Error +ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr) +{ +    Error error; +    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); +    if (pos != m_addr_to_mmap_size.end() && +        InferiorCallMunmap(this, addr, pos->second)) +        m_addr_to_mmap_size.erase (pos); +    else +        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); + +    return error; +} + +size_t +ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) +{ +    static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 }; +    static const uint8_t g_i386_opcode[] = { 0xCC }; + +    ArchSpec arch = GetTarget().GetArchitecture(); +    const uint8_t *opcode = NULL; +    size_t opcode_size = 0; + +    switch (arch.GetMachine()) +    { +    default: +        assert(false && "CPU type not supported!"); +        break; + +    case llvm::Triple::arm: +        { +            // The ARM reference recommends the use of 0xe7fddefe and 0xdefe +            // but the linux kernel does otherwise. +            static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; +            static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; + +            lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); +            AddressClass addr_class = eAddressClassUnknown; + +            if (bp_loc_sp) +                addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); + +            if (addr_class == eAddressClassCodeAlternateISA +                || (addr_class == eAddressClassUnknown +                    && bp_loc_sp->GetAddress().GetOffset() & 1)) +            { +                opcode = g_thumb_breakpoint_opcode; +                opcode_size = sizeof(g_thumb_breakpoint_opcode); +            } +            else +            { +                opcode = g_arm_breakpoint_opcode; +                opcode_size = sizeof(g_arm_breakpoint_opcode); +            } +        } +        break; +    case llvm::Triple::aarch64: +        opcode = g_aarch64_opcode; +        opcode_size = sizeof(g_aarch64_opcode); +        break; + +    case llvm::Triple::x86: +    case llvm::Triple::x86_64: +        opcode = g_i386_opcode; +        opcode_size = sizeof(g_i386_opcode); +        break; +    } + +    bp_site->SetTrapOpcode(opcode, opcode_size); +    return opcode_size; +} + +Error +ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site) +{ +    return EnableSoftwareBreakpoint(bp_site); +} + +Error +ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site) +{ +    return DisableSoftwareBreakpoint(bp_site); +} + +Error +ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) +{ +    Error error; +    if (wp) +    { +        user_id_t watchID = wp->GetID(); +        addr_t addr = wp->GetLoadAddress(); +        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); +        if (log) +            log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")", +                         watchID); +        if (wp->IsEnabled()) +        { +            if (log) +                log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 +                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", +                            watchID, (uint64_t)addr); +            return error; +        } + +        // Try to find a vacant watchpoint slot in the inferiors' main thread +        uint32_t wp_hw_index = LLDB_INVALID_INDEX32; +        Mutex::Locker lock(m_thread_list.GetMutex()); +        FreeBSDThread *thread = static_cast<FreeBSDThread*>( +                               m_thread_list.GetThreadAtIndex(0, false).get()); + +        if (thread) +            wp_hw_index = thread->FindVacantWatchpointIndex(); + +        if (wp_hw_index == LLDB_INVALID_INDEX32) +        { +            error.SetErrorString("Setting hardware watchpoint failed."); +        } +        else +        { +            wp->SetHardwareIndex(wp_hw_index); +            bool wp_enabled = true; +            uint32_t thread_count = m_thread_list.GetSize(false); +            for (uint32_t i = 0; i < thread_count; ++i) +            { +                thread = static_cast<FreeBSDThread*>( +                         m_thread_list.GetThreadAtIndex(i, false).get()); +                if (thread) +                    wp_enabled &= thread->EnableHardwareWatchpoint(wp); +                else +                    wp_enabled = false; +            } +            if (wp_enabled) +            { +                wp->SetEnabled(true, notify); +                return error; +            } +            else +            { +                // Watchpoint enabling failed on at least one +                // of the threads so roll back all of them +                DisableWatchpoint(wp, false); +                error.SetErrorString("Setting hardware watchpoint failed"); +            } +        } +    } +    else +        error.SetErrorString("Watchpoint argument was NULL."); +    return error; +} + +Error +ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) +{ +    Error error; +    if (wp) +    { +        user_id_t watchID = wp->GetID(); +        addr_t addr = wp->GetLoadAddress(); +        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); +        if (log) +            log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")", +                        watchID); +        if (!wp->IsEnabled()) +        { +            if (log) +                log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 +                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", +                            watchID, (uint64_t)addr); +            // This is needed (for now) to keep watchpoints disabled correctly +            wp->SetEnabled(false, notify); +            return error; +        } + +        if (wp->IsHardware()) +        { +            bool wp_disabled = true; +            Mutex::Locker lock(m_thread_list.GetMutex()); +            uint32_t thread_count = m_thread_list.GetSize(false); +            for (uint32_t i = 0; i < thread_count; ++i) +            { +                FreeBSDThread *thread = static_cast<FreeBSDThread*>( +                                      m_thread_list.GetThreadAtIndex(i, false).get()); +                if (thread) +                    wp_disabled &= thread->DisableHardwareWatchpoint(wp); +                else +                    wp_disabled = false; +            } +            if (wp_disabled) +            { +                wp->SetHardwareIndex(LLDB_INVALID_INDEX32); +                wp->SetEnabled(false, notify); +                return error; +            } +            else +                error.SetErrorString("Disabling hardware watchpoint failed"); +        } +    } +    else +        error.SetErrorString("Watchpoint argument was NULL."); +    return error; +} + +Error +ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) +{ +    Error error; +    Mutex::Locker lock(m_thread_list.GetMutex()); +    FreeBSDThread *thread = static_cast<FreeBSDThread*>( +                          m_thread_list.GetThreadAtIndex(0, false).get()); +    if (thread) +        num = thread->NumSupportedHardwareWatchpoints(); +    else +        error.SetErrorString("Process does not exist."); +    return error; +} + +Error +ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) +{ +    Error error = GetWatchpointSupportInfo(num); +    // Watchpoints trigger and halt the inferior after +    // the corresponding instruction has been executed. +    after = true; +    return error; +} + +uint32_t +ProcessFreeBSD::UpdateThreadListIfNeeded() +{ +    Mutex::Locker lock(m_thread_list.GetMutex()); +    // Do not allow recursive updates. +    return m_thread_list.GetSize(false); +} + +#if 0 +bool +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ +    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); + +    bool has_updated = false; +    // Update the process thread list with this new thread. +    // FIXME: We should be using tid, not pid. +    assert(m_monitor); +    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); +    if (!thread_sp) { +        thread_sp.reset(CreateNewFreeBSDThread(*this, GetID())); +        has_updated = true; +    } + +    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) +        log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); +    new_thread_list.AddThread(thread_sp); + +    return has_updated; // the list has been updated +} +#endif + +ByteOrder +ProcessFreeBSD::GetByteOrder() const +{ +    // FIXME: We should be able to extract this value directly.  See comment in +    // ProcessFreeBSD(). +    return m_byte_order; +} + +size_t +ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error) +{ +    ssize_t status; +    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)  +    { +        error.SetErrorToErrno(); +        return 0; +    } +    return status; +} + +//------------------------------------------------------------------------------ +// Utility functions. + +bool +ProcessFreeBSD::HasExited() +{ +    switch (GetPrivateState()) +    { +    default: +        break; + +    case eStateDetached: +    case eStateExited: +        return true; +    } + +    return false; +} + +bool +ProcessFreeBSD::IsStopped() +{ +    switch (GetPrivateState()) +    { +    default: +        break; + +    case eStateStopped: +    case eStateCrashed: +    case eStateSuspended: +        return true; +    } + +    return false; +} + +bool +ProcessFreeBSD::IsAThreadRunning() +{ +    bool is_running = false; +    Mutex::Locker lock(m_thread_list.GetMutex()); +    uint32_t thread_count = m_thread_list.GetSize(false); +    for (uint32_t i = 0; i < thread_count; ++i) +    { +        FreeBSDThread *thread = static_cast<FreeBSDThread*>( +            m_thread_list.GetThreadAtIndex(i, false).get()); +        StateType thread_state = thread->GetState(); +        if (thread_state == eStateRunning || thread_state == eStateStepping) +        { +            is_running = true; +            break; +        } +    } +    return is_running; +} + +const DataBufferSP +ProcessFreeBSD::GetAuxvData () +{ +    // If we're the local platform, we can ask the host for auxv data. +    PlatformSP platform_sp = GetTarget().GetPlatform (); +    if (platform_sp && platform_sp->IsHost ()) +        return lldb_private::Host::GetAuxvData(this); + +    // Somewhat unexpected - the process is not running locally or we don't have a platform. +    assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?"); +    return DataBufferSP (); +} diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h index d6ae3462c73b1..3cc46f4898756 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -13,18 +13,20 @@  // C Includes  // C++ Includes +#include <set>  #include <queue>  // Other libraries and framework includes  #include "lldb/Target/Process.h"  #include "lldb/Target/ThreadList.h"  #include "ProcessMessage.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h"  class ProcessMonitor; +class FreeBSDThread;  class ProcessFreeBSD : -    public ProcessPOSIX +    public lldb_private::Process  {  public: @@ -32,7 +34,7 @@ public:      // Static functions.      //------------------------------------------------------------------      static lldb::ProcessSP -    CreateInstance(lldb_private::Target& target, +    CreateInstance(lldb::TargetSP target_sp,                     lldb_private::Listener &listener,                     const lldb_private::FileSpec *crash_file_path); @@ -51,45 +53,188 @@ public:      //------------------------------------------------------------------      // Constructors and destructors      //------------------------------------------------------------------ -    ProcessFreeBSD(lldb_private::Target& target, -                   lldb_private::Listener &listener); - -    virtual lldb_private::Error -    DoDetach(bool keep_stopped); - -    virtual bool -    UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); +    ProcessFreeBSD(lldb::TargetSP target_sp, +                   lldb_private::Listener &listener, +                   lldb::UnixSignalsSP &unix_signals_sp); -    virtual lldb_private::Error -    DoResume(); +    ~ProcessFreeBSD();      virtual lldb_private::Error -    WillResume(); - -    virtual void -    SendMessage(const ProcessMessage &message); +    WillResume() override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------      virtual lldb_private::ConstString -    GetPluginName(); +    GetPluginName() override;      virtual uint32_t -    GetPluginVersion(); +    GetPluginVersion() override; + +public: +    //------------------------------------------------------------------ +    // Process protocol. +    //------------------------------------------------------------------ +    void +    Finalize() override; + +    bool +    CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + +    lldb_private::Error +    WillLaunch(lldb_private::Module *module) override; + +    lldb_private::Error +    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; + +    lldb_private::Error +    DoLaunch (lldb_private::Module *exe_module,  +              lldb_private::ProcessLaunchInfo &launch_info) override; + +    void +    DidLaunch() override; + +    lldb_private::Error +    DoResume() override; + +    lldb_private::Error +    DoHalt(bool &caused_stop) override; + +    lldb_private::Error +    DoDetach(bool keep_stopped) override; + +    lldb_private::Error +    DoSignal(int signal) override; + +    lldb_private::Error +    DoDestroy() override; + +    void +    DoDidExec() override; + +    void +    RefreshStateAfterStop() override; + +    bool +    IsAlive() override; + +    size_t +    DoReadMemory(lldb::addr_t vm_addr, +                 void *buf, +                 size_t size, +                 lldb_private::Error &error) override; + +    size_t +    DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, +                  lldb_private::Error &error) override; + +    lldb::addr_t +    DoAllocateMemory(size_t size, uint32_t permissions, +                     lldb_private::Error &error) override; + +    lldb_private::Error +    DoDeallocateMemory(lldb::addr_t ptr) override; + +    virtual size_t +    GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); +    lldb_private::Error +    EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + +    lldb_private::Error +    DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; + +    lldb_private::Error +    EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + +    lldb_private::Error +    DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; + +    lldb_private::Error +    GetWatchpointSupportInfo(uint32_t &num) override; + +    lldb_private::Error +    GetWatchpointSupportInfo(uint32_t &num, bool &after) override; + +    virtual uint32_t +    UpdateThreadListIfNeeded(); + +    bool +    UpdateThreadList(lldb_private::ThreadList &old_thread_list,  +                     lldb_private::ThreadList &new_thread_list) override; + +    virtual lldb::ByteOrder +    GetByteOrder() const; + +    lldb::addr_t +    GetImageInfoAddress() override; + +    size_t +    PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; + +    const lldb::DataBufferSP +    GetAuxvData () override; + +    //-------------------------------------------------------------------------- +    // ProcessFreeBSD internal API. + +    /// Registers the given message with this process.      virtual void -    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); +    SendMessage(const ProcessMessage &message); -    virtual lldb_private::Error -    ExecutePluginCommand(lldb_private::Args &command, -                         lldb_private::Stream *strm); +    ProcessMonitor & +    GetMonitor() { assert(m_monitor); return *m_monitor; } + +    lldb_private::FileSpec +    GetFileSpec(const lldb_private::FileAction *file_action, +                const lldb_private::FileSpec &default_file_spec, +                const lldb_private::FileSpec &dbg_pts_file_spec); + +    /// Adds the thread to the list of threads for which we have received the initial stopping signal. +    /// The \p stop_tid parameter indicates the thread which the stop happened for. +    bool +    AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); + +    bool +    WaitingForInitialStop(lldb::tid_t stop_tid); -    virtual lldb_private::Log * -    EnablePluginLogging(lldb_private::Stream *strm, -                        lldb_private::Args &command); +    virtual FreeBSDThread * +    CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);  protected: +    /// Target byte order. +    lldb::ByteOrder m_byte_order; + +    /// Process monitor; +    ProcessMonitor *m_monitor; + +    /// The module we are executing. +    lldb_private::Module *m_module; + +    /// Message queue notifying this instance of inferior process state changes. +    lldb_private::Mutex m_message_mutex; +    std::queue<ProcessMessage> m_message_queue; + +    /// Drive any exit events to completion. +    bool m_exit_now; + +    /// Returns true if the process has exited. +    bool HasExited(); + +    /// Returns true if the process is stopped. +    bool IsStopped(); + +    /// Returns true if at least one running is currently running +    bool IsAThreadRunning(); + +    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; +    MMapMap m_addr_to_mmap_size; + +    typedef std::set<lldb::tid_t> ThreadStopSet; +    /// Every thread begins with a stop signal. This keeps track +    /// of the threads for which we have received the stop signal. +    ThreadStopSet m_seen_initial_stop; +      friend class FreeBSDThread;      typedef std::vector<lldb::tid_t> tid_collection; diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index 427c66ce3e6b3..ceb527b61d80e 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -32,7 +32,7 @@  #include "lldb/Utility/PseudoTerminal.h"  #include "Plugins/Process/POSIX/CrashReason.h" -#include "POSIXThread.h" +#include "FreeBSDThread.h"  #include "ProcessFreeBSD.h"  #include "ProcessPOSIXLog.h"  #include "ProcessMonitor.h" @@ -804,7 +804,7 @@ ProcessMonitor::AttachArgs::~AttachArgs()  /// launching or attaching to the inferior process, and then 2) servicing  /// operations such as register reads/writes, stepping, etc.  See the comments  /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, +ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,                                 Module *module,                                 const char *argv[],                                 const char *envp[], @@ -865,7 +865,7 @@ WAIT_AGAIN:      }  } -ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, +ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,                                 lldb::pid_t pid,                                 lldb_private::Error &error)      : m_process(static_cast<ProcessFreeBSD *>(process)), diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 20ce582d973ec..07fa6b7869add 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -49,7 +49,7 @@ public:      /// Launches an inferior process ready for debugging.  Forms the      /// implementation of Process::DoLaunch. -    ProcessMonitor(ProcessPOSIX *process, +    ProcessMonitor(ProcessFreeBSD *process,                     lldb_private::Module *module,                     char const *argv[],                     char const *envp[], @@ -60,7 +60,7 @@ public:                     const lldb_private::ProcessLaunchInfo &launch_info,                     lldb_private::Error &error); -    ProcessMonitor(ProcessPOSIX *process, +    ProcessMonitor(ProcessFreeBSD *process,                     lldb::pid_t pid,                     lldb_private::Error &error); diff --git a/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp b/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp deleted file mode 100644 index 360382e2e63a7..0000000000000 --- a/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp +++ /dev/null @@ -1,939 +0,0 @@ -//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -#include <errno.h> - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Breakpoint/Watchpoint.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/State.h" -#include "lldb/Host/FileSpec.h" -#include "lldb/Host/Host.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Platform.h" -#include "lldb/Target/Target.h" - -#include "ProcessPOSIX.h" -#include "ProcessPOSIXLog.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" -#include "POSIXThread.h" -#include "ProcessMonitor.h" - -#include "lldb/Host/posix/Fcntl.h" - -using namespace lldb; -using namespace lldb_private; - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp) -    : Process(target, listener, unix_signals_sp), -      m_byte_order(lldb::endian::InlHostByteOrder()), -      m_monitor(NULL), -      m_module(NULL), -      m_message_mutex (Mutex::eMutexTypeRecursive), -      m_exit_now(false), -      m_seen_initial_stop() -{ -    // FIXME: Putting this code in the ctor and saving the byte order in a -    // member variable is a hack to avoid const qual issues in GetByteOrder. -    lldb::ModuleSP module = GetTarget().GetExecutableModule(); -    if (module && module->GetObjectFile()) -        m_byte_order = module->GetObjectFile()->GetByteOrder(); -} - -ProcessPOSIX::~ProcessPOSIX() -{ -    delete m_monitor; -} - -//------------------------------------------------------------------------------ -// Process protocol. -void -ProcessPOSIX::Finalize() -{ -  Process::Finalize(); - -  if (m_monitor) -    m_monitor->StopMonitor(); -} - -bool -ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) -{ -    // For now we are just making sure the file exists for a given module -    ModuleSP exe_module_sp(target.GetExecutableModule()); -    if (exe_module_sp.get()) -        return exe_module_sp->GetFileSpec().Exists(); -    // If there is no executable module, we return true since we might be preparing to attach. -    return true; -} - -Error -ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info) -{ -    Error error; -    assert(m_monitor == NULL); - -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID()); - -    m_monitor = new ProcessMonitor(this, pid, error); - -    if (!error.Success()) -        return error; - -    PlatformSP platform_sp (m_target.GetPlatform ()); -    assert (platform_sp.get()); -    if (!platform_sp) -        return error;  // FIXME: Detatch? - -    // Find out what we can about this process -    ProcessInstanceInfo process_info; -    platform_sp->GetProcessInfo (pid, process_info); - -    // Resolve the executable module -    ModuleSP exe_module_sp; -    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); -    ModuleSpec exe_module_spec(process_info.GetExecutableFile(), m_target.GetArchitecture()); -    error = platform_sp->ResolveExecutable(exe_module_spec, -                                           exe_module_sp, -                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL); -    if (!error.Success()) -        return error; - -    // Fix the target architecture if necessary -    const ArchSpec &module_arch = exe_module_sp->GetArchitecture(); -    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch)) -        m_target.SetArchitecture(module_arch); - -    // Initialize the target module list -    m_target.SetExecutableModule (exe_module_sp, true); - -    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD()); - -    SetID(pid); - -    return error; -} - -Error -ProcessPOSIX::WillLaunch(Module* module) -{ -    Error error; -    return error; -} - -FileSpec -ProcessPOSIX::GetFileSpec(const lldb_private::FileAction *file_action, -                          const FileSpec &default_file_spec, -                          const FileSpec &dbg_pts_file_spec) -{ -    FileSpec file_spec{}; - -    if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) -    { -        file_spec = file_action->GetFileSpec(); -        // By default the stdio paths passed in will be pseudo-terminal -        // (/dev/pts). If so, convert to using a different default path -        // instead to redirect I/O to the debugger console. This should -        // also handle user overrides to /dev/null or a different file. -        if (!file_spec || file_spec == dbg_pts_file_spec) -            file_spec = default_file_spec; -    } -    return file_spec; -} - -Error -ProcessPOSIX::DoLaunch (Module *module, -                        ProcessLaunchInfo &launch_info) -{ -    Error error; -    assert(m_monitor == NULL); - -    FileSpec working_dir = launch_info.GetWorkingDirectory(); -    if (working_dir && -            (!working_dir.ResolvePath() || -             working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) -    { -        error.SetErrorStringWithFormat("No such file or directory: %s", -                working_dir.GetCString()); -        return error; -    } - -    SetPrivateState(eStateLaunching); - -    const lldb_private::FileAction *file_action; - -    // Default of empty will mean to use existing open file descriptors -    FileSpec stdin_file_spec{}; -    FileSpec stdout_file_spec{}; -    FileSpec stderr_file_spec{}; - -    const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false}; - -    file_action = launch_info.GetFileActionForFD (STDIN_FILENO); -    stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec); - -    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); -    stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec); - -    file_action = launch_info.GetFileActionForFD (STDERR_FILENO); -    stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec); - -    m_monitor = new ProcessMonitor(this, -                                   module, -                                   launch_info.GetArguments().GetConstArgumentVector(), -                                   launch_info.GetEnvironmentEntries().GetConstArgumentVector(), -                                   stdin_file_spec, -                                   stdout_file_spec, -                                   stderr_file_spec, -                                   working_dir, -                                   launch_info, -                                   error); - -    m_module = module; - -    if (!error.Success()) -        return error; - -    int terminal = m_monitor->GetTerminalFD(); -    if (terminal >= 0) { -        // The reader thread will close the file descriptor when done, so we pass it a copy. -        int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0); -        if (stdio == -1) { -            error.SetErrorToErrno(); -            return error; -        } -        SetSTDIOFileDescriptor(stdio); -    } - -    SetID(m_monitor->GetPID()); -    return error; -} - -void -ProcessPOSIX::DidLaunch() -{ -} - -Error -ProcessPOSIX::DoResume() -{ -    StateType state = GetPrivateState(); - -    assert(state == eStateStopped); - -    SetPrivateState(eStateRunning); - -    bool did_resume = false; - -    Mutex::Locker lock(m_thread_list.GetMutex()); - -    uint32_t thread_count = m_thread_list.GetSize(false); -    for (uint32_t i = 0; i < thread_count; ++i) -    { -        POSIXThread *thread = static_cast<POSIXThread*>( -            m_thread_list.GetThreadAtIndex(i, false).get()); -        did_resume = thread->Resume() || did_resume; -    } -    assert(did_resume && "Process resume failed!"); - -    return Error(); -} - -addr_t -ProcessPOSIX::GetImageInfoAddress() -{ -    Target *target = &GetTarget(); -    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); -    Address addr = obj_file->GetImageInfoAddress(target); - -    if (addr.IsValid()) -        return addr.GetLoadAddress(target); -    return LLDB_INVALID_ADDRESS; -} - -Error -ProcessPOSIX::DoHalt(bool &caused_stop) -{ -    Error error; - -    if (IsStopped()) -    { -        caused_stop = false; -    } -    else if (kill(GetID(), SIGSTOP)) -    { -        caused_stop = false; -        error.SetErrorToErrno(); -    } -    else -    { -        caused_stop = true; -    } -    return error; -} - -Error -ProcessPOSIX::DoSignal(int signal) -{ -    Error error; - -    if (kill(GetID(), signal)) -        error.SetErrorToErrno(); - -    return error; -} - -Error -ProcessPOSIX::DoDestroy() -{ -    Error error; - -    if (!HasExited()) -    { -        assert(m_monitor); -        m_exit_now = true; -        if (GetID() == LLDB_INVALID_PROCESS_ID) -        { -            error.SetErrorString("invalid process id"); -            return error; -        } -        if (!m_monitor->Kill()) -        { -            error.SetErrorToErrno(); -            return error; -        } - -        SetPrivateState(eStateExited); -    } - -    return error; -} - -void -ProcessPOSIX::DoDidExec() -{ -    Target *target = &GetTarget(); -    if (target) -    { -        PlatformSP platform_sp (target->GetPlatform()); -        assert (platform_sp.get()); -        if (platform_sp) -        { -            ProcessInstanceInfo process_info; -            platform_sp->GetProcessInfo(GetID(), process_info); -            ModuleSP exe_module_sp; -            ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture()); -            FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); -            Error error = platform_sp->ResolveExecutable(exe_module_spec, -                                                         exe_module_sp, -                                                         executable_search_paths.GetSize() ? &executable_search_paths : NULL); -            if (!error.Success()) -                return; -            target->SetExecutableModule(exe_module_sp, true); -        } -    } -} - -void -ProcessPOSIX::SendMessage(const ProcessMessage &message) -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); - -    Mutex::Locker lock(m_message_mutex); - -    Mutex::Locker thread_lock(m_thread_list.GetMutex()); - -    POSIXThread *thread = static_cast<POSIXThread*>( -        m_thread_list.FindThreadByID(message.GetTID(), false).get()); - -    switch (message.GetKind()) -    { -    case ProcessMessage::eInvalidMessage: -        return; - -    case ProcessMessage::eAttachMessage: -        SetPrivateState(eStateStopped); -        return; - -    case ProcessMessage::eLimboMessage: -        assert(thread); -        thread->SetState(eStateStopped); -        if (message.GetTID() == GetID()) -        { -            m_exit_status = message.GetExitStatus(); -            if (m_exit_now) -            { -                SetPrivateState(eStateExited); -                m_monitor->Detach(GetID()); -            } -            else -            { -                SetPrivateState(eStateStopped); -            } -        } -        else -        { -            SetPrivateState(eStateStopped); -        } -        break; - -    case ProcessMessage::eExitMessage: -        if (thread != nullptr) -            thread->SetState(eStateExited); -        else -        { -            if (log) -                log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ()); -        } - -        // FIXME: I'm not sure we need to do this. -        if (message.GetTID() == GetID()) -        { -            SetExitStatus(message.GetExitStatus(), NULL); -        } -        else if (!IsAThreadRunning()) -            SetPrivateState(eStateStopped); -        break; - -    case ProcessMessage::eSignalMessage: -    case ProcessMessage::eSignalDeliveredMessage: -        if (message.GetSignal() == SIGSTOP && -            AddThreadForInitialStopIfNeeded(message.GetTID())) -            return; -        // Intentional fall-through - -    case ProcessMessage::eBreakpointMessage: -    case ProcessMessage::eTraceMessage: -    case ProcessMessage::eWatchpointMessage: -    case ProcessMessage::eCrashMessage: -        assert(thread); -        thread->SetState(eStateStopped); -        SetPrivateState(eStateStopped); -        break; - -    case ProcessMessage::eNewThreadMessage: -    { -        lldb::tid_t  new_tid = message.GetChildTID(); -        if (WaitingForInitialStop(new_tid)) -        { -            m_monitor->WaitForInitialTIDStop(new_tid); -        } -        assert(thread); -        thread->SetState(eStateStopped); -        SetPrivateState(eStateStopped); -        break; -    } - -    case ProcessMessage::eExecMessage: -    { -        assert(thread); -        thread->SetState(eStateStopped); -        SetPrivateState(eStateStopped); -        break; -    } -    } - - -    m_message_queue.push(message); -} - -bool -ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid) -{ -    bool added_to_set = false; -    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid); -    if (it == m_seen_initial_stop.end()) -    { -        m_seen_initial_stop.insert(stop_tid); -        added_to_set = true; -    } -    return added_to_set; -} - -bool -ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid) -{ -    return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end()); -} - -POSIXThread * -ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid) -{ -    return new POSIXThread(process, tid); -} - -void -ProcessPOSIX::RefreshStateAfterStop() -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size()); - -    Mutex::Locker lock(m_message_mutex); - -    // This method used to only handle one message.  Changing it to loop allows -    // it to handle the case where we hit a breakpoint while handling a different -    // breakpoint. -    while (!m_message_queue.empty()) -    { -        ProcessMessage &message = m_message_queue.front(); - -        // Resolve the thread this message corresponds to and pass it along. -        lldb::tid_t tid = message.GetTID(); -        if (log) -            log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid); - -        if (message.GetKind() == ProcessMessage::eNewThreadMessage) -        { -            if (log) -                log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID()); -            lldb::tid_t child_tid = message.GetChildTID(); -            ThreadSP thread_sp; -            thread_sp.reset(CreateNewPOSIXThread(*this, child_tid)); - -            Mutex::Locker lock(m_thread_list.GetMutex()); - -            m_thread_list.AddThread(thread_sp); -        } - -        m_thread_list.RefreshStateAfterStop(); - -        POSIXThread *thread = static_cast<POSIXThread*>( -            GetThreadList().FindThreadByID(tid, false).get()); -        if (thread) -            thread->Notify(message); - -        if (message.GetKind() == ProcessMessage::eExitMessage) -        { -            // FIXME: We should tell the user about this, but the limbo message is probably better for that. -            if (log) -                log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); - -            Mutex::Locker lock(m_thread_list.GetMutex()); - -            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); -            thread_sp.reset(); -            m_seen_initial_stop.erase(tid); -        } - -        m_message_queue.pop(); -    } -} - -bool -ProcessPOSIX::IsAlive() -{ -    StateType state = GetPrivateState(); -    return state != eStateDetached -        && state != eStateExited -        && state != eStateInvalid -        && state != eStateUnloaded; -} - -size_t -ProcessPOSIX::DoReadMemory(addr_t vm_addr, -                           void *buf, size_t size, Error &error) -{ -    assert(m_monitor); -    return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t -ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, -                            Error &error) -{ -    assert(m_monitor); -    return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t -ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, -                               Error &error) -{ -    addr_t allocated_addr = LLDB_INVALID_ADDRESS; - -    unsigned prot = 0; -    if (permissions & lldb::ePermissionsReadable) -        prot |= eMmapProtRead; -    if (permissions & lldb::ePermissionsWritable) -        prot |= eMmapProtWrite; -    if (permissions & lldb::ePermissionsExecutable) -        prot |= eMmapProtExec; - -    if (InferiorCallMmap(this, allocated_addr, 0, size, prot, -                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { -        m_addr_to_mmap_size[allocated_addr] = size; -        error.Clear(); -    } else { -        allocated_addr = LLDB_INVALID_ADDRESS; -        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); -    } - -    return allocated_addr; -} - -Error -ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) -{ -    Error error; -    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); -    if (pos != m_addr_to_mmap_size.end() && -        InferiorCallMunmap(this, addr, pos->second)) -        m_addr_to_mmap_size.erase (pos); -    else -        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr); - -    return error; -} - -size_t -ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) -{ -    static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 }; -    static const uint8_t g_i386_opcode[] = { 0xCC }; - -    ArchSpec arch = GetTarget().GetArchitecture(); -    const uint8_t *opcode = NULL; -    size_t opcode_size = 0; - -    switch (arch.GetMachine()) -    { -    default: -        assert(false && "CPU type not supported!"); -        break; - -    case llvm::Triple::arm: -        { -            // The ARM reference recommends the use of 0xe7fddefe and 0xdefe -            // but the linux kernel does otherwise. -            static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 }; -            static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; - -            lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); -            AddressClass addr_class = eAddressClassUnknown; - -            if (bp_loc_sp) -                addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); - -            if (addr_class == eAddressClassCodeAlternateISA -                || (addr_class == eAddressClassUnknown -                    && bp_loc_sp->GetAddress().GetOffset() & 1)) -            { -                opcode = g_thumb_breakpoint_opcode; -                opcode_size = sizeof(g_thumb_breakpoint_opcode); -            } -            else -            { -                opcode = g_arm_breakpoint_opcode; -                opcode_size = sizeof(g_arm_breakpoint_opcode); -            } -        } -        break; -    case llvm::Triple::aarch64: -        opcode = g_aarch64_opcode; -        opcode_size = sizeof(g_aarch64_opcode); -        break; - -    case llvm::Triple::x86: -    case llvm::Triple::x86_64: -        opcode = g_i386_opcode; -        opcode_size = sizeof(g_i386_opcode); -        break; -    } - -    bp_site->SetTrapOpcode(opcode, opcode_size); -    return opcode_size; -} - -Error -ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site) -{ -    return EnableSoftwareBreakpoint(bp_site); -} - -Error -ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site) -{ -    return DisableSoftwareBreakpoint(bp_site); -} - -Error -ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify) -{ -    Error error; -    if (wp) -    { -        user_id_t watchID = wp->GetID(); -        addr_t addr = wp->GetLoadAddress(); -        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); -        if (log) -            log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")", -                         watchID); -        if (wp->IsEnabled()) -        { -            if (log) -                log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 -                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", -                            watchID, (uint64_t)addr); -            return error; -        } - -        // Try to find a vacant watchpoint slot in the inferiors' main thread -        uint32_t wp_hw_index = LLDB_INVALID_INDEX32; -        Mutex::Locker lock(m_thread_list.GetMutex()); -        POSIXThread *thread = static_cast<POSIXThread*>( -                               m_thread_list.GetThreadAtIndex(0, false).get()); - -        if (thread) -            wp_hw_index = thread->FindVacantWatchpointIndex(); - -        if (wp_hw_index == LLDB_INVALID_INDEX32) -        { -            error.SetErrorString("Setting hardware watchpoint failed."); -        } -        else -        { -            wp->SetHardwareIndex(wp_hw_index); -            bool wp_enabled = true; -            uint32_t thread_count = m_thread_list.GetSize(false); -            for (uint32_t i = 0; i < thread_count; ++i) -            { -                thread = static_cast<POSIXThread*>( -                         m_thread_list.GetThreadAtIndex(i, false).get()); -                if (thread) -                    wp_enabled &= thread->EnableHardwareWatchpoint(wp); -                else -                    wp_enabled = false; -            } -            if (wp_enabled) -            { -                wp->SetEnabled(true, notify); -                return error; -            } -            else -            { -                // Watchpoint enabling failed on at least one -                // of the threads so roll back all of them -                DisableWatchpoint(wp, false); -                error.SetErrorString("Setting hardware watchpoint failed"); -            } -        } -    } -    else -        error.SetErrorString("Watchpoint argument was NULL."); -    return error; -} - -Error -ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify) -{ -    Error error; -    if (wp) -    { -        user_id_t watchID = wp->GetID(); -        addr_t addr = wp->GetLoadAddress(); -        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS)); -        if (log) -            log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")", -                        watchID); -        if (!wp->IsEnabled()) -        { -            if (log) -                log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 -                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.", -                            watchID, (uint64_t)addr); -            // This is needed (for now) to keep watchpoints disabled correctly -            wp->SetEnabled(false, notify); -            return error; -        } - -        if (wp->IsHardware()) -        { -            bool wp_disabled = true; -            Mutex::Locker lock(m_thread_list.GetMutex()); -            uint32_t thread_count = m_thread_list.GetSize(false); -            for (uint32_t i = 0; i < thread_count; ++i) -            { -                POSIXThread *thread = static_cast<POSIXThread*>( -                                      m_thread_list.GetThreadAtIndex(i, false).get()); -                if (thread) -                    wp_disabled &= thread->DisableHardwareWatchpoint(wp); -                else -                    wp_disabled = false; -            } -            if (wp_disabled) -            { -                wp->SetHardwareIndex(LLDB_INVALID_INDEX32); -                wp->SetEnabled(false, notify); -                return error; -            } -            else -                error.SetErrorString("Disabling hardware watchpoint failed"); -        } -    } -    else -        error.SetErrorString("Watchpoint argument was NULL."); -    return error; -} - -Error -ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num) -{ -    Error error; -    Mutex::Locker lock(m_thread_list.GetMutex()); -    POSIXThread *thread = static_cast<POSIXThread*>( -                          m_thread_list.GetThreadAtIndex(0, false).get()); -    if (thread) -        num = thread->NumSupportedHardwareWatchpoints(); -    else -        error.SetErrorString("Process does not exist."); -    return error; -} - -Error -ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after) -{ -    Error error = GetWatchpointSupportInfo(num); -    // Watchpoints trigger and halt the inferior after -    // the corresponding instruction has been executed. -    after = true; -    return error; -} - -uint32_t -ProcessPOSIX::UpdateThreadListIfNeeded() -{ -    Mutex::Locker lock(m_thread_list.GetMutex()); -    // Do not allow recursive updates. -    return m_thread_list.GetSize(false); -} - -bool -ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) -{ -    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID()); - -    bool has_updated = false; -    // Update the process thread list with this new thread. -    // FIXME: We should be using tid, not pid. -    assert(m_monitor); -    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); -    if (!thread_sp) { -        thread_sp.reset(CreateNewPOSIXThread(*this, GetID())); -        has_updated = true; -    } - -    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) -        log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID()); -    new_thread_list.AddThread(thread_sp); - -    return has_updated; // the list has been updated -} - -ByteOrder -ProcessPOSIX::GetByteOrder() const -{ -    // FIXME: We should be able to extract this value directly.  See comment in -    // ProcessPOSIX(). -    return m_byte_order; -} - -size_t -ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) -{ -    ssize_t status; -    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)  -    { -        error.SetErrorToErrno(); -        return 0; -    } -    return status; -} - -//------------------------------------------------------------------------------ -// Utility functions. - -bool -ProcessPOSIX::HasExited() -{ -    switch (GetPrivateState()) -    { -    default: -        break; - -    case eStateDetached: -    case eStateExited: -        return true; -    } - -    return false; -} - -bool -ProcessPOSIX::IsStopped() -{ -    switch (GetPrivateState()) -    { -    default: -        break; - -    case eStateStopped: -    case eStateCrashed: -    case eStateSuspended: -        return true; -    } - -    return false; -} - -bool -ProcessPOSIX::IsAThreadRunning() -{ -    bool is_running = false; -    Mutex::Locker lock(m_thread_list.GetMutex()); -    uint32_t thread_count = m_thread_list.GetSize(false); -    for (uint32_t i = 0; i < thread_count; ++i) -    { -        POSIXThread *thread = static_cast<POSIXThread*>( -            m_thread_list.GetThreadAtIndex(i, false).get()); -        StateType thread_state = thread->GetState(); -        if (thread_state == eStateRunning || thread_state == eStateStepping) -        { -            is_running = true; -            break; -        } -    } -    return is_running; -} - -const DataBufferSP -ProcessPOSIX::GetAuxvData () -{ -    // If we're the local platform, we can ask the host for auxv data. -    PlatformSP platform_sp = m_target.GetPlatform (); -    if (platform_sp && platform_sp->IsHost ()) -        return lldb_private::Host::GetAuxvData(this); - -    // Somewhat unexpected - the process is not running locally or we don't have a platform. -    assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?"); -    return DataBufferSP (); -} diff --git a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h b/source/Plugins/Process/FreeBSD/ProcessPOSIX.h deleted file mode 100644 index 627017c547dc4..0000000000000 --- a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h +++ /dev/null @@ -1,205 +0,0 @@ -//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_ProcessPOSIX_H_ -#define liblldb_ProcessPOSIX_H_ - -// C Includes - -// C++ Includes -#include <queue> -#include <set> - -// Other libraries and framework includes -#include "lldb/Target/Process.h" -#include "ProcessMessage.h" - -class ProcessMonitor; -class POSIXThread; - -class ProcessPOSIX : -    public lldb_private::Process -{ -public: - -    //------------------------------------------------------------------ -    // Constructors and destructors -    //------------------------------------------------------------------ -    ProcessPOSIX(lldb_private::Target& target, -                 lldb_private::Listener &listener, -                 lldb::UnixSignalsSP &unix_signals_sp); - -    virtual -    ~ProcessPOSIX(); - -    //------------------------------------------------------------------ -    // Process protocol. -    //------------------------------------------------------------------ -    void -    Finalize() override; - -    bool -    CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; - -    lldb_private::Error -    WillLaunch(lldb_private::Module *module) override; - -    lldb_private::Error -    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; - -    lldb_private::Error -    DoLaunch (lldb_private::Module *exe_module,  -              lldb_private::ProcessLaunchInfo &launch_info) override; - -    void -    DidLaunch() override; - -    lldb_private::Error -    DoResume() override; - -    lldb_private::Error -    DoHalt(bool &caused_stop) override; - -    lldb_private::Error -    DoDetach(bool keep_stopped) override = 0; - -    lldb_private::Error -    DoSignal(int signal) override; - -    lldb_private::Error -    DoDestroy() override; - -    void -    DoDidExec() override; - -    void -    RefreshStateAfterStop() override; - -    bool -    IsAlive() override; - -    size_t -    DoReadMemory(lldb::addr_t vm_addr, -                 void *buf, -                 size_t size, -                 lldb_private::Error &error) override; - -    size_t -    DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, -                  lldb_private::Error &error) override; - -    lldb::addr_t -    DoAllocateMemory(size_t size, uint32_t permissions, -                     lldb_private::Error &error) override; - -    lldb_private::Error -    DoDeallocateMemory(lldb::addr_t ptr) override; - -    virtual size_t -    GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - -    lldb_private::Error -    EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - -    lldb_private::Error -    DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override; - -    lldb_private::Error -    EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - -    lldb_private::Error -    DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override; - -    lldb_private::Error -    GetWatchpointSupportInfo(uint32_t &num) override; - -    lldb_private::Error -    GetWatchpointSupportInfo(uint32_t &num, bool &after) override; - -    virtual uint32_t -    UpdateThreadListIfNeeded(); - -    bool -    UpdateThreadList(lldb_private::ThreadList &old_thread_list,  -                     lldb_private::ThreadList &new_thread_list) override = 0; - -    virtual lldb::ByteOrder -    GetByteOrder() const; - -    lldb::addr_t -    GetImageInfoAddress() override; - -    size_t -    PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override; - -    const lldb::DataBufferSP -    GetAuxvData () override; - -    //-------------------------------------------------------------------------- -    // ProcessPOSIX internal API. - -    /// Registers the given message with this process. -    virtual void -    SendMessage(const ProcessMessage &message); - -    ProcessMonitor & -    GetMonitor() { assert(m_monitor); return *m_monitor; } - -    lldb_private::FileSpec -    GetFileSpec(const lldb_private::FileAction *file_action, -                const lldb_private::FileSpec &default_file_spec, -                const lldb_private::FileSpec &dbg_pts_file_spec); - -    /// Adds the thread to the list of threads for which we have received the initial stopping signal. -    /// The \p stop_tid parameter indicates the thread which the stop happened for. -    bool -    AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid); - -    bool -    WaitingForInitialStop(lldb::tid_t stop_tid); - -    virtual POSIXThread * -    CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid); - -protected: -    /// Target byte order. -    lldb::ByteOrder m_byte_order; - -    /// Process monitor; -    ProcessMonitor *m_monitor; - -    /// The module we are executing. -    lldb_private::Module *m_module; - -    /// Message queue notifying this instance of inferior process state changes. -    lldb_private::Mutex m_message_mutex; -    std::queue<ProcessMessage> m_message_queue; - -    /// Drive any exit events to completion. -    bool m_exit_now; - -    /// Returns true if the process has exited. -    bool HasExited(); - -    /// Returns true if the process is stopped. -    bool IsStopped(); - -    /// Returns true if at least one running is currently running -    bool IsAThreadRunning(); - -    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; -    MMapMap m_addr_to_mmap_size; - -    typedef std::set<lldb::tid_t> ThreadStopSet; -    /// Every thread begins with a stop signal. This keeps track -    /// of the threads for which we have received the stop signal. -    ThreadStopSet m_seen_initial_stop; -}; - -#endif  // liblldb_MacOSXProcess_H_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h index 6ddd9cfe4c217..6ddd9cfe4c217 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp index ac2f81d53929e..9922311fd9dbe 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp @@ -12,7 +12,7 @@  #include "lldb/Target/Thread.h"  #include "RegisterContextPOSIX_arm.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h"  #include "RegisterContextPOSIXProcessMonitor_arm.h"  #include "ProcessMonitor.h" @@ -32,7 +32,7 @@ ProcessMonitor &  RegisterContextPOSIXProcessMonitor_arm::GetMonitor()  {      ProcessSP base = CalculateProcess(); -    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); +    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());      return process->GetMonitor();  } diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h index 12a43c77837c8..3787502a390cc 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h @@ -10,6 +10,7 @@  #ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_  #define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_ +#include "RegisterContextPOSIX.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"  class RegisterContextPOSIXProcessMonitor_arm: diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp index d79def52499f8..012f4b6e15554 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp @@ -12,7 +12,7 @@  #include "lldb/Target/Thread.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h"  #include "ProcessMonitor.h"  #include "RegisterContextPOSIXProcessMonitor_arm64.h" @@ -32,7 +32,7 @@ ProcessMonitor &  RegisterContextPOSIXProcessMonitor_arm64::GetMonitor()  {      lldb::ProcessSP base = CalculateProcess(); -    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); +    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());      return process->GetMonitor();  } @@ -260,13 +260,11 @@ RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable)  bool  RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint()  { -    // PC points one byte past the int3 responsible for the breakpoint.      lldb::addr_t pc;      if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)          return false; -    SetPC(pc - 1);      return true;  } diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h index eb24d4852ab8d..729385c4a76ec 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h @@ -10,6 +10,7 @@  #ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_  #define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_ +#include "RegisterContextPOSIX.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"  class RegisterContextPOSIXProcessMonitor_arm64: diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp index 893a0f22b6f8d..eeada4b163371 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp @@ -12,7 +12,7 @@  #include "lldb/Target/Thread.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h"  #include "ProcessMonitor.h"  #include "RegisterContextPOSIXProcessMonitor_mips64.h" @@ -32,7 +32,7 @@ ProcessMonitor &  RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()  {      ProcessSP base = CalculateProcess(); -    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); +    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());      return process->GetMonitor();  } diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h index 79e4468b1adf9..e61621bec197c 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h @@ -10,6 +10,7 @@  #ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_  #define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_ +#include "RegisterContextPOSIX.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"  class RegisterContextPOSIXProcessMonitor_mips64: diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp index 8c12b62a202f8..321e6ea262ce7 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp @@ -12,7 +12,7 @@  #include "lldb/Target/Thread.h"  #include "RegisterContextPOSIX_powerpc.h" -#include "ProcessPOSIX.h" +#include "ProcessFreeBSD.h"  #include "RegisterContextPOSIXProcessMonitor_powerpc.h"  #include "ProcessMonitor.h" @@ -32,7 +32,7 @@ ProcessMonitor &  RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()  {      ProcessSP base = CalculateProcess(); -    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); +    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());      return process->GetMonitor();  } diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h index 5c686df4836fa..ff1d0f36171b6 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h @@ -10,6 +10,7 @@  #ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_  #define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_ +#include "RegisterContextPOSIX.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"  class RegisterContextPOSIXProcessMonitor_powerpc: diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp index 9245441f659f9..31b9e7a38b21e 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp @@ -11,7 +11,7 @@  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "Plugins/Process/FreeBSD/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"  #include "RegisterContextPOSIXProcessMonitor_x86.h"  #include "Plugins/Process/FreeBSD/ProcessMonitor.h" @@ -58,13 +58,16 @@ RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x8                                                                                       lldb_private::RegisterInfoInterface *register_info)      : RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)  { +    // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea' +    const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl"); +    m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;  }  ProcessMonitor &  RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()  {      ProcessSP base = CalculateProcess(); -    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get()); +    ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());      return process->GetMonitor();  } @@ -254,10 +257,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_      }      // Get pointer to m_fpr.xstate.fxsave variable and set the data from it. -    assert (reg_info->byte_offset < sizeof(m_fpr)); -    uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;  +    // Byte offsets of all registers are calculated wrt 'UserArea' structure. +    // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} +    // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu +    // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure. + +    // Since, FPR structure is also one of the member of UserArea structure. +    // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) +    assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); +    uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;      switch (reg_info->byte_size)      { +        case 1: +            value.SetUInt8(*(uint8_t *)src); +            return true;          case 2:              value.SetUInt16(*(uint16_t *)src);              return true; @@ -308,10 +321,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg          else          {              // Get pointer to m_fpr.xstate.fxsave variable and set the data to it. -            assert (reg_info->byte_offset < sizeof(m_fpr)); -            uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;  +            // Byte offsets of all registers are calculated wrt 'UserArea' structure. +            // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu +            // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should +            // be written in m_fpr at byte offsets calculated wrt FPR structure. + +            // Since, FPR structure is also one of the member of UserArea structure. +            // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea) +            assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr)); +            uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;              switch (reg_info->byte_size)              { +                case 1: +                    *(uint8_t *)dst = value.GetAsUInt8(); +                    break;                  case 2:                      *(uint16_t *)dst = value.GetAsUInt16();                      break; diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h index 2afb195c4c365..f55d917ee75d2 100644 --- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h +++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h @@ -10,6 +10,7 @@  #ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_  #define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_ +#include "RegisterContextPOSIX.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"  class RegisterContextPOSIXProcessMonitor_x86_64: @@ -90,6 +91,7 @@ protected:  private:      ProcessMonitor &      GetMonitor(); +    uint32_t m_fctrl_offset_in_userarea;  // Offset of 'fctrl' in 'UserArea' Structure  };  #endif diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp index 6de13f470c5e8..44409a4ce5528 100644 --- a/source/Plugins/Process/POSIX/CrashReason.cpp +++ b/source/Plugins/Process/POSIX/CrashReason.cpp @@ -28,11 +28,12 @@ GetCrashReasonForSIGSEGV(const siginfo_t& info)      switch (info.si_code)      { +#ifdef SI_KERNEL      case SI_KERNEL: -        // Linux will occasionally send spurious SI_KERNEL codes. -        // (this is poorly documented in sigaction) +        // Some platforms will occasionally send nonstandard spurious SI_KERNEL codes.          // One way to get this is via unaligned SIMD loads.          return CrashReason::eInvalidAddress; // for lack of anything better +#endif      case SEGV_MAPERR:          return CrashReason::eInvalidAddress;      case SEGV_ACCERR: diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index 4eff442c1a0dc..26de4b549c9fc 100644 --- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -99,7 +99,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con              return 0;          } -        // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, +        // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'ehframe' : 2,          // 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },          RegisterInfo reg_info;          std::vector<uint32_t> value_regs; @@ -325,8 +325,12 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con          // Fill in the register numbers          reg_info.kinds[lldb::eRegisterKindLLDB] = i; -        reg_info.kinds[lldb::eRegisterKindGDB] = i; -        reg_info_dict->GetValueForKeyAsInteger("gcc", reg_info.kinds[lldb::eRegisterKindGCC], LLDB_INVALID_REGNUM); +        reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i; +        uint32_t eh_frame_regno = LLDB_INVALID_REGNUM; +        reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno, LLDB_INVALID_REGNUM); +        if (eh_frame_regno == LLDB_INVALID_REGNUM) +            reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno, LLDB_INVALID_REGNUM); +        reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno;          reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);          std::string generic_str;          if (reg_info_dict->GetValueForKeyAsString("generic", generic_str)) @@ -703,12 +707,12 @@ DynamicRegisterInfo::Dump () const                   m_regs[i].byte_offset,                   m_regs[i].encoding,                   FormatManager::GetFormatAsCString (m_regs[i].format)); -        if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM) -            s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]); +        if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM) +            s.Printf(", process plugin = %3u", m_regs[i].kinds[eRegisterKindProcessPlugin]);          if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)              s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]); -        if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM) -            s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]); +        if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) +            s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]);          if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)              s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);          if (m_regs[i].alt_name) diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/source/Plugins/Process/Utility/FreeBSDSignals.cpp index c143d36e87c75..e575e2c6a496d 100644 --- a/source/Plugins/Process/Utility/FreeBSDSignals.cpp +++ b/source/Plugins/Process/Utility/FreeBSDSignals.cpp @@ -26,70 +26,70 @@ FreeBSDSignals::Reset()  {      UnixSignals::Reset(); -    //        SIGNO   NAME           SHORT NAME  SUPPRESS STOP   NOTIFY DESCRIPTION  -    //        ======  ============   ==========  ======== ====== ====== =================================================== -    AddSignal (32,    "SIGTHR",      "THR",      false,   true , true , "thread interrupt"); -    AddSignal (33,    "SIGLIBRT",    "LIBRT",    false,   true , true , "reserved by real-time library"); -    AddSignal (65,    "SIGRTMIN",    "RTMIN",    false,   true , true , "real time signal 0"); -    AddSignal (66,    "SIGRTMIN+1",  "RTMIN+1",  false,   true , true , "real time signal 1"); -    AddSignal (67,    "SIGRTMIN+2",  "RTMIN+2",  false,   true , true , "real time signal 2"); -    AddSignal (68,    "SIGRTMIN+3",  "RTMIN+3",  false,   true , true , "real time signal 3"); -    AddSignal (69,    "SIGRTMIN+4",  "RTMIN+4",  false,   true , true , "real time signal 4"); -    AddSignal (70,    "SIGRTMIN+5",  "RTMIN+5",  false,   true , true , "real time signal 5"); -    AddSignal (71,    "SIGRTMIN+6",  "RTMIN+6",  false,   true , true , "real time signal 6"); -    AddSignal (72,    "SIGRTMIN+7",  "RTMIN+7",  false,   true , true , "real time signal 7"); -    AddSignal (73,    "SIGRTMIN+8",  "RTMIN+8",  false,   true , true , "real time signal 8"); -    AddSignal (74,    "SIGRTMIN+9",  "RTMIN+9",  false,   true , true , "real time signal 9"); -    AddSignal (75,    "SIGRTMIN+10", "RTMIN+10", false,   true , true , "real time signal 10"); -    AddSignal (76,    "SIGRTMIN+11", "RTMIN+11", false,   true , true , "real time signal 11"); -    AddSignal (77,    "SIGRTMIN+12", "RTMIN+12", false,   true , true , "real time signal 12"); -    AddSignal (78,    "SIGRTMIN+13", "RTMIN+13", false,   true , true , "real time signal 13"); -    AddSignal (79,    "SIGRTMIN+14", "RTMIN+14", false,   true , true , "real time signal 14"); -    AddSignal (80,    "SIGRTMIN+15", "RTMIN+15", false,   true , true , "real time signal 15"); -    AddSignal (81,    "SIGRTMIN+16", "RTMIN+16", false,   true , true , "real time signal 16"); -    AddSignal (82,    "SIGRTMIN+17", "RTMIN+17", false,   true , true , "real time signal 17"); -    AddSignal (83,    "SIGRTMIN+18", "RTMIN+18", false,   true , true , "real time signal 18"); -    AddSignal (84,    "SIGRTMIN+19", "RTMIN+19", false,   true , true , "real time signal 19"); -    AddSignal (85,    "SIGRTMIN+20", "RTMIN+20", false,   true , true , "real time signal 20"); -    AddSignal (86,    "SIGRTMIN+21", "RTMIN+21", false,   true , true , "real time signal 21"); -    AddSignal (87,    "SIGRTMIN+22", "RTMIN+22", false,   true , true , "real time signal 22"); -    AddSignal (88,    "SIGRTMIN+23", "RTMIN+23", false,   true , true , "real time signal 23"); -    AddSignal (89,    "SIGRTMIN+24", "RTMIN+24", false,   true , true , "real time signal 24"); -    AddSignal (90,    "SIGRTMIN+25", "RTMIN+25", false,   true , true , "real time signal 25"); -    AddSignal (91,    "SIGRTMIN+26", "RTMIN+26", false,   true , true , "real time signal 26"); -    AddSignal (92,    "SIGRTMIN+27", "RTMIN+27", false,   true , true , "real time signal 27"); -    AddSignal (93,    "SIGRTMIN+28", "RTMIN+28", false,   true , true , "real time signal 28"); -    AddSignal (94,    "SIGRTMIN+29", "RTMIN+29", false,   true , true , "real time signal 29"); -    AddSignal (95,    "SIGRTMIN+30", "RTMIN+30", false,   true , true , "real time signal 30"); -    AddSignal (96,    "SIGRTMAX-30", "RTMAX-30", false,   true , true , "real time signal 31"); -    AddSignal (97,    "SIGRTMAX-29", "RTMAX-29", false,   true , true , "real time signal 32"); -    AddSignal (98,    "SIGRTMAX-28", "RTMAX-28", false,   true , true , "real time signal 33"); -    AddSignal (99,    "SIGRTMAX-27", "RTMAX-27", false,   true , true , "real time signal 34"); -    AddSignal (100,   "SIGRTMAX-26", "RTMAX-26", false,   true , true , "real time signal 35"); -    AddSignal (101,   "SIGRTMAX-25", "RTMAX-25", false,   true , true , "real time signal 36"); -    AddSignal (102,   "SIGRTMAX-24", "RTMAX-24", false,   true , true , "real time signal 37"); -    AddSignal (103,   "SIGRTMAX-23", "RTMAX-23", false,   true , true , "real time signal 38"); -    AddSignal (104,   "SIGRTMAX-22", "RTMAX-22", false,   true , true , "real time signal 39"); -    AddSignal (105,   "SIGRTMAX-21", "RTMAX-21", false,   true , true , "real time signal 40"); -    AddSignal (106,   "SIGRTMAX-20", "RTMAX-20", false,   true , true , "real time signal 41"); -    AddSignal (107,   "SIGRTMAX-19", "RTMAX-19", false,   true , true , "real time signal 42"); -    AddSignal (108,   "SIGRTMAX-18", "RTMAX-18", false,   true , true , "real time signal 43"); -    AddSignal (109,   "SIGRTMAX-17", "RTMAX-17", false,   true , true , "real time signal 44"); -    AddSignal (110,   "SIGRTMAX-16", "RTMAX-16", false,   true , true , "real time signal 45"); -    AddSignal (111,   "SIGRTMAX-15", "RTMAX-15", false,   true , true , "real time signal 46"); -    AddSignal (112,   "SIGRTMAX-14", "RTMAX-14", false,   true , true , "real time signal 47"); -    AddSignal (113,   "SIGRTMAX-13", "RTMAX-13", false,   true , true , "real time signal 48"); -    AddSignal (114,   "SIGRTMAX-12", "RTMAX-12", false,   true , true , "real time signal 49"); -    AddSignal (115,   "SIGRTMAX-11", "RTMAX-11", false,   true , true , "real time signal 50"); -    AddSignal (116,   "SIGRTMAX-10", "RTMAX-10", false,   true , true , "real time signal 51"); -    AddSignal (117,   "SIGRTMAX-9",  "RTMAX-9",  false,   true , true , "real time signal 52"); -    AddSignal (118,   "SIGRTMAX-8",  "RTMAX-8",  false,   true , true , "real time signal 53"); -    AddSignal (119,   "SIGRTMAX-7",  "RTMAX-7",  false,   true , true , "real time signal 54"); -    AddSignal (120,   "SIGRTMAX-6",  "RTMAX-6",  false,   true , true , "real time signal 55"); -    AddSignal (121,   "SIGRTMAX-5",  "RTMAX-5",  false,   true , true , "real time signal 56"); -    AddSignal (122,   "SIGRTMAX-4",  "RTMAX-4",  false,   true , true , "real time signal 57"); -    AddSignal (123,   "SIGRTMAX-3",  "RTMAX-3",  false,   true , true , "real time signal 58"); -    AddSignal (124,   "SIGRTMAX-2",  "RTMAX-2",  false,   true , true , "real time signal 59"); -    AddSignal (125,   "SIGRTMAX-1",  "RTMAX-1",  false,   true , true , "real time signal 60"); -    AddSignal (126,   "SIGRTMAX",    "RTMAX",    false,   true , true , "real time signal 61"); +    //        SIGNO   NAME            SUPPRESS STOP   NOTIFY DESCRIPTION  +    //        ======  ============    ======== ====== ====== =================================================== +    AddSignal (32,    "SIGTHR",       false,   false, false, "thread interrupt"); +    AddSignal (33,    "SIGLIBRT",     false,   false, false, "reserved by real-time library"); +    AddSignal (65,    "SIGRTMIN",     false,   false, false, "real time signal 0"); +    AddSignal (66,    "SIGRTMIN+1",   false,   false, false, "real time signal 1"); +    AddSignal (67,    "SIGRTMIN+2",   false,   false, false, "real time signal 2"); +    AddSignal (68,    "SIGRTMIN+3",   false,   false, false, "real time signal 3"); +    AddSignal (69,    "SIGRTMIN+4",   false,   false, false, "real time signal 4"); +    AddSignal (70,    "SIGRTMIN+5",   false,   false, false, "real time signal 5"); +    AddSignal (71,    "SIGRTMIN+6",   false,   false, false, "real time signal 6"); +    AddSignal (72,    "SIGRTMIN+7",   false,   false, false, "real time signal 7"); +    AddSignal (73,    "SIGRTMIN+8",   false,   false, false, "real time signal 8"); +    AddSignal (74,    "SIGRTMIN+9",   false,   false, false, "real time signal 9"); +    AddSignal (75,    "SIGRTMIN+10",  false,   false, false, "real time signal 10"); +    AddSignal (76,    "SIGRTMIN+11",  false,   false, false, "real time signal 11"); +    AddSignal (77,    "SIGRTMIN+12",  false,   false, false, "real time signal 12"); +    AddSignal (78,    "SIGRTMIN+13",  false,   false, false, "real time signal 13"); +    AddSignal (79,    "SIGRTMIN+14",  false,   false, false, "real time signal 14"); +    AddSignal (80,    "SIGRTMIN+15",  false,   false, false, "real time signal 15"); +    AddSignal (81,    "SIGRTMIN+16",  false,   false, false, "real time signal 16"); +    AddSignal (82,    "SIGRTMIN+17",  false,   false, false, "real time signal 17"); +    AddSignal (83,    "SIGRTMIN+18",  false,   false, false, "real time signal 18"); +    AddSignal (84,    "SIGRTMIN+19",  false,   false, false, "real time signal 19"); +    AddSignal (85,    "SIGRTMIN+20",  false,   false, false, "real time signal 20"); +    AddSignal (86,    "SIGRTMIN+21",  false,   false, false, "real time signal 21"); +    AddSignal (87,    "SIGRTMIN+22",  false,   false, false, "real time signal 22"); +    AddSignal (88,    "SIGRTMIN+23",  false,   false, false, "real time signal 23"); +    AddSignal (89,    "SIGRTMIN+24",  false,   false, false, "real time signal 24"); +    AddSignal (90,    "SIGRTMIN+25",  false,   false, false, "real time signal 25"); +    AddSignal (91,    "SIGRTMIN+26",  false,   false, false, "real time signal 26"); +    AddSignal (92,    "SIGRTMIN+27",  false,   false, false, "real time signal 27"); +    AddSignal (93,    "SIGRTMIN+28",  false,   false, false, "real time signal 28"); +    AddSignal (94,    "SIGRTMIN+29",  false,   false, false, "real time signal 29"); +    AddSignal (95,    "SIGRTMIN+30",  false,   false, false, "real time signal 30"); +    AddSignal (96,    "SIGRTMAX-30",  false,   false, false, "real time signal 31"); +    AddSignal (97,    "SIGRTMAX-29",  false,   false, false, "real time signal 32"); +    AddSignal (98,    "SIGRTMAX-28",  false,   false, false, "real time signal 33"); +    AddSignal (99,    "SIGRTMAX-27",  false,   false, false, "real time signal 34"); +    AddSignal (100,   "SIGRTMAX-26",  false,   false, false, "real time signal 35"); +    AddSignal (101,   "SIGRTMAX-25",  false,   false, false, "real time signal 36"); +    AddSignal (102,   "SIGRTMAX-24",  false,   false, false, "real time signal 37"); +    AddSignal (103,   "SIGRTMAX-23",  false,   false, false, "real time signal 38"); +    AddSignal (104,   "SIGRTMAX-22",  false,   false, false, "real time signal 39"); +    AddSignal (105,   "SIGRTMAX-21",  false,   false, false, "real time signal 40"); +    AddSignal (106,   "SIGRTMAX-20",  false,   false, false, "real time signal 41"); +    AddSignal (107,   "SIGRTMAX-19",  false,   false, false, "real time signal 42"); +    AddSignal (108,   "SIGRTMAX-18",  false,   false, false, "real time signal 43"); +    AddSignal (109,   "SIGRTMAX-17",  false,   false, false, "real time signal 44"); +    AddSignal (110,   "SIGRTMAX-16",  false,   false, false, "real time signal 45"); +    AddSignal (111,   "SIGRTMAX-15",  false,   false, false, "real time signal 46"); +    AddSignal (112,   "SIGRTMAX-14",  false,   false, false, "real time signal 47"); +    AddSignal (113,   "SIGRTMAX-13",  false,   false, false, "real time signal 48"); +    AddSignal (114,   "SIGRTMAX-12",  false,   false, false, "real time signal 49"); +    AddSignal (115,   "SIGRTMAX-11",  false,   false, false, "real time signal 50"); +    AddSignal (116,   "SIGRTMAX-10",  false,   false, false, "real time signal 51"); +    AddSignal (117,   "SIGRTMAX-9",   false,   false, false, "real time signal 52"); +    AddSignal (118,   "SIGRTMAX-8",   false,   false, false, "real time signal 53"); +    AddSignal (119,   "SIGRTMAX-7",   false,   false, false, "real time signal 54"); +    AddSignal (120,   "SIGRTMAX-6",   false,   false, false, "real time signal 55"); +    AddSignal (121,   "SIGRTMAX-5",   false,   false, false, "real time signal 56"); +    AddSignal (122,   "SIGRTMAX-4",   false,   false, false, "real time signal 57"); +    AddSignal (123,   "SIGRTMAX-3",   false,   false, false, "real time signal 58"); +    AddSignal (124,   "SIGRTMAX-2",   false,   false, false, "real time signal 59"); +    AddSignal (125,   "SIGRTMAX-1",   false,   false, false, "real time signal 60"); +    AddSignal (126,   "SIGRTMAX",     false,   false, false, "real time signal 61");  } diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h index 51173c626d71d..e87f6496134b4 100644 --- a/source/Plugins/Process/Utility/HistoryThread.h +++ b/source/Plugins/Process/Utility/HistoryThread.h @@ -10,6 +10,10 @@  #ifndef liblldb_HistoryThread_h_  #define liblldb_HistoryThread_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Host/Mutex.h"  #include "lldb/Core/Broadcaster.h" @@ -37,52 +41,55 @@ class HistoryThread : public lldb_private::Thread  public:      HistoryThread (lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid); -    virtual ~HistoryThread (); +    ~HistoryThread() override; -    virtual lldb::RegisterContextSP -    GetRegisterContext (); +    lldb::RegisterContextSP +    GetRegisterContext() override; -    virtual lldb::RegisterContextSP -    CreateRegisterContextForFrame (StackFrame *frame); +    lldb::RegisterContextSP +    CreateRegisterContextForFrame(StackFrame *frame) override; -    virtual void -    RefreshStateAfterStop() { } +    void +    RefreshStateAfterStop() override { }      bool -    CalculateStopInfo () { return false; } +    CalculateStopInfo() override +    { +        return false; +    }      void  -    SetExtendedBacktraceToken (uint64_t token) +    SetExtendedBacktraceToken(uint64_t token) override      {          m_extended_unwind_token = token;      }      uint64_t -    GetExtendedBacktraceToken () +    GetExtendedBacktraceToken() override      {          return m_extended_unwind_token;      }      const char * -    GetQueueName () +    GetQueueName() override      {          return m_queue_name.c_str();      }      void -    SetQueueName (const char *name) +    SetQueueName(const char *name) override      {          m_queue_name = name;      }      lldb::queue_id_t -    GetQueueID () +    GetQueueID() override      {          return m_queue_id;      }      void -    SetQueueID (lldb::queue_id_t queue) +    SetQueueID(lldb::queue_id_t queue) override      {          m_queue_id = queue;      } @@ -94,7 +101,7 @@ public:      }      uint32_t -    GetExtendedBacktraceOriginatingIndexID (); +    GetExtendedBacktraceOriginatingIndexID() override;      void      SetThreadName (const char *name) @@ -102,14 +109,14 @@ public:          m_thread_name = name;      } -    virtual const char * -    GetName () +    const char * +    GetName() override      {          return m_thread_name.c_str();      } -    virtual void -    SetName(const char *name) +    void +    SetName(const char *name) override      {          m_thread_name = name;      } @@ -133,4 +140,4 @@ protected:  } // namespace lldb_private -#endif  // liblldb_HistoryThread_h_ +#endif // liblldb_HistoryThread_h_ diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h index 733f93e1ff87e..2cb78bc1dc637 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/source/Plugins/Process/Utility/HistoryUnwind.h @@ -10,8 +10,12 @@  #ifndef liblldb_HistoryUnwind_h_  #define liblldb_HistoryUnwind_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Host/Mutex.h"  #include "lldb/Target/Unwind.h" @@ -23,21 +27,21 @@ class HistoryUnwind : public lldb_private::Unwind  public:      HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, bool stop_id_is_valid); -    virtual ~HistoryUnwind (); +    ~HistoryUnwind() override;  protected:      void -    DoClear(); +    DoClear() override;      lldb::RegisterContextSP -    DoCreateRegisterContextForFrame (StackFrame *frame); +    DoCreateRegisterContextForFrame(StackFrame *frame) override;      bool -    DoGetFrameInfoAtIndex (uint32_t frame_idx, -                           lldb::addr_t& cfa,  -                           lldb::addr_t& pc); +    DoGetFrameInfoAtIndex(uint32_t frame_idx, +                          lldb::addr_t& cfa,  +                          lldb::addr_t& pc) override;      uint32_t -    DoGetFrameCount (); +    DoGetFrameCount() override;  private: @@ -47,4 +51,4 @@ private:  } // namespace lldb_private -#endif  // liblldb_HistoryUnwind_h_ +#endif // liblldb_HistoryUnwind_h_ diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 3923c54334067..bd3978cc0ab41 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -93,7 +93,7 @@ lldb_private::InferiorCallMmap (Process *process,              if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))              {                  ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); -                ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); +                CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();                  lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };                  lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,                                                                               mmap_range.GetBaseAddress(), @@ -103,9 +103,6 @@ lldb_private::InferiorCallMmap (Process *process,                  if (call_plan_sp)                  {                      StreamFile error_strm; -                    // This plan is a utility plan, so set it to discard itself when done. -                    call_plan_sp->SetIsMasterPlan (true); -                    call_plan_sp->SetOkayToDiscard(true);                      StackFrame *frame = thread->GetStackFrameAtIndex (0).get();                      if (frame) @@ -182,15 +179,12 @@ lldb_private::InferiorCallMunmap (Process *process,                  lldb::addr_t args[] = { addr, length };                  lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,                                                                              munmap_range.GetBaseAddress(), -                                                                            ClangASTType(), +                                                                            CompilerType(),                                                                              args,                                                                              options));                  if (call_plan_sp)                  {                      StreamFile error_strm; -                    // This plan is a utility plan, so set it to discard itself when done. -                    call_plan_sp->SetIsMasterPlan (true); -                    call_plan_sp->SetOkayToDiscard(true);                      StackFrame *frame = thread->GetStackFrameAtIndex (0).get();                      if (frame) @@ -235,7 +229,7 @@ lldb_private::InferiorCall (Process *process,      options.SetTimeoutUsec(500000);      ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); -    ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); +    CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();      lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,                                                                   *address,                                                                   clang_void_ptr_type, @@ -244,9 +238,6 @@ lldb_private::InferiorCall (Process *process,      if (call_plan_sp)      {          StreamString error_strm; -        // This plan is a utility plan, so set it to discard itself when done. -        call_plan_sp->SetIsMasterPlan (true); -        call_plan_sp->SetOkayToDiscard(true);          StackFrame *frame = thread->GetStackFrameAtIndex (0).get();          if (frame) diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp index cd1fc8165eb9c..5687577f9d165 100644 --- a/source/Plugins/Process/Utility/LinuxSignals.cpp +++ b/source/Plugins/Process/Utility/LinuxSignals.cpp @@ -24,72 +24,70 @@ void  LinuxSignals::Reset()  {      m_signals.clear(); - -    AddSignal (1,    "SIGHUP",      "HUP",      false,   true , true , "hangup"); -    AddSignal (2,    "SIGINT",      "INT",      true ,   true , true , "interrupt"); -    AddSignal (3,    "SIGQUIT",     "QUIT",     false,   true , true , "quit"); -    AddSignal (4,    "SIGILL",      "ILL",      false,   true , true , "illegal instruction"); -    AddSignal (5,    "SIGTRAP",     "TRAP",     true ,   true , true , "trace trap (not reset when caught)"); -    AddSignal (6,    "SIGABRT",     "ABRT",     false,   true , true , "abort()"); -    AddSignal (6,    "SIGIOT",      "IOT",      false,   true , true , "IOT trap"); -    AddSignal (7,    "SIGBUS",      "BUS",      false,   true , true , "bus error"); -    AddSignal (8,    "SIGFPE",      "FPE",      false,   true , true , "floating point exception"); -    AddSignal (9,    "SIGKILL",     "KILL",     false,   true , true , "kill"); -    AddSignal (10,   "SIGUSR1",     "USR1",     false,   true , true , "user defined signal 1"); -    AddSignal (11,   "SIGSEGV",     "SEGV",     false,   true , true , "segmentation violation"); -    AddSignal (12,   "SIGUSR2",     "USR2",     false,   true , true , "user defined signal 2"); -    AddSignal (13,   "SIGPIPE",     "PIPE",     false,   true , true , "write to pipe with reading end closed"); -    AddSignal (14,   "SIGALRM",     "ALRM",     false,   false, false, "alarm"); -    AddSignal (15,   "SIGTERM",     "TERM",     false,   true , true , "termination requested"); -    AddSignal (16,   "SIGSTKFLT",   "STKFLT",   false,   true , true , "stack fault"); -    AddSignal (16,   "SIGCLD",      "CLD",      false,   false, true , "same as SIGCHLD"); -    AddSignal (17,   "SIGCHLD",     "CHLD",     false,   false, true , "child status has changed"); -    AddSignal (18,   "SIGCONT",     "CONT",     false,   true , true , "process continue"); -    AddSignal (19,   "SIGSTOP",     "STOP",     true ,   true , true , "process stop"); -    AddSignal (20,   "SIGTSTP",     "TSTP",     false,   true , true , "tty stop"); -    AddSignal (21,   "SIGTTIN",     "TTIN",     false,   true , true , "background tty read"); -    AddSignal (22,   "SIGTTOU",     "TTOU",     false,   true , true , "background tty write"); -    AddSignal (23,   "SIGURG",      "URG",      false,   true , true , "urgent data on socket"); -    AddSignal (24,   "SIGXCPU",     "XCPU",     false,   true , true , "CPU resource exceeded"); -    AddSignal (25,   "SIGXFSZ",     "XFSZ",     false,   true , true , "file size limit exceeded"); -    AddSignal (26,   "SIGVTALRM",   "VTALRM",   false,   true , true , "virtual time alarm"); -    AddSignal (27,   "SIGPROF",     "PROF",     false,   false, false, "profiling time alarm"); -    AddSignal (28,   "SIGWINCH",    "WINCH",    false,   true , true , "window size changes"); -    AddSignal (29,   "SIGPOLL",     "POLL",     false,   true , true , "pollable event"); -    AddSignal (29,   "SIGIO",       "IO",       false,   true , true , "input/output ready"); -    AddSignal (30,   "SIGPWR",      "PWR",      false,   true , true , "power failure"); -    AddSignal (31,   "SIGSYS",      "SYS",      false,   true , true , "invalid system call"); -    AddSignal (32,   "SIG32",       "SIG32",    false,   true , true , "threading library internal signal 1"); -    AddSignal (33,   "SIG33",       "SIG33",    false,   true , true , "threading library internal signal 2"); -    AddSignal (34,   "SIGRTMIN",    "RTMIN",    false,   true , true , "real time signal 0"); -    AddSignal (35,   "SIGRTMIN+1",  "RTMIN+1",  false,   true , true , "real time signal 1"); -    AddSignal (36,   "SIGRTMIN+2",  "RTMIN+2",  false,   true , true , "real time signal 2"); -    AddSignal (37,   "SIGRTMIN+3",  "RTMIN+3",  false,   true , true , "real time signal 3"); -    AddSignal (38,   "SIGRTMIN+4",  "RTMIN+4",  false,   true , true , "real time signal 4"); -    AddSignal (39,   "SIGRTMIN+5",  "RTMIN+5",  false,   true , true , "real time signal 5"); -    AddSignal (40,   "SIGRTMIN+6",  "RTMIN+6",  false,   true , true , "real time signal 6"); -    AddSignal (41,   "SIGRTMIN+7",  "RTMIN+7",  false,   true , true , "real time signal 7"); -    AddSignal (42,   "SIGRTMIN+8",  "RTMIN+8",  false,   true , true , "real time signal 8"); -    AddSignal (43,   "SIGRTMIN+9",  "RTMIN+9",  false,   true , true , "real time signal 9"); -    AddSignal (44,   "SIGRTMIN+10", "RTMIN+10", false,   true , true , "real time signal 10"); -    AddSignal (45,   "SIGRTMIN+11", "RTMIN+11", false,   true , true , "real time signal 11"); -    AddSignal (46,   "SIGRTMIN+12", "RTMIN+12", false,   true , true , "real time signal 12"); -    AddSignal (47,   "SIGRTMIN+13", "RTMIN+13", false,   true , true , "real time signal 13"); -    AddSignal (48,   "SIGRTMIN+14", "RTMIN+14", false,   true , true , "real time signal 14"); -    AddSignal (49,   "SIGRTMIN+15", "RTMIN+15", false,   true , true , "real time signal 15"); -    AddSignal (50,   "SIGRTMAX-14", "RTMAX-14", false,   true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output -    AddSignal (51,   "SIGRTMAX-13", "RTMAX-13", false,   true , true , "real time signal 17"); -    AddSignal (52,   "SIGRTMAX-12", "RTMAX-12", false,   true , true , "real time signal 18"); -    AddSignal (53,   "SIGRTMAX-11", "RTMAX-11", false,   true , true , "real time signal 19"); -    AddSignal (54,   "SIGRTMAX-10", "RTMAX-10", false,   true , true , "real time signal 20"); -    AddSignal (55,   "SIGRTMAX-9",  "RTMAX-9",  false,   true , true , "real time signal 21"); -    AddSignal (56,   "SIGRTMAX-8",  "RTMAX-8",  false,   true , true , "real time signal 22"); -    AddSignal (57,   "SIGRTMAX-7",  "RTMAX-7",  false,   true , true , "real time signal 23"); -    AddSignal (58,   "SIGRTMAX-6",  "RTMAX-6",  false,   true , true , "real time signal 24"); -    AddSignal (59,   "SIGRTMAX-5",  "RTMAX-5",  false,   true , true , "real time signal 25"); -    AddSignal (60,   "SIGRTMAX-4",  "RTMAX-4",  false,   true , true , "real time signal 26"); -    AddSignal (61,   "SIGRTMAX-3",  "RTMAX-3",  false,   true , true , "real time signal 27"); -    AddSignal (62,   "SIGRTMAX-2",  "RTMAX-2",  false,   true , true , "real time signal 28"); -    AddSignal (63,   "SIGRTMAX-1",  "RTMAX-1",  false,   true , true , "real time signal 29"); -    AddSignal (64,   "SIGRTMAX",    "RTMAX",    false,   true , true , "real time signal 30"); +    //        SIGNO  NAME             SUPPRESS STOP   NOTIFY DESCRIPTION                              ALIAS +    //        =====  ===========      ======== =====  ====== ======================================   ====== +    AddSignal (1,    "SIGHUP",        false,   true , true , "hangup"                                        ); +    AddSignal (2,    "SIGINT",        true ,   true , true , "interrupt"                                     ); +    AddSignal (3,    "SIGQUIT",       false,   true , true , "quit"                                          ); +    AddSignal (4,    "SIGILL",        false,   true , true , "illegal instruction"                           ); +    AddSignal (5,    "SIGTRAP",       true ,   true , true , "trace trap (not reset when caught)"            ); +    AddSignal (6,    "SIGABRT",       false,   true , true , "abort()/IOT trap",                     "SIGIOT"); +    AddSignal (7,    "SIGBUS",        false,   true , true , "bus error"                                     ); +    AddSignal (8,    "SIGFPE",        false,   true , true , "floating point exception"                      ); +    AddSignal (9,    "SIGKILL",       false,   true , true , "kill"                                          ); +    AddSignal (10,   "SIGUSR1",       false,   true , true , "user defined signal 1"                         ); +    AddSignal (11,   "SIGSEGV",       false,   true , true , "segmentation violation"                        ); +    AddSignal (12,   "SIGUSR2",       false,   true , true , "user defined signal 2"                         ); +    AddSignal (13,   "SIGPIPE",       false,   true , true , "write to pipe with reading end closed"         ); +    AddSignal (14,   "SIGALRM",       false,   false, false, "alarm"                                         ); +    AddSignal (15,   "SIGTERM",       false,   true , true , "termination requested"                         ); +    AddSignal (16,   "SIGSTKFLT",     false,   true , true , "stack fault"                                   ); +    AddSignal (17,   "SIGCHLD",       false,   false, true , "child status has changed",             "SIGCLD"); +    AddSignal (18,   "SIGCONT",       false,   true , true , "process continue"                              ); +    AddSignal (19,   "SIGSTOP",       true ,   true , true , "process stop"                                  ); +    AddSignal (20,   "SIGTSTP",       false,   true , true , "tty stop"                                      ); +    AddSignal (21,   "SIGTTIN",       false,   true , true , "background tty read"                           ); +    AddSignal (22,   "SIGTTOU",       false,   true , true , "background tty write"                          ); +    AddSignal (23,   "SIGURG",        false,   true , true , "urgent data on socket"                         ); +    AddSignal (24,   "SIGXCPU",       false,   true , true , "CPU resource exceeded"                         ); +    AddSignal (25,   "SIGXFSZ",       false,   true , true , "file size limit exceeded"                      ); +    AddSignal (26,   "SIGVTALRM",     false,   true , true , "virtual time alarm"                            ); +    AddSignal (27,   "SIGPROF",       false,   false, false, "profiling time alarm"                          ); +    AddSignal (28,   "SIGWINCH",      false,   true , true , "window size changes"                           ); +    AddSignal (29,   "SIGIO",         false,   true , true , "input/output ready/Pollable event",   "SIGPOLL"); +    AddSignal (30,   "SIGPWR",        false,   true , true , "power failure"                                 ); +    AddSignal (31,   "SIGSYS",        false,   true , true , "invalid system call"                           ); +    AddSignal (32,   "SIG32",         false,   false, false, "threading library internal signal 1"           ); +    AddSignal (33,   "SIG33",         false,   false, false, "threading library internal signal 2"           ); +    AddSignal (34,   "SIGRTMIN",      false,   false, false, "real time signal 0"                            ); +    AddSignal (35,   "SIGRTMIN+1",    false,   false, false, "real time signal 1"                            ); +    AddSignal (36,   "SIGRTMIN+2",    false,   false, false, "real time signal 2"                            ); +    AddSignal (37,   "SIGRTMIN+3",    false,   false, false, "real time signal 3"                            ); +    AddSignal (38,   "SIGRTMIN+4",    false,   false, false, "real time signal 4"                            ); +    AddSignal (39,   "SIGRTMIN+5",    false,   false, false, "real time signal 5"                            ); +    AddSignal (40,   "SIGRTMIN+6",    false,   false, false, "real time signal 6"                            ); +    AddSignal (41,   "SIGRTMIN+7",    false,   false, false, "real time signal 7"                            ); +    AddSignal (42,   "SIGRTMIN+8",    false,   false, false, "real time signal 8"                            ); +    AddSignal (43,   "SIGRTMIN+9",    false,   false, false, "real time signal 9"                            ); +    AddSignal (44,   "SIGRTMIN+10",   false,   false, false, "real time signal 10"                           ); +    AddSignal (45,   "SIGRTMIN+11",   false,   false, false, "real time signal 11"                           ); +    AddSignal (46,   "SIGRTMIN+12",   false,   false, false, "real time signal 12"                           ); +    AddSignal (47,   "SIGRTMIN+13",   false,   false, false, "real time signal 13"                           ); +    AddSignal (48,   "SIGRTMIN+14",   false,   false, false, "real time signal 14"                           ); +    AddSignal (49,   "SIGRTMIN+15",   false,   false, false, "real time signal 15"                           ); +    AddSignal (50,   "SIGRTMAX-14",   false,   false, false, "real time signal 16"                           ); // switching to SIGRTMAX-xxx to match "kill -l" output +    AddSignal (51,   "SIGRTMAX-13",   false,   false, false, "real time signal 17"                           ); +    AddSignal (52,   "SIGRTMAX-12",   false,   false, false, "real time signal 18"                           ); +    AddSignal (53,   "SIGRTMAX-11",   false,   false, false, "real time signal 19"                           ); +    AddSignal (54,   "SIGRTMAX-10",   false,   false, false, "real time signal 20"                           ); +    AddSignal (55,   "SIGRTMAX-9",    false,   false, false, "real time signal 21"                           ); +    AddSignal (56,   "SIGRTMAX-8",    false,   false, false, "real time signal 22"                           ); +    AddSignal (57,   "SIGRTMAX-7",    false,   false, false, "real time signal 23"                           ); +    AddSignal (58,   "SIGRTMAX-6",    false,   false, false, "real time signal 24"                           ); +    AddSignal (59,   "SIGRTMAX-5",    false,   false, false, "real time signal 25"                           ); +    AddSignal (60,   "SIGRTMAX-4",    false,   false, false, "real time signal 26"                           ); +    AddSignal (61,   "SIGRTMAX-3",    false,   false, false, "real time signal 27"                           ); +    AddSignal (62,   "SIGRTMAX-2",    false,   false, false, "real time signal 28"                           ); +    AddSignal (63,   "SIGRTMAX-1",    false,   false, false, "real time signal 29"                           ); +    AddSignal (64,   "SIGRTMAX",      false,   false, false, "real time signal 30"                           );  } diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp index 1dc0be81c0aee..422fc9b642d0e 100644 --- a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp +++ b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp @@ -24,72 +24,70 @@ void  MipsLinuxSignals::Reset()  {      m_signals.clear(); - -    AddSignal (1,    "SIGHUP",      "HUP",      false,   true , true , "hangup"); -    AddSignal (2,    "SIGINT",      "INT",      true ,   true , true , "interrupt"); -    AddSignal (3,    "SIGQUIT",     "QUIT",     false,   true , true , "quit"); -    AddSignal (4,    "SIGILL",      "ILL",      false,   true , true , "illegal instruction"); -    AddSignal (5,    "SIGTRAP",     "TRAP",     true ,   true , true , "trace trap (not reset when caught)"); -    AddSignal (6,    "SIGABRT",     "ABRT",     false,   true , true , "abort()"); -    AddSignal (6,    "SIGIOT",      "IOT",      false,   true , true , "IOT trap"); -    AddSignal (7,    "SIGEMT",      "EMT",      false,   true , true , "terminate process with core dump"); -    AddSignal (8,    "SIGFPE",      "FPE",      false,   true , true , "floating point exception"); -    AddSignal (9,    "SIGKILL",     "KILL",     false,   true , true , "kill"); -    AddSignal (10,   "SIGBUS",      "BUS",      false,   true , true , "bus error"); -    AddSignal (11,   "SIGSEGV",     "SEGV",     false,   true , true , "segmentation violation"); -    AddSignal (12,   "SIGSYS",      "SYS",      false,   true , true , "invalid system call"); -    AddSignal (13,   "SIGPIPE",     "PIPE",     false,   true , true , "write to pipe with reading end closed"); -    AddSignal (14,   "SIGALRM",     "ALRM",     false,   false, false, "alarm"); -    AddSignal (15,   "SIGTERM",     "TERM",     false,   true , true , "termination requested"); -    AddSignal (16,   "SIGUSR1",     "USR1",     false,   true , true , "user defined signal 1"); -    AddSignal (17,   "SIGUSR2",     "USR2",     false,   true , true , "user defined signal 2"); -    AddSignal (18,   "SIGCLD",      "CLD",      false,   false, true , "same as SIGCHLD"); -    AddSignal (18,   "SIGCHLD",     "CHLD",     false,   false, true , "child status has changed"); -    AddSignal (19,   "SIGPWR",      "PWR",      false,   true , true , "power failure"); -    AddSignal (20,   "SIGWINCH",    "WINCH",    false,   true , true , "window size changes"); -    AddSignal (21,   "SIGURG",      "URG",      false,   true , true , "urgent data on socket"); -    AddSignal (22,   "SIGIO",       "IO",       false,   true , true , "input/output ready"); -    AddSignal (22,   "SIGPOLL",     "POLL",     false,   true , true , "pollable event"); -    AddSignal (23,   "SIGSTOP",     "STOP",     true ,   true , true , "process stop"); -    AddSignal (24,   "SIGTSTP",     "TSTP",     false,   true , true , "tty stop"); -    AddSignal (25,   "SIGCONT",     "CONT",     false,   true , true , "process continue"); -    AddSignal (26,   "SIGTTIN",     "TTIN",     false,   true , true , "background tty read"); -    AddSignal (27,   "SIGTTOU",     "TTOU",     false,   true , true , "background tty write"); -    AddSignal (28,   "SIGVTALRM",   "VTALRM",   false,   true , true , "virtual time alarm"); -    AddSignal (29,   "SIGPROF",     "PROF",     false,   false, false, "profiling time alarm"); -    AddSignal (30,   "SIGXCPU",     "XCPU",     false,   true , true , "CPU resource exceeded"); -    AddSignal (31,   "SIGXFSZ",     "XFSZ",     false,   true , true , "file size limit exceeded"); -    AddSignal (32,   "SIG32",       "SIG32",    false,   true , true , "threading library internal signal 1"); -    AddSignal (33,   "SIG33",       "SIG33",    false,   true , true , "threading library internal signal 2"); -    AddSignal (34,   "SIGRTMIN",    "RTMIN",    false,   true , true , "real time signal 0"); -    AddSignal (35,   "SIGRTMIN+1",  "RTMIN+1",  false,   true , true , "real time signal 1"); -    AddSignal (36,   "SIGRTMIN+2",  "RTMIN+2",  false,   true , true , "real time signal 2"); -    AddSignal (37,   "SIGRTMIN+3",  "RTMIN+3",  false,   true , true , "real time signal 3"); -    AddSignal (38,   "SIGRTMIN+4",  "RTMIN+4",  false,   true , true , "real time signal 4"); -    AddSignal (39,   "SIGRTMIN+5",  "RTMIN+5",  false,   true , true , "real time signal 5"); -    AddSignal (40,   "SIGRTMIN+6",  "RTMIN+6",  false,   true , true , "real time signal 6"); -    AddSignal (41,   "SIGRTMIN+7",  "RTMIN+7",  false,   true , true , "real time signal 7"); -    AddSignal (42,   "SIGRTMIN+8",  "RTMIN+8",  false,   true , true , "real time signal 8"); -    AddSignal (43,   "SIGRTMIN+9",  "RTMIN+9",  false,   true , true , "real time signal 9"); -    AddSignal (44,   "SIGRTMIN+10", "RTMIN+10", false,   true , true , "real time signal 10"); -    AddSignal (45,   "SIGRTMIN+11", "RTMIN+11", false,   true , true , "real time signal 11"); -    AddSignal (46,   "SIGRTMIN+12", "RTMIN+12", false,   true , true , "real time signal 12"); -    AddSignal (47,   "SIGRTMIN+13", "RTMIN+13", false,   true , true , "real time signal 13"); -    AddSignal (48,   "SIGRTMIN+14", "RTMIN+14", false,   true , true , "real time signal 14"); -    AddSignal (49,   "SIGRTMIN+15", "RTMIN+15", false,   true , true , "real time signal 15"); -    AddSignal (50,   "SIGRTMAX-14", "RTMAX-14", false,   true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output -    AddSignal (51,   "SIGRTMAX-13", "RTMAX-13", false,   true , true , "real time signal 17"); -    AddSignal (52,   "SIGRTMAX-12", "RTMAX-12", false,   true , true , "real time signal 18"); -    AddSignal (53,   "SIGRTMAX-11", "RTMAX-11", false,   true , true , "real time signal 19"); -    AddSignal (54,   "SIGRTMAX-10", "RTMAX-10", false,   true , true , "real time signal 20"); -    AddSignal (55,   "SIGRTMAX-9",  "RTMAX-9",  false,   true , true , "real time signal 21"); -    AddSignal (56,   "SIGRTMAX-8",  "RTMAX-8",  false,   true , true , "real time signal 22"); -    AddSignal (57,   "SIGRTMAX-7",  "RTMAX-7",  false,   true , true , "real time signal 23"); -    AddSignal (58,   "SIGRTMAX-6",  "RTMAX-6",  false,   true , true , "real time signal 24"); -    AddSignal (59,   "SIGRTMAX-5",  "RTMAX-5",  false,   true , true , "real time signal 25"); -    AddSignal (60,   "SIGRTMAX-4",  "RTMAX-4",  false,   true , true , "real time signal 26"); -    AddSignal (61,   "SIGRTMAX-3",  "RTMAX-3",  false,   true , true , "real time signal 27"); -    AddSignal (62,   "SIGRTMAX-2",  "RTMAX-2",  false,   true , true , "real time signal 28"); -    AddSignal (63,   "SIGRTMAX-1",  "RTMAX-1",  false,   true , true , "real time signal 29"); -    AddSignal (64,   "SIGRTMAX",    "RTMAX",    false,   true , true , "real time signal 30"); +    //        SIGNO  NAME            SUPPRESS STOP   NOTIFY DESCRIPTION                              ALIAS +    //        =====  ===========     ======== =====  ====== ======================================   ======== +    AddSignal (1,    "SIGHUP",       false,   true , true , "hangup"                                         ); +    AddSignal (2,    "SIGINT",       true ,   true , true , "interrupt"                                      ); +    AddSignal (3,    "SIGQUIT",      false,   true , true , "quit"                                           ); +    AddSignal (4,    "SIGILL",       false,   true , true , "illegal instruction"                            ); +    AddSignal (5,    "SIGTRAP",      true ,   true , true , "trace trap (not reset when caught)"             ); +    AddSignal (6,    "SIGABRT",      false,   true , true , "abort()/IOT trap",                      "SIGIOT"); +    AddSignal (7,    "SIGEMT",       false,   true , true , "terminate process with core dump"               ); +    AddSignal (8,    "SIGFPE",       false,   true , true , "floating point exception"                       ); +    AddSignal (9,    "SIGKILL",      false,   true , true , "kill"                                           ); +    AddSignal (10,   "SIGBUS",       false,   true , true , "bus error"                                      ); +    AddSignal (11,   "SIGSEGV",      false,   true , true , "segmentation violation"                         ); +    AddSignal (12,   "SIGSYS",       false,   true , true , "invalid system call"                            ); +    AddSignal (13,   "SIGPIPE",      false,   true , true , "write to pipe with reading end closed"          ); +    AddSignal (14,   "SIGALRM",      false,   false, false, "alarm"                                          ); +    AddSignal (15,   "SIGTERM",      false,   true , true , "termination requested"                          ); +    AddSignal (16,   "SIGUSR1",      false,   true , true , "user defined signal 1"                          ); +    AddSignal (17,   "SIGUSR2",      false,   true , true , "user defined signal 2"                          ); +    AddSignal (18,   "SIGCHLD",      false,   false, true , "child status has changed",              "SIGCLD"); +    AddSignal (19,   "SIGPWR",       false,   true , true , "power failure"                                  ); +    AddSignal (20,   "SIGWINCH",     false,   true , true , "window size changes"                            ); +    AddSignal (21,   "SIGURG",       false,   true , true , "urgent data on socket"                          ); +    AddSignal (22,   "SIGIO",        false,   true , true , "input/output ready/Pollable event",    "SIGPOLL"); +    AddSignal (23,   "SIGSTOP",      true ,   true , true , "process stop"                                   ); +    AddSignal (24,   "SIGTSTP",      false,   true , true , "tty stop"                                       ); +    AddSignal (25,   "SIGCONT",      false,   true , true , "process continue"                               ); +    AddSignal (26,   "SIGTTIN",      false,   true , true , "background tty read"                            ); +    AddSignal (27,   "SIGTTOU",      false,   true , true , "background tty write"                           ); +    AddSignal (28,   "SIGVTALRM",    false,   true , true , "virtual time alarm"                             ); +    AddSignal (29,   "SIGPROF",      false,   false, false, "profiling time alarm"                           ); +    AddSignal (30,   "SIGXCPU",      false,   true , true , "CPU resource exceeded"                          ); +    AddSignal (31,   "SIGXFSZ",      false,   true , true , "file size limit exceeded"                       ); +    AddSignal (32,   "SIG32",        false,   false, false, "threading library internal signal 1"            ); +    AddSignal (33,   "SIG33",        false,   false, false, "threading library internal signal 2"            ); +    AddSignal (34,   "SIGRTMIN",     false,   false, false, "real time signal 0"                             ); +    AddSignal (35,   "SIGRTMIN+1",   false,   false, false, "real time signal 1"                             ); +    AddSignal (36,   "SIGRTMIN+2",   false,   false, false, "real time signal 2"                             ); +    AddSignal (37,   "SIGRTMIN+3",   false,   false, false, "real time signal 3"                             ); +    AddSignal (38,   "SIGRTMIN+4",   false,   false, false, "real time signal 4"                             ); +    AddSignal (39,   "SIGRTMIN+5",   false,   false, false, "real time signal 5"                             ); +    AddSignal (40,   "SIGRTMIN+6",   false,   false, false, "real time signal 6"                             ); +    AddSignal (41,   "SIGRTMIN+7",   false,   false, false, "real time signal 7"                             ); +    AddSignal (42,   "SIGRTMIN+8",   false,   false, false, "real time signal 8"                             ); +    AddSignal (43,   "SIGRTMIN+9",   false,   false, false, "real time signal 9"                             ); +    AddSignal (44,   "SIGRTMIN+10",  false,   false, false, "real time signal 10"                            ); +    AddSignal (45,   "SIGRTMIN+11",  false,   false, false, "real time signal 11"                            ); +    AddSignal (46,   "SIGRTMIN+12",  false,   false, false, "real time signal 12"                            ); +    AddSignal (47,   "SIGRTMIN+13",  false,   false, false, "real time signal 13"                            ); +    AddSignal (48,   "SIGRTMIN+14",  false,   false, false, "real time signal 14"                            ); +    AddSignal (49,   "SIGRTMIN+15",  false,   false, false, "real time signal 15"                            ); +    AddSignal (50,   "SIGRTMAX-14",  false,   false, false, "real time signal 16"                            ); // switching to SIGRTMAX-xxx to match "kill -l" output +    AddSignal (51,   "SIGRTMAX-13",  false,   false, false, "real time signal 17"                            ); +    AddSignal (52,   "SIGRTMAX-12",  false,   false, false, "real time signal 18"                            ); +    AddSignal (53,   "SIGRTMAX-11",  false,   false, false, "real time signal 19"                            ); +    AddSignal (54,   "SIGRTMAX-10",  false,   false, false, "real time signal 20"                            ); +    AddSignal (55,   "SIGRTMAX-9",   false,   false, false, "real time signal 21"                            ); +    AddSignal (56,   "SIGRTMAX-8",   false,   false, false, "real time signal 22"                            ); +    AddSignal (57,   "SIGRTMAX-7",   false,   false, false, "real time signal 23"                            ); +    AddSignal (58,   "SIGRTMAX-6",   false,   false, false, "real time signal 24"                            ); +    AddSignal (59,   "SIGRTMAX-5",   false,   false, false, "real time signal 25"                            ); +    AddSignal (60,   "SIGRTMAX-4",   false,   false, false, "real time signal 26"                            ); +    AddSignal (61,   "SIGRTMAX-3",   false,   false, false, "real time signal 27"                            ); +    AddSignal (62,   "SIGRTMAX-2",   false,   false, false, "real time signal 28"                            ); +    AddSignal (63,   "SIGRTMAX-1",   false,   false, false, "real time signal 29"                            ); +    AddSignal (64,   "SIGRTMAX",     false,   false, false, "real time signal 30"                            );  } diff --git a/source/Plugins/Process/Utility/NetBSDSignals.cpp b/source/Plugins/Process/Utility/NetBSDSignals.cpp new file mode 100644 index 0000000000000..5dce51616c4e3 --- /dev/null +++ b/source/Plugins/Process/Utility/NetBSDSignals.cpp @@ -0,0 +1,34 @@ +//===-- NetBSDSignals.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "NetBSDSignals.h" + +using namespace lldb_private; + +NetBSDSignals::NetBSDSignals() +    : UnixSignals() +{ +    Reset(); +} + +void +NetBSDSignals::Reset() +{ +    UnixSignals::Reset(); +    //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION +    //        ====== ============  ======== ====== ====== =================================================== +    AddSignal (32,   "SIGPWR",     false,   true , true , "power fail/restart (not reset when caught)"); +#ifdef SIGRTMIN /* SIGRTMAX */ +    /* Kernel only; not exposed to userland yet */ +#endif +} diff --git a/source/Plugins/Process/Utility/NetBSDSignals.h b/source/Plugins/Process/Utility/NetBSDSignals.h new file mode 100644 index 0000000000000..441402b056dbd --- /dev/null +++ b/source/Plugins/Process/Utility/NetBSDSignals.h @@ -0,0 +1,31 @@ +//===-- NetBSDSignals.h ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_NetBSDSignals_H_ +#define liblldb_NetBSDSignals_H_ + +// Project includes +#include "lldb/Target/UnixSignals.h" + +namespace lldb_private { + +/// NetBSD specific set of Unix signals. +class NetBSDSignals : public UnixSignals +{ +public: +    NetBSDSignals(); + +private: +    void +    Reset() override; +}; + +} // namespace lldb_private + +#endif // liblldb_NetBSDSignals_H_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 4138a6aaa2aab..452fb47ebc8a7 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -34,8 +34,8 @@  #endif  // Project includes -#include "ARM_GCC_Registers.h"  #include "ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  #include "llvm/ADT/STLExtras.h" @@ -172,89 +172,69 @@ enum  }; -RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) : -    RegisterContext(thread, concrete_frame_idx), -    gpr(), -    fpu(), -    exc() -{ -    uint32_t i; -    for (i=0; i<kNumErrors; i++) -    { -        gpr_errs[i] = -1; -        fpu_errs[i] = -1; -        exc_errs[i] = -1; -    } -} - -RegisterContextDarwin_arm::~RegisterContextDarwin_arm() -{ -} - -  #define GPR_OFFSET(idx) ((idx) * 4)  #define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))  #define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))  #define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))) -#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL +#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL  #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))  static RegisterInfo g_register_infos[] = {  // General purpose registers -//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE   VALUE REGS    INVALIDATE REGS +//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          EH_FRAME                DWARF               GENERIC                     PROCESS PLUGIN          LLDB NATIVE   VALUE REGS    INVALIDATE REGS  //  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    =============== -{   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,        gdb_arm_r0,             gpr_r0      },      NULL,              NULL}, -{   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,        gdb_arm_r1,             gpr_r1      },      NULL,              NULL}, -{   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,        gdb_arm_r2,             gpr_r2      },      NULL,              NULL}, -{   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,        gdb_arm_r3,             gpr_r3      },      NULL,              NULL}, -{   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             gpr_r4      },      NULL,              NULL}, -{   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             gpr_r5      },      NULL,              NULL}, -{   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             gpr_r6      },      NULL,              NULL}, -{   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             gpr_r7      },      NULL,              NULL}, -{   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             gpr_r8      },      NULL,              NULL}, -{   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             gpr_r9      },      NULL,              NULL}, -{   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            gpr_r10     },      NULL,              NULL}, -{   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            gpr_r11     },      NULL,              NULL}, -{   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            gpr_r12     },      NULL,              NULL}, -{   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             gpr_sp      },      NULL,              NULL}, -{   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             gpr_lr      },      NULL,              NULL}, -{   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             gpr_pc      },      NULL,              NULL}, -{   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           gpr_cpsr    },      NULL,              NULL}, - -{   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             fpu_s0      },      NULL,              NULL}, -{   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             fpu_s1      },      NULL,              NULL}, -{   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             fpu_s2      },      NULL,              NULL}, -{   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             fpu_s3      },      NULL,              NULL}, -{   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             fpu_s4      },      NULL,              NULL}, -{   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             fpu_s5      },      NULL,              NULL}, -{   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             fpu_s6      },      NULL,              NULL}, -{   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             fpu_s7      },      NULL,              NULL}, -{   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             fpu_s8      },      NULL,              NULL}, -{   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             fpu_s9      },      NULL,              NULL}, -{   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            fpu_s10     },      NULL,              NULL}, -{   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            fpu_s11     },      NULL,              NULL}, -{   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            fpu_s12     },      NULL,              NULL}, -{   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            fpu_s13     },      NULL,              NULL}, -{   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            fpu_s14     },      NULL,              NULL}, -{   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            fpu_s15     },      NULL,              NULL}, -{   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            fpu_s16     },      NULL,              NULL}, -{   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            fpu_s17     },      NULL,              NULL}, -{   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            fpu_s18     },      NULL,              NULL}, -{   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            fpu_s19     },      NULL,              NULL}, -{   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            fpu_s20     },      NULL,              NULL}, -{   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            fpu_s21     },      NULL,              NULL}, -{   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            fpu_s22     },      NULL,              NULL}, -{   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            fpu_s23     },      NULL,              NULL}, -{   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            fpu_s24     },      NULL,              NULL}, -{   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            fpu_s25     },      NULL,              NULL}, -{   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            fpu_s26     },      NULL,              NULL}, -{   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            fpu_s27     },      NULL,              NULL}, -{   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            fpu_s28     },      NULL,              NULL}, -{   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            fpu_s29     },      NULL,              NULL}, -{   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            fpu_s30     },      NULL,              NULL}, -{   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            fpu_s31     },      NULL,              NULL}, -{   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          fpu_fpscr   },      NULL,              NULL}, +{   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { ehframe_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r0      },      NULL,              NULL}, +{   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { ehframe_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r1      },      NULL,              NULL}, +{   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { ehframe_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r2      },      NULL,              NULL}, +{   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { ehframe_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r3      },      NULL,              NULL}, +{   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { ehframe_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r4      },      NULL,              NULL}, +{   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { ehframe_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r5      },      NULL,              NULL}, +{   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { ehframe_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r6      },      NULL,              NULL}, +{   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { ehframe_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,    gpr_r7      },      NULL,              NULL}, +{   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { ehframe_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r8      },      NULL,              NULL}, +{   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { ehframe_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r9      },      NULL,              NULL}, +{   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { ehframe_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r10     },      NULL,              NULL}, +{   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { ehframe_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r11     },      NULL,              NULL}, +{   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { ehframe_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    gpr_r12     },      NULL,              NULL}, +{   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { ehframe_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,    gpr_sp      },      NULL,              NULL}, +{   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { ehframe_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,    gpr_lr      },      NULL,              NULL}, +{   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { ehframe_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,    gpr_pc      },      NULL,              NULL}, +{   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { ehframe_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,    gpr_cpsr    },      NULL,              NULL}, + +{   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s0      },      NULL,              NULL}, +{   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s1      },      NULL,              NULL}, +{   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s2      },      NULL,              NULL}, +{   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s3      },      NULL,              NULL}, +{   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s4      },      NULL,              NULL}, +{   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s5      },      NULL,              NULL}, +{   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s6      },      NULL,              NULL}, +{   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s7      },      NULL,              NULL}, +{   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s8      },      NULL,              NULL}, +{   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s9      },      NULL,              NULL}, +{   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s10     },      NULL,              NULL}, +{   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s11     },      NULL,              NULL}, +{   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s12     },      NULL,              NULL}, +{   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s13     },      NULL,              NULL}, +{   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s14     },      NULL,              NULL}, +{   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s15     },      NULL,              NULL}, +{   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s16     },      NULL,              NULL}, +{   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s17     },      NULL,              NULL}, +{   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s18     },      NULL,              NULL}, +{   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s19     },      NULL,              NULL}, +{   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s20     },      NULL,              NULL}, +{   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s21     },      NULL,              NULL}, +{   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s22     },      NULL,              NULL}, +{   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s23     },      NULL,              NULL}, +{   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s24     },      NULL,              NULL}, +{   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s25     },      NULL,              NULL}, +{   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s26     },      NULL,              NULL}, +{   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s27     },      NULL,              NULL}, +{   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s28     },      NULL,              NULL}, +{   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s29     },      NULL,              NULL}, +{   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s30     },      NULL,              NULL}, +{   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_s31     },      NULL,              NULL}, +{   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    fpu_fpscr   },      NULL,              NULL},  {   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL},  {   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_fsr       },    NULL,              NULL}, @@ -403,6 +383,26 @@ g_exc_regnums[] =  static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) : +    RegisterContext(thread, concrete_frame_idx), +    gpr(), +    fpu(), +    exc() +{ +    uint32_t i; +    for (i=0; i<kNumErrors; i++) +    { +        gpr_errs[i] = -1; +        fpu_errs[i] = -1; +        exc_errs[i] = -1; +    } +} + +RegisterContextDarwin_arm::~RegisterContextDarwin_arm() +{ +} + +  void  RegisterContextDarwin_arm::InvalidateAllRegisters ()  { @@ -940,27 +940,27 @@ RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKi              break;          }      } -    else if (kind == eRegisterKindGCC) +    else if (kind == eRegisterKindEHFrame)      {          switch (reg)          { -        case gcc_r0:    return gpr_r0; -        case gcc_r1:    return gpr_r1; -        case gcc_r2:    return gpr_r2; -        case gcc_r3:    return gpr_r3; -        case gcc_r4:    return gpr_r4; -        case gcc_r5:    return gpr_r5; -        case gcc_r6:    return gpr_r6; -        case gcc_r7:    return gpr_r7; -        case gcc_r8:    return gpr_r8; -        case gcc_r9:    return gpr_r9; -        case gcc_r10:   return gpr_r10; -        case gcc_r11:   return gpr_r11; -        case gcc_r12:   return gpr_r12; -        case gcc_sp:    return gpr_sp; -        case gcc_lr:    return gpr_lr; -        case gcc_pc:    return gpr_pc; -        case gcc_cpsr:  return gpr_cpsr; +        case ehframe_r0:    return gpr_r0; +        case ehframe_r1:    return gpr_r1; +        case ehframe_r2:    return gpr_r2; +        case ehframe_r3:    return gpr_r3; +        case ehframe_r4:    return gpr_r4; +        case ehframe_r5:    return gpr_r5; +        case ehframe_r6:    return gpr_r6; +        case ehframe_r7:    return gpr_r7; +        case ehframe_r8:    return gpr_r8; +        case ehframe_r9:    return gpr_r9; +        case ehframe_r10:   return gpr_r10; +        case ehframe_r11:   return gpr_r11; +        case ehframe_r12:   return gpr_r12; +        case ehframe_sp:    return gpr_sp; +        case ehframe_lr:    return gpr_lr; +        case ehframe_pc:    return gpr_pc; +        case ehframe_cpsr:  return gpr_cpsr;          }      }      else if (kind == eRegisterKindLLDB) diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h index 23134efd43e67..f4d82259f9df9 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h @@ -51,61 +51,59 @@  class RegisterContextDarwin_arm : public lldb_private::RegisterContext  {  public: -      RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx); -    virtual -    ~RegisterContextDarwin_arm(); +    ~RegisterContextDarwin_arm() override; -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info,  -                  lldb_private::RegisterValue ®_value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue ®_value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, -                   const lldb_private::RegisterValue ®_value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue ®_value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -    virtual uint32_t -    NumSupportedHardwareBreakpoints (); +    uint32_t +    NumSupportedHardwareBreakpoints() override; -    virtual uint32_t -    SetHardwareBreakpoint (lldb::addr_t addr, size_t size); +    uint32_t +    SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; -    virtual bool -    ClearHardwareBreakpoint (uint32_t hw_idx); +    bool +    ClearHardwareBreakpoint(uint32_t hw_idx) override; -    virtual uint32_t -    NumSupportedHardwareWatchpoints (); +    uint32_t +    NumSupportedHardwareWatchpoints() override; -    virtual uint32_t -    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); +    uint32_t +    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; -    virtual bool -    ClearHardwareWatchpoint (uint32_t hw_index); +    bool +    ClearHardwareWatchpoint(uint32_t hw_index) override;      struct GPR      { @@ -113,7 +111,6 @@ public:          uint32_t    cpsr;   // CPSR      }; -      struct QReg      {          uint8_t bytes[16]; @@ -163,7 +160,6 @@ public:      LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);  protected: -      enum      {          GPRRegSet = 1, // ARM_THREAD_STATE @@ -330,4 +326,4 @@ protected:      GetRegisterInfos ();  }; -#endif  // liblldb_RegisterContextDarwin_arm_h_ +#endif // liblldb_RegisterContextDarwin_arm_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp index e08a87369e4d1..7de042dd11a93 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp @@ -36,31 +36,11 @@  #endif  // Project includes -#include "ARM64_GCC_Registers.h"  #include "ARM64_DWARF_Registers.h"  using namespace lldb;  using namespace lldb_private; -RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) : -    RegisterContext(thread, concrete_frame_idx), -    gpr(), -    fpu(), -    exc() -{ -    uint32_t i; -    for (i=0; i<kNumErrors; i++) -    { -        gpr_errs[i] = -1; -        fpu_errs[i] = -1; -        exc_errs[i] = -1; -    } -} - -RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() -{ -} -  #define GPR_OFFSET(idx) ((idx) * 8)  #define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg)) @@ -71,7 +51,7 @@ RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()  #define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))  #define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC)) -#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL +#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL  #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))  //----------------------------------------------------------------------------- @@ -173,6 +153,26 @@ g_exc_regnums[] =  static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64); +RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) : +    RegisterContext(thread, concrete_frame_idx), +    gpr(), +    fpu(), +    exc() +{ +    uint32_t i; +    for (i=0; i<kNumErrors; i++) +    { +        gpr_errs[i] = -1; +        fpu_errs[i] = -1; +        exc_errs[i] = -1; +    } +} + +RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64() +{ +} + +  void  RegisterContextDarwin_arm64::InvalidateAllRegisters ()  { @@ -488,7 +488,7 @@ RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, Registe      case fpu_v29:      case fpu_v30:      case fpu_v31: -        value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); +        value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, endian::InlHostByteOrder());          break;      case fpu_fpsr: @@ -770,44 +770,44 @@ RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind k              break;          }      } -    else if (kind == eRegisterKindGCC) +    else if (kind == eRegisterKindEHFrame)      {          switch (reg)          { -        case arm64_gcc::x0:  return gpr_x0; -        case arm64_gcc::x1:  return gpr_x1; -        case arm64_gcc::x2:  return gpr_x2; -        case arm64_gcc::x3:  return gpr_x3; -        case arm64_gcc::x4:  return gpr_x4; -        case arm64_gcc::x5:  return gpr_x5; -        case arm64_gcc::x6:  return gpr_x6; -        case arm64_gcc::x7:  return gpr_x7; -        case arm64_gcc::x8:  return gpr_x8; -        case arm64_gcc::x9:  return gpr_x9; -        case arm64_gcc::x10: return gpr_x10; -        case arm64_gcc::x11: return gpr_x11; -        case arm64_gcc::x12: return gpr_x12; -        case arm64_gcc::x13: return gpr_x13; -        case arm64_gcc::x14: return gpr_x14; -        case arm64_gcc::x15: return gpr_x15; -        case arm64_gcc::x16: return gpr_x16; -        case arm64_gcc::x17: return gpr_x17; -        case arm64_gcc::x18: return gpr_x18; -        case arm64_gcc::x19: return gpr_x19; -        case arm64_gcc::x20: return gpr_x20; -        case arm64_gcc::x21: return gpr_x21; -        case arm64_gcc::x22: return gpr_x22; -        case arm64_gcc::x23: return gpr_x23; -        case arm64_gcc::x24: return gpr_x24; -        case arm64_gcc::x25: return gpr_x25; -        case arm64_gcc::x26: return gpr_x26; -        case arm64_gcc::x27: return gpr_x27; -        case arm64_gcc::x28: return gpr_x28; -        case arm64_gcc::fp:   return gpr_fp; -        case arm64_gcc::sp:   return gpr_sp; -        case arm64_gcc::lr:   return gpr_lr; -        case arm64_gcc::pc:   return gpr_pc; -        case arm64_gcc::cpsr: return gpr_cpsr; +        case arm64_ehframe::x0:  return gpr_x0; +        case arm64_ehframe::x1:  return gpr_x1; +        case arm64_ehframe::x2:  return gpr_x2; +        case arm64_ehframe::x3:  return gpr_x3; +        case arm64_ehframe::x4:  return gpr_x4; +        case arm64_ehframe::x5:  return gpr_x5; +        case arm64_ehframe::x6:  return gpr_x6; +        case arm64_ehframe::x7:  return gpr_x7; +        case arm64_ehframe::x8:  return gpr_x8; +        case arm64_ehframe::x9:  return gpr_x9; +        case arm64_ehframe::x10: return gpr_x10; +        case arm64_ehframe::x11: return gpr_x11; +        case arm64_ehframe::x12: return gpr_x12; +        case arm64_ehframe::x13: return gpr_x13; +        case arm64_ehframe::x14: return gpr_x14; +        case arm64_ehframe::x15: return gpr_x15; +        case arm64_ehframe::x16: return gpr_x16; +        case arm64_ehframe::x17: return gpr_x17; +        case arm64_ehframe::x18: return gpr_x18; +        case arm64_ehframe::x19: return gpr_x19; +        case arm64_ehframe::x20: return gpr_x20; +        case arm64_ehframe::x21: return gpr_x21; +        case arm64_ehframe::x22: return gpr_x22; +        case arm64_ehframe::x23: return gpr_x23; +        case arm64_ehframe::x24: return gpr_x24; +        case arm64_ehframe::x25: return gpr_x25; +        case arm64_ehframe::x26: return gpr_x26; +        case arm64_ehframe::x27: return gpr_x27; +        case arm64_ehframe::x28: return gpr_x28; +        case arm64_ehframe::fp:   return gpr_fp; +        case arm64_ehframe::sp:   return gpr_sp; +        case arm64_ehframe::lr:   return gpr_lr; +        case arm64_ehframe::pc:   return gpr_pc; +        case arm64_ehframe::cpsr: return gpr_cpsr;          }      }      else if (kind == eRegisterKindLLDB) diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h index aeac15e9b09a0..b228c42ade531 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h @@ -32,52 +32,50 @@  class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext  {  public: -      RegisterContextDarwin_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx); -    virtual -    ~RegisterContextDarwin_arm64(); +    ~RegisterContextDarwin_arm64() override; -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info,  -                  lldb_private::RegisterValue ®_value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue ®_value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, -                   const lldb_private::RegisterValue ®_value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue ®_value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -    virtual uint32_t -    NumSupportedHardwareWatchpoints (); +    uint32_t +    NumSupportedHardwareWatchpoints() override; -    virtual uint32_t -    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); +    uint32_t +    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; -    virtual bool -    ClearHardwareWatchpoint (uint32_t hw_index); +    bool +    ClearHardwareWatchpoint(uint32_t hw_index) override;      // mirrors <mach/arm/thread_status.h> arm_thread_state64_t      struct GPR @@ -90,7 +88,6 @@ public:          uint32_t    cpsr;   // cpsr      }; -      struct VReg      {          uint8_t bytes[16]; @@ -126,7 +123,6 @@ public:      LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);  protected: -      enum      {          GPRRegSet = 6,  // ARM_THREAD_STATE64 @@ -293,4 +289,4 @@ protected:      GetRegisterInfos ();  }; -#endif  // liblldb_RegisterContextDarwin_arm64_h_ +#endif // liblldb_RegisterContextDarwin_arm64_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp index 08144bf7ec262..1b01c28b5d964 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp @@ -98,16 +98,16 @@ enum  enum  { -    gcc_eax = 0, -    gcc_ecx, -    gcc_edx, -    gcc_ebx, -    gcc_ebp, -    gcc_esp, -    gcc_esi, -    gcc_edi, -    gcc_eip, -    gcc_eflags +    ehframe_eax = 0, +    ehframe_ecx, +    ehframe_edx, +    ehframe_ebx, +    ehframe_ebp, +    ehframe_esp, +    ehframe_esi, +    ehframe_edi, +    ehframe_eip, +    ehframe_eflags  };  enum @@ -140,79 +140,6 @@ enum      dwarf_xmm7  }; -enum -{ -    gdb_eax        =  0, -    gdb_ecx        =  1, -    gdb_edx        =  2, -    gdb_ebx        =  3, -    gdb_esp        =  4, -    gdb_ebp        =  5, -    gdb_esi        =  6, -    gdb_edi        =  7, -    gdb_eip        =  8, -    gdb_eflags     =  9, -    gdb_cs         = 10, -    gdb_ss         = 11, -    gdb_ds         = 12, -    gdb_es         = 13, -    gdb_fs         = 14, -    gdb_gs         = 15, -    gdb_stmm0      = 16, -    gdb_stmm1      = 17, -    gdb_stmm2      = 18, -    gdb_stmm3      = 19, -    gdb_stmm4      = 20, -    gdb_stmm5      = 21, -    gdb_stmm6      = 22, -    gdb_stmm7      = 23, -    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl, -    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat, -    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag, -    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg, -    gdb_fioff      = 28,    gdb_ip      = gdb_fioff, -    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg, -    gdb_fooff      = 30,    gdb_dp      = gdb_fooff, -    gdb_fop        = 31, -    gdb_xmm0       = 32, -    gdb_xmm1       = 33, -    gdb_xmm2       = 34, -    gdb_xmm3       = 35, -    gdb_xmm4       = 36, -    gdb_xmm5       = 37, -    gdb_xmm6       = 38, -    gdb_xmm7       = 39, -    gdb_mxcsr      = 40, -    gdb_mm0        = 41, -    gdb_mm1        = 42, -    gdb_mm2        = 43, -    gdb_mm3        = 44, -    gdb_mm4        = 45, -    gdb_mm5        = 46, -    gdb_mm6        = 47, -    gdb_mm7        = 48 -}; - -RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) : -    RegisterContext(thread, concrete_frame_idx), -    gpr(), -    fpu(), -    exc() -{ -    uint32_t i; -    for (i=0; i<kNumErrors; i++) -    { -        gpr_errs[i] = -1; -        fpu_errs[i] = -1; -        exc_errs[i] = -1; -    } -} - -RegisterContextDarwin_i386::~RegisterContextDarwin_i386() -{ -} - -  #define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::GPR, reg))  #define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR)) @@ -224,42 +151,42 @@ RegisterContextDarwin_i386::~RegisterContextDarwin_i386()  // sizes and offsets.  #define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex  #define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL +#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL  #define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex  #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC))  static RegisterInfo g_register_infos[] =  { -//  Macro auto defines most stuff   GCC                     DWARF                 GENERIC                    GDB                  LLDB              VALUE REGS    INVALIDATE REGS +//  Macro auto defines most stuff   eh_frame                DWARF                 GENERIC                    PROCESS PLUGIN       LLDB              VALUE REGS    INVALIDATE REGS  //  =============================== ======================= ===================   =========================  ==================   ================= ==========    =============== -    { DEFINE_GPR(eax    , NULL)     , { gcc_eax             , dwarf_eax          , LLDB_INVALID_REGNUM       , gdb_eax            , gpr_eax      },      NULL,              NULL}, -    { DEFINE_GPR(ebx    , NULL)     , { gcc_ebx             , dwarf_ebx          , LLDB_INVALID_REGNUM       , gdb_ebx            , gpr_ebx      },      NULL,              NULL}, -    { DEFINE_GPR(ecx    , NULL)     , { gcc_ecx             , dwarf_ecx          , LLDB_INVALID_REGNUM       , gdb_ecx            , gpr_ecx      },      NULL,              NULL}, -    { DEFINE_GPR(edx    , NULL)     , { gcc_edx             , dwarf_edx          , LLDB_INVALID_REGNUM       , gdb_edx            , gpr_edx      },      NULL,              NULL}, -    { DEFINE_GPR(edi    , NULL)     , { gcc_edi             , dwarf_edi          , LLDB_INVALID_REGNUM       , gdb_edi            , gpr_edi      },      NULL,              NULL}, -    { DEFINE_GPR(esi    , NULL)     , { gcc_esi             , dwarf_esi          , LLDB_INVALID_REGNUM       , gdb_esi            , gpr_esi      },      NULL,              NULL}, -    { DEFINE_GPR(ebp    , "fp")     , { gcc_ebp             , dwarf_ebp          , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , gpr_ebp      },      NULL,              NULL}, -    { DEFINE_GPR(esp    , "sp")     , { gcc_esp             , dwarf_esp          , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , gpr_esp      },      NULL,              NULL}, -    { DEFINE_GPR(ss     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ss             , gpr_ss       },      NULL,              NULL}, -    { DEFINE_GPR(eflags , "flags")  , { gcc_eflags          , dwarf_eflags       , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , gpr_eflags   },      NULL,              NULL}, -    { DEFINE_GPR(eip    , "pc")     , { gcc_eip             , dwarf_eip          , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , gpr_eip      },      NULL,              NULL}, -    { DEFINE_GPR(cs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_cs             , gpr_cs       },      NULL,              NULL}, -    { DEFINE_GPR(ds     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ds             , gpr_ds       },      NULL,              NULL}, -    { DEFINE_GPR(es     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_es             , gpr_es       },      NULL,              NULL}, -    { DEFINE_GPR(fs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fs             , gpr_fs       },      NULL,              NULL}, -    { DEFINE_GPR(gs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_gs             , gpr_gs       },      NULL,              NULL}, - -    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fcw            , fpu_fcw      },      NULL,              NULL}, -    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fsw            , fpu_fsw      },      NULL,              NULL}, -    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ftw            , fpu_ftw      },      NULL,              NULL}, -    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fop            , fpu_fop      },      NULL,              NULL}, -    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ip             , fpu_ip       },      NULL,              NULL}, -    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_cs             , fpu_cs       },      NULL,              NULL}, -    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_dp             , fpu_dp       },      NULL,              NULL}, -    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ds             , fpu_ds       },      NULL,              NULL}, -    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_mxcsr          , fpu_mxcsr    },      NULL,              NULL}, -    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, fpu_mxcsrmask},      NULL,              NULL}, +    { DEFINE_GPR(eax    , NULL)     , { ehframe_eax        , dwarf_eax          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_eax      },      NULL,              NULL}, +    { DEFINE_GPR(ebx    , NULL)     , { ehframe_ebx        , dwarf_ebx          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_ebx      },      NULL,              NULL}, +    { DEFINE_GPR(ecx    , NULL)     , { ehframe_ecx        , dwarf_ecx          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_ecx      },      NULL,              NULL}, +    { DEFINE_GPR(edx    , NULL)     , { ehframe_edx        , dwarf_edx          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_edx      },      NULL,              NULL}, +    { DEFINE_GPR(edi    , NULL)     , { ehframe_edi        , dwarf_edi          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_edi      },      NULL,              NULL}, +    { DEFINE_GPR(esi    , NULL)     , { ehframe_esi        , dwarf_esi          , LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, gpr_esi      },      NULL,              NULL}, +    { DEFINE_GPR(ebp    , "fp")     , { ehframe_ebp        , dwarf_ebp          , LLDB_REGNUM_GENERIC_FP    , LLDB_INVALID_REGNUM, gpr_ebp      },      NULL,              NULL}, +    { DEFINE_GPR(esp    , "sp")     , { ehframe_esp        , dwarf_esp          , LLDB_REGNUM_GENERIC_SP    , LLDB_INVALID_REGNUM, gpr_esp      },      NULL,              NULL}, +    { DEFINE_GPR(ss     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_ss       },      NULL,              NULL}, +    { DEFINE_GPR(eflags , "flags")  , { ehframe_eflags     , dwarf_eflags       , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, gpr_eflags   },      NULL,              NULL}, +    { DEFINE_GPR(eip    , "pc")     , { ehframe_eip        , dwarf_eip          , LLDB_REGNUM_GENERIC_PC    , LLDB_INVALID_REGNUM, gpr_eip      },      NULL,              NULL}, +    { DEFINE_GPR(cs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_cs       },      NULL,              NULL}, +    { DEFINE_GPR(ds     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_ds       },      NULL,              NULL}, +    { DEFINE_GPR(es     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_es       },      NULL,              NULL}, +    { DEFINE_GPR(fs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_fs       },      NULL,              NULL}, +    { DEFINE_GPR(gs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_gs       },      NULL,              NULL}, + +    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fcw      },      NULL,              NULL}, +    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fsw      },      NULL,              NULL}, +    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ftw      },      NULL,              NULL}, +    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fop      },      NULL,              NULL}, +    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ip       },      NULL,              NULL}, +    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_cs       },      NULL,              NULL}, +    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_dp       },      NULL,              NULL}, +    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ds       },      NULL,              NULL}, +    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_mxcsr    },      NULL,              NULL}, +    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_mxcsrmask},      NULL,              NULL},      { DEFINE_FPU_VECT(stmm,0)   },      { DEFINE_FPU_VECT(stmm,1)   },      { DEFINE_FPU_VECT(stmm,2)   }, @@ -277,13 +204,33 @@ static RegisterInfo g_register_infos[] =      { DEFINE_FPU_VECT(xmm,6)    },      { DEFINE_FPU_VECT(xmm,7)    }, -    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_trapno },       NULL,              NULL}, -    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_err },          NULL,              NULL}, -    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_faultvaddr },   NULL,              NULL} +    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM, exc_trapno },       NULL,              NULL}, +    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM, exc_err },          NULL,              NULL}, +    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM, exc_faultvaddr },   NULL,              NULL}  };  static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) : +    RegisterContext(thread, concrete_frame_idx), +    gpr(), +    fpu(), +    exc() +{ +    uint32_t i; +    for (i=0; i<kNumErrors; i++) +    { +        gpr_errs[i] = -1; +        fpu_errs[i] = -1; +        exc_errs[i] = -1; +    } +} + +RegisterContextDarwin_i386::~RegisterContextDarwin_i386() +{ +} + +  void  RegisterContextDarwin_i386::InvalidateAllRegisters ()  { @@ -859,7 +806,7 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK              break;          }      } -    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) +    else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)      {          switch (reg)          { @@ -893,55 +840,6 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK              break;          }      } -    else if (kind == eRegisterKindGDB) -    { -        switch (reg) -        { -        case gdb_eax     : return gpr_eax; -        case gdb_ebx     : return gpr_ebx; -        case gdb_ecx     : return gpr_ecx; -        case gdb_edx     : return gpr_edx; -        case gdb_esi     : return gpr_esi; -        case gdb_edi     : return gpr_edi; -        case gdb_ebp     : return gpr_ebp; -        case gdb_esp     : return gpr_esp; -        case gdb_eip     : return gpr_eip; -        case gdb_eflags  : return gpr_eflags; -        case gdb_cs      : return gpr_cs; -        case gdb_ss      : return gpr_ss; -        case gdb_ds      : return gpr_ds; -        case gdb_es      : return gpr_es; -        case gdb_fs      : return gpr_fs; -        case gdb_gs      : return gpr_gs; -        case gdb_stmm0   : return fpu_stmm0; -        case gdb_stmm1   : return fpu_stmm1; -        case gdb_stmm2   : return fpu_stmm2; -        case gdb_stmm3   : return fpu_stmm3; -        case gdb_stmm4   : return fpu_stmm4; -        case gdb_stmm5   : return fpu_stmm5; -        case gdb_stmm6   : return fpu_stmm6; -        case gdb_stmm7   : return fpu_stmm7; -        case gdb_fctrl   : return fpu_fctrl; -        case gdb_fstat   : return fpu_fstat; -        case gdb_ftag    : return fpu_ftag; -        case gdb_fiseg   : return fpu_fiseg; -        case gdb_fioff   : return fpu_fioff; -        case gdb_foseg   : return fpu_foseg; -        case gdb_fooff   : return fpu_fooff; -        case gdb_fop     : return fpu_fop; -        case gdb_xmm0    : return fpu_xmm0; -        case gdb_xmm1    : return fpu_xmm1; -        case gdb_xmm2    : return fpu_xmm2; -        case gdb_xmm3    : return fpu_xmm3; -        case gdb_xmm4    : return fpu_xmm4; -        case gdb_xmm5    : return fpu_xmm5; -        case gdb_xmm6    : return fpu_xmm6; -        case gdb_xmm7    : return fpu_xmm7; -        case gdb_mxcsr   : return fpu_mxcsr; -        default: -            break; -        } -    }      else if (kind == eRegisterKindLLDB)      {          return reg; diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h index 1d03feb9f3dd1..9568b0332b4cf 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h @@ -20,45 +20,45 @@  class RegisterContextDarwin_i386 : public lldb_private::RegisterContext  {  public: -      RegisterContextDarwin_i386(lldb_private::Thread &thread, -                             uint32_t concrete_frame_idx); +                               uint32_t concrete_frame_idx); -    virtual -    ~RegisterContextDarwin_i386(); +    ~RegisterContextDarwin_i386() override; -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -    virtual bool -    HardwareSingleStep (bool enable); +    bool +    HardwareSingleStep(bool enable) override;      struct GPR      { @@ -121,7 +121,6 @@ public:      };  protected: -      enum      {          GPRRegSet = 1, @@ -266,4 +265,4 @@ protected:      GetRegisterInfos ();  }; -#endif  // liblldb_RegisterContextDarwin_i386_h_ +#endif // liblldb_RegisterContextDarwin_i386_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp index 54124d187d545..aee6e1228d2a9 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp @@ -111,132 +111,52 @@ enum      fpu_fooff = fpu_dp  }; -enum gcc_dwarf_regnums -{ -    gcc_dwarf_gpr_rax = 0, -    gcc_dwarf_gpr_rdx, -    gcc_dwarf_gpr_rcx, -    gcc_dwarf_gpr_rbx, -    gcc_dwarf_gpr_rsi, -    gcc_dwarf_gpr_rdi, -    gcc_dwarf_gpr_rbp, -    gcc_dwarf_gpr_rsp, -    gcc_dwarf_gpr_r8, -    gcc_dwarf_gpr_r9, -    gcc_dwarf_gpr_r10, -    gcc_dwarf_gpr_r11, -    gcc_dwarf_gpr_r12, -    gcc_dwarf_gpr_r13, -    gcc_dwarf_gpr_r14, -    gcc_dwarf_gpr_r15, -    gcc_dwarf_gpr_rip, -    gcc_dwarf_fpu_xmm0, -    gcc_dwarf_fpu_xmm1, -    gcc_dwarf_fpu_xmm2, -    gcc_dwarf_fpu_xmm3, -    gcc_dwarf_fpu_xmm4, -    gcc_dwarf_fpu_xmm5, -    gcc_dwarf_fpu_xmm6, -    gcc_dwarf_fpu_xmm7, -    gcc_dwarf_fpu_xmm8, -    gcc_dwarf_fpu_xmm9, -    gcc_dwarf_fpu_xmm10, -    gcc_dwarf_fpu_xmm11, -    gcc_dwarf_fpu_xmm12, -    gcc_dwarf_fpu_xmm13, -    gcc_dwarf_fpu_xmm14, -    gcc_dwarf_fpu_xmm15, -    gcc_dwarf_fpu_stmm0, -    gcc_dwarf_fpu_stmm1, -    gcc_dwarf_fpu_stmm2, -    gcc_dwarf_fpu_stmm3, -    gcc_dwarf_fpu_stmm4, -    gcc_dwarf_fpu_stmm5, -    gcc_dwarf_fpu_stmm6, -    gcc_dwarf_fpu_stmm7 - -}; +enum ehframe_dwarf_regnums +{ +    ehframe_dwarf_gpr_rax = 0, +    ehframe_dwarf_gpr_rdx, +    ehframe_dwarf_gpr_rcx, +    ehframe_dwarf_gpr_rbx, +    ehframe_dwarf_gpr_rsi, +    ehframe_dwarf_gpr_rdi, +    ehframe_dwarf_gpr_rbp, +    ehframe_dwarf_gpr_rsp, +    ehframe_dwarf_gpr_r8, +    ehframe_dwarf_gpr_r9, +    ehframe_dwarf_gpr_r10, +    ehframe_dwarf_gpr_r11, +    ehframe_dwarf_gpr_r12, +    ehframe_dwarf_gpr_r13, +    ehframe_dwarf_gpr_r14, +    ehframe_dwarf_gpr_r15, +    ehframe_dwarf_gpr_rip, +    ehframe_dwarf_fpu_xmm0, +    ehframe_dwarf_fpu_xmm1, +    ehframe_dwarf_fpu_xmm2, +    ehframe_dwarf_fpu_xmm3, +    ehframe_dwarf_fpu_xmm4, +    ehframe_dwarf_fpu_xmm5, +    ehframe_dwarf_fpu_xmm6, +    ehframe_dwarf_fpu_xmm7, +    ehframe_dwarf_fpu_xmm8, +    ehframe_dwarf_fpu_xmm9, +    ehframe_dwarf_fpu_xmm10, +    ehframe_dwarf_fpu_xmm11, +    ehframe_dwarf_fpu_xmm12, +    ehframe_dwarf_fpu_xmm13, +    ehframe_dwarf_fpu_xmm14, +    ehframe_dwarf_fpu_xmm15, +    ehframe_dwarf_fpu_stmm0, +    ehframe_dwarf_fpu_stmm1, +    ehframe_dwarf_fpu_stmm2, +    ehframe_dwarf_fpu_stmm3, +    ehframe_dwarf_fpu_stmm4, +    ehframe_dwarf_fpu_stmm5, +    ehframe_dwarf_fpu_stmm6, +    ehframe_dwarf_fpu_stmm7 -enum gdb_regnums -{ -    gdb_gpr_rax     =   0, -    gdb_gpr_rbx     =   1, -    gdb_gpr_rcx     =   2, -    gdb_gpr_rdx     =   3, -    gdb_gpr_rsi     =   4, -    gdb_gpr_rdi     =   5, -    gdb_gpr_rbp     =   6, -    gdb_gpr_rsp     =   7, -    gdb_gpr_r8      =   8, -    gdb_gpr_r9      =   9, -    gdb_gpr_r10     =  10, -    gdb_gpr_r11     =  11, -    gdb_gpr_r12     =  12, -    gdb_gpr_r13     =  13, -    gdb_gpr_r14     =  14, -    gdb_gpr_r15     =  15, -    gdb_gpr_rip     =  16, -    gdb_gpr_rflags  =  17, -    gdb_gpr_cs      =  18, -    gdb_gpr_ss      =  19, -    gdb_gpr_ds      =  20, -    gdb_gpr_es      =  21, -    gdb_gpr_fs      =  22, -    gdb_gpr_gs      =  23, -    gdb_fpu_stmm0   =  24, -    gdb_fpu_stmm1   =  25, -    gdb_fpu_stmm2   =  26, -    gdb_fpu_stmm3   =  27, -    gdb_fpu_stmm4   =  28, -    gdb_fpu_stmm5   =  29, -    gdb_fpu_stmm6   =  30, -    gdb_fpu_stmm7   =  31, -    gdb_fpu_fctrl   =  32,  gdb_fpu_fcw = gdb_fpu_fctrl, -    gdb_fpu_fstat   =  33,  gdb_fpu_fsw = gdb_fpu_fstat, -    gdb_fpu_ftag    =  34,  gdb_fpu_ftw = gdb_fpu_ftag, -    gdb_fpu_fiseg   =  35,  gdb_fpu_cs  = gdb_fpu_fiseg, -    gdb_fpu_fioff   =  36,  gdb_fpu_ip  = gdb_fpu_fioff, -    gdb_fpu_foseg   =  37,  gdb_fpu_ds  = gdb_fpu_foseg, -    gdb_fpu_fooff   =  38,  gdb_fpu_dp  = gdb_fpu_fooff, -    gdb_fpu_fop     =  39, -    gdb_fpu_xmm0    =  40, -    gdb_fpu_xmm1    =  41, -    gdb_fpu_xmm2    =  42, -    gdb_fpu_xmm3    =  43, -    gdb_fpu_xmm4    =  44, -    gdb_fpu_xmm5    =  45, -    gdb_fpu_xmm6    =  46, -    gdb_fpu_xmm7    =  47, -    gdb_fpu_xmm8    =  48, -    gdb_fpu_xmm9    =  49, -    gdb_fpu_xmm10   =  50, -    gdb_fpu_xmm11   =  51, -    gdb_fpu_xmm12   =  52, -    gdb_fpu_xmm13   =  53, -    gdb_fpu_xmm14   =  54, -    gdb_fpu_xmm15   =  55, -    gdb_fpu_mxcsr   =  56  }; -RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) : -    RegisterContext (thread, concrete_frame_idx), -    gpr(), -    fpu(), -    exc() -{ -    uint32_t i; -    for (i=0; i<kNumErrors; i++) -    { -        gpr_errs[i] = -1; -        fpu_errs[i] = -1; -        exc_errs[i] = -1; -    } -} - -RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() -{ -} -  #define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::GPR, reg))  #define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR))  #define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU)) @@ -247,7 +167,7 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()  // sizes and offsets.  #define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex  #define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex -#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL +#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { ehframe_dwarf_fpu_##reg##i, ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL  #define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex  #define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC)) @@ -255,39 +175,39 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()  // General purpose registers for 64 bit  static RegisterInfo g_register_infos[] =  { -//  Macro auto defines most stuff   GCC                    DWARF                GENERIC                    GDB                  LLDB                VALUE REGS    INVALIDATE REGS -//  =============================== ====================== ===================  ========================== ==================== =================== ==========    =============== -    { DEFINE_GPR (rax   , NULL)     , { gcc_dwarf_gpr_rax  , gcc_dwarf_gpr_rax  , LLDB_INVALID_REGNUM      , gdb_gpr_rax        , gpr_rax       },       NULL,              NULL}, -    { DEFINE_GPR (rbx   , NULL)     , { gcc_dwarf_gpr_rbx  , gcc_dwarf_gpr_rbx  , LLDB_INVALID_REGNUM      , gdb_gpr_rbx        , gpr_rbx       },       NULL,              NULL}, -    { DEFINE_GPR (rcx   , NULL)     , { gcc_dwarf_gpr_rcx  , gcc_dwarf_gpr_rcx  , LLDB_INVALID_REGNUM      , gdb_gpr_rcx        , gpr_rcx       },       NULL,              NULL}, -    { DEFINE_GPR (rdx   , NULL)     , { gcc_dwarf_gpr_rdx  , gcc_dwarf_gpr_rdx  , LLDB_INVALID_REGNUM      , gdb_gpr_rdx        , gpr_rdx       },       NULL,              NULL}, -    { DEFINE_GPR (rdi   , NULL)     , { gcc_dwarf_gpr_rdi  , gcc_dwarf_gpr_rdi  , LLDB_INVALID_REGNUM      , gdb_gpr_rdi        , gpr_rdi       },       NULL,              NULL}, -    { DEFINE_GPR (rsi   , NULL)     , { gcc_dwarf_gpr_rsi  , gcc_dwarf_gpr_rsi  , LLDB_INVALID_REGNUM      , gdb_gpr_rsi        , gpr_rsi       },       NULL,              NULL}, -    { DEFINE_GPR (rbp   , "fp")     , { gcc_dwarf_gpr_rbp  , gcc_dwarf_gpr_rbp  , LLDB_REGNUM_GENERIC_FP   , gdb_gpr_rbp        , gpr_rbp       },       NULL,              NULL}, -    { DEFINE_GPR (rsp   , "sp")     , { gcc_dwarf_gpr_rsp  , gcc_dwarf_gpr_rsp  , LLDB_REGNUM_GENERIC_SP   , gdb_gpr_rsp        , gpr_rsp       },       NULL,              NULL}, -    { DEFINE_GPR (r8    , NULL)     , { gcc_dwarf_gpr_r8   , gcc_dwarf_gpr_r8   , LLDB_INVALID_REGNUM      , gdb_gpr_r8         , gpr_r8        },       NULL,              NULL}, -    { DEFINE_GPR (r9    , NULL)     , { gcc_dwarf_gpr_r9   , gcc_dwarf_gpr_r9   , LLDB_INVALID_REGNUM      , gdb_gpr_r9         , gpr_r9        },       NULL,              NULL}, -    { DEFINE_GPR (r10   , NULL)     , { gcc_dwarf_gpr_r10  , gcc_dwarf_gpr_r10  , LLDB_INVALID_REGNUM      , gdb_gpr_r10        , gpr_r10       },       NULL,              NULL}, -    { DEFINE_GPR (r11   , NULL)     , { gcc_dwarf_gpr_r11  , gcc_dwarf_gpr_r11  , LLDB_INVALID_REGNUM      , gdb_gpr_r11        , gpr_r11       },       NULL,              NULL}, -    { DEFINE_GPR (r12   , NULL)     , { gcc_dwarf_gpr_r12  , gcc_dwarf_gpr_r12  , LLDB_INVALID_REGNUM      , gdb_gpr_r12        , gpr_r12       },       NULL,              NULL}, -    { DEFINE_GPR (r13   , NULL)     , { gcc_dwarf_gpr_r13  , gcc_dwarf_gpr_r13  , LLDB_INVALID_REGNUM      , gdb_gpr_r13        , gpr_r13       },       NULL,              NULL}, -    { DEFINE_GPR (r14   , NULL)     , { gcc_dwarf_gpr_r14  , gcc_dwarf_gpr_r14  , LLDB_INVALID_REGNUM      , gdb_gpr_r14        , gpr_r14       },       NULL,              NULL}, -    { DEFINE_GPR (r15   , NULL)     , { gcc_dwarf_gpr_r15  , gcc_dwarf_gpr_r15  , LLDB_INVALID_REGNUM      , gdb_gpr_r15        , gpr_r15       },       NULL,              NULL}, -    { DEFINE_GPR (rip   , "pc")     , { gcc_dwarf_gpr_rip  , gcc_dwarf_gpr_rip  , LLDB_REGNUM_GENERIC_PC   , gdb_gpr_rip        , gpr_rip       },       NULL,              NULL}, -    { DEFINE_GPR (rflags, "flags")  , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags     , gpr_rflags    },       NULL,              NULL}, -    { DEFINE_GPR (cs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_cs         , gpr_cs        },       NULL,              NULL}, -    { DEFINE_GPR (fs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_fs         , gpr_fs        },       NULL,              NULL}, -    { DEFINE_GPR (gs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_gs         , gpr_gs        },       NULL,              NULL}, - -    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fcw        , fpu_fcw       },       NULL,              NULL}, -    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fsw        , fpu_fsw       },       NULL,              NULL}, -    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ftw        , fpu_ftw       },       NULL,              NULL}, -    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fop        , fpu_fop       },       NULL,              NULL}, -    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ip         , fpu_ip        },       NULL,              NULL}, -    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_cs         , fpu_cs        },       NULL,              NULL}, -    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_dp         , fpu_dp        },       NULL,              NULL}, -    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ds         , fpu_ds        },       NULL,              NULL}, -    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_mxcsr      , fpu_mxcsr     },       NULL,              NULL}, +//  Macro auto defines most stuff   EH_FRAME                    DWARF                    GENERIC                    PROCESS PLUGIN       LLDB                VALUE REGS    INVALIDATE REGS +//  =============================== ======================      ===================      ========================== ==================== =================== ==========    =============== +    { DEFINE_GPR (rax   , NULL)     , { ehframe_dwarf_gpr_rax  , ehframe_dwarf_gpr_rax  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rax       },       NULL,              NULL}, +    { DEFINE_GPR (rbx   , NULL)     , { ehframe_dwarf_gpr_rbx  , ehframe_dwarf_gpr_rbx  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rbx       },       NULL,              NULL}, +    { DEFINE_GPR (rcx   , NULL)     , { ehframe_dwarf_gpr_rcx  , ehframe_dwarf_gpr_rcx  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rcx       },       NULL,              NULL}, +    { DEFINE_GPR (rdx   , NULL)     , { ehframe_dwarf_gpr_rdx  , ehframe_dwarf_gpr_rdx  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rdx       },       NULL,              NULL}, +    { DEFINE_GPR (rdi   , NULL)     , { ehframe_dwarf_gpr_rdi  , ehframe_dwarf_gpr_rdi  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rdi       },       NULL,              NULL}, +    { DEFINE_GPR (rsi   , NULL)     , { ehframe_dwarf_gpr_rsi  , ehframe_dwarf_gpr_rsi  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_rsi       },       NULL,              NULL}, +    { DEFINE_GPR (rbp   , "fp")     , { ehframe_dwarf_gpr_rbp  , ehframe_dwarf_gpr_rbp  , LLDB_REGNUM_GENERIC_FP   , LLDB_INVALID_REGNUM, gpr_rbp       },       NULL,              NULL}, +    { DEFINE_GPR (rsp   , "sp")     , { ehframe_dwarf_gpr_rsp  , ehframe_dwarf_gpr_rsp  , LLDB_REGNUM_GENERIC_SP   , LLDB_INVALID_REGNUM, gpr_rsp       },       NULL,              NULL}, +    { DEFINE_GPR (r8    , NULL)     , { ehframe_dwarf_gpr_r8   , ehframe_dwarf_gpr_r8   , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r8        },       NULL,              NULL}, +    { DEFINE_GPR (r9    , NULL)     , { ehframe_dwarf_gpr_r9   , ehframe_dwarf_gpr_r9   , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r9        },       NULL,              NULL}, +    { DEFINE_GPR (r10   , NULL)     , { ehframe_dwarf_gpr_r10  , ehframe_dwarf_gpr_r10  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r10       },       NULL,              NULL}, +    { DEFINE_GPR (r11   , NULL)     , { ehframe_dwarf_gpr_r11  , ehframe_dwarf_gpr_r11  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r11       },       NULL,              NULL}, +    { DEFINE_GPR (r12   , NULL)     , { ehframe_dwarf_gpr_r12  , ehframe_dwarf_gpr_r12  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r12       },       NULL,              NULL}, +    { DEFINE_GPR (r13   , NULL)     , { ehframe_dwarf_gpr_r13  , ehframe_dwarf_gpr_r13  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r13       },       NULL,              NULL}, +    { DEFINE_GPR (r14   , NULL)     , { ehframe_dwarf_gpr_r14  , ehframe_dwarf_gpr_r14  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r14       },       NULL,              NULL}, +    { DEFINE_GPR (r15   , NULL)     , { ehframe_dwarf_gpr_r15  , ehframe_dwarf_gpr_r15  , LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_r15       },       NULL,              NULL}, +    { DEFINE_GPR (rip   , "pc")     , { ehframe_dwarf_gpr_rip  , ehframe_dwarf_gpr_rip  , LLDB_REGNUM_GENERIC_PC   , LLDB_INVALID_REGNUM, gpr_rip       },       NULL,              NULL}, +    { DEFINE_GPR (rflags, "flags")  , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_rflags    },       NULL,              NULL}, +    { DEFINE_GPR (cs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_cs        },       NULL,              NULL}, +    { DEFINE_GPR (fs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_fs        },       NULL,              NULL}, +    { DEFINE_GPR (gs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, gpr_gs        },       NULL,              NULL}, + +    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fcw       },       NULL,              NULL}, +    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fsw       },       NULL,              NULL}, +    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ftw       },       NULL,              NULL}, +    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_fop       },       NULL,              NULL}, +    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ip        },       NULL,              NULL}, +    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_cs        },       NULL,              NULL}, +    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_dp        },       NULL,              NULL}, +    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_ds        },       NULL,              NULL}, +    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_mxcsr     },       NULL,              NULL},      { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_mxcsrmask },       NULL,              NULL},      { DEFINE_FPU_VECT(stmm,0)   },      { DEFINE_FPU_VECT(stmm,1)   }, @@ -321,6 +241,25 @@ static RegisterInfo g_register_infos[] =  static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) : +    RegisterContext (thread, concrete_frame_idx), +    gpr(), +    fpu(), +    exc() +{ +    uint32_t i; +    for (i=0; i<kNumErrors; i++) +    { +        gpr_errs[i] = -1; +        fpu_errs[i] = -1; +        exc_errs[i] = -1; +    } +} + +RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64() +{ +} +  void  RegisterContextDarwin_x86_64::InvalidateAllRegisters () @@ -687,7 +626,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,      case fpu_stmm5:      case fpu_stmm6:      case fpu_stmm7: -        value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); +        value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());          break;      case fpu_xmm0: @@ -706,7 +645,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,      case fpu_xmm13:      case fpu_xmm14:      case fpu_xmm15: -        value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); +        value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());          break;      case exc_trapno: @@ -919,116 +858,51 @@ RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (lldb::Registe              break;          }      } -    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) -    { -        switch (reg) -        { -        case gcc_dwarf_gpr_rax:  return gpr_rax; -        case gcc_dwarf_gpr_rdx:  return gpr_rdx; -        case gcc_dwarf_gpr_rcx:  return gpr_rcx; -        case gcc_dwarf_gpr_rbx:  return gpr_rbx; -        case gcc_dwarf_gpr_rsi:  return gpr_rsi; -        case gcc_dwarf_gpr_rdi:  return gpr_rdi; -        case gcc_dwarf_gpr_rbp:  return gpr_rbp; -        case gcc_dwarf_gpr_rsp:  return gpr_rsp; -        case gcc_dwarf_gpr_r8:   return gpr_r8; -        case gcc_dwarf_gpr_r9:   return gpr_r9; -        case gcc_dwarf_gpr_r10:  return gpr_r10; -        case gcc_dwarf_gpr_r11:  return gpr_r11; -        case gcc_dwarf_gpr_r12:  return gpr_r12; -        case gcc_dwarf_gpr_r13:  return gpr_r13; -        case gcc_dwarf_gpr_r14:  return gpr_r14; -        case gcc_dwarf_gpr_r15:  return gpr_r15; -        case gcc_dwarf_gpr_rip:  return gpr_rip; -        case gcc_dwarf_fpu_xmm0: return fpu_xmm0; -        case gcc_dwarf_fpu_xmm1: return fpu_xmm1; -        case gcc_dwarf_fpu_xmm2: return fpu_xmm2; -        case gcc_dwarf_fpu_xmm3: return fpu_xmm3; -        case gcc_dwarf_fpu_xmm4: return fpu_xmm4; -        case gcc_dwarf_fpu_xmm5: return fpu_xmm5; -        case gcc_dwarf_fpu_xmm6: return fpu_xmm6; -        case gcc_dwarf_fpu_xmm7: return fpu_xmm7; -        case gcc_dwarf_fpu_xmm8: return fpu_xmm8; -        case gcc_dwarf_fpu_xmm9: return fpu_xmm9; -        case gcc_dwarf_fpu_xmm10: return fpu_xmm10; -        case gcc_dwarf_fpu_xmm11: return fpu_xmm11; -        case gcc_dwarf_fpu_xmm12: return fpu_xmm12; -        case gcc_dwarf_fpu_xmm13: return fpu_xmm13; -        case gcc_dwarf_fpu_xmm14: return fpu_xmm14; -        case gcc_dwarf_fpu_xmm15: return fpu_xmm15; -        case gcc_dwarf_fpu_stmm0: return fpu_stmm0; -        case gcc_dwarf_fpu_stmm1: return fpu_stmm1; -        case gcc_dwarf_fpu_stmm2: return fpu_stmm2; -        case gcc_dwarf_fpu_stmm3: return fpu_stmm3; -        case gcc_dwarf_fpu_stmm4: return fpu_stmm4; -        case gcc_dwarf_fpu_stmm5: return fpu_stmm5; -        case gcc_dwarf_fpu_stmm6: return fpu_stmm6; -        case gcc_dwarf_fpu_stmm7: return fpu_stmm7; -        default: -            break; -        } -    } -    else if (kind == eRegisterKindGDB) +    else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)      {          switch (reg)          { -        case gdb_gpr_rax     : return gpr_rax; -        case gdb_gpr_rbx     : return gpr_rbx; -        case gdb_gpr_rcx     : return gpr_rcx; -        case gdb_gpr_rdx     : return gpr_rdx; -        case gdb_gpr_rsi     : return gpr_rsi; -        case gdb_gpr_rdi     : return gpr_rdi; -        case gdb_gpr_rbp     : return gpr_rbp; -        case gdb_gpr_rsp     : return gpr_rsp; -        case gdb_gpr_r8      : return gpr_r8; -        case gdb_gpr_r9      : return gpr_r9; -        case gdb_gpr_r10     : return gpr_r10; -        case gdb_gpr_r11     : return gpr_r11; -        case gdb_gpr_r12     : return gpr_r12; -        case gdb_gpr_r13     : return gpr_r13; -        case gdb_gpr_r14     : return gpr_r14; -        case gdb_gpr_r15     : return gpr_r15; -        case gdb_gpr_rip     : return gpr_rip; -        case gdb_gpr_rflags  : return gpr_rflags; -        case gdb_gpr_cs      : return gpr_cs; -        case gdb_gpr_ss      : return gpr_gs;   // HACK: For now for "ss", just copy what is in "gs" -        case gdb_gpr_ds      : return gpr_gs;   // HACK: For now for "ds", just copy what is in "gs" -        case gdb_gpr_es      : return gpr_gs;   // HACK: For now for "es", just copy what is in "gs" -        case gdb_gpr_fs      : return gpr_fs; -        case gdb_gpr_gs      : return gpr_gs; -        case gdb_fpu_stmm0   : return fpu_stmm0; -        case gdb_fpu_stmm1   : return fpu_stmm1; -        case gdb_fpu_stmm2   : return fpu_stmm2; -        case gdb_fpu_stmm3   : return fpu_stmm3; -        case gdb_fpu_stmm4   : return fpu_stmm4; -        case gdb_fpu_stmm5   : return fpu_stmm5; -        case gdb_fpu_stmm6   : return fpu_stmm6; -        case gdb_fpu_stmm7   : return fpu_stmm7; -        case gdb_fpu_fctrl   : return fpu_fctrl; -        case gdb_fpu_fstat   : return fpu_fstat; -        case gdb_fpu_ftag    : return fpu_ftag; -        case gdb_fpu_fiseg   : return fpu_fiseg; -        case gdb_fpu_fioff   : return fpu_fioff; -        case gdb_fpu_foseg   : return fpu_foseg; -        case gdb_fpu_fooff   : return fpu_fooff; -        case gdb_fpu_fop     : return fpu_fop; -        case gdb_fpu_xmm0    : return fpu_xmm0; -        case gdb_fpu_xmm1    : return fpu_xmm1; -        case gdb_fpu_xmm2    : return fpu_xmm2; -        case gdb_fpu_xmm3    : return fpu_xmm3; -        case gdb_fpu_xmm4    : return fpu_xmm4; -        case gdb_fpu_xmm5    : return fpu_xmm5; -        case gdb_fpu_xmm6    : return fpu_xmm6; -        case gdb_fpu_xmm7    : return fpu_xmm7; -        case gdb_fpu_xmm8    : return fpu_xmm8; -        case gdb_fpu_xmm9    : return fpu_xmm9; -        case gdb_fpu_xmm10   : return fpu_xmm10; -        case gdb_fpu_xmm11   : return fpu_xmm11; -        case gdb_fpu_xmm12   : return fpu_xmm12; -        case gdb_fpu_xmm13   : return fpu_xmm13; -        case gdb_fpu_xmm14   : return fpu_xmm14; -        case gdb_fpu_xmm15   : return fpu_xmm15; -        case gdb_fpu_mxcsr   : return fpu_mxcsr; +        case ehframe_dwarf_gpr_rax:  return gpr_rax; +        case ehframe_dwarf_gpr_rdx:  return gpr_rdx; +        case ehframe_dwarf_gpr_rcx:  return gpr_rcx; +        case ehframe_dwarf_gpr_rbx:  return gpr_rbx; +        case ehframe_dwarf_gpr_rsi:  return gpr_rsi; +        case ehframe_dwarf_gpr_rdi:  return gpr_rdi; +        case ehframe_dwarf_gpr_rbp:  return gpr_rbp; +        case ehframe_dwarf_gpr_rsp:  return gpr_rsp; +        case ehframe_dwarf_gpr_r8:   return gpr_r8; +        case ehframe_dwarf_gpr_r9:   return gpr_r9; +        case ehframe_dwarf_gpr_r10:  return gpr_r10; +        case ehframe_dwarf_gpr_r11:  return gpr_r11; +        case ehframe_dwarf_gpr_r12:  return gpr_r12; +        case ehframe_dwarf_gpr_r13:  return gpr_r13; +        case ehframe_dwarf_gpr_r14:  return gpr_r14; +        case ehframe_dwarf_gpr_r15:  return gpr_r15; +        case ehframe_dwarf_gpr_rip:  return gpr_rip; +        case ehframe_dwarf_fpu_xmm0: return fpu_xmm0; +        case ehframe_dwarf_fpu_xmm1: return fpu_xmm1; +        case ehframe_dwarf_fpu_xmm2: return fpu_xmm2; +        case ehframe_dwarf_fpu_xmm3: return fpu_xmm3; +        case ehframe_dwarf_fpu_xmm4: return fpu_xmm4; +        case ehframe_dwarf_fpu_xmm5: return fpu_xmm5; +        case ehframe_dwarf_fpu_xmm6: return fpu_xmm6; +        case ehframe_dwarf_fpu_xmm7: return fpu_xmm7; +        case ehframe_dwarf_fpu_xmm8: return fpu_xmm8; +        case ehframe_dwarf_fpu_xmm9: return fpu_xmm9; +        case ehframe_dwarf_fpu_xmm10: return fpu_xmm10; +        case ehframe_dwarf_fpu_xmm11: return fpu_xmm11; +        case ehframe_dwarf_fpu_xmm12: return fpu_xmm12; +        case ehframe_dwarf_fpu_xmm13: return fpu_xmm13; +        case ehframe_dwarf_fpu_xmm14: return fpu_xmm14; +        case ehframe_dwarf_fpu_xmm15: return fpu_xmm15; +        case ehframe_dwarf_fpu_stmm0: return fpu_stmm0; +        case ehframe_dwarf_fpu_stmm1: return fpu_stmm1; +        case ehframe_dwarf_fpu_stmm2: return fpu_stmm2; +        case ehframe_dwarf_fpu_stmm3: return fpu_stmm3; +        case ehframe_dwarf_fpu_stmm4: return fpu_stmm4; +        case ehframe_dwarf_fpu_stmm5: return fpu_stmm5; +        case ehframe_dwarf_fpu_stmm6: return fpu_stmm6; +        case ehframe_dwarf_fpu_stmm7: return fpu_stmm7;          default:              break;          } diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h index 09e35e9c423ed..ed627e194a26c 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h @@ -23,41 +23,42 @@ public:      RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,                                    uint32_t concrete_frame_idx); -    virtual -    ~RegisterContextDarwin_x86_64(); +    ~RegisterContextDarwin_x86_64() override; -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -    virtual bool -    HardwareSingleStep (bool enable); +    bool +    HardwareSingleStep(bool enable) override;      struct GPR      { @@ -268,7 +269,6 @@ protected:      static const lldb_private::RegisterInfo *      GetRegisterInfos (); -  }; -#endif  // liblldb_RegisterContextDarwin_x86_64_h_ +#endif // liblldb_RegisterContextDarwin_x86_64_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp index 329b0a7968a21..0859e4e9419ce 100644 --- a/source/Plugins/Process/Utility/RegisterContextDummy.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp @@ -51,10 +51,10 @@ RegisterContext (thread, concrete_frame_idx)      m_pc_reg_info.format = eFormatPointer;      m_pc_reg_info.invalidate_regs = NULL;      m_pc_reg_info.value_regs = NULL; -    m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM; +    m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; -    m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM; +    m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;  } diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.h b/source/Plugins/Process/Utility/RegisterContextDummy.h index ddf4667130480..9f6a8dc347b51 100644 --- a/source/Plugins/Process/Utility/RegisterContextDummy.h +++ b/source/Plugins/Process/Utility/RegisterContextDummy.h @@ -10,8 +10,12 @@  #ifndef lldb_RegisterContextDummy_h_  #define lldb_RegisterContextDummy_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h"  #include "lldb/Symbol/SymbolContext.h" @@ -25,42 +29,39 @@ public:      RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size); -    /// -    // pure virtual functions from the base class that we must implement -    /// +    ~RegisterContextDummy() override; -    virtual -    ~RegisterContextDummy (); +    void +    InvalidateAllRegisters() override; -    virtual void -    InvalidateAllRegisters (); +    size_t +    GetRegisterCount() override; -    virtual size_t -    GetRegisterCount (); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    size_t +    GetRegisterSetCount() override; -    virtual size_t -    GetRegisterSetCount (); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t reg_set); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); - -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  private:      //------------------------------------------------------------------ @@ -72,6 +73,7 @@ private:      DISALLOW_COPY_AND_ASSIGN (RegisterContextDummy);  }; +  } // namespace lldb_private -#endif  // lldb_RegisterContextDummy_h_ +#endif // lldb_RegisterContextDummy_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp index 8005a6339f6d7..a507dad69f602 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp @@ -23,6 +23,7 @@ using namespace lldb_private;  // http://svnweb.freebsd.org/base/head/sys/arm/include/reg.h  #define GPR_OFFSET(idx) ((idx) * 4)  #define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR)) +#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::FPU, fpscr) + sizeof (RegisterContextFreeBSD_arm::GPR))  #define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU))  #define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::DBG, reg) + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU) + sizeof (RegisterContextFreeBSD_arm::EXC))) diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h index c4287e9f0a474..f2d9364b3ce6d 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h @@ -12,7 +12,6 @@  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h" -#include "RegisterContextPOSIX.h"  #include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_arm diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h index 249027aaa76c6..cfdae4d2b557d 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextFreeBSD_arm64_H_  #define liblldb_RegisterContextFreeBSD_arm64_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_arm64:      public lldb_private::RegisterInfoInterface diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h index 62792c02e2b91..9527fc03f7281 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextFreeBSD_i386_H_  #define liblldb_RegisterContextFreeBSD_i386_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_i386    : public lldb_private::RegisterInfoInterface diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h index f9a3ce09c5b19..5c042af20eac3 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextFreeBSD_mips64_H_  #define liblldb_RegisterContextFreeBSD_mips64_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_mips64:      public lldb_private::RegisterInfoInterface diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h index b907fe99b5e05..930683f8a870a 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h @@ -7,17 +7,21 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextFreeBSD_powerpc_H_ -#define liblldb_RegisterContextFreeBSD_powerpc_H_ +#ifndef liblldb_RegisterContextFreeBSD_powerpc_h_ +#define liblldb_RegisterContextFreeBSD_powerpc_h_ -#include "RegisterContextPOSIX.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_powerpc:      public lldb_private::RegisterInfoInterface  {  public:      RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch); -    virtual ~RegisterContextFreeBSD_powerpc(); +    ~RegisterContextFreeBSD_powerpc() override;      size_t      GetGPRSize() const override; @@ -34,7 +38,7 @@ class RegisterContextFreeBSD_powerpc32:  {  public:      RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch); -    virtual ~RegisterContextFreeBSD_powerpc32(); +    ~RegisterContextFreeBSD_powerpc32() override;      size_t      GetGPRSize() const override; @@ -51,7 +55,7 @@ class RegisterContextFreeBSD_powerpc64:  {  public:      RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch); -    virtual ~RegisterContextFreeBSD_powerpc64(); +    ~RegisterContextFreeBSD_powerpc64() override;      size_t      GetGPRSize() const override; @@ -63,4 +67,4 @@ public:      GetRegisterCount() const override;  }; -#endif +#endif // liblldb_RegisterContextFreeBSD_powerpc_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h index 21fbdb4681b3b..e739fa50ed6c5 100644 --- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextFreeBSD_x86_64_H_  #define liblldb_RegisterContextFreeBSD_x86_64_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextFreeBSD_x86_64:      public lldb_private::RegisterInfoInterface diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp index 3c370103629e2..9d2181376e09b 100644 --- a/source/Plugins/Process/Utility/RegisterContextHistory.cpp +++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp @@ -52,10 +52,10 @@ RegisterContext (thread, concrete_frame_idx),      m_pc_reg_info.format = eFormatPointer;      m_pc_reg_info.invalidate_regs = NULL;      m_pc_reg_info.value_regs = NULL; -    m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM; +    m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; -    m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM; +    m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;      m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;  } diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.h b/source/Plugins/Process/Utility/RegisterContextHistory.h index 04842c62aff17..3f44a1fde68bf 100644 --- a/source/Plugins/Process/Utility/RegisterContextHistory.h +++ b/source/Plugins/Process/Utility/RegisterContextHistory.h @@ -10,8 +10,12 @@  #ifndef lldb_RegisterContextHistory_h_  #define lldb_RegisterContextHistory_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h"  #include "lldb/Symbol/SymbolContext.h" @@ -25,42 +29,39 @@ public:      RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, lldb::addr_t pc_value); -    /// -    // pure virtual functions from the base class that we must implement -    /// +    ~RegisterContextHistory() override; -    virtual -    ~RegisterContextHistory (); +    void +    InvalidateAllRegisters() override; -    virtual void -    InvalidateAllRegisters (); +    size_t +    GetRegisterCount() override; -    virtual size_t -    GetRegisterCount (); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    size_t +    GetRegisterSetCount() override; -    virtual size_t -    GetRegisterSetCount (); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t reg_set); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); - -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  private:      //------------------------------------------------------------------ @@ -76,4 +77,4 @@ private:  };  } // namespace lldb_private -#endif  // lldb_RegisterContextHistory_h_ +#endif // lldb_RegisterContextHistory_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index 37b007cfffcfb..278a1d5dabf64 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -17,6 +17,7 @@  #include "lldb/Core/RegisterValue.h"  #include "lldb/Core/Value.h"  #include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ArmUnwindInfo.h"  #include "lldb/Symbol/DWARFCallFrameInfo.h"  #include "lldb/Symbol/FuncUnwinders.h"  #include "lldb/Symbol/Function.h" @@ -634,28 +635,30 @@ bool  RegisterContextLLDB::CheckIfLoopingStack ()  {      // If we have a bad stack setup, we can get the same CFA value multiple times -- or even -    // more devious, we can actually oscillate between two CFA values.  Detect that here and +    // more devious, we can actually oscillate between two CFA values. Detect that here and      // break out to avoid a possible infinite loop in lldb trying to unwind the stack. -    addr_t next_frame_cfa; -    addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; -    if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa)) +    // To detect when we have the same CFA value multiple times, we compare the CFA of the current +    // frame with the 2nd next frame because in some specail case (e.g. signal hanlders, hand +    // written assembly without ABI compiance) we can have 2 frames with the same CFA (in theory we +    // can have arbitrary number of frames with the same CFA, but more then 2 is very very unlikely) + +    RegisterContextLLDB::SharedPtr next_frame = GetNextFrame(); +    if (next_frame)      { -        if (next_frame_cfa == m_cfa) +        RegisterContextLLDB::SharedPtr next_next_frame = next_frame->GetNextFrame(); +        addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS; +        if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa))          { -            // We have a loop in the stack unwind -            return true; -        } -        if (GetNextFrame()->GetNextFrame().get() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa) -            && next_next_frame_cfa == m_cfa) -        { -            // We have a loop in the stack unwind -            return true;  +            if (next_next_frame_cfa == m_cfa) +            { +                // We have a loop in the stack unwind +                return true;  +            }          }      }      return false;  } -  bool  RegisterContextLLDB::IsFrameZero () const  { @@ -792,24 +795,38 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()          func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);      } -    // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer). -    // Try using the eh_frame information relative to the current PC, -    // and finally fall back on the architectural default unwind. +    // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its +    // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). +    // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall +    // back to the architectural default unwind.      if (!func_unwinders_sp)      { -        DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ?  -            pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr; -          m_frame_type = eNormalFrame; -        if (eh_frame && m_current_pc.IsValid()) + +        if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid()) +            return arch_default_unwind_plan_sp; + +        // Even with -fomit-frame-pointer, we can try eh_frame to get back on track. +        DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo(); +        if (eh_frame)          {              unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); -            // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.              if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))                  return unwind_plan_sp;              else                  unwind_plan_sp.reset();          } + +        ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo(); +        if (arm_exidx) +        { +            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); +            if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp)) +                return unwind_plan_sp; +            else +                unwind_plan_sp.reset(); +        } +          return arch_default_unwind_plan_sp;      } @@ -864,12 +881,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()                  // then the architecture default plan and for hand written assembly code it is often                  // written in a way that it valid at all location what helps in the most common                  // cases when the instruction emulation fails. -                UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); -                if (eh_frame_unwind_plan && -                    eh_frame_unwind_plan.get() != unwind_plan_sp.get() && -                    eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) +                UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one); +                if (call_site_unwind_plan && +                    call_site_unwind_plan.get() != unwind_plan_sp.get() && +                    call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())                  { -                    m_fallback_unwind_plan_sp = eh_frame_unwind_plan; +                    m_fallback_unwind_plan_sp = call_site_unwind_plan;                  }                  else                  { @@ -909,12 +926,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()          // more reliable even on non call sites then the architecture default plan and for hand          // written assembly code it is often written in a way that it valid at all location what          // helps in the most common cases when the instruction emulation fails. -        UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one); -        if (eh_frame_unwind_plan && -            eh_frame_unwind_plan.get() != unwind_plan_sp.get() && -            eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName()) +        UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one); +        if (call_site_unwind_plan && +            call_site_unwind_plan.get() != unwind_plan_sp.get() && +            call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())          { -            m_fallback_unwind_plan_sp = eh_frame_unwind_plan; +            m_fallback_unwind_plan_sp = call_site_unwind_plan;          }          else          { @@ -1488,7 +1505,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat                                   unwindplan_regloc.GetDWARFExpressionLength(),                                   process->GetByteOrder(), process->GetAddressByteSize());          ModuleSP opcode_ctx; -        DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength()); +        DWARFExpression dwarfexpr (opcode_ctx, +                                   dwarfdata, +                                   nullptr, +                                   0, +                                   unwindplan_regloc.GetDWARFExpressionLength());          dwarfexpr.SetRegisterKind (unwindplan_registerkind);          Value result;          Error error; @@ -1784,7 +1805,11 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,                                       row->GetCFAValue().GetDWARFExpressionLength(),                                       process->GetByteOrder(), process->GetAddressByteSize());              ModuleSP opcode_ctx; -            DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, row->GetCFAValue().GetDWARFExpressionLength()); +            DWARFExpression dwarfexpr (opcode_ctx, +                                       dwarfdata, +                                       nullptr, +                                       0, +                                       row->GetCFAValue().GetDWARFExpressionLength());              dwarfexpr.SetRegisterKind (row_register_kind);              Value result;              Error error; diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h index 5f94a977448d5..68dca3d4965f6 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.h +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h @@ -10,8 +10,12 @@  #ifndef lldb_RegisterContextLLDB_h_  #define lldb_RegisterContextLLDB_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h"  #include "lldb/Symbol/UnwindPlan.h" @@ -33,42 +37,39 @@ public:                           lldb_private::SymbolContext& sym_ctx,                           uint32_t frame_number, lldb_private::UnwindLLDB& unwind_lldb); -    /// -    // pure virtual functions from the base class that we must implement -    /// - -    virtual -    ~RegisterContextLLDB () { } +    ~RegisterContextLLDB() override = default; -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t reg_set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;      bool      IsValid () const; @@ -99,7 +100,6 @@ private:      // UnwindLLDB needs to pass around references to RegisterLocations      friend class UnwindLLDB; -      // Returns true if we have an unwind loop -- the same stack frame unwinding       // multiple times.      bool @@ -130,7 +130,6 @@ private:      bool      IsSkipFrame () const; -      //------------------------------------------------------------------      /// Determines if a SymbolContext is a trap handler or not      /// @@ -221,7 +220,6 @@ private:      bool      IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset); -      lldb_private::Thread& m_thread;      /// @@ -269,4 +267,4 @@ private:  } // namespace lldb_private -#endif  // lldb_RegisterContextLLDB_h_ +#endif // lldb_RegisterContextLLDB_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp index e7784b1712c34..f8d97aa3482cc 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp @@ -22,6 +22,7 @@ using namespace lldb_private;  // Based on RegisterContextDarwin_arm.cpp  #define GPR_OFFSET(idx) ((idx) * 4)  #define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR)) +#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextLinux_arm::FPU, fpscr) + sizeof (RegisterContextLinux_arm::GPR))  #define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU))  #define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextLinux_arm::DBG, reg) + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC))) diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm.h index 7087eb4c3dcc2..c3d41f686dcda 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm.h @@ -12,7 +12,6 @@  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h" -#include "RegisterContextPOSIX.h"  #include "RegisterInfoInterface.h"  class RegisterContextLinux_arm diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp index 8c23e39ff013b..a4ab083995f69 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp @@ -21,7 +21,7 @@  #define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::GPR, reg))  #define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextLinux_arm64::GPR)) -#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg)) +#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg) + sizeof (RegisterContextLinux_arm64::GPR))  #define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::EXC, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU))  #define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::DBG, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC)) diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h index a9a5a0985f25b..3de94b8625835 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h @@ -12,7 +12,6 @@  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h" -#include "RegisterContextPOSIX.h"  #include "RegisterInfoInterface.h"  class RegisterContextLinux_arm64 diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp index 4f6bbc8f8ab83..e39beef428884 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp @@ -26,7 +26,7 @@ struct GPR      uint32_t es;      uint32_t fs;      uint32_t gs; -    uint32_t orig_ax; +    uint32_t orig_eax;      uint32_t eip;      uint32_t cs;      uint32_t eflags; @@ -38,7 +38,8 @@ struct FPR_i386  {      uint16_t fctrl;         // FPU Control Word (fcw)      uint16_t fstat;         // FPU Status Word (fsw) -    uint16_t ftag;          // FPU Tag Word (ftw) +    uint8_t ftag;           // FPU Tag Word (ftw) +    uint8_t reserved_1;     // Reserved      uint16_t fop;           // Last Instruction Opcode (fop)      union      { @@ -98,6 +99,9 @@ struct UserArea  RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) :      RegisterInfoInterface(target_arch)  { +    RegisterInfo orig_ax = { "orig_eax", NULL, sizeof(((GPR*)NULL)->orig_eax), (LLVM_EXTENSION offsetof(GPR, orig_eax)), eEncodingUint, \ +              eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }; +    d_register_infos.push_back(orig_ax);  }  size_t @@ -131,3 +135,9 @@ RegisterContextLinux_i386::GetUserRegisterCount () const  {      return static_cast<uint32_t> (k_num_user_registers_i386);  } + +const std::vector<lldb_private::RegisterInfo> * +RegisterContextLinux_i386::GetDynamicRegisterInfoP() const +{ +    return &d_register_infos; +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h index cb71d7993e172..6c4768f49ac11 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextLinux_i386_H_  #define liblldb_RegisterContextLinux_i386_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextLinux_i386    : public lldb_private::RegisterInfoInterface @@ -29,6 +29,12 @@ public:      uint32_t      GetUserRegisterCount () const override; + +    const std::vector<lldb_private::RegisterInfo> * +    GetDynamicRegisterInfoP() const override; + +private: +    std::vector<lldb_private::RegisterInfo> d_register_infos;  };  #endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp index 4d58b85b56657..1b2281004d267 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp @@ -10,7 +10,7 @@  #include <vector>  #include <stddef.h> -// For GDB, GCC and DWARF Register numbers +// For eh_frame and DWARF Register numbers  #include "RegisterContextLinux_mips.h"  // Internal codes for mips registers @@ -29,8 +29,17 @@ using namespace lldb;  #include "RegisterInfos_mips.h"  #undef DECLARE_REGISTER_INFOS_MIPS_STRUCT -RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch) : -    RegisterInfoInterface(target_arch) +uint32_t +GetUserRegisterInfoCount (bool msa_present) +{ +    if (msa_present) +        return static_cast<uint32_t> (k_num_user_registers_mips); +    return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips); +} + +RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch, bool msa_present) : +    RegisterInfoInterface(target_arch), +    m_user_register_count (GetUserRegisterInfoCount (msa_present))  {  } @@ -63,5 +72,5 @@ RegisterContextLinux_mips::GetRegisterCount () const  uint32_t  RegisterContextLinux_mips::GetUserRegisterCount () const  { -    return static_cast<uint32_t> (k_num_user_registers_mips); +    return static_cast<uint32_t> (m_user_register_count);  } diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h index bcc2d002c8546..c0bd5ad4f4f9f 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h @@ -17,7 +17,7 @@ class RegisterContextLinux_mips      : public lldb_private::RegisterInfoInterface  {  public: -    RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch); +    RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, bool msa_present = true);      size_t      GetGPRSize() const override; @@ -30,6 +30,9 @@ public:      uint32_t      GetUserRegisterCount () const override; + +private: +    uint32_t m_user_register_count;  };  #endif diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp index 7f512f82be803..f2871e3b7352d 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp @@ -12,7 +12,7 @@  #include <vector>  #include <stddef.h> -// For GDB, GCC and DWARF Register numbers +// For eh_frame and DWARF Register numbers  #include "RegisterContextLinux_mips64.h"  // For GP and FP buffers @@ -75,27 +75,31 @@ GetRegisterInfoCount (const ArchSpec &target_arch)  }  uint32_t -GetUserRegisterInfoCount (const ArchSpec &target_arch) +GetUserRegisterInfoCount (const ArchSpec &target_arch, bool msa_present)  {      switch (target_arch.GetMachine())      {          case llvm::Triple::mips:          case llvm::Triple::mipsel: -            return static_cast<uint32_t> (k_num_user_registers_mips); +            if (msa_present) +                return static_cast<uint32_t> (k_num_user_registers_mips); +            return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips);           case llvm::Triple::mips64el:          case llvm::Triple::mips64: -            return static_cast<uint32_t> (k_num_user_registers_mips64); +            if (msa_present) +                return static_cast<uint32_t> (k_num_user_registers_mips64); +            return static_cast<uint32_t> (k_num_user_registers_mips64 - k_num_msa_registers_mips64);          default:              assert(false && "Unhandled target architecture.");              return 0;      }  } -RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch) : +RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch, bool msa_present) :      lldb_private::RegisterInfoInterface(target_arch),      m_register_info_p (GetRegisterInfoPtr (target_arch)),      m_register_info_count (GetRegisterInfoCount (target_arch)), -    m_user_register_count (GetUserRegisterInfoCount (target_arch)) +    m_user_register_count (GetUserRegisterInfoCount (target_arch, msa_present))  {  } diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h index 86c662c52cea3..843328c92e43d 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h @@ -19,7 +19,7 @@ class RegisterContextLinux_mips64      : public lldb_private::RegisterInfoInterface  {  public: -    RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch); +    RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, bool msa_present = true);      size_t      GetGPRSize() const override; diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp index c0993b47a1265..78afe72fcfa95 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp @@ -32,7 +32,7 @@ typedef struct _GPR      uint64_t rdx;      uint64_t rsi;      uint64_t rdi; -    uint64_t orig_ax; +    uint64_t orig_rax;      uint64_t rip;      uint64_t cs;      uint64_t rflags; @@ -171,6 +171,9 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_      m_register_info_count (GetRegisterInfoCount (target_arch)),      m_user_register_count (GetUserRegisterInfoCount (target_arch))  { +    RegisterInfo orig_ax = { "orig_rax", NULL, sizeof(((GPR*)NULL)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, \ +              eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }; +    d_register_infos.push_back(orig_ax);  }  size_t @@ -179,6 +182,12 @@ RegisterContextLinux_x86_64::GetGPRSize() const      return sizeof(GPR);  } +const std::vector<lldb_private::RegisterInfo> * +RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const +{ +    return &d_register_infos; +} +  const RegisterInfo *  RegisterContextLinux_x86_64::GetRegisterInfo() const  { diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h index 0cdfae9ac9438..ed0b7de9aae8b 100644 --- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h @@ -10,7 +10,7 @@  #ifndef liblldb_RegisterContextLinux_x86_64_H_  #define liblldb_RegisterContextLinux_x86_64_H_ -#include "RegisterContextPOSIX.h" +#include "RegisterInfoInterface.h"  class RegisterContextLinux_x86_64      : public lldb_private::RegisterInfoInterface @@ -30,10 +30,15 @@ public:      uint32_t      GetUserRegisterCount () const override; +    const std::vector<lldb_private::RegisterInfo> * +    GetDynamicRegisterInfoP() const override; +  private:      const lldb_private::RegisterInfo *m_register_info_p;      uint32_t m_register_info_count;      uint32_t m_user_register_count; +    std::vector<lldb_private::RegisterInfo> d_register_infos; +  };  #endif diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h index 505b8d44a27a3..0ddadbed01e0b 100644 --- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h +++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h @@ -22,56 +22,49 @@  class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread,                                           uint32_t concrete_frame_idx,                                           const UnwindMacOSXFrameBackchain::Cursor &cursor); -    virtual -    ~RegisterContextMacOSXFrameBackchain (); +    ~RegisterContextMacOSXFrameBackchain() override; -    //------------------------------------------------------------------ -    // Subclasses must override these functions -    //------------------------------------------------------------------ -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t reg_set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  private:      UnwindMacOSXFrameBackchain::Cursor m_cursor;      bool m_cursor_is_valid; -    //------------------------------------------------------------------ -    // For RegisterContextMacOSXFrameBackchain only -    //------------------------------------------------------------------ +      DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain);  }; -#endif  // lldb_RegisterContextMacOSXFrameBackchain_h_ +#endif // lldb_RegisterContextMacOSXFrameBackchain_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h index 9d97dfa723beb..d61aba9543d47 100644 --- a/source/Plugins/Process/Utility/RegisterContextMemory.h +++ b/source/Plugins/Process/Utility/RegisterContextMemory.h @@ -25,39 +25,31 @@ class DynamicRegisterInfo;  class RegisterContextMemory : public lldb_private::RegisterContext  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      RegisterContextMemory (lldb_private::Thread &thread,                              uint32_t concrete_frame_idx,                              DynamicRegisterInfo ®_info,                              lldb::addr_t reg_data_addr); -    virtual -    ~RegisterContextMemory (); +    ~RegisterContextMemory() override; -    //------------------------------------------------------------------ -    // Subclasses must override these functions -    //------------------------------------------------------------------ -    virtual void -    InvalidateAllRegisters (); +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const lldb_private::RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const lldb_private::RegisterSet * -    GetRegisterSet (size_t reg_set); +    const lldb_private::RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -          //------------------------------------------------------------------      // If all of the thread register are in a contiguous buffer in       // memory, then the default ReadRegister/WriteRegister and @@ -66,24 +58,24 @@ public:      // class and modify the read/write functions as needed.      //------------------------------------------------------------------ -    virtual bool -    ReadRegister (const lldb_private::RegisterInfo *reg_info,  -                  lldb_private::RegisterValue ®_value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue ®_value) override; -    virtual bool -    WriteRegister (const lldb_private::RegisterInfo *reg_info,  -                   const lldb_private::RegisterValue ®_value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue ®_value) override; -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      void      SetAllRegisterData  (const lldb::DataBufferSP &data_sp); +  protected: -          void      SetAllRegisterValid (bool b); @@ -93,10 +85,7 @@ protected:      lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory  private: -    //------------------------------------------------------------------ -    // For RegisterContextMemory only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory);  }; -#endif  // lldb_RegisterContextMemory_h_ +#endif // lldb_RegisterContextMemory_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp index d306f86256bc3..029a0e7352ec5 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp @@ -88,6 +88,54 @@ static const uint32_t g_fpu_regnums_arm[] =      fpu_s30_arm,      fpu_s31_arm,      fpu_fpscr_arm, +    fpu_d0_arm, +    fpu_d1_arm, +    fpu_d2_arm, +    fpu_d3_arm, +    fpu_d4_arm, +    fpu_d5_arm, +    fpu_d6_arm, +    fpu_d7_arm, +    fpu_d8_arm, +    fpu_d9_arm, +    fpu_d10_arm, +    fpu_d11_arm, +    fpu_d12_arm, +    fpu_d13_arm, +    fpu_d14_arm, +    fpu_d15_arm, +    fpu_d16_arm, +    fpu_d17_arm, +    fpu_d18_arm, +    fpu_d19_arm, +    fpu_d20_arm, +    fpu_d21_arm, +    fpu_d22_arm, +    fpu_d23_arm, +    fpu_d24_arm, +    fpu_d25_arm, +    fpu_d26_arm, +    fpu_d27_arm, +    fpu_d28_arm, +    fpu_d29_arm, +    fpu_d30_arm, +    fpu_d31_arm, +    fpu_q0_arm, +    fpu_q1_arm, +    fpu_q2_arm, +    fpu_q3_arm, +    fpu_q4_arm, +    fpu_q5_arm, +    fpu_q6_arm, +    fpu_q7_arm, +    fpu_q8_arm, +    fpu_q9_arm, +    fpu_q10_arm, +    fpu_q11_arm, +    fpu_q12_arm, +    fpu_q13_arm, +    fpu_q14_arm, +    fpu_q15_arm,      LLDB_INVALID_REGNUM // register sets need to end with this flag  }; diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h index a3a2926262f70..fbbcb94029112 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_arm.h ----------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_arm.h ------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,12 +7,17 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_arm_H_ -#define liblldb_RegisterContextPOSIX_arm_H_ +#ifndef liblldb_RegisterContextPOSIX_arm_h_ +#define liblldb_RegisterContextPOSIX_arm_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" +#include "RegisterInfoInterface.h"  #include "lldb-arm-register-enums.h" -#include "RegisterContextPOSIX.h"  class ProcessMonitor; @@ -24,16 +29,16 @@ public:                              uint32_t concrete_frame_idx,                              lldb_private::RegisterInfoInterface *register_info); -    ~RegisterContextPOSIX_arm(); +    ~RegisterContextPOSIX_arm() override;      void      Invalidate();      void -    InvalidateAllRegisters(); +    InvalidateAllRegisters() override;      size_t -    GetRegisterCount(); +    GetRegisterCount() override;      virtual size_t      GetGPRSize(); @@ -45,19 +50,19 @@ public:      GetRegisterOffset(unsigned reg);      const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex(size_t reg); +    GetRegisterInfoAtIndex(size_t reg) override;      size_t -    GetRegisterSetCount(); +    GetRegisterSetCount() override;      const lldb_private::RegisterSet * -    GetRegisterSet(size_t set); +    GetRegisterSet(size_t set) override;      const char *      GetRegisterName(unsigned reg);      uint32_t -    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  protected:      struct RegInfo @@ -117,5 +122,4 @@ protected:      virtual bool WriteFPR() = 0;  }; -#endif // #ifndef liblldb_RegisterContextPOSIX_arm_H_ - +#endif // liblldb_RegisterContextPOSIX_arm_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index 29e7a7d21e023..225d4f25168ef 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -7,12 +7,17 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_arm64_H_ -#define liblldb_RegisterContextPOSIX_arm64_H_ +#ifndef liblldb_RegisterContextPOSIX_arm64_h_ +#define liblldb_RegisterContextPOSIX_arm64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Log.h" +#include "lldb/Target/RegisterContext.h" +#include "RegisterInfoInterface.h"  #include "lldb-arm64-register-enums.h" -#include "RegisterContextPOSIX.h"  class ProcessMonitor; @@ -24,16 +29,16 @@ public:                              uint32_t concrete_frame_idx,                              lldb_private::RegisterInfoInterface *register_info); -    ~RegisterContextPOSIX_arm64(); +    ~RegisterContextPOSIX_arm64() override;      void      Invalidate();      void -    InvalidateAllRegisters(); +    InvalidateAllRegisters() override;      size_t -    GetRegisterCount(); +    GetRegisterCount() override;      virtual size_t      GetGPRSize(); @@ -45,19 +50,19 @@ public:      GetRegisterOffset(unsigned reg);      const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex(size_t reg); +    GetRegisterInfoAtIndex(size_t reg) override;      size_t -    GetRegisterSetCount(); +    GetRegisterSetCount() override;      const lldb_private::RegisterSet * -    GetRegisterSet(size_t set); +    GetRegisterSet(size_t set) override;      const char *      GetRegisterName(unsigned reg);      uint32_t -    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  protected:      struct RegInfo @@ -116,4 +121,4 @@ protected:      virtual bool WriteFPR() = 0;  }; -#endif // #ifndef liblldb_RegisterContextPOSIX_arm64_H_ +#endif // liblldb_RegisterContextPOSIX_arm64_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h index 612a034669831..07552d8d681d1 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h @@ -7,11 +7,16 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_mips64_H_ -#define liblldb_RegisterContextPOSIX_mips64_H_ +#ifndef liblldb_RegisterContextPOSIX_mips64_h_ +#define liblldb_RegisterContextPOSIX_mips64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Log.h" -#include "RegisterContextPOSIX.h" +#include "lldb/Target/RegisterContext.h" +#include "RegisterInfoInterface.h"  #include "RegisterContext_mips.h"  #include "lldb-mips-freebsd-register-enums.h" @@ -27,16 +32,16 @@ public:                              uint32_t concrete_frame_idx,                              lldb_private::RegisterInfoInterface *register_info); -    ~RegisterContextPOSIX_mips64(); +    ~RegisterContextPOSIX_mips64() override;      void      Invalidate();      void -    InvalidateAllRegisters(); +    InvalidateAllRegisters() override;      size_t -    GetRegisterCount(); +    GetRegisterCount() override;      virtual size_t      GetGPRSize(); @@ -48,19 +53,19 @@ public:      GetRegisterOffset(unsigned reg);      const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex(size_t reg); +    GetRegisterInfoAtIndex(size_t reg) override;      size_t -    GetRegisterSetCount(); +    GetRegisterSetCount() override;      const lldb_private::RegisterSet * -    GetRegisterSet(size_t set); +    GetRegisterSet(size_t set) override;      const char *      GetRegisterName(unsigned reg);      uint32_t -    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  protected:      uint64_t m_gpr_mips64[k_num_gpr_registers_mips64];         // general purpose registers. @@ -87,4 +92,4 @@ protected:      virtual bool WriteFPR() = 0;  }; -#endif // #ifndef liblldb_RegisterContextPOSIX_mips64_H_ +#endif // liblldb_RegisterContextPOSIX_mips64_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h index c7a2451d7811c..4168e46ebd9a5 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h @@ -1,4 +1,4 @@ -//===-- RegisterContextPOSIX_powerpc.h ---------------------------*- C++ -*-===// +//===-- RegisterContextPOSIX_powerpc.h --------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,11 +7,16 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_powerpc_H_ -#define liblldb_RegisterContextPOSIX_powerpc_H_ +#ifndef liblldb_RegisterContextPOSIX_powerpc_h_ +#define liblldb_RegisterContextPOSIX_powerpc_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Log.h" -#include "RegisterContextPOSIX.h" +#include "lldb/Target/RegisterContext.h" +#include "RegisterInfoInterface.h"  #include "RegisterContext_powerpc.h"  class ProcessMonitor; @@ -148,16 +153,16 @@ public:                              uint32_t concrete_frame_idx,                              lldb_private::RegisterInfoInterface *register_info); -    ~RegisterContextPOSIX_powerpc(); +    ~RegisterContextPOSIX_powerpc() override;      void      Invalidate();      void -    InvalidateAllRegisters(); +    InvalidateAllRegisters() override;      size_t -    GetRegisterCount(); +    GetRegisterCount() override;      virtual size_t      GetGPRSize(); @@ -169,19 +174,19 @@ public:      GetRegisterOffset(unsigned reg);      const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex(size_t reg); +    GetRegisterInfoAtIndex(size_t reg) override;      size_t -    GetRegisterSetCount(); +    GetRegisterSetCount() override;      const lldb_private::RegisterSet * -    GetRegisterSet(size_t set); +    GetRegisterSet(size_t set) override;      const char *      GetRegisterName(unsigned reg);      uint32_t -    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;  protected:      uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc];         // general purpose registers. @@ -215,4 +220,4 @@ protected:      virtual bool WriteVMX() = 0;  }; -#endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_ +#endif // liblldb_RegisterContextPOSIX_powerpc_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h index 0eec1d909c1ac..b4708255a5660 100644 --- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h @@ -7,13 +7,18 @@  //  //===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextPOSIX_x86_H_ -#define liblldb_RegisterContextPOSIX_x86_H_ +#ifndef liblldb_RegisterContextPOSIX_x86_h_ +#define liblldb_RegisterContextPOSIX_x86_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/Log.h" -#include "lldb-x86-register-enums.h" -#include "RegisterContextPOSIX.h" +#include "lldb/Target/RegisterContext.h" +#include "RegisterInfoInterface.h"  #include "RegisterContext_x86.h" +#include "lldb-x86-register-enums.h"  class ProcessMonitor; @@ -25,16 +30,16 @@ public:                              uint32_t concrete_frame_idx,                              lldb_private::RegisterInfoInterface *register_info); -    ~RegisterContextPOSIX_x86(); +    ~RegisterContextPOSIX_x86() override;      void      Invalidate();      void -    InvalidateAllRegisters(); +    InvalidateAllRegisters() override;      size_t -    GetRegisterCount(); +    GetRegisterCount() override;      virtual size_t      GetGPRSize(); @@ -46,19 +51,19 @@ public:      GetRegisterOffset(unsigned reg);      const lldb_private::RegisterInfo * -    GetRegisterInfoAtIndex(size_t reg); +    GetRegisterInfoAtIndex(size_t reg) override;      size_t -    GetRegisterSetCount(); +    GetRegisterSetCount() override;      const lldb_private::RegisterSet * -    GetRegisterSet(size_t set); +    GetRegisterSet(size_t set) override;      const char *      GetRegisterName(unsigned reg);      uint32_t -    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num); +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;      //---------------------------------------------------------------------------      // Note: prefer kernel definitions over user-land @@ -186,4 +191,4 @@ protected:      virtual bool WriteFPR() = 0;  }; -#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_ +#endif // liblldb_RegisterContextPOSIX_x86_h_ diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h index 161ef040e651a..b4680de795144 100644 --- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h +++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h @@ -10,8 +10,12 @@  #ifndef lldb_RegisterContextThreadMemory_h_  #define lldb_RegisterContextThreadMemory_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/RegisterContext.h"  #include "lldb/Symbol/SymbolContext.h" @@ -24,30 +28,28 @@ public:      RegisterContextThreadMemory (Thread &thread,                                   lldb::addr_t register_data_addr); -    virtual ~RegisterContextThreadMemory(); -    //------------------------------------------------------------------ -    // Subclasses must override these functions -    //------------------------------------------------------------------ -    virtual void -    InvalidateAllRegisters (); +    ~RegisterContextThreadMemory() override; + +    void +    InvalidateAllRegisters() override; -    virtual size_t -    GetRegisterCount (); +    size_t +    GetRegisterCount() override; -    virtual const RegisterInfo * -    GetRegisterInfoAtIndex (size_t reg); +    const RegisterInfo * +    GetRegisterInfoAtIndex(size_t reg) override; -    virtual size_t -    GetRegisterSetCount (); +    size_t +    GetRegisterSetCount() override; -    virtual const RegisterSet * -    GetRegisterSet (size_t reg_set); +    const RegisterSet * +    GetRegisterSet(size_t reg_set) override; -    virtual bool -    ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value); +    bool +    ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; -    virtual bool -    WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value); +    bool +    WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override;      // These two functions are used to implement "push" and "pop" of register states.  They are used primarily      // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then @@ -56,48 +58,50 @@ public:      // may mean e.g. interrupting a thread that is sitting in a kernel trap.  That is a somewhat disruptive operation,      // so these API's should only be used when this behavior is needed. -    virtual bool -    ReadAllRegisterValues (lldb::DataBufferSP &data_sp); +    bool +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; -    virtual bool -    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp); +    bool +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool      CopyFromRegisterContext (lldb::RegisterContextSP context); -    virtual uint32_t -    ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num); -     -    //------------------------------------------------------------------ -    // Subclasses can override these functions if desired -    //------------------------------------------------------------------ -    virtual uint32_t -    NumSupportedHardwareBreakpoints (); -     -    virtual uint32_t -    SetHardwareBreakpoint (lldb::addr_t addr, size_t size); +    uint32_t +    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; -    virtual bool -    ClearHardwareBreakpoint (uint32_t hw_idx); +    uint32_t +    NumSupportedHardwareBreakpoints() override; -    virtual uint32_t -    NumSupportedHardwareWatchpoints (); +    uint32_t +    SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; -    virtual uint32_t -    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); -     -    virtual bool -    ClearHardwareWatchpoint (uint32_t hw_index); +    bool +    ClearHardwareBreakpoint(uint32_t hw_idx) override; -    virtual bool -    HardwareSingleStep (bool enable); +    uint32_t +    NumSupportedHardwareWatchpoints() override; -    virtual Error -    ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value); +    uint32_t +    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override; -    virtual Error -    WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value); +    bool +    ClearHardwareWatchpoint(uint32_t hw_index) override; +    bool +    HardwareSingleStep(bool enable) override; +     +    Error +    ReadRegisterValueFromMemory(const lldb_private::RegisterInfo *reg_info, +                                lldb::addr_t src_addr, +                                uint32_t src_len, +                                RegisterValue ®_value) override; +     +    Error +    WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info, +                               lldb::addr_t dst_addr, uint32_t dst_len, +                               const RegisterValue ®_value) override; +  protected:      void      UpdateRegisterContext (); @@ -106,9 +110,11 @@ protected:      lldb::RegisterContextSP m_reg_ctx_sp;      lldb::addr_t m_register_data_addr;      uint32_t m_stop_id; +  private:      DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory);  }; +  } // namespace lldb_private -#endif  // lldb_RegisterContextThreadMemory_h_ +#endif // lldb_RegisterContextThreadMemory_h_ diff --git a/source/Plugins/Process/Utility/RegisterContext_mips.h b/source/Plugins/Process/Utility/RegisterContext_mips.h index de2b4d6dcceee..3603227d5e73c 100644 --- a/source/Plugins/Process/Utility/RegisterContext_mips.h +++ b/source/Plugins/Process/Utility/RegisterContext_mips.h @@ -15,455 +15,228 @@  enum  {      // GP Registers -    gcc_dwarf_zero_mips = 0, -    gcc_dwarf_r1_mips, -    gcc_dwarf_r2_mips, -    gcc_dwarf_r3_mips, -    gcc_dwarf_r4_mips, -    gcc_dwarf_r5_mips, -    gcc_dwarf_r6_mips, -    gcc_dwarf_r7_mips, -    gcc_dwarf_r8_mips, -    gcc_dwarf_r9_mips, -    gcc_dwarf_r10_mips, -    gcc_dwarf_r11_mips, -    gcc_dwarf_r12_mips, -    gcc_dwarf_r13_mips, -    gcc_dwarf_r14_mips, -    gcc_dwarf_r15_mips, -    gcc_dwarf_r16_mips, -    gcc_dwarf_r17_mips, -    gcc_dwarf_r18_mips, -    gcc_dwarf_r19_mips, -    gcc_dwarf_r20_mips, -    gcc_dwarf_r21_mips, -    gcc_dwarf_r22_mips, -    gcc_dwarf_r23_mips, -    gcc_dwarf_r24_mips, -    gcc_dwarf_r25_mips, -    gcc_dwarf_r26_mips, -    gcc_dwarf_r27_mips, -    gcc_dwarf_gp_mips, -    gcc_dwarf_sp_mips, -    gcc_dwarf_r30_mips, -    gcc_dwarf_ra_mips, -    gcc_dwarf_sr_mips, -    gcc_dwarf_lo_mips, -    gcc_dwarf_hi_mips, -    gcc_dwarf_bad_mips, -    gcc_dwarf_cause_mips, -    gcc_dwarf_pc_mips, -    gcc_dwarf_f0_mips, -    gcc_dwarf_f1_mips, -    gcc_dwarf_f2_mips, -    gcc_dwarf_f3_mips, -    gcc_dwarf_f4_mips, -    gcc_dwarf_f5_mips, -    gcc_dwarf_f6_mips, -    gcc_dwarf_f7_mips, -    gcc_dwarf_f8_mips, -    gcc_dwarf_f9_mips, -    gcc_dwarf_f10_mips, -    gcc_dwarf_f11_mips, -    gcc_dwarf_f12_mips, -    gcc_dwarf_f13_mips, -    gcc_dwarf_f14_mips, -    gcc_dwarf_f15_mips, -    gcc_dwarf_f16_mips, -    gcc_dwarf_f17_mips, -    gcc_dwarf_f18_mips, -    gcc_dwarf_f19_mips, -    gcc_dwarf_f20_mips, -    gcc_dwarf_f21_mips, -    gcc_dwarf_f22_mips, -    gcc_dwarf_f23_mips, -    gcc_dwarf_f24_mips, -    gcc_dwarf_f25_mips, -    gcc_dwarf_f26_mips, -    gcc_dwarf_f27_mips, -    gcc_dwarf_f28_mips, -    gcc_dwarf_f29_mips, -    gcc_dwarf_f30_mips, -    gcc_dwarf_f31_mips, -    gcc_dwarf_fcsr_mips, -    gcc_dwarf_fir_mips, -    gcc_dwarf_w0_mips, -    gcc_dwarf_w1_mips, -    gcc_dwarf_w2_mips, -    gcc_dwarf_w3_mips, -    gcc_dwarf_w4_mips, -    gcc_dwarf_w5_mips, -    gcc_dwarf_w6_mips, -    gcc_dwarf_w7_mips, -    gcc_dwarf_w8_mips, -    gcc_dwarf_w9_mips, -    gcc_dwarf_w10_mips, -    gcc_dwarf_w11_mips, -    gcc_dwarf_w12_mips, -    gcc_dwarf_w13_mips, -    gcc_dwarf_w14_mips, -    gcc_dwarf_w15_mips, -    gcc_dwarf_w16_mips, -    gcc_dwarf_w17_mips, -    gcc_dwarf_w18_mips, -    gcc_dwarf_w19_mips, -    gcc_dwarf_w20_mips, -    gcc_dwarf_w21_mips, -    gcc_dwarf_w22_mips, -    gcc_dwarf_w23_mips, -    gcc_dwarf_w24_mips, -    gcc_dwarf_w25_mips, -    gcc_dwarf_w26_mips, -    gcc_dwarf_w27_mips, -    gcc_dwarf_w28_mips, -    gcc_dwarf_w29_mips, -    gcc_dwarf_w30_mips, -    gcc_dwarf_w31_mips, -    gcc_dwarf_mcsr_mips, -    gcc_dwarf_mir_mips, -    gcc_dwarf_config5_mips, -    gcc_dwarf_ic_mips, -    gcc_dwarf_dummy_mips +    dwarf_zero_mips = 0, +    dwarf_r1_mips, +    dwarf_r2_mips, +    dwarf_r3_mips, +    dwarf_r4_mips, +    dwarf_r5_mips, +    dwarf_r6_mips, +    dwarf_r7_mips, +    dwarf_r8_mips, +    dwarf_r9_mips, +    dwarf_r10_mips, +    dwarf_r11_mips, +    dwarf_r12_mips, +    dwarf_r13_mips, +    dwarf_r14_mips, +    dwarf_r15_mips, +    dwarf_r16_mips, +    dwarf_r17_mips, +    dwarf_r18_mips, +    dwarf_r19_mips, +    dwarf_r20_mips, +    dwarf_r21_mips, +    dwarf_r22_mips, +    dwarf_r23_mips, +    dwarf_r24_mips, +    dwarf_r25_mips, +    dwarf_r26_mips, +    dwarf_r27_mips, +    dwarf_gp_mips, +    dwarf_sp_mips, +    dwarf_r30_mips, +    dwarf_ra_mips, +    dwarf_sr_mips, +    dwarf_lo_mips, +    dwarf_hi_mips, +    dwarf_bad_mips, +    dwarf_cause_mips, +    dwarf_pc_mips, +    dwarf_f0_mips, +    dwarf_f1_mips, +    dwarf_f2_mips, +    dwarf_f3_mips, +    dwarf_f4_mips, +    dwarf_f5_mips, +    dwarf_f6_mips, +    dwarf_f7_mips, +    dwarf_f8_mips, +    dwarf_f9_mips, +    dwarf_f10_mips, +    dwarf_f11_mips, +    dwarf_f12_mips, +    dwarf_f13_mips, +    dwarf_f14_mips, +    dwarf_f15_mips, +    dwarf_f16_mips, +    dwarf_f17_mips, +    dwarf_f18_mips, +    dwarf_f19_mips, +    dwarf_f20_mips, +    dwarf_f21_mips, +    dwarf_f22_mips, +    dwarf_f23_mips, +    dwarf_f24_mips, +    dwarf_f25_mips, +    dwarf_f26_mips, +    dwarf_f27_mips, +    dwarf_f28_mips, +    dwarf_f29_mips, +    dwarf_f30_mips, +    dwarf_f31_mips, +    dwarf_fcsr_mips, +    dwarf_fir_mips, +    dwarf_w0_mips, +    dwarf_w1_mips, +    dwarf_w2_mips, +    dwarf_w3_mips, +    dwarf_w4_mips, +    dwarf_w5_mips, +    dwarf_w6_mips, +    dwarf_w7_mips, +    dwarf_w8_mips, +    dwarf_w9_mips, +    dwarf_w10_mips, +    dwarf_w11_mips, +    dwarf_w12_mips, +    dwarf_w13_mips, +    dwarf_w14_mips, +    dwarf_w15_mips, +    dwarf_w16_mips, +    dwarf_w17_mips, +    dwarf_w18_mips, +    dwarf_w19_mips, +    dwarf_w20_mips, +    dwarf_w21_mips, +    dwarf_w22_mips, +    dwarf_w23_mips, +    dwarf_w24_mips, +    dwarf_w25_mips, +    dwarf_w26_mips, +    dwarf_w27_mips, +    dwarf_w28_mips, +    dwarf_w29_mips, +    dwarf_w30_mips, +    dwarf_w31_mips, +    dwarf_mcsr_mips, +    dwarf_mir_mips, +    dwarf_config5_mips, +    dwarf_ic_mips, +    dwarf_dummy_mips  };  enum  { -    gcc_dwarf_zero_mips64 = 0, -    gcc_dwarf_r1_mips64, -    gcc_dwarf_r2_mips64, -    gcc_dwarf_r3_mips64, -    gcc_dwarf_r4_mips64, -    gcc_dwarf_r5_mips64, -    gcc_dwarf_r6_mips64, -    gcc_dwarf_r7_mips64, -    gcc_dwarf_r8_mips64, -    gcc_dwarf_r9_mips64, -    gcc_dwarf_r10_mips64, -    gcc_dwarf_r11_mips64, -    gcc_dwarf_r12_mips64, -    gcc_dwarf_r13_mips64, -    gcc_dwarf_r14_mips64, -    gcc_dwarf_r15_mips64, -    gcc_dwarf_r16_mips64, -    gcc_dwarf_r17_mips64, -    gcc_dwarf_r18_mips64, -    gcc_dwarf_r19_mips64, -    gcc_dwarf_r20_mips64, -    gcc_dwarf_r21_mips64, -    gcc_dwarf_r22_mips64, -    gcc_dwarf_r23_mips64, -    gcc_dwarf_r24_mips64, -    gcc_dwarf_r25_mips64, -    gcc_dwarf_r26_mips64, -    gcc_dwarf_r27_mips64, -    gcc_dwarf_gp_mips64, -    gcc_dwarf_sp_mips64, -    gcc_dwarf_r30_mips64, -    gcc_dwarf_ra_mips64, -    gcc_dwarf_sr_mips64, -    gcc_dwarf_lo_mips64, -    gcc_dwarf_hi_mips64, -    gcc_dwarf_bad_mips64, -    gcc_dwarf_cause_mips64, -    gcc_dwarf_pc_mips64, -    gcc_dwarf_f0_mips64, -    gcc_dwarf_f1_mips64, -    gcc_dwarf_f2_mips64, -    gcc_dwarf_f3_mips64, -    gcc_dwarf_f4_mips64, -    gcc_dwarf_f5_mips64, -    gcc_dwarf_f6_mips64, -    gcc_dwarf_f7_mips64, -    gcc_dwarf_f8_mips64, -    gcc_dwarf_f9_mips64, -    gcc_dwarf_f10_mips64, -    gcc_dwarf_f11_mips64, -    gcc_dwarf_f12_mips64, -    gcc_dwarf_f13_mips64, -    gcc_dwarf_f14_mips64, -    gcc_dwarf_f15_mips64, -    gcc_dwarf_f16_mips64, -    gcc_dwarf_f17_mips64, -    gcc_dwarf_f18_mips64, -    gcc_dwarf_f19_mips64, -    gcc_dwarf_f20_mips64, -    gcc_dwarf_f21_mips64, -    gcc_dwarf_f22_mips64, -    gcc_dwarf_f23_mips64, -    gcc_dwarf_f24_mips64, -    gcc_dwarf_f25_mips64, -    gcc_dwarf_f26_mips64, -    gcc_dwarf_f27_mips64, -    gcc_dwarf_f28_mips64, -    gcc_dwarf_f29_mips64, -    gcc_dwarf_f30_mips64, -    gcc_dwarf_f31_mips64, -    gcc_dwarf_fcsr_mips64, -    gcc_dwarf_fir_mips64, -    gcc_dwarf_ic_mips64, -    gcc_dwarf_dummy_mips64, -    gcc_dwarf_w0_mips64, -    gcc_dwarf_w1_mips64, -    gcc_dwarf_w2_mips64, -    gcc_dwarf_w3_mips64, -    gcc_dwarf_w4_mips64, -    gcc_dwarf_w5_mips64, -    gcc_dwarf_w6_mips64, -    gcc_dwarf_w7_mips64, -    gcc_dwarf_w8_mips64, -    gcc_dwarf_w9_mips64, -    gcc_dwarf_w10_mips64, -    gcc_dwarf_w11_mips64, -    gcc_dwarf_w12_mips64, -    gcc_dwarf_w13_mips64, -    gcc_dwarf_w14_mips64, -    gcc_dwarf_w15_mips64, -    gcc_dwarf_w16_mips64, -    gcc_dwarf_w17_mips64, -    gcc_dwarf_w18_mips64, -    gcc_dwarf_w19_mips64, -    gcc_dwarf_w20_mips64, -    gcc_dwarf_w21_mips64, -    gcc_dwarf_w22_mips64, -    gcc_dwarf_w23_mips64, -    gcc_dwarf_w24_mips64, -    gcc_dwarf_w25_mips64, -    gcc_dwarf_w26_mips64, -    gcc_dwarf_w27_mips64, -    gcc_dwarf_w28_mips64, -    gcc_dwarf_w29_mips64, -    gcc_dwarf_w30_mips64, -    gcc_dwarf_w31_mips64, -    gcc_dwarf_mcsr_mips64, -    gcc_dwarf_mir_mips64, -    gcc_dwarf_config5_mips64, -}; - -// GDB Register numbers (eRegisterKindGDB) -enum -{ -    gdb_zero_mips = 0, -    gdb_r1_mips, -    gdb_r2_mips, -    gdb_r3_mips, -    gdb_r4_mips, -    gdb_r5_mips, -    gdb_r6_mips, -    gdb_r7_mips, -    gdb_r8_mips, -    gdb_r9_mips, -    gdb_r10_mips, -    gdb_r11_mips, -    gdb_r12_mips, -    gdb_r13_mips, -    gdb_r14_mips, -    gdb_r15_mips, -    gdb_r16_mips, -    gdb_r17_mips, -    gdb_r18_mips, -    gdb_r19_mips, -    gdb_r20_mips, -    gdb_r21_mips, -    gdb_r22_mips, -    gdb_r23_mips, -    gdb_r24_mips, -    gdb_r25_mips, -    gdb_r26_mips, -    gdb_r27_mips, -    gdb_gp_mips, -    gdb_sp_mips, -    gdb_r30_mips, -    gdb_ra_mips, -    gdb_sr_mips, -    gdb_lo_mips, -    gdb_hi_mips, -    gdb_bad_mips, -    gdb_cause_mips, -    gdb_pc_mips, -    gdb_f0_mips, -    gdb_f1_mips, -    gdb_f2_mips, -    gdb_f3_mips, -    gdb_f4_mips, -    gdb_f5_mips, -    gdb_f6_mips, -    gdb_f7_mips, -    gdb_f8_mips, -    gdb_f9_mips, -    gdb_f10_mips, -    gdb_f11_mips, -    gdb_f12_mips, -    gdb_f13_mips, -    gdb_f14_mips, -    gdb_f15_mips, -    gdb_f16_mips, -    gdb_f17_mips, -    gdb_f18_mips, -    gdb_f19_mips, -    gdb_f20_mips, -    gdb_f21_mips, -    gdb_f22_mips, -    gdb_f23_mips, -    gdb_f24_mips, -    gdb_f25_mips, -    gdb_f26_mips, -    gdb_f27_mips, -    gdb_f28_mips, -    gdb_f29_mips, -    gdb_f30_mips, -    gdb_f31_mips, -    gdb_fcsr_mips, -    gdb_fir_mips, -    gdb_w0_mips, -    gdb_w1_mips, -    gdb_w2_mips, -    gdb_w3_mips, -    gdb_w4_mips, -    gdb_w5_mips, -    gdb_w6_mips, -    gdb_w7_mips, -    gdb_w8_mips, -    gdb_w9_mips, -    gdb_w10_mips, -    gdb_w11_mips, -    gdb_w12_mips, -    gdb_w13_mips, -    gdb_w14_mips, -    gdb_w15_mips, -    gdb_w16_mips, -    gdb_w17_mips, -    gdb_w18_mips, -    gdb_w19_mips, -    gdb_w20_mips, -    gdb_w21_mips, -    gdb_w22_mips, -    gdb_w23_mips, -    gdb_w24_mips, -    gdb_w25_mips, -    gdb_w26_mips, -    gdb_w27_mips, -    gdb_w28_mips, -    gdb_w29_mips, -    gdb_w30_mips, -    gdb_w31_mips, -    gdb_mcsr_mips, -    gdb_mir_mips, -    gdb_config5_mips, -    gdb_ic_mips, -    gdb_dummy_mips -}; - -enum -{ -    gdb_zero_mips64 = 0, -    gdb_r1_mips64, -    gdb_r2_mips64, -    gdb_r3_mips64, -    gdb_r4_mips64, -    gdb_r5_mips64, -    gdb_r6_mips64, -    gdb_r7_mips64, -    gdb_r8_mips64, -    gdb_r9_mips64, -    gdb_r10_mips64, -    gdb_r11_mips64, -    gdb_r12_mips64, -    gdb_r13_mips64, -    gdb_r14_mips64, -    gdb_r15_mips64, -    gdb_r16_mips64, -    gdb_r17_mips64, -    gdb_r18_mips64, -    gdb_r19_mips64, -    gdb_r20_mips64, -    gdb_r21_mips64, -    gdb_r22_mips64, -    gdb_r23_mips64, -    gdb_r24_mips64, -    gdb_r25_mips64, -    gdb_r26_mips64, -    gdb_r27_mips64, -    gdb_gp_mips64, -    gdb_sp_mips64, -    gdb_r30_mips64, -    gdb_ra_mips64, -    gdb_sr_mips64, -    gdb_lo_mips64, -    gdb_hi_mips64, -    gdb_bad_mips64, -    gdb_cause_mips64, -    gdb_pc_mips64, -    gdb_f0_mips64, -    gdb_f1_mips64, -    gdb_f2_mips64, -    gdb_f3_mips64, -    gdb_f4_mips64, -    gdb_f5_mips64, -    gdb_f6_mips64, -    gdb_f7_mips64, -    gdb_f8_mips64, -    gdb_f9_mips64, -    gdb_f10_mips64, -    gdb_f11_mips64, -    gdb_f12_mips64, -    gdb_f13_mips64, -    gdb_f14_mips64, -    gdb_f15_mips64, -    gdb_f16_mips64, -    gdb_f17_mips64, -    gdb_f18_mips64, -    gdb_f19_mips64, -    gdb_f20_mips64, -    gdb_f21_mips64, -    gdb_f22_mips64, -    gdb_f23_mips64, -    gdb_f24_mips64, -    gdb_f25_mips64, -    gdb_f26_mips64, -    gdb_f27_mips64, -    gdb_f28_mips64, -    gdb_f29_mips64, -    gdb_f30_mips64, -    gdb_f31_mips64, -    gdb_fcsr_mips64, -    gdb_fir_mips64, -    gdb_ic_mips64, -    gdb_dummy_mips64, -    gdb_w0_mips64, -    gdb_w1_mips64, -    gdb_w2_mips64, -    gdb_w3_mips64, -    gdb_w4_mips64, -    gdb_w5_mips64, -    gdb_w6_mips64, -    gdb_w7_mips64, -    gdb_w8_mips64, -    gdb_w9_mips64, -    gdb_w10_mips64, -    gdb_w11_mips64, -    gdb_w12_mips64, -    gdb_w13_mips64, -    gdb_w14_mips64, -    gdb_w15_mips64, -    gdb_w16_mips64, -    gdb_w17_mips64, -    gdb_w18_mips64, -    gdb_w19_mips64, -    gdb_w20_mips64, -    gdb_w21_mips64, -    gdb_w22_mips64, -    gdb_w23_mips64, -    gdb_w24_mips64, -    gdb_w25_mips64, -    gdb_w26_mips64, -    gdb_w27_mips64, -    gdb_w28_mips64, -    gdb_w29_mips64, -    gdb_w30_mips64, -    gdb_w31_mips64, -    gdb_mcsr_mips64, -    gdb_mir_mips64, -    gdb_config5_mips64, +    dwarf_zero_mips64 = 0, +    dwarf_r1_mips64, +    dwarf_r2_mips64, +    dwarf_r3_mips64, +    dwarf_r4_mips64, +    dwarf_r5_mips64, +    dwarf_r6_mips64, +    dwarf_r7_mips64, +    dwarf_r8_mips64, +    dwarf_r9_mips64, +    dwarf_r10_mips64, +    dwarf_r11_mips64, +    dwarf_r12_mips64, +    dwarf_r13_mips64, +    dwarf_r14_mips64, +    dwarf_r15_mips64, +    dwarf_r16_mips64, +    dwarf_r17_mips64, +    dwarf_r18_mips64, +    dwarf_r19_mips64, +    dwarf_r20_mips64, +    dwarf_r21_mips64, +    dwarf_r22_mips64, +    dwarf_r23_mips64, +    dwarf_r24_mips64, +    dwarf_r25_mips64, +    dwarf_r26_mips64, +    dwarf_r27_mips64, +    dwarf_gp_mips64, +    dwarf_sp_mips64, +    dwarf_r30_mips64, +    dwarf_ra_mips64, +    dwarf_sr_mips64, +    dwarf_lo_mips64, +    dwarf_hi_mips64, +    dwarf_bad_mips64, +    dwarf_cause_mips64, +    dwarf_pc_mips64, +    dwarf_f0_mips64, +    dwarf_f1_mips64, +    dwarf_f2_mips64, +    dwarf_f3_mips64, +    dwarf_f4_mips64, +    dwarf_f5_mips64, +    dwarf_f6_mips64, +    dwarf_f7_mips64, +    dwarf_f8_mips64, +    dwarf_f9_mips64, +    dwarf_f10_mips64, +    dwarf_f11_mips64, +    dwarf_f12_mips64, +    dwarf_f13_mips64, +    dwarf_f14_mips64, +    dwarf_f15_mips64, +    dwarf_f16_mips64, +    dwarf_f17_mips64, +    dwarf_f18_mips64, +    dwarf_f19_mips64, +    dwarf_f20_mips64, +    dwarf_f21_mips64, +    dwarf_f22_mips64, +    dwarf_f23_mips64, +    dwarf_f24_mips64, +    dwarf_f25_mips64, +    dwarf_f26_mips64, +    dwarf_f27_mips64, +    dwarf_f28_mips64, +    dwarf_f29_mips64, +    dwarf_f30_mips64, +    dwarf_f31_mips64, +    dwarf_fcsr_mips64, +    dwarf_fir_mips64, +    dwarf_ic_mips64, +    dwarf_dummy_mips64, +    dwarf_w0_mips64, +    dwarf_w1_mips64, +    dwarf_w2_mips64, +    dwarf_w3_mips64, +    dwarf_w4_mips64, +    dwarf_w5_mips64, +    dwarf_w6_mips64, +    dwarf_w7_mips64, +    dwarf_w8_mips64, +    dwarf_w9_mips64, +    dwarf_w10_mips64, +    dwarf_w11_mips64, +    dwarf_w12_mips64, +    dwarf_w13_mips64, +    dwarf_w14_mips64, +    dwarf_w15_mips64, +    dwarf_w16_mips64, +    dwarf_w17_mips64, +    dwarf_w18_mips64, +    dwarf_w19_mips64, +    dwarf_w20_mips64, +    dwarf_w21_mips64, +    dwarf_w22_mips64, +    dwarf_w23_mips64, +    dwarf_w24_mips64, +    dwarf_w25_mips64, +    dwarf_w26_mips64, +    dwarf_w27_mips64, +    dwarf_w28_mips64, +    dwarf_w29_mips64, +    dwarf_w30_mips64, +    dwarf_w31_mips64, +    dwarf_mcsr_mips64, +    dwarf_mir_mips64, +    dwarf_config5_mips64,  };  struct IOVEC_mips diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h index 7438b88971b3e..2e3053cf37bc2 100644 --- a/source/Plugins/Process/Utility/RegisterContext_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h @@ -10,223 +10,114 @@  #ifndef liblldb_RegisterContext_powerpc_H_  #define liblldb_RegisterContext_powerpc_H_ -// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF) +// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)  enum  { -    gcc_dwarf_r0_powerpc = 0, -    gcc_dwarf_r1_powerpc, -    gcc_dwarf_r2_powerpc, -    gcc_dwarf_r3_powerpc, -    gcc_dwarf_r4_powerpc, -    gcc_dwarf_r5_powerpc, -    gcc_dwarf_r6_powerpc, -    gcc_dwarf_r7_powerpc, -    gcc_dwarf_r8_powerpc, -    gcc_dwarf_r9_powerpc, -    gcc_dwarf_r10_powerpc, -    gcc_dwarf_r11_powerpc, -    gcc_dwarf_r12_powerpc, -    gcc_dwarf_r13_powerpc, -    gcc_dwarf_r14_powerpc, -    gcc_dwarf_r15_powerpc, -    gcc_dwarf_r16_powerpc, -    gcc_dwarf_r17_powerpc, -    gcc_dwarf_r18_powerpc, -    gcc_dwarf_r19_powerpc, -    gcc_dwarf_r20_powerpc, -    gcc_dwarf_r21_powerpc, -    gcc_dwarf_r22_powerpc, -    gcc_dwarf_r23_powerpc, -    gcc_dwarf_r24_powerpc, -    gcc_dwarf_r25_powerpc, -    gcc_dwarf_r26_powerpc, -    gcc_dwarf_r27_powerpc, -    gcc_dwarf_r28_powerpc, -    gcc_dwarf_r29_powerpc, -    gcc_dwarf_r30_powerpc, -    gcc_dwarf_r31_powerpc, -    gcc_dwarf_f0_powerpc, -    gcc_dwarf_f1_powerpc, -    gcc_dwarf_f2_powerpc, -    gcc_dwarf_f3_powerpc, -    gcc_dwarf_f4_powerpc, -    gcc_dwarf_f5_powerpc, -    gcc_dwarf_f6_powerpc, -    gcc_dwarf_f7_powerpc, -    gcc_dwarf_f8_powerpc, -    gcc_dwarf_f9_powerpc, -    gcc_dwarf_f10_powerpc, -    gcc_dwarf_f11_powerpc, -    gcc_dwarf_f12_powerpc, -    gcc_dwarf_f13_powerpc, -    gcc_dwarf_f14_powerpc, -    gcc_dwarf_f15_powerpc, -    gcc_dwarf_f16_powerpc, -    gcc_dwarf_f17_powerpc, -    gcc_dwarf_f18_powerpc, -    gcc_dwarf_f19_powerpc, -    gcc_dwarf_f20_powerpc, -    gcc_dwarf_f21_powerpc, -    gcc_dwarf_f22_powerpc, -    gcc_dwarf_f23_powerpc, -    gcc_dwarf_f24_powerpc, -    gcc_dwarf_f25_powerpc, -    gcc_dwarf_f26_powerpc, -    gcc_dwarf_f27_powerpc, -    gcc_dwarf_f28_powerpc, -    gcc_dwarf_f29_powerpc, -    gcc_dwarf_f30_powerpc, -    gcc_dwarf_f31_powerpc, -    gcc_dwarf_cr_powerpc, -    gcc_dwarf_fpscr_powerpc, -    gcc_dwarf_msr_powerpc, -    gcc_dwarf_vscr_powerpc, -    gcc_dwarf_xer_powerpc = 101, -    gcc_dwarf_lr_powerpc = 108, -    gcc_dwarf_ctr_powerpc, -    gcc_dwarf_pc_powerpc, -    gcc_dwarf_vrsave_powerpc = 356, -    gcc_dwarf_v0_powerpc = 1124, -    gcc_dwarf_v1_powerpc, -    gcc_dwarf_v2_powerpc, -    gcc_dwarf_v3_powerpc, -    gcc_dwarf_v4_powerpc, -    gcc_dwarf_v5_powerpc, -    gcc_dwarf_v6_powerpc, -    gcc_dwarf_v7_powerpc, -    gcc_dwarf_v8_powerpc, -    gcc_dwarf_v9_powerpc, -    gcc_dwarf_v10_powerpc, -    gcc_dwarf_v11_powerpc, -    gcc_dwarf_v12_powerpc, -    gcc_dwarf_v13_powerpc, -    gcc_dwarf_v14_powerpc, -    gcc_dwarf_v15_powerpc, -    gcc_dwarf_v16_powerpc, -    gcc_dwarf_v17_powerpc, -    gcc_dwarf_v18_powerpc, -    gcc_dwarf_v19_powerpc, -    gcc_dwarf_v20_powerpc, -    gcc_dwarf_v21_powerpc, -    gcc_dwarf_v22_powerpc, -    gcc_dwarf_v23_powerpc, -    gcc_dwarf_v24_powerpc, -    gcc_dwarf_v25_powerpc, -    gcc_dwarf_v26_powerpc, -    gcc_dwarf_v27_powerpc, -    gcc_dwarf_v28_powerpc, -    gcc_dwarf_v29_powerpc, -    gcc_dwarf_v30_powerpc, -    gcc_dwarf_v31_powerpc, -}; - -// GDB Register numbers (eRegisterKindGDB) -enum -{ -    gdb_r0_powerpc = 0, -    gdb_r1_powerpc, -    gdb_r2_powerpc, -    gdb_r3_powerpc, -    gdb_r4_powerpc, -    gdb_r5_powerpc, -    gdb_r6_powerpc, -    gdb_r7_powerpc, -    gdb_r8_powerpc, -    gdb_r9_powerpc, -    gdb_r10_powerpc, -    gdb_r11_powerpc, -    gdb_r12_powerpc, -    gdb_r13_powerpc, -    gdb_r14_powerpc, -    gdb_r15_powerpc, -    gdb_r16_powerpc, -    gdb_r17_powerpc, -    gdb_r18_powerpc, -    gdb_r19_powerpc, -    gdb_r20_powerpc, -    gdb_r21_powerpc, -    gdb_r22_powerpc, -    gdb_r23_powerpc, -    gdb_r24_powerpc, -    gdb_r25_powerpc, -    gdb_r26_powerpc, -    gdb_r27_powerpc, -    gdb_r28_powerpc, -    gdb_r29_powerpc, -    gdb_r30_powerpc, -    gdb_r31_powerpc, -    gdb_f0_powerpc, -    gdb_f1_powerpc, -    gdb_f2_powerpc, -    gdb_f3_powerpc, -    gdb_f4_powerpc, -    gdb_f5_powerpc, -    gdb_f6_powerpc, -    gdb_f7_powerpc, -    gdb_f8_powerpc, -    gdb_f9_powerpc, -    gdb_f10_powerpc, -    gdb_f11_powerpc, -    gdb_f12_powerpc, -    gdb_f13_powerpc, -    gdb_f14_powerpc, -    gdb_f15_powerpc, -    gdb_f16_powerpc, -    gdb_f17_powerpc, -    gdb_f18_powerpc, -    gdb_f19_powerpc, -    gdb_f20_powerpc, -    gdb_f21_powerpc, -    gdb_f22_powerpc, -    gdb_f23_powerpc, -    gdb_f24_powerpc, -    gdb_f25_powerpc, -    gdb_f26_powerpc, -    gdb_f27_powerpc, -    gdb_f28_powerpc, -    gdb_f29_powerpc, -    gdb_f30_powerpc, -    gdb_f31_powerpc, -    gdb_pc_powerpc, -    gdb_cr_powerpc = 66, -    gdb_lr_powerpc, -    gdb_ctr_powerpc, -    gdb_xer_powerpc, -    gdb_fpscr_powerpc, -    gdb_v0_powerpc = 106, -    gdb_v1_powerpc, -    gdb_v2_powerpc, -    gdb_v3_powerpc, -    gdb_v4_powerpc, -    gdb_v5_powerpc, -    gdb_v6_powerpc, -    gdb_v7_powerpc, -    gdb_v8_powerpc, -    gdb_v9_powerpc, -    gdb_v10_powerpc, -    gdb_v11_powerpc, -    gdb_v12_powerpc, -    gdb_v13_powerpc, -    gdb_v14_powerpc, -    gdb_v15_powerpc, -    gdb_v16_powerpc, -    gdb_v17_powerpc, -    gdb_v18_powerpc, -    gdb_v19_powerpc, -    gdb_v20_powerpc, -    gdb_v21_powerpc, -    gdb_v22_powerpc, -    gdb_v23_powerpc, -    gdb_v24_powerpc, -    gdb_v25_powerpc, -    gdb_v26_powerpc, -    gdb_v27_powerpc, -    gdb_v28_powerpc, -    gdb_v29_powerpc, -    gdb_v30_powerpc, -    gdb_v31_powerpc, -    gdb_vscr_powerpc, -    gdb_vrsave_powerpc, +    dwarf_r0_powerpc = 0, +    dwarf_r1_powerpc, +    dwarf_r2_powerpc, +    dwarf_r3_powerpc, +    dwarf_r4_powerpc, +    dwarf_r5_powerpc, +    dwarf_r6_powerpc, +    dwarf_r7_powerpc, +    dwarf_r8_powerpc, +    dwarf_r9_powerpc, +    dwarf_r10_powerpc, +    dwarf_r11_powerpc, +    dwarf_r12_powerpc, +    dwarf_r13_powerpc, +    dwarf_r14_powerpc, +    dwarf_r15_powerpc, +    dwarf_r16_powerpc, +    dwarf_r17_powerpc, +    dwarf_r18_powerpc, +    dwarf_r19_powerpc, +    dwarf_r20_powerpc, +    dwarf_r21_powerpc, +    dwarf_r22_powerpc, +    dwarf_r23_powerpc, +    dwarf_r24_powerpc, +    dwarf_r25_powerpc, +    dwarf_r26_powerpc, +    dwarf_r27_powerpc, +    dwarf_r28_powerpc, +    dwarf_r29_powerpc, +    dwarf_r30_powerpc, +    dwarf_r31_powerpc, +    dwarf_f0_powerpc, +    dwarf_f1_powerpc, +    dwarf_f2_powerpc, +    dwarf_f3_powerpc, +    dwarf_f4_powerpc, +    dwarf_f5_powerpc, +    dwarf_f6_powerpc, +    dwarf_f7_powerpc, +    dwarf_f8_powerpc, +    dwarf_f9_powerpc, +    dwarf_f10_powerpc, +    dwarf_f11_powerpc, +    dwarf_f12_powerpc, +    dwarf_f13_powerpc, +    dwarf_f14_powerpc, +    dwarf_f15_powerpc, +    dwarf_f16_powerpc, +    dwarf_f17_powerpc, +    dwarf_f18_powerpc, +    dwarf_f19_powerpc, +    dwarf_f20_powerpc, +    dwarf_f21_powerpc, +    dwarf_f22_powerpc, +    dwarf_f23_powerpc, +    dwarf_f24_powerpc, +    dwarf_f25_powerpc, +    dwarf_f26_powerpc, +    dwarf_f27_powerpc, +    dwarf_f28_powerpc, +    dwarf_f29_powerpc, +    dwarf_f30_powerpc, +    dwarf_f31_powerpc, +    dwarf_cr_powerpc, +    dwarf_fpscr_powerpc, +    dwarf_msr_powerpc, +    dwarf_vscr_powerpc, +    dwarf_xer_powerpc = 101, +    dwarf_lr_powerpc = 108, +    dwarf_ctr_powerpc, +    dwarf_pc_powerpc, +    dwarf_vrsave_powerpc = 356, +    dwarf_v0_powerpc = 1124, +    dwarf_v1_powerpc, +    dwarf_v2_powerpc, +    dwarf_v3_powerpc, +    dwarf_v4_powerpc, +    dwarf_v5_powerpc, +    dwarf_v6_powerpc, +    dwarf_v7_powerpc, +    dwarf_v8_powerpc, +    dwarf_v9_powerpc, +    dwarf_v10_powerpc, +    dwarf_v11_powerpc, +    dwarf_v12_powerpc, +    dwarf_v13_powerpc, +    dwarf_v14_powerpc, +    dwarf_v15_powerpc, +    dwarf_v16_powerpc, +    dwarf_v17_powerpc, +    dwarf_v18_powerpc, +    dwarf_v19_powerpc, +    dwarf_v20_powerpc, +    dwarf_v21_powerpc, +    dwarf_v22_powerpc, +    dwarf_v23_powerpc, +    dwarf_v24_powerpc, +    dwarf_v25_powerpc, +    dwarf_v26_powerpc, +    dwarf_v27_powerpc, +    dwarf_v28_powerpc, +    dwarf_v29_powerpc, +    dwarf_v30_powerpc, +    dwarf_v31_powerpc,  };  #endif // liblldb_RegisterContext_powerpc_H_ diff --git a/source/Plugins/Process/Utility/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h index 6b3f6fb43e331..252f1253a0869 100644 --- a/source/Plugins/Process/Utility/RegisterContext_x86.h +++ b/source/Plugins/Process/Utility/RegisterContext_x86.h @@ -11,67 +11,56 @@  #define liblldb_RegisterContext_x86_H_  //--------------------------------------------------------------------------- -// i386 gcc, dwarf, gdb enums +// i386 ehframe, dwarf regnums  //--------------------------------------------------------------------------- -// Register numbers seen in eh_frame (eRegisterKindGCC) +// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems (non-Darwin)  // -// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame -// CFI.  The only registers that are described in eh_frame CFI are those that are -// preserved across function calls aka callee-saved aka non-volatile.  And none -// of the floating point registers on x86 are preserved across function calls. -// -// The only reason there is a "gcc register" and a "dwarf register" is because of a -// mistake years and years ago with i386 where they got esp and ebp -// backwards when they emitted the eh_frame instructions.  Once there were -// binaries In The Wild using the reversed numbering, we had to stick with it -// forever.  enum  { -    // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32. -    // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register -    gcc_eax_i386 = 0, -    gcc_ecx_i386, -    gcc_edx_i386, -    gcc_ebx_i386, +    ehframe_eax_i386 = 0, +    ehframe_ecx_i386, +    ehframe_edx_i386, +    ehframe_ebx_i386,      // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus dwarf's reg numbering).      // To be specific:      //    i386+darwin eh_frame:        4 is ebp, 5 is esp      //    i386+everyone else eh_frame: 4 is esp, 5 is ebp      //    i386 dwarf:                  4 is esp, 5 is ebp -    // lldb will get the darwin-specific eh_frame reg numberings from debugserver instead of here so we -    // only encode the 4 == esp, 5 == ebp numbers in this generic header. -    gcc_esp_i386, -    gcc_ebp_i386,   -    gcc_esi_i386, -    gcc_edi_i386, -    gcc_eip_i386, -    gcc_eflags_i386, -    gcc_st0_i386 = 12, -    gcc_st1_i386, -    gcc_st2_i386, -    gcc_st3_i386, -    gcc_st4_i386, -    gcc_st5_i386, -    gcc_st6_i386, -    gcc_st7_i386, -    gcc_xmm0_i386 = 21, -    gcc_xmm1_i386, -    gcc_xmm2_i386, -    gcc_xmm3_i386, -    gcc_xmm4_i386, -    gcc_xmm5_i386, -    gcc_xmm6_i386, -    gcc_xmm7_i386, -    gcc_mm0_i386 = 29, -    gcc_mm1_i386, -    gcc_mm2_i386, -    gcc_mm3_i386, -    gcc_mm4_i386, -    gcc_mm5_i386, -    gcc_mm6_i386, -    gcc_mm7_i386, +    // lldb will get the darwin-specific eh_frame reg numberings from debugserver, or the ABI, so we +    // only encode the generally correct 4 == esp, 5 == ebp numbers in this generic header. + +    ehframe_esp_i386, +    ehframe_ebp_i386,   +    ehframe_esi_i386, +    ehframe_edi_i386, +    ehframe_eip_i386, +    ehframe_eflags_i386, +    ehframe_st0_i386 = 12, +    ehframe_st1_i386, +    ehframe_st2_i386, +    ehframe_st3_i386, +    ehframe_st4_i386, +    ehframe_st5_i386, +    ehframe_st6_i386, +    ehframe_st7_i386, +    ehframe_xmm0_i386 = 21, +    ehframe_xmm1_i386, +    ehframe_xmm2_i386, +    ehframe_xmm3_i386, +    ehframe_xmm4_i386, +    ehframe_xmm5_i386, +    ehframe_xmm6_i386, +    ehframe_xmm7_i386, +    ehframe_mm0_i386 = 29, +    ehframe_mm1_i386, +    ehframe_mm2_i386, +    ehframe_mm3_i386, +    ehframe_mm4_i386, +    ehframe_mm5_i386, +    ehframe_mm6_i386, +    ehframe_mm7_i386,  };  // DWARF register numbers (eRegisterKindDWARF) @@ -130,258 +119,109 @@ enum      //  then differentiate based on size of the register.  }; -// Register numbers GDB uses (eRegisterKindGDB) -// -// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format. -enum -{ -    gdb_eax_i386, -    gdb_ecx_i386, -    gdb_edx_i386, -    gdb_ebx_i386, -    gdb_esp_i386, -    gdb_ebp_i386, -    gdb_esi_i386, -    gdb_edi_i386, -    gdb_eip_i386, -    gdb_eflags_i386, -    gdb_cs_i386, -    gdb_ss_i386, -    gdb_ds_i386, -    gdb_es_i386, -    gdb_fs_i386, -    gdb_gs_i386, -    gdb_st0_i386 = 16, -    gdb_st1_i386, -    gdb_st2_i386, -    gdb_st3_i386, -    gdb_st4_i386, -    gdb_st5_i386, -    gdb_st6_i386, -    gdb_st7_i386, -    gdb_fctrl_i386, // FPU Control Word -    gdb_fstat_i386, // FPU Status Word -    gdb_ftag_i386,  // FPU Tag Word -    gdb_fiseg_i386, // FPU IP Selector  -    gdb_fioff_i386, // FPU IP Offset -    gdb_foseg_i386, // FPU Operand Pointer Selector -    gdb_fooff_i386, // FPU Operand Pointer Offset -    gdb_fop_i386,   // Last Instruction Opcode -    gdb_xmm0_i386 = 32, -    gdb_xmm1_i386, -    gdb_xmm2_i386, -    gdb_xmm3_i386, -    gdb_xmm4_i386, -    gdb_xmm5_i386, -    gdb_xmm6_i386, -    gdb_xmm7_i386, -    gdb_mxcsr_i386 = 40, -    gdb_ymm0h_i386, -    gdb_ymm1h_i386, -    gdb_ymm2h_i386, -    gdb_ymm3h_i386, -    gdb_ymm4h_i386, -    gdb_ymm5h_i386, -    gdb_ymm6h_i386, -    gdb_ymm7h_i386, -    gdb_mm0_i386, -    gdb_mm1_i386, -    gdb_mm2_i386, -    gdb_mm3_i386, -    gdb_mm4_i386, -    gdb_mm5_i386, -    gdb_mm6_i386, -    gdb_mm7_i386, -}; -  //--------------------------------------------------------------------------- -// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums +// AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums  //--------------------------------------------------------------------------- -// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF) +// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)  //  This is the spec I used (as opposed to x86-64-abi-0.99.pdf):  //  http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf  enum  {      // GP Registers -    gcc_dwarf_rax_x86_64 = 0, -    gcc_dwarf_rdx_x86_64, -    gcc_dwarf_rcx_x86_64, -    gcc_dwarf_rbx_x86_64, -    gcc_dwarf_rsi_x86_64, -    gcc_dwarf_rdi_x86_64, -    gcc_dwarf_rbp_x86_64, -    gcc_dwarf_rsp_x86_64, +    dwarf_rax_x86_64 = 0, +    dwarf_rdx_x86_64, +    dwarf_rcx_x86_64, +    dwarf_rbx_x86_64, +    dwarf_rsi_x86_64, +    dwarf_rdi_x86_64, +    dwarf_rbp_x86_64, +    dwarf_rsp_x86_64,      // Extended GP Registers -    gcc_dwarf_r8_x86_64 = 8, -    gcc_dwarf_r9_x86_64, -    gcc_dwarf_r10_x86_64, -    gcc_dwarf_r11_x86_64, -    gcc_dwarf_r12_x86_64, -    gcc_dwarf_r13_x86_64, -    gcc_dwarf_r14_x86_64, -    gcc_dwarf_r15_x86_64, +    dwarf_r8_x86_64 = 8, +    dwarf_r9_x86_64, +    dwarf_r10_x86_64, +    dwarf_r11_x86_64, +    dwarf_r12_x86_64, +    dwarf_r13_x86_64, +    dwarf_r14_x86_64, +    dwarf_r15_x86_64,      // Return Address (RA) mapped to RIP -    gcc_dwarf_rip_x86_64 = 16, +    dwarf_rip_x86_64 = 16,      // SSE Vector Registers -    gcc_dwarf_xmm0_x86_64 = 17, -    gcc_dwarf_xmm1_x86_64, -    gcc_dwarf_xmm2_x86_64, -    gcc_dwarf_xmm3_x86_64, -    gcc_dwarf_xmm4_x86_64, -    gcc_dwarf_xmm5_x86_64, -    gcc_dwarf_xmm6_x86_64, -    gcc_dwarf_xmm7_x86_64, -    gcc_dwarf_xmm8_x86_64, -    gcc_dwarf_xmm9_x86_64, -    gcc_dwarf_xmm10_x86_64, -    gcc_dwarf_xmm11_x86_64, -    gcc_dwarf_xmm12_x86_64, -    gcc_dwarf_xmm13_x86_64, -    gcc_dwarf_xmm14_x86_64, -    gcc_dwarf_xmm15_x86_64, +    dwarf_xmm0_x86_64 = 17, +    dwarf_xmm1_x86_64, +    dwarf_xmm2_x86_64, +    dwarf_xmm3_x86_64, +    dwarf_xmm4_x86_64, +    dwarf_xmm5_x86_64, +    dwarf_xmm6_x86_64, +    dwarf_xmm7_x86_64, +    dwarf_xmm8_x86_64, +    dwarf_xmm9_x86_64, +    dwarf_xmm10_x86_64, +    dwarf_xmm11_x86_64, +    dwarf_xmm12_x86_64, +    dwarf_xmm13_x86_64, +    dwarf_xmm14_x86_64, +    dwarf_xmm15_x86_64,      // Floating Point Registers -    gcc_dwarf_st0_x86_64 = 33, -    gcc_dwarf_st1_x86_64, -    gcc_dwarf_st2_x86_64, -    gcc_dwarf_st3_x86_64, -    gcc_dwarf_st4_x86_64, -    gcc_dwarf_st5_x86_64, -    gcc_dwarf_st6_x86_64, -    gcc_dwarf_st7_x86_64, +    dwarf_st0_x86_64 = 33, +    dwarf_st1_x86_64, +    dwarf_st2_x86_64, +    dwarf_st3_x86_64, +    dwarf_st4_x86_64, +    dwarf_st5_x86_64, +    dwarf_st6_x86_64, +    dwarf_st7_x86_64,      // MMX Registers -    gcc_dwarf_mm0_x86_64 = 41, -    gcc_dwarf_mm1_x86_64, -    gcc_dwarf_mm2_x86_64, -    gcc_dwarf_mm3_x86_64, -    gcc_dwarf_mm4_x86_64, -    gcc_dwarf_mm5_x86_64, -    gcc_dwarf_mm6_x86_64, -    gcc_dwarf_mm7_x86_64, +    dwarf_mm0_x86_64 = 41, +    dwarf_mm1_x86_64, +    dwarf_mm2_x86_64, +    dwarf_mm3_x86_64, +    dwarf_mm4_x86_64, +    dwarf_mm5_x86_64, +    dwarf_mm6_x86_64, +    dwarf_mm7_x86_64,      // Control and Status Flags Register -    gcc_dwarf_rflags_x86_64 = 49, +    dwarf_rflags_x86_64 = 49,      //  selector registers -    gcc_dwarf_es_x86_64 = 50, -    gcc_dwarf_cs_x86_64, -    gcc_dwarf_ss_x86_64, -    gcc_dwarf_ds_x86_64, -    gcc_dwarf_fs_x86_64, -    gcc_dwarf_gs_x86_64, +    dwarf_es_x86_64 = 50, +    dwarf_cs_x86_64, +    dwarf_ss_x86_64, +    dwarf_ds_x86_64, +    dwarf_fs_x86_64, +    dwarf_gs_x86_64,      // Floating point control registers -    gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status -    gcc_dwarf_fctrl_x86_64,      // x87 control word -    gcc_dwarf_fstat_x86_64,      // x87 status word +    dwarf_mxcsr_x86_64 = 64, // Media Control and Status +    dwarf_fctrl_x86_64,      // x87 control word +    dwarf_fstat_x86_64,      // x87 status word      // Upper Vector Registers     -    gcc_dwarf_ymm0h_x86_64 = 67, -    gcc_dwarf_ymm1h_x86_64, -    gcc_dwarf_ymm2h_x86_64, -    gcc_dwarf_ymm3h_x86_64, -    gcc_dwarf_ymm4h_x86_64, -    gcc_dwarf_ymm5h_x86_64, -    gcc_dwarf_ymm6h_x86_64, -    gcc_dwarf_ymm7h_x86_64, -    gcc_dwarf_ymm8h_x86_64, -    gcc_dwarf_ymm9h_x86_64, -    gcc_dwarf_ymm10h_x86_64, -    gcc_dwarf_ymm11h_x86_64, -    gcc_dwarf_ymm12h_x86_64, -    gcc_dwarf_ymm13h_x86_64, -    gcc_dwarf_ymm14h_x86_64, -    gcc_dwarf_ymm15h_x86_64, +    dwarf_ymm0h_x86_64 = 67, +    dwarf_ymm1h_x86_64, +    dwarf_ymm2h_x86_64, +    dwarf_ymm3h_x86_64, +    dwarf_ymm4h_x86_64, +    dwarf_ymm5h_x86_64, +    dwarf_ymm6h_x86_64, +    dwarf_ymm7h_x86_64, +    dwarf_ymm8h_x86_64, +    dwarf_ymm9h_x86_64, +    dwarf_ymm10h_x86_64, +    dwarf_ymm11h_x86_64, +    dwarf_ymm12h_x86_64, +    dwarf_ymm13h_x86_64, +    dwarf_ymm14h_x86_64, +    dwarf_ymm15h_x86_64,      // AVX2 Vector Mask Registers -    // gcc_dwarf_k0_x86_64 = 118, -    // gcc_dwarf_k1_x86_64, -    // gcc_dwarf_k2_x86_64, -    // gcc_dwarf_k3_x86_64, -    // gcc_dwarf_k4_x86_64, -    // gcc_dwarf_k5_x86_64, -    // gcc_dwarf_k6_x86_64, -    // gcc_dwarf_k7_x86_64, -}; - -// GDB Register numbers (eRegisterKindGDB) -enum -{ -    // GP Registers -    gdb_rax_x86_64 = 0, -    gdb_rbx_x86_64, -    gdb_rcx_x86_64, -    gdb_rdx_x86_64, -    gdb_rsi_x86_64, -    gdb_rdi_x86_64, -    gdb_rbp_x86_64, -    gdb_rsp_x86_64, -    // Extended GP Registers -    gdb_r8_x86_64, -    gdb_r9_x86_64, -    gdb_r10_x86_64, -    gdb_r11_x86_64, -    gdb_r12_x86_64, -    gdb_r13_x86_64, -    gdb_r14_x86_64, -    gdb_r15_x86_64, -    // Return Address (RA) mapped to RIP -    gdb_rip_x86_64, -    // Control and Status Flags Register -    gdb_rflags_x86_64, -    gdb_cs_x86_64, -    gdb_ss_x86_64, -    gdb_ds_x86_64, -    gdb_es_x86_64, -    gdb_fs_x86_64, -    gdb_gs_x86_64, -    // Floating Point Registers -    gdb_st0_x86_64, -    gdb_st1_x86_64, -    gdb_st2_x86_64, -    gdb_st3_x86_64, -    gdb_st4_x86_64, -    gdb_st5_x86_64, -    gdb_st6_x86_64, -    gdb_st7_x86_64, -    gdb_fctrl_x86_64, -    gdb_fstat_x86_64, -    gdb_ftag_x86_64, -    gdb_fiseg_x86_64, -    gdb_fioff_x86_64, -    gdb_foseg_x86_64, -    gdb_fooff_x86_64, -    gdb_fop_x86_64, -    // SSE Vector Registers -    gdb_xmm0_x86_64 = 40, -    gdb_xmm1_x86_64, -    gdb_xmm2_x86_64, -    gdb_xmm3_x86_64, -    gdb_xmm4_x86_64, -    gdb_xmm5_x86_64, -    gdb_xmm6_x86_64, -    gdb_xmm7_x86_64, -    gdb_xmm8_x86_64, -    gdb_xmm9_x86_64, -    gdb_xmm10_x86_64, -    gdb_xmm11_x86_64, -    gdb_xmm12_x86_64, -    gdb_xmm13_x86_64, -    gdb_xmm14_x86_64, -    gdb_xmm15_x86_64, -    // Floating point control registers -    gdb_mxcsr_x86_64 = 56, -    gdb_ymm0h_x86_64, -    gdb_ymm1h_x86_64, -    gdb_ymm2h_x86_64, -    gdb_ymm3h_x86_64, -    gdb_ymm4h_x86_64, -    gdb_ymm5h_x86_64, -    gdb_ymm6h_x86_64, -    gdb_ymm7h_x86_64, -    gdb_ymm8h_x86_64, -    gdb_ymm9h_x86_64, -    gdb_ymm10h_x86_64, -    gdb_ymm11h_x86_64, -    gdb_ymm12h_x86_64, -    gdb_ymm13h_x86_64, -    gdb_ymm14h_x86_64, -    gdb_ymm15h_x86_64 +    // dwarf_k0_x86_64 = 118, +    // dwarf_k1_x86_64, +    // dwarf_k2_x86_64, +    // dwarf_k3_x86_64, +    // dwarf_k4_x86_64, +    // dwarf_k5_x86_64, +    // dwarf_k6_x86_64, +    // dwarf_k7_x86_64,  };  //--------------------------------------------------------------------------- @@ -404,7 +244,8 @@ struct FXSAVE  {      uint16_t fctrl;         // FPU Control Word (fcw)      uint16_t fstat;         // FPU Status Word (fsw) -    uint16_t ftag;          // FPU Tag Word (ftw) +    uint8_t ftag;           // FPU Tag Word (ftw) +    uint8_t reserved_1;     // Reserved      uint16_t fop;           // Last Instruction Opcode (fop)      union      { diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h index 94cb5cc791c6e..801885d5f4c56 100644 --- a/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -10,6 +10,8 @@  #ifndef lldb_RegisterInfoInterface_h  #define lldb_RegisterInfoInterface_h +#include <vector> +  #include "lldb/Core/ArchSpec.h"  namespace lldb_private @@ -50,6 +52,26 @@ namespace lldb_private          GetTargetArchitecture() const              { return m_target_arch; } +        virtual const lldb_private::RegisterInfo * +        GetDynamicRegisterInfo(const char *reg_name) const +        { +            const std::vector <lldb_private::RegisterInfo> * d_register_infos = GetDynamicRegisterInfoP(); +            if(d_register_infos != nullptr) +            { +                std::vector <lldb_private::RegisterInfo> ::const_iterator pos = d_register_infos->begin(); +                for(; pos < d_register_infos->end() ; pos++) +                { +                    if(::strcmp(reg_name, pos->name) == 0) +                        return(d_register_infos->data() + (pos - d_register_infos->begin()) ); +                } +            } +            return nullptr; +        } + +        virtual const std::vector<lldb_private::RegisterInfo> * +        GetDynamicRegisterInfoP() const +        { return nullptr; } +      public:          // FIXME make private.          lldb_private::ArchSpec m_target_arch; diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm.h b/source/Plugins/Process/Utility/RegisterInfos_arm.h index 3d144d6694153..03457728b632c 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_arm.h +++ b/source/Plugins/Process/Utility/RegisterInfos_arm.h @@ -1,21 +1,25 @@ -//===-- RegisterInfos_arm.h ----------------------------------*- C++ -*-===// +//===-- RegisterInfos_arm.h -------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===//  #ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/lldb-defines.h"  #include "lldb/lldb-enumerations.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  #include "Utility/ARM_DWARF_Registers.h"  using namespace lldb; @@ -25,17 +29,16 @@ using namespace lldb_private;  #error GPR_OFFSET must be defined before including this header file  #endif -  #ifndef FPU_OFFSET  #error FPU_OFFSET must be defined before including this header file  #endif -#ifndef EXC_OFFSET -#error EXC_OFFSET_NAME must be defined before including this header file +#ifndef FPSCR_OFFSET +#error FPSCR_OFFSET must be defined before including this header file  #endif -#ifndef DBG_OFFSET -#error DBG_OFFSET_NAME must be defined before including this header file +#ifndef EXC_OFFSET +#error EXC_OFFSET_NAME must be defined before including this header file  #endif  #ifndef DEFINE_DBG @@ -96,6 +99,56 @@ enum      fpu_s31,      fpu_fpscr, +    fpu_d0, +    fpu_d1, +    fpu_d2, +    fpu_d3, +    fpu_d4, +    fpu_d5, +    fpu_d6, +    fpu_d7, +    fpu_d8, +    fpu_d9, +    fpu_d10, +    fpu_d11, +    fpu_d12, +    fpu_d13, +    fpu_d14, +    fpu_d15, +    fpu_d16, +    fpu_d17, +    fpu_d18, +    fpu_d19, +    fpu_d20, +    fpu_d21, +    fpu_d22, +    fpu_d23, +    fpu_d24, +    fpu_d25, +    fpu_d26, +    fpu_d27, +    fpu_d28, +    fpu_d29, +    fpu_d30, +    fpu_d31, + +    fpu_q0, +    fpu_q1, +    fpu_q2, +    fpu_q3, +    fpu_q4, +    fpu_q5, +    fpu_q6, +    fpu_q7, +    fpu_q8, +    fpu_q9, +    fpu_q10, +    fpu_q11, +    fpu_q12, +    fpu_q13, +    fpu_q14, +    fpu_q15, +      exc_exception,      exc_fsr,      exc_far, @@ -171,65 +224,214 @@ enum      k_num_registers  }; +static uint32_t g_s0_invalidates[]  = { fpu_d0,  fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_s1_invalidates[]  = { fpu_d0,  fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_s2_invalidates[]  = { fpu_d1,  fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_s3_invalidates[]  = { fpu_d1,  fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_s4_invalidates[]  = { fpu_d2,  fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_s5_invalidates[]  = { fpu_d2,  fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_s6_invalidates[]  = { fpu_d3,  fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_s7_invalidates[]  = { fpu_d3,  fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_s8_invalidates[]  = { fpu_d4,  fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_s9_invalidates[]  = { fpu_d4,  fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_s10_invalidates[] = { fpu_d5,  fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_s11_invalidates[] = { fpu_d5,  fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_s12_invalidates[] = { fpu_d6,  fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_s13_invalidates[] = { fpu_d6,  fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_s14_invalidates[] = { fpu_d7,  fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_s15_invalidates[] = { fpu_d7,  fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_s16_invalidates[] = { fpu_d8,  fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_s17_invalidates[] = { fpu_d8,  fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_s18_invalidates[] = { fpu_d9,  fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_s19_invalidates[] = { fpu_d9,  fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_s20_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_s21_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_s22_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_s23_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_s24_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_s25_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_s26_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_s27_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_s28_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM }; +static uint32_t g_s29_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM }; +static uint32_t g_s30_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM }; +static uint32_t g_s31_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM }; + +static uint32_t g_d0_contains[] =  { fpu_s0,  fpu_s1,  LLDB_INVALID_REGNUM }; +static uint32_t g_d1_contains[] =  { fpu_s2,  fpu_s3,  LLDB_INVALID_REGNUM }; +static uint32_t g_d2_contains[] =  { fpu_s4,  fpu_s5,  LLDB_INVALID_REGNUM }; +static uint32_t g_d3_contains[] =  { fpu_s6,  fpu_s7,  LLDB_INVALID_REGNUM }; +static uint32_t g_d4_contains[] =  { fpu_s8,  fpu_s9,  LLDB_INVALID_REGNUM }; +static uint32_t g_d5_contains[] =  { fpu_s10, fpu_s11, LLDB_INVALID_REGNUM }; +static uint32_t g_d6_contains[] =  { fpu_s12, fpu_s13, LLDB_INVALID_REGNUM }; +static uint32_t g_d7_contains[] =  { fpu_s14, fpu_s15, LLDB_INVALID_REGNUM }; +static uint32_t g_d8_contains[] =  { fpu_s16, fpu_s17, LLDB_INVALID_REGNUM }; +static uint32_t g_d9_contains[] =  { fpu_s18, fpu_s19, LLDB_INVALID_REGNUM }; +static uint32_t g_d10_contains[] = { fpu_s20, fpu_s21, LLDB_INVALID_REGNUM }; +static uint32_t g_d11_contains[] = { fpu_s22, fpu_s23, LLDB_INVALID_REGNUM }; +static uint32_t g_d12_contains[] = { fpu_s24, fpu_s25, LLDB_INVALID_REGNUM }; +static uint32_t g_d13_contains[] = { fpu_s26, fpu_s27, LLDB_INVALID_REGNUM }; +static uint32_t g_d14_contains[] = { fpu_s28, fpu_s29, LLDB_INVALID_REGNUM }; +static uint32_t g_d15_contains[] = { fpu_s30, fpu_s31, LLDB_INVALID_REGNUM }; + +static uint32_t g_d0_invalidates[]  = { fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_d1_invalidates[]  = { fpu_q0, LLDB_INVALID_REGNUM }; +static uint32_t g_d2_invalidates[]  = { fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_d3_invalidates[]  = { fpu_q1, LLDB_INVALID_REGNUM }; +static uint32_t g_d4_invalidates[]  = { fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_d5_invalidates[]  = { fpu_q2, LLDB_INVALID_REGNUM }; +static uint32_t g_d6_invalidates[]  = { fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_d7_invalidates[]  = { fpu_q3, LLDB_INVALID_REGNUM }; +static uint32_t g_d8_invalidates[]  = { fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_d9_invalidates[]  = { fpu_q4, LLDB_INVALID_REGNUM }; +static uint32_t g_d10_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_d11_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM }; +static uint32_t g_d12_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_d13_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM }; +static uint32_t g_d14_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM }; +static uint32_t g_d15_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM }; +static uint32_t g_d16_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM }; +static uint32_t g_d17_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM }; +static uint32_t g_d18_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM }; +static uint32_t g_d19_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM }; +static uint32_t g_d20_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM }; +static uint32_t g_d21_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM }; +static uint32_t g_d22_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM }; +static uint32_t g_d23_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM }; +static uint32_t g_d24_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM }; +static uint32_t g_d25_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM }; +static uint32_t g_d26_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM }; +static uint32_t g_d27_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM }; +static uint32_t g_d28_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM }; +static uint32_t g_d29_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM }; +static uint32_t g_d30_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM }; +static uint32_t g_d31_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM }; + +static uint32_t g_q0_contains[] =  { fpu_d0,  fpu_d1,  fpu_s0,  fpu_s1,  fpu_s2,  fpu_s3,  LLDB_INVALID_REGNUM }; +static uint32_t g_q1_contains[] =  { fpu_d2,  fpu_d3,  fpu_s4,  fpu_s5,  fpu_s6,  fpu_s7,  LLDB_INVALID_REGNUM }; +static uint32_t g_q2_contains[] =  { fpu_d4,  fpu_d5,  fpu_s8,  fpu_s9,  fpu_s10, fpu_s11, LLDB_INVALID_REGNUM }; +static uint32_t g_q3_contains[] =  { fpu_d6,  fpu_d7,  fpu_s12, fpu_s13, fpu_s14, fpu_s15, LLDB_INVALID_REGNUM }; +static uint32_t g_q4_contains[] =  { fpu_d8,  fpu_d9,  fpu_s16, fpu_s17, fpu_s18, fpu_s19, LLDB_INVALID_REGNUM }; +static uint32_t g_q5_contains[] =  { fpu_d10, fpu_d11, fpu_s20, fpu_s21, fpu_s22, fpu_s23, LLDB_INVALID_REGNUM }; +static uint32_t g_q6_contains[] =  { fpu_d12, fpu_d13, fpu_s24, fpu_s25, fpu_s26, fpu_s27, LLDB_INVALID_REGNUM }; +static uint32_t g_q7_contains[] =  { fpu_d14, fpu_d15, fpu_s28, fpu_s29, fpu_s30, fpu_s31, LLDB_INVALID_REGNUM }; +static uint32_t g_q8_contains[] =  { fpu_d16, fpu_d17, LLDB_INVALID_REGNUM }; +static uint32_t g_q9_contains[] =  { fpu_d18, fpu_d19, LLDB_INVALID_REGNUM }; +static uint32_t g_q10_contains[] = { fpu_d20, fpu_d21, LLDB_INVALID_REGNUM }; +static uint32_t g_q11_contains[] = { fpu_d22, fpu_d23, LLDB_INVALID_REGNUM }; +static uint32_t g_q12_contains[] = { fpu_d24, fpu_d25, LLDB_INVALID_REGNUM }; +static uint32_t g_q13_contains[] = { fpu_d26, fpu_d27, LLDB_INVALID_REGNUM }; +static uint32_t g_q14_contains[] = { fpu_d28, fpu_d29, LLDB_INVALID_REGNUM }; +static uint32_t g_q15_contains[] = { fpu_d30, fpu_d31, LLDB_INVALID_REGNUM }; +  static RegisterInfo g_register_infos_arm[] = { -// General purpose registers -//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE   VALUE REGS    INVALIDATE REGS -//  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    =============== -{   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { gcc_r0,               dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   gdb_arm_r0,             gpr_r0      },      NULL,              NULL}, -{   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { gcc_r1,               dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   gdb_arm_r1,             gpr_r1      },      NULL,              NULL}, -{   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { gcc_r2,               dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   gdb_arm_r2,             gpr_r2      },      NULL,              NULL}, -{   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { gcc_r3,               dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   gdb_arm_r3,             gpr_r3      },      NULL,              NULL}, -{   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             gpr_r4      },      NULL,              NULL}, -{   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             gpr_r5      },      NULL,              NULL}, -{   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             gpr_r6      },      NULL,              NULL}, -{   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { gcc_r7,               dwarf_r7,           LLDB_INVALID_REGNUM,        gdb_arm_r7,             gpr_r7      },      NULL,              NULL}, -{   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             gpr_r8      },      NULL,              NULL}, -{   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             gpr_r9      },      NULL,              NULL}, -{   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            gpr_r10     },      NULL,              NULL}, -{   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { gcc_r11,              dwarf_r11,          LLDB_REGNUM_GENERIC_FP,     gdb_arm_r11,            gpr_r11     },      NULL,              NULL}, -{   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            gpr_r12     },      NULL,              NULL}, -{   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             gpr_sp      },      NULL,              NULL}, -{   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             gpr_lr      },      NULL,              NULL}, -{   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             gpr_pc      },      NULL,              NULL}, -{   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           gpr_cpsr    },      NULL,              NULL}, - -{   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             fpu_s0      },      NULL,              NULL}, -{   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             fpu_s1      },      NULL,              NULL}, -{   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             fpu_s2      },      NULL,              NULL}, -{   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             fpu_s3      },      NULL,              NULL}, -{   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             fpu_s4      },      NULL,              NULL}, -{   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             fpu_s5      },      NULL,              NULL}, -{   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             fpu_s6      },      NULL,              NULL}, -{   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             fpu_s7      },      NULL,              NULL}, -{   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             fpu_s8      },      NULL,              NULL}, -{   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             fpu_s9      },      NULL,              NULL}, -{   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            fpu_s10     },      NULL,              NULL}, -{   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            fpu_s11     },      NULL,              NULL}, -{   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            fpu_s12     },      NULL,              NULL}, -{   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            fpu_s13     },      NULL,              NULL}, -{   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            fpu_s14     },      NULL,              NULL}, -{   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            fpu_s15     },      NULL,              NULL}, -{   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            fpu_s16     },      NULL,              NULL}, -{   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            fpu_s17     },      NULL,              NULL}, -{   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            fpu_s18     },      NULL,              NULL}, -{   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            fpu_s19     },      NULL,              NULL}, -{   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            fpu_s20     },      NULL,              NULL}, -{   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            fpu_s21     },      NULL,              NULL}, -{   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            fpu_s22     },      NULL,              NULL}, -{   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            fpu_s23     },      NULL,              NULL}, -{   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            fpu_s24     },      NULL,              NULL}, -{   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            fpu_s25     },      NULL,              NULL}, -{   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            fpu_s26     },      NULL,              NULL}, -{   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            fpu_s27     },      NULL,              NULL}, -{   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            fpu_s28     },      NULL,              NULL}, -{   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            fpu_s29     },      NULL,              NULL}, -{   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            fpu_s30     },      NULL,              NULL}, -{   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            fpu_s31     },      NULL,              NULL}, -{   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          fpu_fpscr   },      NULL,              NULL}, - -{   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL}, -{   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_fsr       },    NULL,              NULL}, -{   "far",      NULL,   4,  EXC_OFFSET(2),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    NULL,              NULL}, +//  NAME         ALT     SZ   OFFSET          ENCODING          FORMAT                  EH_FRAME             DWARF                GENERIC                     PROCESS PLUGIN       LLDB NATIVE      VALUE REGS      INVALIDATE REGS +//  ===========  ======= ==   ==============  ================  ====================    ===================  ===================  ==========================  ===================  =============    ==============  ================= +{   "r0",        nullptr, 4,  GPR_OFFSET(0),  eEncodingUint,    eFormatHex,           { ehframe_r0,          dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM, gpr_r0        }, nullptr,        nullptr           }, +{   "r1",        nullptr, 4,  GPR_OFFSET(1),  eEncodingUint,    eFormatHex,           { ehframe_r1,          dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM, gpr_r1        }, nullptr,        nullptr           }, +{   "r2",        nullptr, 4,  GPR_OFFSET(2),  eEncodingUint,    eFormatHex,           { ehframe_r2,          dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM, gpr_r2        }, nullptr,        nullptr           }, +{   "r3",        nullptr, 4,  GPR_OFFSET(3),  eEncodingUint,    eFormatHex,           { ehframe_r3,          dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM, gpr_r3        }, nullptr,        nullptr           }, +{   "r4",        nullptr, 4,  GPR_OFFSET(4),  eEncodingUint,    eFormatHex,           { ehframe_r4,          dwarf_r4,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r4        }, nullptr,        nullptr           }, +{   "r5",        nullptr, 4,  GPR_OFFSET(5),  eEncodingUint,    eFormatHex,           { ehframe_r5,          dwarf_r5,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r5        }, nullptr,        nullptr           }, +{   "r6",        nullptr, 4,  GPR_OFFSET(6),  eEncodingUint,    eFormatHex,           { ehframe_r6,          dwarf_r6,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r6        }, nullptr,        nullptr           }, +{   "r7",        nullptr, 4,  GPR_OFFSET(7),  eEncodingUint,    eFormatHex,           { ehframe_r7,          dwarf_r7,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r7        }, nullptr,        nullptr           }, +{   "r8",        nullptr, 4,  GPR_OFFSET(8),  eEncodingUint,    eFormatHex,           { ehframe_r8,          dwarf_r8,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r8        }, nullptr,        nullptr           }, +{   "r9",        nullptr, 4,  GPR_OFFSET(9),  eEncodingUint,    eFormatHex,           { ehframe_r9,          dwarf_r9,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r9        }, nullptr,        nullptr           }, +{   "r10",       nullptr, 4,  GPR_OFFSET(10), eEncodingUint,    eFormatHex,           { ehframe_r10,         dwarf_r10,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r10       }, nullptr,        nullptr           }, +{   "r11",       nullptr, 4,  GPR_OFFSET(11), eEncodingUint,    eFormatHex,           { ehframe_r11,         dwarf_r11,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM, gpr_r11       }, nullptr,        nullptr           }, +{   "r12",       nullptr, 4,  GPR_OFFSET(12), eEncodingUint,    eFormatHex,           { ehframe_r12,         dwarf_r12,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, gpr_r12       }, nullptr,        nullptr           }, +{   "sp",        "r13",   4,  GPR_OFFSET(13), eEncodingUint,    eFormatHex,           { ehframe_sp,          dwarf_sp,            LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM, gpr_sp        }, nullptr,        nullptr           }, +{   "lr",        "r14",   4,  GPR_OFFSET(14), eEncodingUint,    eFormatHex,           { ehframe_lr,          dwarf_lr,            LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM, gpr_lr        }, nullptr,        nullptr           }, +{   "pc",        "r15",   4,  GPR_OFFSET(15), eEncodingUint,    eFormatHex,           { ehframe_pc,          dwarf_pc,            LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM, gpr_pc        }, nullptr,        nullptr           }, +{   "cpsr",      "psr",   4,  GPR_OFFSET(16), eEncodingUint,    eFormatHex,           { ehframe_cpsr,        dwarf_cpsr,          LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM, gpr_cpsr      }, nullptr,        nullptr           }, + +{   "s0",        nullptr, 4,  FPU_OFFSET(0),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s0        }, nullptr,        g_s0_invalidates  }, +{   "s1",        nullptr, 4,  FPU_OFFSET(1),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s1        }, nullptr,        g_s1_invalidates  }, +{   "s2",        nullptr, 4,  FPU_OFFSET(2),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s2        }, nullptr,        g_s2_invalidates  }, +{   "s3",        nullptr, 4,  FPU_OFFSET(3),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s3        }, nullptr,        g_s3_invalidates  }, +{   "s4",        nullptr, 4,  FPU_OFFSET(4),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s4        }, nullptr,        g_s4_invalidates  }, +{   "s5",        nullptr, 4,  FPU_OFFSET(5),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s5        }, nullptr,        g_s5_invalidates  }, +{   "s6",        nullptr, 4,  FPU_OFFSET(6),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s6        }, nullptr,        g_s6_invalidates  }, +{   "s7",        nullptr, 4,  FPU_OFFSET(7),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s7        }, nullptr,        g_s7_invalidates  }, +{   "s8",        nullptr, 4,  FPU_OFFSET(8),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s8        }, nullptr,        g_s8_invalidates  }, +{   "s9",        nullptr, 4,  FPU_OFFSET(9),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s9        }, nullptr,        g_s9_invalidates  }, +{   "s10",       nullptr, 4,  FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s10       }, nullptr,        g_s10_invalidates }, +{   "s11",       nullptr, 4,  FPU_OFFSET(11), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s11       }, nullptr,        g_s11_invalidates }, +{   "s12",       nullptr, 4,  FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s12       }, nullptr,        g_s12_invalidates }, +{   "s13",       nullptr, 4,  FPU_OFFSET(13), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s13       }, nullptr,        g_s13_invalidates }, +{   "s14",       nullptr, 4,  FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s14       }, nullptr,        g_s14_invalidates }, +{   "s15",       nullptr, 4,  FPU_OFFSET(15), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s15       }, nullptr,        g_s15_invalidates }, +{   "s16",       nullptr, 4,  FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s16       }, nullptr,        g_s16_invalidates }, +{   "s17",       nullptr, 4,  FPU_OFFSET(17), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s17       }, nullptr,        g_s17_invalidates }, +{   "s18",       nullptr, 4,  FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s18       }, nullptr,        g_s18_invalidates }, +{   "s19",       nullptr, 4,  FPU_OFFSET(19), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s19       }, nullptr,        g_s19_invalidates }, +{   "s20",       nullptr, 4,  FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s20       }, nullptr,        g_s20_invalidates }, +{   "s21",       nullptr, 4,  FPU_OFFSET(21), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s21       }, nullptr,        g_s21_invalidates }, +{   "s22",       nullptr, 4,  FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s22       }, nullptr,        g_s22_invalidates }, +{   "s23",       nullptr, 4,  FPU_OFFSET(23), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s23       }, nullptr,        g_s23_invalidates }, +{   "s24",       nullptr, 4,  FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s24       }, nullptr,        g_s24_invalidates }, +{   "s25",       nullptr, 4,  FPU_OFFSET(25), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s25       }, nullptr,        g_s25_invalidates }, +{   "s26",       nullptr, 4,  FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s26       }, nullptr,        g_s26_invalidates }, +{   "s27",       nullptr, 4,  FPU_OFFSET(27), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s27       }, nullptr,        g_s27_invalidates }, +{   "s28",       nullptr, 4,  FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s28       }, nullptr,        g_s28_invalidates }, +{   "s29",       nullptr, 4,  FPU_OFFSET(29), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s29       }, nullptr,        g_s29_invalidates }, +{   "s30",       nullptr, 4,  FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s30       }, nullptr,        g_s30_invalidates }, +{   "s31",       nullptr, 4,  FPU_OFFSET(31), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_s31       }, nullptr,        g_s31_invalidates }, +{   "fpscr",     nullptr, 4,  FPSCR_OFFSET,   eEncodingUint,    eFormatHex,           { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_fpscr     }, nullptr,        nullptr           }, + +{   "d0",        nullptr, 8,  FPU_OFFSET(0),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d0        }, g_d0_contains,  g_d0_invalidates  }, +{   "d1",        nullptr, 8,  FPU_OFFSET(2),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d1        }, g_d1_contains,  g_d1_invalidates  }, +{   "d2",        nullptr, 8,  FPU_OFFSET(4),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d2        }, g_d2_contains,  g_d2_invalidates  }, +{   "d3",        nullptr, 8,  FPU_OFFSET(6),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d3        }, g_d3_contains,  g_d3_invalidates  }, +{   "d4",        nullptr, 8,  FPU_OFFSET(8),  eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d4        }, g_d4_contains,  g_d4_invalidates  }, +{   "d5",        nullptr, 8,  FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d5        }, g_d5_contains,  g_d5_invalidates  }, +{   "d6",        nullptr, 8,  FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d6        }, g_d6_contains,  g_d6_invalidates  }, +{   "d7",        nullptr, 8,  FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d7        }, g_d7_contains,  g_d7_invalidates  }, +{   "d8",        nullptr, 8,  FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d8        }, g_d8_contains,  g_d8_invalidates  }, +{   "d9",        nullptr, 8,  FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d9        }, g_d9_contains,  g_d9_invalidates  }, +{   "d10",       nullptr, 8,  FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d10       }, g_d10_contains, g_d10_invalidates }, +{   "d11",       nullptr, 8,  FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d11       }, g_d11_contains, g_d11_invalidates }, +{   "d12",       nullptr, 8,  FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d12       }, g_d12_contains, g_d12_invalidates }, +{   "d13",       nullptr, 8,  FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d13       }, g_d13_contains, g_d13_invalidates }, +{   "d14",       nullptr, 8,  FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d14       }, g_d14_contains, g_d14_invalidates }, +{   "d15",       nullptr, 8,  FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d15       }, g_d15_contains, g_d15_invalidates }, +{   "d16",       nullptr, 8,  FPU_OFFSET(32), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d16       }, nullptr,        g_d16_invalidates }, +{   "d17",       nullptr, 8,  FPU_OFFSET(34), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d17       }, nullptr,        g_d17_invalidates }, +{   "d18",       nullptr, 8,  FPU_OFFSET(36), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d18       }, nullptr,        g_d18_invalidates }, +{   "d19",       nullptr, 8,  FPU_OFFSET(38), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d19       }, nullptr,        g_d19_invalidates }, +{   "d20",       nullptr, 8,  FPU_OFFSET(40), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d20       }, nullptr,        g_d20_invalidates }, +{   "d21",       nullptr, 8,  FPU_OFFSET(42), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d21       }, nullptr,        g_d21_invalidates }, +{   "d22",       nullptr, 8,  FPU_OFFSET(44), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d22       }, nullptr,        g_d22_invalidates }, +{   "d23",       nullptr, 8,  FPU_OFFSET(46), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d23       }, nullptr,        g_d23_invalidates }, +{   "d24",       nullptr, 8,  FPU_OFFSET(48), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d24       }, nullptr,        g_d24_invalidates }, +{   "d25",       nullptr, 8,  FPU_OFFSET(50), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d25       }, nullptr,        g_d25_invalidates }, +{   "d26",       nullptr, 8,  FPU_OFFSET(52), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d26       }, nullptr,        g_d26_invalidates }, +{   "d27",       nullptr, 8,  FPU_OFFSET(54), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d27       }, nullptr,        g_d27_invalidates }, +{   "d28",       nullptr, 8,  FPU_OFFSET(56), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d28       }, nullptr,        g_d28_invalidates }, +{   "d29",       nullptr, 8,  FPU_OFFSET(58), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d29       }, nullptr,        g_d29_invalidates }, +{   "d30",       nullptr, 8,  FPU_OFFSET(60), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d30       }, nullptr,        g_d30_invalidates }, +{   "d31",       nullptr, 8,  FPU_OFFSET(62), eEncodingIEEE754, eFormatFloat,         { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_d31       }, nullptr,        g_d31_invalidates }, + +{   "q0",        nullptr, 16, FPU_OFFSET(0),  eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q0        }, g_q0_contains,  nullptr,          }, +{   "q1",        nullptr, 16, FPU_OFFSET(4),  eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q1        }, g_q1_contains,  nullptr,          }, +{   "q2",        nullptr, 16, FPU_OFFSET(8),  eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q2        }, g_q2_contains,  nullptr,          }, +{   "q3",        nullptr, 16, FPU_OFFSET(12), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q3        }, g_q3_contains,  nullptr,          }, +{   "q4",        nullptr, 16, FPU_OFFSET(16), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q4        }, g_q4_contains,  nullptr,          }, +{   "q5",        nullptr, 16, FPU_OFFSET(20), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q5        }, g_q5_contains,  nullptr,          }, +{   "q6",        nullptr, 16, FPU_OFFSET(24), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q6        }, g_q6_contains,  nullptr,          }, +{   "q7",        nullptr, 16, FPU_OFFSET(28), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q7        }, g_q7_contains,  nullptr,          }, +{   "q8",        nullptr, 16, FPU_OFFSET(32), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q8        }, g_q8_contains,  nullptr,          }, +{   "q9",        nullptr, 16, FPU_OFFSET(36), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,            LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q9        }, g_q9_contains,  nullptr,          }, +{   "q10",       nullptr, 16, FPU_OFFSET(40), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q10       }, g_q10_contains, nullptr,          }, +{   "q11",       nullptr, 16, FPU_OFFSET(44), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q11       }, g_q11_contains, nullptr,          }, +{   "q12",       nullptr, 16, FPU_OFFSET(48), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q12       }, g_q12_contains, nullptr,          }, +{   "q13",       nullptr, 16, FPU_OFFSET(52), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q13       }, g_q13_contains, nullptr,          }, +{   "q14",       nullptr, 16, FPU_OFFSET(56), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q14       }, g_q14_contains, nullptr,          }, +{   "q15",       nullptr, 16, FPU_OFFSET(60), eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, fpu_q15       }, g_q15_contains, nullptr,          }, + +{   "exception", nullptr, 4,  EXC_OFFSET(0),  eEncodingUint,    eFormatHex,           { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, exc_exception }, nullptr,           nullptr        }, +{   "fsr",       nullptr, 4,  EXC_OFFSET(1),  eEncodingUint,    eFormatHex,           { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, exc_fsr       }, nullptr,           nullptr        }, +{   "far",       nullptr, 4,  EXC_OFFSET(2),  eEncodingUint,    eFormatHex,           { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM, exc_far       }, nullptr,           nullptr        },  {   DEFINE_DBG (bvr, 0) },  {   DEFINE_DBG (bvr, 1) }, diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h index 0255a3bc7d608..715321149a734 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -1,22 +1,26 @@ -//===-- RegisterInfos_arm64.h ----------------------------------*- C++ -*-===// +//===-- RegisterInfos_arm64.h -----------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===//  #ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/lldb-defines.h"  #include "lldb/lldb-enumerations.h" -#include "Utility/ARM64_GCC_Registers.h"  #include "Utility/ARM64_DWARF_Registers.h" +#include "Utility/ARM64_ehframe_Registers.h"  #ifndef GPR_OFFSET  #error GPR_OFFSET must be defined before including this header file @@ -196,84 +200,84 @@ enum  static lldb_private::RegisterInfo g_register_infos_arm64[] = {  // General purpose registers -//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE   VALUE REGS    INVALIDATE REGS -//  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    =============== -{   "x0",       NULL,   8,  GPR_OFFSET(0),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x0,               arm64_dwarf::x0,           LLDB_REGNUM_GENERIC_ARG1,   arm64_gcc::x0,             gpr_x0      },      NULL,              NULL}, -{   "x1",       NULL,   8,  GPR_OFFSET(1),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x1,               arm64_dwarf::x1,           LLDB_REGNUM_GENERIC_ARG2,   arm64_gcc::x1,             gpr_x1      },      NULL,              NULL}, -{   "x2",       NULL,   8,  GPR_OFFSET(2),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x2,               arm64_dwarf::x2,           LLDB_REGNUM_GENERIC_ARG3,   arm64_gcc::x2,             gpr_x2      },      NULL,              NULL}, -{   "x3",       NULL,   8,  GPR_OFFSET(3),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x3,               arm64_dwarf::x3,           LLDB_REGNUM_GENERIC_ARG4,   arm64_gcc::x3,             gpr_x3      },      NULL,              NULL}, -{   "x4",       NULL,   8,  GPR_OFFSET(4),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x4,               arm64_dwarf::x4,           LLDB_REGNUM_GENERIC_ARG5,   arm64_gcc::x4,             gpr_x4      },      NULL,              NULL}, -{   "x5",       NULL,   8,  GPR_OFFSET(5),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x5,               arm64_dwarf::x5,           LLDB_REGNUM_GENERIC_ARG6,   arm64_gcc::x5,             gpr_x5      },      NULL,              NULL}, -{   "x6",       NULL,   8,  GPR_OFFSET(6),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x6,               arm64_dwarf::x6,           LLDB_REGNUM_GENERIC_ARG7,   arm64_gcc::x6,             gpr_x6      },      NULL,              NULL}, -{   "x7",       NULL,   8,  GPR_OFFSET(7),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x7,               arm64_dwarf::x7,           LLDB_REGNUM_GENERIC_ARG8,   arm64_gcc::x7,             gpr_x7      },      NULL,              NULL}, -{   "x8",       NULL,   8,  GPR_OFFSET(8),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x8,               arm64_dwarf::x8,           LLDB_INVALID_REGNUM,        arm64_gcc::x8,             gpr_x8      },      NULL,              NULL}, -{   "x9",       NULL,   8,  GPR_OFFSET(9),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x9,               arm64_dwarf::x9,           LLDB_INVALID_REGNUM,        arm64_gcc::x9,             gpr_x9      },      NULL,              NULL}, -{   "x10",      NULL,   8,  GPR_OFFSET(10),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x10,              arm64_dwarf::x10,          LLDB_INVALID_REGNUM,        arm64_gcc::x10,            gpr_x10     },      NULL,              NULL}, -{   "x11",      NULL,   8,  GPR_OFFSET(11),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x11,              arm64_dwarf::x11,          LLDB_INVALID_REGNUM,        arm64_gcc::x11,            gpr_x11     },      NULL,              NULL}, -{   "x12",      NULL,   8,  GPR_OFFSET(12),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x12,              arm64_dwarf::x12,          LLDB_INVALID_REGNUM,        arm64_gcc::x12,            gpr_x12     },      NULL,              NULL}, -{   "x13",      NULL,   8,  GPR_OFFSET(13),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x13,              arm64_dwarf::x13,          LLDB_INVALID_REGNUM,        arm64_gcc::x13,            gpr_x13     },      NULL,              NULL}, -{   "x14",      NULL,   8,  GPR_OFFSET(14),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x14,              arm64_dwarf::x14,          LLDB_INVALID_REGNUM,        arm64_gcc::x14,            gpr_x14     },      NULL,              NULL}, -{   "x15",      NULL,   8,  GPR_OFFSET(15),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x15,              arm64_dwarf::x15,          LLDB_INVALID_REGNUM,        arm64_gcc::x15,            gpr_x15     },      NULL,              NULL}, -{   "x16",      NULL,   8,  GPR_OFFSET(16),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x16,              arm64_dwarf::x16,          LLDB_INVALID_REGNUM,        arm64_gcc::x16,            gpr_x16     },      NULL,              NULL}, -{   "x17",      NULL,   8,  GPR_OFFSET(17),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x17,              arm64_dwarf::x17,          LLDB_INVALID_REGNUM,        arm64_gcc::x17,            gpr_x17     },      NULL,              NULL}, -{   "x18",      NULL,   8,  GPR_OFFSET(18),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x18,              arm64_dwarf::x18,          LLDB_INVALID_REGNUM,        arm64_gcc::x18,            gpr_x18     },      NULL,              NULL}, -{   "x19",      NULL,   8,  GPR_OFFSET(19),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x19,              arm64_dwarf::x19,          LLDB_INVALID_REGNUM,        arm64_gcc::x19,            gpr_x19     },      NULL,              NULL}, -{   "x20",      NULL,   8,  GPR_OFFSET(20),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x20,              arm64_dwarf::x20,          LLDB_INVALID_REGNUM,        arm64_gcc::x20,            gpr_x20     },      NULL,              NULL}, -{   "x21",      NULL,   8,  GPR_OFFSET(21),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x21,              arm64_dwarf::x21,          LLDB_INVALID_REGNUM,        arm64_gcc::x21,            gpr_x21     },      NULL,              NULL}, -{   "x22",      NULL,   8,  GPR_OFFSET(22),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x22,              arm64_dwarf::x22,          LLDB_INVALID_REGNUM,        arm64_gcc::x22,            gpr_x22     },      NULL,              NULL}, -{   "x23",      NULL,   8,  GPR_OFFSET(23),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x23,              arm64_dwarf::x23,          LLDB_INVALID_REGNUM,        arm64_gcc::x23,            gpr_x23     },      NULL,              NULL}, -{   "x24",      NULL,   8,  GPR_OFFSET(24),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x24,              arm64_dwarf::x24,          LLDB_INVALID_REGNUM,        arm64_gcc::x24,            gpr_x24     },      NULL,              NULL}, -{   "x25",      NULL,   8,  GPR_OFFSET(25),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x25,              arm64_dwarf::x25,          LLDB_INVALID_REGNUM,        arm64_gcc::x25,            gpr_x25     },      NULL,              NULL}, -{   "x26",      NULL,   8,  GPR_OFFSET(26),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x26,              arm64_dwarf::x26,          LLDB_INVALID_REGNUM,        arm64_gcc::x26,            gpr_x26     },      NULL,              NULL}, -{   "x27",      NULL,   8,  GPR_OFFSET(27),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x27,              arm64_dwarf::x27,          LLDB_INVALID_REGNUM,        arm64_gcc::x27,            gpr_x27     },      NULL,              NULL}, -{   "x28",      NULL,   8,  GPR_OFFSET(28),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::x28,              arm64_dwarf::x28,          LLDB_INVALID_REGNUM,        arm64_gcc::x28,            gpr_x28     },      NULL,              NULL}, +//  NAME        ALT     SZ  OFFSET              ENCODING                FORMAT                 EH_FRAME                     DWARF                      GENERIC                     PROCESS PLUGIN          LLDB NATIVE   VALUE REGS    INVALIDATE REGS +//  ======      ======= ==  =============       =============         ============            ===============              ===============            =========================   =====================   ============= ==========    =============== +{   "x0",       nullptr,  8,  GPR_OFFSET(0),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x0,           arm64_dwarf::x0,           LLDB_REGNUM_GENERIC_ARG1,   LLDB_INVALID_REGNUM,       gpr_x0      },      nullptr,        nullptr}, +{   "x1",       nullptr,  8,  GPR_OFFSET(1),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x1,           arm64_dwarf::x1,           LLDB_REGNUM_GENERIC_ARG2,   LLDB_INVALID_REGNUM,       gpr_x1      },      nullptr,        nullptr}, +{   "x2",       nullptr,  8,  GPR_OFFSET(2),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x2,           arm64_dwarf::x2,           LLDB_REGNUM_GENERIC_ARG3,   LLDB_INVALID_REGNUM,       gpr_x2      },      nullptr,        nullptr}, +{   "x3",       nullptr,  8,  GPR_OFFSET(3),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x3,           arm64_dwarf::x3,           LLDB_REGNUM_GENERIC_ARG4,   LLDB_INVALID_REGNUM,       gpr_x3      },      nullptr,        nullptr}, +{   "x4",       nullptr,  8,  GPR_OFFSET(4),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x4,           arm64_dwarf::x4,           LLDB_REGNUM_GENERIC_ARG5,   LLDB_INVALID_REGNUM,       gpr_x4      },      nullptr,        nullptr}, +{   "x5",       nullptr,  8,  GPR_OFFSET(5),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x5,           arm64_dwarf::x5,           LLDB_REGNUM_GENERIC_ARG6,   LLDB_INVALID_REGNUM,       gpr_x5      },      nullptr,        nullptr}, +{   "x6",       nullptr,  8,  GPR_OFFSET(6),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x6,           arm64_dwarf::x6,           LLDB_REGNUM_GENERIC_ARG7,   LLDB_INVALID_REGNUM,       gpr_x6      },      nullptr,        nullptr}, +{   "x7",       nullptr,  8,  GPR_OFFSET(7),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x7,           arm64_dwarf::x7,           LLDB_REGNUM_GENERIC_ARG8,   LLDB_INVALID_REGNUM,       gpr_x7      },      nullptr,        nullptr}, +{   "x8",       nullptr,  8,  GPR_OFFSET(8),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x8,           arm64_dwarf::x8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x8      },      nullptr,        nullptr}, +{   "x9",       nullptr,  8,  GPR_OFFSET(9),      lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x9,           arm64_dwarf::x9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x9      },      nullptr,        nullptr}, +{   "x10",      nullptr,  8,  GPR_OFFSET(10),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x10,          arm64_dwarf::x10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x10     },      nullptr,        nullptr}, +{   "x11",      nullptr,  8,  GPR_OFFSET(11),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x11,          arm64_dwarf::x11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x11     },      nullptr,        nullptr}, +{   "x12",      nullptr,  8,  GPR_OFFSET(12),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x12,          arm64_dwarf::x12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x12     },      nullptr,        nullptr}, +{   "x13",      nullptr,  8,  GPR_OFFSET(13),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x13,          arm64_dwarf::x13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x13     },      nullptr,        nullptr}, +{   "x14",      nullptr,  8,  GPR_OFFSET(14),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x14,          arm64_dwarf::x14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x14     },      nullptr,        nullptr}, +{   "x15",      nullptr,  8,  GPR_OFFSET(15),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x15,          arm64_dwarf::x15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x15     },      nullptr,        nullptr}, +{   "x16",      nullptr,  8,  GPR_OFFSET(16),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x16,          arm64_dwarf::x16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x16     },      nullptr,        nullptr}, +{   "x17",      nullptr,  8,  GPR_OFFSET(17),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x17,          arm64_dwarf::x17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x17     },      nullptr,        nullptr}, +{   "x18",      nullptr,  8,  GPR_OFFSET(18),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x18,          arm64_dwarf::x18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x18     },      nullptr,        nullptr}, +{   "x19",      nullptr,  8,  GPR_OFFSET(19),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x19,          arm64_dwarf::x19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x19     },      nullptr,        nullptr}, +{   "x20",      nullptr,  8,  GPR_OFFSET(20),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x20,          arm64_dwarf::x20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x20     },      nullptr,        nullptr}, +{   "x21",      nullptr,  8,  GPR_OFFSET(21),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x21,          arm64_dwarf::x21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x21     },      nullptr,        nullptr}, +{   "x22",      nullptr,  8,  GPR_OFFSET(22),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x22,          arm64_dwarf::x22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x22     },      nullptr,        nullptr}, +{   "x23",      nullptr,  8,  GPR_OFFSET(23),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x23,          arm64_dwarf::x23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x23     },      nullptr,        nullptr}, +{   "x24",      nullptr,  8,  GPR_OFFSET(24),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x24,          arm64_dwarf::x24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x24     },      nullptr,        nullptr}, +{   "x25",      nullptr,  8,  GPR_OFFSET(25),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x25,          arm64_dwarf::x25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x25     },      nullptr,        nullptr}, +{   "x26",      nullptr,  8,  GPR_OFFSET(26),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x26,          arm64_dwarf::x26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x26     },      nullptr,        nullptr}, +{   "x27",      nullptr,  8,  GPR_OFFSET(27),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x27,          arm64_dwarf::x27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x27     },      nullptr,        nullptr}, +{   "x28",      nullptr,  8,  GPR_OFFSET(28),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::x28,          arm64_dwarf::x28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       gpr_x28     },      nullptr,        nullptr}, -{   "fp",       "x29",  8,  GPR_OFFSET(29),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::fp,               arm64_dwarf::fp,           LLDB_REGNUM_GENERIC_FP,     arm64_gcc::fp,             gpr_fp      },      NULL,              NULL}, -{   "lr",       "x30",  8,  GPR_OFFSET(30),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::lr,               arm64_dwarf::lr,           LLDB_REGNUM_GENERIC_RA,     arm64_gcc::lr,             gpr_lr      },      NULL,              NULL}, -{   "sp",       "x31",  8,  GPR_OFFSET(31),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::sp,               arm64_dwarf::sp,           LLDB_REGNUM_GENERIC_SP,     arm64_gcc::sp,             gpr_sp      },      NULL,              NULL}, -{   "pc",       NULL,   8,  GPR_OFFSET(32),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_gcc::pc,               arm64_dwarf::pc,           LLDB_REGNUM_GENERIC_PC,     arm64_gcc::pc,             gpr_pc      },      NULL,              NULL}, +{   "fp",       "x29",    8,  GPR_OFFSET(29),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::fp,           arm64_dwarf::fp,           LLDB_REGNUM_GENERIC_FP,     LLDB_INVALID_REGNUM,       gpr_fp      },      nullptr,        nullptr}, +{   "lr",       "x30",    8,  GPR_OFFSET(30),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::lr,           arm64_dwarf::lr,           LLDB_REGNUM_GENERIC_RA,     LLDB_INVALID_REGNUM,       gpr_lr      },      nullptr,        nullptr}, +{   "sp",       "x31",    8,  GPR_OFFSET(31),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::sp,           arm64_dwarf::sp,           LLDB_REGNUM_GENERIC_SP,     LLDB_INVALID_REGNUM,       gpr_sp      },      nullptr,        nullptr}, +{   "pc",       nullptr,  8,  GPR_OFFSET(32),     lldb::eEncodingUint,  lldb::eFormatHex,     { arm64_ehframe::pc,           arm64_dwarf::pc,           LLDB_REGNUM_GENERIC_PC,     LLDB_INVALID_REGNUM,       gpr_pc      },      nullptr,        nullptr}, -{   "cpsr",     NULL,   4,  GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint,  lldb::eFormatHex,  { arm64_gcc::cpsr,             arm64_dwarf::cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  arm64_gcc::cpsr,           gpr_cpsr    },      NULL,              NULL}, +{   "cpsr",     nullptr,  4,  GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint,  lldb::eFormatHex,  { arm64_ehframe::cpsr,         arm64_dwarf::cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  LLDB_INVALID_REGNUM,       gpr_cpsr    },      nullptr,        nullptr}, -{   "v0",       NULL,  16,  FPU_OFFSET(0),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v0,           LLDB_INVALID_REGNUM,        arm64_gcc::v0,             fpu_v0      },      NULL,              NULL}, -{   "v1",       NULL,  16,  FPU_OFFSET(1),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v1,           LLDB_INVALID_REGNUM,        arm64_gcc::v1,             fpu_v1      },      NULL,              NULL}, -{   "v2",       NULL,  16,  FPU_OFFSET(2),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v2,           LLDB_INVALID_REGNUM,        arm64_gcc::v2,             fpu_v2      },      NULL,              NULL}, -{   "v3",       NULL,  16,  FPU_OFFSET(3),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v3,           LLDB_INVALID_REGNUM,        arm64_gcc::v3,             fpu_v3      },      NULL,              NULL}, -{   "v4",       NULL,  16,  FPU_OFFSET(4),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v4,           LLDB_INVALID_REGNUM,        arm64_gcc::v4,             fpu_v4      },      NULL,              NULL}, -{   "v5",       NULL,  16,  FPU_OFFSET(5),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v5,           LLDB_INVALID_REGNUM,        arm64_gcc::v5,             fpu_v5      },      NULL,              NULL}, -{   "v6",       NULL,  16,  FPU_OFFSET(6),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v6,           LLDB_INVALID_REGNUM,        arm64_gcc::v6,             fpu_v6      },      NULL,              NULL}, -{   "v7",       NULL,  16,  FPU_OFFSET(7),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v7,           LLDB_INVALID_REGNUM,        arm64_gcc::v7,             fpu_v7      },      NULL,              NULL}, -{   "v8",       NULL,  16,  FPU_OFFSET(8),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v8,           LLDB_INVALID_REGNUM,        arm64_gcc::v8,             fpu_v8      },      NULL,              NULL}, -{   "v9",       NULL,  16,  FPU_OFFSET(9),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v9,           LLDB_INVALID_REGNUM,        arm64_gcc::v9,             fpu_v9      },      NULL,              NULL}, -{   "v10",      NULL,  16,  FPU_OFFSET(10),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v10,          LLDB_INVALID_REGNUM,        arm64_gcc::v10,            fpu_v10     },      NULL,              NULL}, -{   "v11",      NULL,  16,  FPU_OFFSET(11),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v11,          LLDB_INVALID_REGNUM,        arm64_gcc::v11,            fpu_v11     },      NULL,              NULL}, -{   "v12",      NULL,  16,  FPU_OFFSET(12),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v12,          LLDB_INVALID_REGNUM,        arm64_gcc::v12,            fpu_v12     },      NULL,              NULL}, -{   "v13",      NULL,  16,  FPU_OFFSET(13),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v13,          LLDB_INVALID_REGNUM,        arm64_gcc::v13,            fpu_v13     },      NULL,              NULL}, -{   "v14",      NULL,  16,  FPU_OFFSET(14),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v14,          LLDB_INVALID_REGNUM,        arm64_gcc::v14,            fpu_v14     },      NULL,              NULL}, -{   "v15",      NULL,  16,  FPU_OFFSET(15),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v15,          LLDB_INVALID_REGNUM,        arm64_gcc::v15,            fpu_v15     },      NULL,              NULL}, -{   "v16",      NULL,  16,  FPU_OFFSET(16),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v16,          LLDB_INVALID_REGNUM,        arm64_gcc::v16,            fpu_v16     },      NULL,              NULL}, -{   "v17",      NULL,  16,  FPU_OFFSET(17),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v17,          LLDB_INVALID_REGNUM,        arm64_gcc::v17,            fpu_v17     },      NULL,              NULL}, -{   "v18",      NULL,  16,  FPU_OFFSET(18),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v18,          LLDB_INVALID_REGNUM,        arm64_gcc::v18,            fpu_v18     },      NULL,              NULL}, -{   "v19",      NULL,  16,  FPU_OFFSET(19),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v19,          LLDB_INVALID_REGNUM,        arm64_gcc::v19,            fpu_v19     },      NULL,              NULL}, -{   "v20",      NULL,  16,  FPU_OFFSET(20),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v20,          LLDB_INVALID_REGNUM,        arm64_gcc::v20,            fpu_v20     },      NULL,              NULL}, -{   "v21",      NULL,  16,  FPU_OFFSET(21),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v21,          LLDB_INVALID_REGNUM,        arm64_gcc::v21,            fpu_v21     },      NULL,              NULL}, -{   "v22",      NULL,  16,  FPU_OFFSET(22),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v22,          LLDB_INVALID_REGNUM,        arm64_gcc::v22,            fpu_v22     },      NULL,              NULL}, -{   "v23",      NULL,  16,  FPU_OFFSET(23),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v23,          LLDB_INVALID_REGNUM,        arm64_gcc::v23,            fpu_v23     },      NULL,              NULL}, -{   "v24",      NULL,  16,  FPU_OFFSET(24),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v24,          LLDB_INVALID_REGNUM,        arm64_gcc::v24,            fpu_v24     },      NULL,              NULL}, -{   "v25",      NULL,  16,  FPU_OFFSET(25),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v25,          LLDB_INVALID_REGNUM,        arm64_gcc::v25,            fpu_v25     },      NULL,              NULL}, -{   "v26",      NULL,  16,  FPU_OFFSET(26),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v26,          LLDB_INVALID_REGNUM,        arm64_gcc::v26,            fpu_v26     },      NULL,              NULL}, -{   "v27",      NULL,  16,  FPU_OFFSET(27),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v27,          LLDB_INVALID_REGNUM,        arm64_gcc::v27,            fpu_v27     },      NULL,              NULL}, -{   "v28",      NULL,  16,  FPU_OFFSET(28),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v28,          LLDB_INVALID_REGNUM,        arm64_gcc::v28,            fpu_v28     },      NULL,              NULL}, -{   "v29",      NULL,  16,  FPU_OFFSET(29),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v29,          LLDB_INVALID_REGNUM,        arm64_gcc::v29,            fpu_v29     },      NULL,              NULL}, -{   "v30",      NULL,  16,  FPU_OFFSET(30),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v30,          LLDB_INVALID_REGNUM,        arm64_gcc::v30,            fpu_v30     },      NULL,              NULL}, -{   "v31",      NULL,  16,  FPU_OFFSET(31),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v31,          LLDB_INVALID_REGNUM,        arm64_gcc::v31,            fpu_v31     },      NULL,              NULL}, +{   "v0",       nullptr, 16,  FPU_OFFSET(0),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v0,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v0      },      nullptr,        nullptr}, +{   "v1",       nullptr, 16,  FPU_OFFSET(1),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v1,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v1      },      nullptr,        nullptr}, +{   "v2",       nullptr, 16,  FPU_OFFSET(2),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v2,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v2      },      nullptr,        nullptr}, +{   "v3",       nullptr, 16,  FPU_OFFSET(3),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v3,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v3      },      nullptr,        nullptr}, +{   "v4",       nullptr, 16,  FPU_OFFSET(4),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v4,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v4      },      nullptr,        nullptr}, +{   "v5",       nullptr, 16,  FPU_OFFSET(5),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v5,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v5      },      nullptr,        nullptr}, +{   "v6",       nullptr, 16,  FPU_OFFSET(6),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v6,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v6      },      nullptr,        nullptr}, +{   "v7",       nullptr, 16,  FPU_OFFSET(7),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v7,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v7      },      nullptr,        nullptr}, +{   "v8",       nullptr, 16,  FPU_OFFSET(8),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v8,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v8      },      nullptr,        nullptr}, +{   "v9",       nullptr, 16,  FPU_OFFSET(9),      lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v9,           LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v9      },      nullptr,        nullptr}, +{   "v10",      nullptr, 16,  FPU_OFFSET(10),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v10,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v10     },      nullptr,        nullptr}, +{   "v11",      nullptr, 16,  FPU_OFFSET(11),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v11,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v11     },      nullptr,        nullptr}, +{   "v12",      nullptr, 16,  FPU_OFFSET(12),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v12,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v12     },      nullptr,        nullptr}, +{   "v13",      nullptr, 16,  FPU_OFFSET(13),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v13,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v13     },      nullptr,        nullptr}, +{   "v14",      nullptr, 16,  FPU_OFFSET(14),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v14,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v14     },      nullptr,        nullptr}, +{   "v15",      nullptr, 16,  FPU_OFFSET(15),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v15,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v15     },      nullptr,        nullptr}, +{   "v16",      nullptr, 16,  FPU_OFFSET(16),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v16,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v16     },      nullptr,        nullptr}, +{   "v17",      nullptr, 16,  FPU_OFFSET(17),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v17,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v17     },      nullptr,        nullptr}, +{   "v18",      nullptr, 16,  FPU_OFFSET(18),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v18,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v18     },      nullptr,        nullptr}, +{   "v19",      nullptr, 16,  FPU_OFFSET(19),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v19,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v19     },      nullptr,        nullptr}, +{   "v20",      nullptr, 16,  FPU_OFFSET(20),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v20,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v20     },      nullptr,        nullptr}, +{   "v21",      nullptr, 16,  FPU_OFFSET(21),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v21,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v21     },      nullptr,        nullptr}, +{   "v22",      nullptr, 16,  FPU_OFFSET(22),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v22,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v22     },      nullptr,        nullptr}, +{   "v23",      nullptr, 16,  FPU_OFFSET(23),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v23,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v23     },      nullptr,        nullptr}, +{   "v24",      nullptr, 16,  FPU_OFFSET(24),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v24,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v24     },      nullptr,        nullptr}, +{   "v25",      nullptr, 16,  FPU_OFFSET(25),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v25,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v25     },      nullptr,        nullptr}, +{   "v26",      nullptr, 16,  FPU_OFFSET(26),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v26,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v26     },      nullptr,        nullptr}, +{   "v27",      nullptr, 16,  FPU_OFFSET(27),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v27,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v27     },      nullptr,        nullptr}, +{   "v28",      nullptr, 16,  FPU_OFFSET(28),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v28,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v28     },      nullptr,        nullptr}, +{   "v29",      nullptr, 16,  FPU_OFFSET(29),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v29,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v29     },      nullptr,        nullptr}, +{   "v30",      nullptr, 16,  FPU_OFFSET(30),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v30,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v30     },      nullptr,        nullptr}, +{   "v31",      nullptr, 16,  FPU_OFFSET(31),     lldb::eEncodingVector, lldb::eFormatVectorOfUInt8,  { LLDB_INVALID_REGNUM,  arm64_dwarf::v31,          LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,       fpu_v31     },      nullptr,        nullptr}, -{   "fpsr",    NULL,   4,  FPU_OFFSET_NAME(fpsr),     lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpsr   },      NULL,              NULL}, -{   "fpcr",    NULL,   4,  FPU_OFFSET_NAME(fpcr),     lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpcr   },      NULL,              NULL}, +{   "fpsr",     nullptr,  4,  FPU_OFFSET_NAME(fpsr),     lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpsr   },      nullptr,        nullptr}, +{   "fpcr",     nullptr,  4,  FPU_OFFSET_NAME(fpcr),     lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,  fpu_fpcr   },      nullptr,        nullptr}, -{   "far",      NULL,   8,  EXC_OFFSET_NAME(far),       lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    NULL,              NULL}, -{   "esr",      NULL,   4,  EXC_OFFSET_NAME(esr),       lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_esr       },    NULL,              NULL}, -{   "exception",NULL,   4,  EXC_OFFSET_NAME(exception), lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL}, +{   "far",      nullptr,  8,  EXC_OFFSET_NAME(far),       lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    nullptr,        nullptr}, +{   "esr",      nullptr,  4,  EXC_OFFSET_NAME(esr),       lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_esr       },    nullptr,        nullptr}, +{   "exception",nullptr,  4,  EXC_OFFSET_NAME(exception), lldb::eEncodingUint,  lldb::eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    nullptr,        nullptr},  {   DEFINE_DBG (bvr, 0) },  {   DEFINE_DBG (bvr, 1) }, diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h index 69825362134b0..904ec4d1f0bdd 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_i386.h +++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h @@ -1,15 +1,21 @@ -//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===// +//===-- RegisterInfos_i386.h ------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" +//===----------------------------------------------------------------------===// +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Compiler.h" + +// Project includes +  #ifdef DECLARE_REGISTER_INFOS_I386_STRUCT  // Computes the offset of the given GPR in the user data area. @@ -52,31 +58,31 @@      { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint,   \        eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_i386 }, NULL, NULL } -// RegisterKind: GCC, DWARF, Generic, GDB, LLDB +// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB  #define DEFINE_FP_ST(reg, i)                                       \      { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]),    \        eEncodingVector, eFormatVectorOfUInt8,                       \ -      { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, lldb_st##i##_i386 }, \ +      { ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_i386 }, \        NULL, NULL }  #define DEFINE_FP_MM(reg, i)                                                \      { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]),   \        eEncodingUint, eFormatHex,                                            \ -      { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, lldb_mm##i##_i386 }, \ +      { ehframe_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_i386 }, \        NULL, NULL }  #define DEFINE_XMM(reg, i)                                         \      { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),   \        eEncodingVector, eFormatVectorOfUInt8,                       \ -      { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, lldb_##reg##i##_i386}, \ +      { ehframe_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386}, \        NULL, NULL }  // I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size.  #define DEFINE_YMM(reg, i)                                         \      { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i),        \        eEncodingVector, eFormatVectorOfUInt8,                       \ -      { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, lldb_##reg##i##_i386 }, \ +      { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \        NULL, NULL }  #define DEFINE_DR(reg, i)                                               \ @@ -98,22 +104,22 @@ static RegisterInfo  g_register_infos_i386[] =  {      // General purpose registers. -    DEFINE_GPR(eax,    NULL,    gcc_eax_i386,        dwarf_eax_i386,      LLDB_INVALID_REGNUM,       gdb_eax_i386), -    DEFINE_GPR(ebx,    NULL,    gcc_ebx_i386,        dwarf_ebx_i386,      LLDB_INVALID_REGNUM,       gdb_ebx_i386), -    DEFINE_GPR(ecx,    NULL,    gcc_ecx_i386,        dwarf_ecx_i386,      LLDB_INVALID_REGNUM,       gdb_ecx_i386), -    DEFINE_GPR(edx,    NULL,    gcc_edx_i386,        dwarf_edx_i386,      LLDB_INVALID_REGNUM,       gdb_edx_i386), -    DEFINE_GPR(edi,    NULL,    gcc_edi_i386,        dwarf_edi_i386,      LLDB_INVALID_REGNUM,       gdb_edi_i386), -    DEFINE_GPR(esi,    NULL,    gcc_esi_i386,        dwarf_esi_i386,      LLDB_INVALID_REGNUM,       gdb_esi_i386), -    DEFINE_GPR(ebp,    "fp",    gcc_ebp_i386,        dwarf_ebp_i386,      LLDB_REGNUM_GENERIC_FP,    gdb_ebp_i386), -    DEFINE_GPR(esp,    "sp",    gcc_esp_i386,        dwarf_esp_i386,      LLDB_REGNUM_GENERIC_SP,    gdb_esp_i386), -    DEFINE_GPR(eip,    "pc",    gcc_eip_i386,        dwarf_eip_i386,      LLDB_REGNUM_GENERIC_PC,    gdb_eip_i386), -    DEFINE_GPR(eflags, "flags", gcc_eflags_i386,     dwarf_eflags_i386,   LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386), -    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM, dwarf_cs_i386,       LLDB_INVALID_REGNUM,       gdb_cs_i386), -    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM, dwarf_fs_i386,       LLDB_INVALID_REGNUM,       gdb_fs_i386), -    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM, dwarf_gs_i386,       LLDB_INVALID_REGNUM,       gdb_gs_i386), -    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM, dwarf_ss_i386,       LLDB_INVALID_REGNUM,       gdb_ss_i386), -    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM, dwarf_ds_i386,       LLDB_INVALID_REGNUM,       gdb_ds_i386), -    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM, dwarf_es_i386,       LLDB_INVALID_REGNUM,       gdb_es_i386), +    DEFINE_GPR(eax,    nullptr, ehframe_eax_i386,    dwarf_eax_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ebx,    nullptr, ehframe_ebx_i386,    dwarf_ebx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ecx,    nullptr, ehframe_ecx_i386,    dwarf_ecx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(edx,    nullptr, ehframe_edx_i386,    dwarf_edx_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(edi,    nullptr, ehframe_edi_i386,    dwarf_edi_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(esi,    nullptr, ehframe_esi_i386,    dwarf_esi_i386,      LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ebp,    "fp",    ehframe_ebp_i386,    dwarf_ebp_i386,      LLDB_REGNUM_GENERIC_FP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(esp,    "sp",    ehframe_esp_i386,    dwarf_esp_i386,      LLDB_REGNUM_GENERIC_SP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(eip,    "pc",    ehframe_eip_i386,    dwarf_eip_i386,      LLDB_REGNUM_GENERIC_PC,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386,   LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), +    DEFINE_GPR(cs,     nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(fs,     nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(gs,     nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ss,     nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ds,     nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(es,     nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386,       LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM),      DEFINE_GPR_PSEUDO_16(ax,  eax),      DEFINE_GPR_PSEUDO_16(bx,  ebx), @@ -133,15 +139,15 @@ g_register_infos_i386[] =      DEFINE_GPR_PSEUDO_8L(dl,  edx),      // i387 Floating point registers. -    DEFINE_FPR(fctrl,     fctrl,          LLDB_INVALID_REGNUM, dwarf_fctrl_i386,    LLDB_INVALID_REGNUM, gdb_fctrl_i386), -    DEFINE_FPR(fstat,     fstat,          LLDB_INVALID_REGNUM, dwarf_fstat_i386,    LLDB_INVALID_REGNUM, gdb_fstat_i386), -    DEFINE_FPR(ftag,      ftag,           LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386), -    DEFINE_FPR(fop,       fop,            LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386), -    DEFINE_FPR(fiseg,     ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386), -    DEFINE_FPR(fioff,     ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386), -    DEFINE_FPR(foseg,     ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386), -    DEFINE_FPR(fooff,     ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386), -    DEFINE_FPR(mxcsr,     mxcsr,          LLDB_INVALID_REGNUM, dwarf_mxcsr_i386,    LLDB_INVALID_REGNUM, gdb_mxcsr_i386), +    DEFINE_FPR(fctrl,     fctrl,          LLDB_INVALID_REGNUM, dwarf_fctrl_i386,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fstat,     fstat,          LLDB_INVALID_REGNUM, dwarf_fstat_i386,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(ftag,      ftag,           LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fop,       fop,            LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fiseg,     ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fioff,     ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(foseg,     ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fooff,     ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(mxcsr,     mxcsr,          LLDB_INVALID_REGNUM, dwarf_mxcsr_i386,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),      DEFINE_FPR(mxcsrmask, mxcsrmask,      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),      // FP registers. @@ -192,6 +198,7 @@ g_register_infos_i386[] =      DEFINE_DR(dr, 6),      DEFINE_DR(dr, 7)  }; +  static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386,      "g_register_infos_x86_64 has wrong number of register infos"); diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips.h b/source/Plugins/Process/Utility/RegisterInfos_mips.h index 83ce6f0d4327a..eef27f0208e03 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_mips.h +++ b/source/Plugins/Process/Utility/RegisterInfos_mips.h @@ -6,10 +6,16 @@  // License. See LICENSE.TXT for details.  //  //===---------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Compiler.h" + +// Project includes +  #ifdef DECLARE_REGISTER_INFOS_MIPS_STRUCT  // Computes the offset of the given GPR in the user data area. @@ -44,123 +50,124 @@      { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \        eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL } -// RegisterKind: GCC, DWARF, Generic, GDB, LLDB +// RegisterKind: EH_Frame, DWARF, Generic, Procss Plugin, LLDB  static RegisterInfo  g_register_infos_mips[] =  { -    DEFINE_GPR (zero,     "zero", gcc_dwarf_zero_mips,  gcc_dwarf_zero_mips,  LLDB_INVALID_REGNUM,    gdb_zero_mips), -    DEFINE_GPR (r1,       "at",   gcc_dwarf_r1_mips,    gcc_dwarf_r1_mips,    LLDB_INVALID_REGNUM,    gdb_r1_mips), -    DEFINE_GPR (r2,       NULL,   gcc_dwarf_r2_mips,    gcc_dwarf_r2_mips,    LLDB_INVALID_REGNUM,    gdb_r2_mips), -    DEFINE_GPR (r3,       NULL,   gcc_dwarf_r3_mips,    gcc_dwarf_r3_mips,    LLDB_INVALID_REGNUM,    gdb_r3_mips), -    DEFINE_GPR (r4,       NULL,   gcc_dwarf_r4_mips,    gcc_dwarf_r4_mips,    LLDB_REGNUM_GENERIC_ARG1,    gdb_r4_mips), -    DEFINE_GPR (r5,       NULL,   gcc_dwarf_r5_mips,    gcc_dwarf_r5_mips,    LLDB_REGNUM_GENERIC_ARG2,    gdb_r5_mips), -    DEFINE_GPR (r6,       NULL,   gcc_dwarf_r6_mips,    gcc_dwarf_r6_mips,    LLDB_REGNUM_GENERIC_ARG3,    gdb_r6_mips), -    DEFINE_GPR (r7,       NULL,   gcc_dwarf_r7_mips,    gcc_dwarf_r7_mips,    LLDB_REGNUM_GENERIC_ARG4,    gdb_r7_mips), -    DEFINE_GPR (r8,       NULL,   gcc_dwarf_r8_mips,    gcc_dwarf_r8_mips,    LLDB_INVALID_REGNUM,    gdb_r8_mips), -    DEFINE_GPR (r9,       NULL,   gcc_dwarf_r9_mips,    gcc_dwarf_r9_mips,    LLDB_INVALID_REGNUM,    gdb_r9_mips), -    DEFINE_GPR (r10,      NULL,   gcc_dwarf_r10_mips,   gcc_dwarf_r10_mips,   LLDB_INVALID_REGNUM,    gdb_r10_mips), -    DEFINE_GPR (r11,      NULL,   gcc_dwarf_r11_mips,   gcc_dwarf_r11_mips,   LLDB_INVALID_REGNUM,    gdb_r11_mips), -    DEFINE_GPR (r12,      NULL,   gcc_dwarf_r12_mips,   gcc_dwarf_r12_mips,   LLDB_INVALID_REGNUM,    gdb_r12_mips), -    DEFINE_GPR (r13,      NULL,   gcc_dwarf_r13_mips,   gcc_dwarf_r13_mips,   LLDB_INVALID_REGNUM,    gdb_r13_mips), -    DEFINE_GPR (r14,      NULL,   gcc_dwarf_r14_mips,   gcc_dwarf_r14_mips,   LLDB_INVALID_REGNUM,    gdb_r14_mips), -    DEFINE_GPR (r15,      NULL,   gcc_dwarf_r15_mips,   gcc_dwarf_r15_mips,   LLDB_INVALID_REGNUM,    gdb_r15_mips), -    DEFINE_GPR (r16,      NULL,   gcc_dwarf_r16_mips,   gcc_dwarf_r16_mips,   LLDB_INVALID_REGNUM,    gdb_r16_mips), -    DEFINE_GPR (r17,      NULL,   gcc_dwarf_r17_mips,   gcc_dwarf_r17_mips,   LLDB_INVALID_REGNUM,    gdb_r17_mips), -    DEFINE_GPR (r18,      NULL,   gcc_dwarf_r18_mips,   gcc_dwarf_r18_mips,   LLDB_INVALID_REGNUM,    gdb_r18_mips), -    DEFINE_GPR (r19,      NULL,   gcc_dwarf_r19_mips,   gcc_dwarf_r19_mips,   LLDB_INVALID_REGNUM,    gdb_r19_mips), -    DEFINE_GPR (r20,      NULL,   gcc_dwarf_r20_mips,   gcc_dwarf_r20_mips,   LLDB_INVALID_REGNUM,    gdb_r20_mips), -    DEFINE_GPR (r21,      NULL,   gcc_dwarf_r21_mips,   gcc_dwarf_r21_mips,   LLDB_INVALID_REGNUM,    gdb_r21_mips), -    DEFINE_GPR (r22,      NULL,   gcc_dwarf_r22_mips,   gcc_dwarf_r22_mips,   LLDB_INVALID_REGNUM,    gdb_r22_mips), -    DEFINE_GPR (r23,      NULL,   gcc_dwarf_r23_mips,   gcc_dwarf_r23_mips,   LLDB_INVALID_REGNUM,    gdb_r23_mips), -    DEFINE_GPR (r24,      NULL,   gcc_dwarf_r24_mips,   gcc_dwarf_r24_mips,   LLDB_INVALID_REGNUM,    gdb_r24_mips), -    DEFINE_GPR (r25,      NULL,   gcc_dwarf_r25_mips,   gcc_dwarf_r25_mips,   LLDB_INVALID_REGNUM,    gdb_r25_mips), -    DEFINE_GPR (r26,      NULL,   gcc_dwarf_r26_mips,   gcc_dwarf_r26_mips,   LLDB_INVALID_REGNUM,    gdb_r26_mips), -    DEFINE_GPR (r27,      NULL,   gcc_dwarf_r27_mips,   gcc_dwarf_r27_mips,   LLDB_INVALID_REGNUM,    gdb_r27_mips), -    DEFINE_GPR (gp,       "gp",   gcc_dwarf_gp_mips,    gcc_dwarf_gp_mips,    LLDB_INVALID_REGNUM,    gdb_gp_mips), -    DEFINE_GPR (sp,       "sp",   gcc_dwarf_sp_mips,    gcc_dwarf_sp_mips,    LLDB_REGNUM_GENERIC_SP, gdb_sp_mips), -    DEFINE_GPR (r30,      "fp",   gcc_dwarf_r30_mips,   gcc_dwarf_r30_mips,   LLDB_REGNUM_GENERIC_FP, gdb_r30_mips), -    DEFINE_GPR (ra,       "ra",   gcc_dwarf_ra_mips,    gcc_dwarf_ra_mips,    LLDB_REGNUM_GENERIC_RA, gdb_ra_mips), -    DEFINE_GPR (sr,   "status",   gcc_dwarf_sr_mips,    gcc_dwarf_sr_mips,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), -    DEFINE_GPR (mullo,    NULL,   gcc_dwarf_lo_mips,    gcc_dwarf_lo_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR (mulhi,    NULL,   gcc_dwarf_hi_mips,    gcc_dwarf_hi_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR (badvaddr, NULL,   gcc_dwarf_bad_mips,    gcc_dwarf_bad_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR (cause,    NULL,   gcc_dwarf_cause_mips,    gcc_dwarf_cause_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR (pc,       NULL,   gcc_dwarf_pc_mips,    gcc_dwarf_pc_mips,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), -    DEFINE_GPR (config5,    NULL,   gcc_dwarf_config5_mips,    gcc_dwarf_config5_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_FPR (f0,    NULL,   gcc_dwarf_f0_mips,   gcc_dwarf_f0_mips,   LLDB_INVALID_REGNUM,    gdb_f0_mips), -    DEFINE_FPR (f1,    NULL,   gcc_dwarf_f1_mips,   gcc_dwarf_f1_mips,   LLDB_INVALID_REGNUM,    gdb_f1_mips), -    DEFINE_FPR (f2,    NULL,   gcc_dwarf_f2_mips,   gcc_dwarf_f2_mips,   LLDB_INVALID_REGNUM,    gdb_f2_mips), -    DEFINE_FPR (f3,    NULL,   gcc_dwarf_f3_mips,   gcc_dwarf_f3_mips,   LLDB_INVALID_REGNUM,    gdb_f3_mips), -    DEFINE_FPR (f4,    NULL,   gcc_dwarf_f4_mips,   gcc_dwarf_f4_mips,   LLDB_INVALID_REGNUM,    gdb_f4_mips), -    DEFINE_FPR (f5,    NULL,   gcc_dwarf_f5_mips,   gcc_dwarf_f5_mips,   LLDB_INVALID_REGNUM,    gdb_f5_mips), -    DEFINE_FPR (f6,    NULL,   gcc_dwarf_f6_mips,   gcc_dwarf_f6_mips,   LLDB_INVALID_REGNUM,    gdb_f6_mips), -    DEFINE_FPR (f7,    NULL,   gcc_dwarf_f7_mips,   gcc_dwarf_f7_mips,   LLDB_INVALID_REGNUM,    gdb_f7_mips), -    DEFINE_FPR (f8,    NULL,   gcc_dwarf_f8_mips,   gcc_dwarf_f8_mips,   LLDB_INVALID_REGNUM,    gdb_f8_mips), -    DEFINE_FPR (f9,    NULL,   gcc_dwarf_f9_mips,   gcc_dwarf_f9_mips,   LLDB_INVALID_REGNUM,    gdb_f9_mips), -    DEFINE_FPR (f10,   NULL,   gcc_dwarf_f10_mips,  gcc_dwarf_f10_mips,  LLDB_INVALID_REGNUM,    gdb_f10_mips), -    DEFINE_FPR (f11,   NULL,   gcc_dwarf_f11_mips,  gcc_dwarf_f11_mips,  LLDB_INVALID_REGNUM,    gdb_f11_mips), -    DEFINE_FPR (f12,   NULL,   gcc_dwarf_f12_mips,  gcc_dwarf_f12_mips,  LLDB_INVALID_REGNUM,    gdb_f12_mips), -    DEFINE_FPR (f13,   NULL,   gcc_dwarf_f13_mips,  gcc_dwarf_f13_mips,  LLDB_INVALID_REGNUM,    gdb_f13_mips), -    DEFINE_FPR (f14,   NULL,   gcc_dwarf_f14_mips,  gcc_dwarf_f14_mips,  LLDB_INVALID_REGNUM,    gdb_f14_mips), -    DEFINE_FPR (f15,   NULL,   gcc_dwarf_f15_mips,  gcc_dwarf_f15_mips,  LLDB_INVALID_REGNUM,    gdb_f15_mips), -    DEFINE_FPR (f16,   NULL,   gcc_dwarf_f16_mips,  gcc_dwarf_f16_mips,  LLDB_INVALID_REGNUM,    gdb_f16_mips), -    DEFINE_FPR (f17,   NULL,   gcc_dwarf_f17_mips,  gcc_dwarf_f17_mips,  LLDB_INVALID_REGNUM,    gdb_f17_mips), -    DEFINE_FPR (f18,   NULL,   gcc_dwarf_f18_mips,  gcc_dwarf_f18_mips,  LLDB_INVALID_REGNUM,    gdb_f18_mips), -    DEFINE_FPR (f19,   NULL,   gcc_dwarf_f19_mips,  gcc_dwarf_f19_mips,  LLDB_INVALID_REGNUM,    gdb_f19_mips), -    DEFINE_FPR (f20,   NULL,   gcc_dwarf_f20_mips,  gcc_dwarf_f20_mips,  LLDB_INVALID_REGNUM,    gdb_f20_mips), -    DEFINE_FPR (f21,   NULL,   gcc_dwarf_f21_mips,  gcc_dwarf_f21_mips,  LLDB_INVALID_REGNUM,    gdb_f21_mips), -    DEFINE_FPR (f22,   NULL,   gcc_dwarf_f22_mips,  gcc_dwarf_f22_mips,  LLDB_INVALID_REGNUM,    gdb_f22_mips), -    DEFINE_FPR (f23,   NULL,   gcc_dwarf_f23_mips,  gcc_dwarf_f23_mips,  LLDB_INVALID_REGNUM,    gdb_f23_mips), -    DEFINE_FPR (f24,   NULL,   gcc_dwarf_f24_mips,  gcc_dwarf_f24_mips,  LLDB_INVALID_REGNUM,    gdb_f24_mips), -    DEFINE_FPR (f25,   NULL,   gcc_dwarf_f25_mips,  gcc_dwarf_f25_mips,  LLDB_INVALID_REGNUM,    gdb_f25_mips), -    DEFINE_FPR (f26,   NULL,   gcc_dwarf_f26_mips,  gcc_dwarf_f26_mips,  LLDB_INVALID_REGNUM,    gdb_f26_mips), -    DEFINE_FPR (f27,   NULL,   gcc_dwarf_f27_mips,  gcc_dwarf_f27_mips,  LLDB_INVALID_REGNUM,    gdb_f27_mips), -    DEFINE_FPR (f28,   NULL,   gcc_dwarf_f28_mips,  gcc_dwarf_f28_mips,  LLDB_INVALID_REGNUM,    gdb_f28_mips), -    DEFINE_FPR (f29,   NULL,   gcc_dwarf_f29_mips,  gcc_dwarf_f29_mips,  LLDB_INVALID_REGNUM,    gdb_f29_mips), -    DEFINE_FPR (f30,   NULL,   gcc_dwarf_f30_mips,  gcc_dwarf_f30_mips,  LLDB_INVALID_REGNUM,    gdb_f30_mips), -    DEFINE_FPR (f31,   NULL,   gcc_dwarf_f31_mips,  gcc_dwarf_f31_mips,  LLDB_INVALID_REGNUM,    gdb_f31_mips), -    DEFINE_FPR (fcsr,  NULL,   gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM,    gdb_fcsr_mips), -    DEFINE_FPR (fir,   NULL,   gcc_dwarf_fir_mips,  gcc_dwarf_fir_mips,  LLDB_INVALID_REGNUM,    gdb_fir_mips), -    DEFINE_FPR (config5,   NULL,   gcc_dwarf_config5_mips,  gcc_dwarf_config5_mips,  LLDB_INVALID_REGNUM,    gdb_config5_mips), -    DEFINE_MSA (w0,    NULL,   gcc_dwarf_w0_mips,   gcc_dwarf_w0_mips,   LLDB_INVALID_REGNUM,    gdb_w0_mips), -    DEFINE_MSA (w1,    NULL,   gcc_dwarf_w1_mips,   gcc_dwarf_w1_mips,   LLDB_INVALID_REGNUM,    gdb_w1_mips), -    DEFINE_MSA (w2,    NULL,   gcc_dwarf_w2_mips,   gcc_dwarf_w2_mips,   LLDB_INVALID_REGNUM,    gdb_w2_mips), -    DEFINE_MSA (w3,    NULL,   gcc_dwarf_w3_mips,   gcc_dwarf_w3_mips,   LLDB_INVALID_REGNUM,    gdb_w3_mips), -    DEFINE_MSA (w4,    NULL,   gcc_dwarf_w4_mips,   gcc_dwarf_w4_mips,   LLDB_INVALID_REGNUM,    gdb_w4_mips), -    DEFINE_MSA (w5,    NULL,   gcc_dwarf_w5_mips,   gcc_dwarf_w5_mips,   LLDB_INVALID_REGNUM,    gdb_w5_mips), -    DEFINE_MSA (w6,    NULL,   gcc_dwarf_w6_mips,   gcc_dwarf_w6_mips,   LLDB_INVALID_REGNUM,    gdb_w6_mips), -    DEFINE_MSA (w7,    NULL,   gcc_dwarf_w7_mips,   gcc_dwarf_w7_mips,   LLDB_INVALID_REGNUM,    gdb_w7_mips), -    DEFINE_MSA (w8,    NULL,   gcc_dwarf_w8_mips,   gcc_dwarf_w8_mips,   LLDB_INVALID_REGNUM,    gdb_w8_mips), -    DEFINE_MSA (w9,    NULL,   gcc_dwarf_w9_mips,   gcc_dwarf_w9_mips,   LLDB_INVALID_REGNUM,    gdb_w9_mips), -    DEFINE_MSA (w10,   NULL,   gcc_dwarf_w10_mips,  gcc_dwarf_w10_mips,  LLDB_INVALID_REGNUM,    gdb_w10_mips), -    DEFINE_MSA (w11,   NULL,   gcc_dwarf_w11_mips,  gcc_dwarf_w11_mips,  LLDB_INVALID_REGNUM,    gdb_w11_mips), -    DEFINE_MSA (w12,   NULL,   gcc_dwarf_w12_mips,  gcc_dwarf_w12_mips,  LLDB_INVALID_REGNUM,    gdb_w12_mips), -    DEFINE_MSA (w13,   NULL,   gcc_dwarf_w13_mips,  gcc_dwarf_w13_mips,  LLDB_INVALID_REGNUM,    gdb_w13_mips), -    DEFINE_MSA (w14,   NULL,   gcc_dwarf_w14_mips,  gcc_dwarf_w14_mips,  LLDB_INVALID_REGNUM,    gdb_w14_mips), -    DEFINE_MSA (w15,   NULL,   gcc_dwarf_w15_mips,  gcc_dwarf_w15_mips,  LLDB_INVALID_REGNUM,    gdb_w15_mips), -    DEFINE_MSA (w16,   NULL,   gcc_dwarf_w16_mips,  gcc_dwarf_w16_mips,  LLDB_INVALID_REGNUM,    gdb_w16_mips), -    DEFINE_MSA (w17,   NULL,   gcc_dwarf_w17_mips,  gcc_dwarf_w17_mips,  LLDB_INVALID_REGNUM,    gdb_w17_mips), -    DEFINE_MSA (w18,   NULL,   gcc_dwarf_w18_mips,  gcc_dwarf_w18_mips,  LLDB_INVALID_REGNUM,    gdb_w18_mips), -    DEFINE_MSA (w19,   NULL,   gcc_dwarf_w19_mips,  gcc_dwarf_w19_mips,  LLDB_INVALID_REGNUM,    gdb_w19_mips), -    DEFINE_MSA (w20,   NULL,   gcc_dwarf_w10_mips,  gcc_dwarf_w20_mips,  LLDB_INVALID_REGNUM,    gdb_w20_mips), -    DEFINE_MSA (w21,   NULL,   gcc_dwarf_w21_mips,  gcc_dwarf_w21_mips,  LLDB_INVALID_REGNUM,    gdb_w21_mips), -    DEFINE_MSA (w22,   NULL,   gcc_dwarf_w22_mips,  gcc_dwarf_w22_mips,  LLDB_INVALID_REGNUM,    gdb_w22_mips), -    DEFINE_MSA (w23,   NULL,   gcc_dwarf_w23_mips,  gcc_dwarf_w23_mips,  LLDB_INVALID_REGNUM,    gdb_w23_mips), -    DEFINE_MSA (w24,   NULL,   gcc_dwarf_w24_mips,  gcc_dwarf_w24_mips,  LLDB_INVALID_REGNUM,    gdb_w24_mips), -    DEFINE_MSA (w25,   NULL,   gcc_dwarf_w25_mips,  gcc_dwarf_w25_mips,  LLDB_INVALID_REGNUM,    gdb_w25_mips), -    DEFINE_MSA (w26,   NULL,   gcc_dwarf_w26_mips,  gcc_dwarf_w26_mips,  LLDB_INVALID_REGNUM,    gdb_w26_mips), -    DEFINE_MSA (w27,   NULL,   gcc_dwarf_w27_mips,  gcc_dwarf_w27_mips,  LLDB_INVALID_REGNUM,    gdb_w27_mips), -    DEFINE_MSA (w28,   NULL,   gcc_dwarf_w28_mips,  gcc_dwarf_w28_mips,  LLDB_INVALID_REGNUM,    gdb_w28_mips), -    DEFINE_MSA (w29,   NULL,   gcc_dwarf_w29_mips,  gcc_dwarf_w29_mips,  LLDB_INVALID_REGNUM,    gdb_w29_mips), -    DEFINE_MSA (w30,   NULL,   gcc_dwarf_w30_mips,  gcc_dwarf_w30_mips,  LLDB_INVALID_REGNUM,    gdb_w30_mips), -    DEFINE_MSA (w31,   NULL,   gcc_dwarf_w31_mips,  gcc_dwarf_w31_mips,  LLDB_INVALID_REGNUM,    gdb_w31_mips), -    DEFINE_MSA_INFO (mcsr,  NULL,   gcc_dwarf_mcsr_mips, gcc_dwarf_mcsr_mips, LLDB_INVALID_REGNUM,    gdb_mcsr_mips), -    DEFINE_MSA_INFO (mir,   NULL,   gcc_dwarf_mir_mips,  gcc_dwarf_mir_mips,  LLDB_INVALID_REGNUM,    gdb_mir_mips), -    DEFINE_MSA_INFO (fcsr,  NULL,   gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM,    gdb_fcsr_mips), -    DEFINE_MSA_INFO (fir,   NULL,   gcc_dwarf_fir_mips,  gcc_dwarf_fir_mips,  LLDB_INVALID_REGNUM,    gdb_fir_mips), -    DEFINE_MSA_INFO (config5, NULL,   gcc_dwarf_config5_mips,  gcc_dwarf_config5_mips,  LLDB_INVALID_REGNUM,    gdb_config5_mips) +    DEFINE_GPR (zero,     "zero",     dwarf_zero_mips,      dwarf_zero_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r1,       "at",       dwarf_r1_mips,        dwarf_r1_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r2,       nullptr,    dwarf_r2_mips,        dwarf_r2_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r3,       nullptr,    dwarf_r3_mips,        dwarf_r3_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r4,       nullptr,    dwarf_r4_mips,        dwarf_r4_mips,    LLDB_REGNUM_GENERIC_ARG1,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r5,       nullptr,    dwarf_r5_mips,        dwarf_r5_mips,    LLDB_REGNUM_GENERIC_ARG2,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r6,       nullptr,    dwarf_r6_mips,        dwarf_r6_mips,    LLDB_REGNUM_GENERIC_ARG3,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r7,       nullptr,    dwarf_r7_mips,        dwarf_r7_mips,    LLDB_REGNUM_GENERIC_ARG4,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r8,       nullptr,    dwarf_r8_mips,        dwarf_r8_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r9,       nullptr,    dwarf_r9_mips,        dwarf_r9_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r10,      nullptr,    dwarf_r10_mips,       dwarf_r10_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r11,      nullptr,    dwarf_r11_mips,       dwarf_r11_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r12,      nullptr,    dwarf_r12_mips,       dwarf_r12_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r13,      nullptr,    dwarf_r13_mips,       dwarf_r13_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r14,      nullptr,    dwarf_r14_mips,       dwarf_r14_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r15,      nullptr,    dwarf_r15_mips,       dwarf_r15_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r16,      nullptr,    dwarf_r16_mips,       dwarf_r16_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r17,      nullptr,    dwarf_r17_mips,       dwarf_r17_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r18,      nullptr,    dwarf_r18_mips,       dwarf_r18_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r19,      nullptr,    dwarf_r19_mips,       dwarf_r19_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r20,      nullptr,    dwarf_r20_mips,       dwarf_r20_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r21,      nullptr,    dwarf_r21_mips,       dwarf_r21_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r22,      nullptr,    dwarf_r22_mips,       dwarf_r22_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r23,      nullptr,    dwarf_r23_mips,       dwarf_r23_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r24,      nullptr,    dwarf_r24_mips,       dwarf_r24_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r25,      nullptr,    dwarf_r25_mips,       dwarf_r25_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r26,      nullptr,    dwarf_r26_mips,       dwarf_r26_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (r27,      nullptr,    dwarf_r27_mips,       dwarf_r27_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (gp,       "gp",       dwarf_gp_mips,        dwarf_gp_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (sp,       "sp",       dwarf_sp_mips,        dwarf_sp_mips,    LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), +    DEFINE_GPR (r30,      "fp",       dwarf_r30_mips,       dwarf_r30_mips,   LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), +    DEFINE_GPR (ra,       "ra",       dwarf_ra_mips,        dwarf_ra_mips,    LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), +    DEFINE_GPR (sr,   "status",       dwarf_sr_mips,        dwarf_sr_mips,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (mullo,    nullptr,    dwarf_lo_mips,        dwarf_lo_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (mulhi,    nullptr,    dwarf_hi_mips,        dwarf_hi_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (badvaddr, nullptr,    dwarf_bad_mips,        dwarf_bad_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (cause,    nullptr,    dwarf_cause_mips,        dwarf_cause_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR (pc,       nullptr,    dwarf_pc_mips,        dwarf_pc_mips,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), +    DEFINE_GPR (config5,    nullptr,    dwarf_config5_mips,        dwarf_config5_mips,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f0,    nullptr,    dwarf_f0_mips,       dwarf_f0_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f1,    nullptr,    dwarf_f1_mips,       dwarf_f1_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f2,    nullptr,    dwarf_f2_mips,       dwarf_f2_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f3,    nullptr,    dwarf_f3_mips,       dwarf_f3_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f4,    nullptr,    dwarf_f4_mips,       dwarf_f4_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f5,    nullptr,    dwarf_f5_mips,       dwarf_f5_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f6,    nullptr,    dwarf_f6_mips,       dwarf_f6_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f7,    nullptr,    dwarf_f7_mips,       dwarf_f7_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f8,    nullptr,    dwarf_f8_mips,       dwarf_f8_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f9,    nullptr,    dwarf_f9_mips,       dwarf_f9_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f10,   nullptr,    dwarf_f10_mips,      dwarf_f10_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f11,   nullptr,    dwarf_f11_mips,      dwarf_f11_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f12,   nullptr,    dwarf_f12_mips,      dwarf_f12_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f13,   nullptr,    dwarf_f13_mips,      dwarf_f13_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f14,   nullptr,    dwarf_f14_mips,      dwarf_f14_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f15,   nullptr,    dwarf_f15_mips,      dwarf_f15_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f16,   nullptr,    dwarf_f16_mips,      dwarf_f16_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f17,   nullptr,    dwarf_f17_mips,      dwarf_f17_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f18,   nullptr,    dwarf_f18_mips,      dwarf_f18_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f19,   nullptr,    dwarf_f19_mips,      dwarf_f19_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f20,   nullptr,    dwarf_f20_mips,      dwarf_f20_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f21,   nullptr,    dwarf_f21_mips,      dwarf_f21_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f22,   nullptr,    dwarf_f22_mips,      dwarf_f22_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f23,   nullptr,    dwarf_f23_mips,      dwarf_f23_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f24,   nullptr,    dwarf_f24_mips,      dwarf_f24_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f25,   nullptr,    dwarf_f25_mips,      dwarf_f25_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f26,   nullptr,    dwarf_f26_mips,      dwarf_f26_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f27,   nullptr,    dwarf_f27_mips,      dwarf_f27_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f28,   nullptr,    dwarf_f28_mips,      dwarf_f28_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f29,   nullptr,    dwarf_f29_mips,      dwarf_f29_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f30,   nullptr,    dwarf_f30_mips,      dwarf_f30_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f31,   nullptr,    dwarf_f31_mips,      dwarf_f31_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (fcsr,  nullptr,    dwarf_fcsr_mips,     dwarf_fcsr_mips, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (fir,   nullptr,    dwarf_fir_mips,      dwarf_fir_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (config5,   nullptr,    dwarf_config5_mips,      dwarf_config5_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w0,    nullptr,    dwarf_w0_mips,       dwarf_w0_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w1,    nullptr,    dwarf_w1_mips,       dwarf_w1_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w2,    nullptr,    dwarf_w2_mips,       dwarf_w2_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w3,    nullptr,    dwarf_w3_mips,       dwarf_w3_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w4,    nullptr,    dwarf_w4_mips,       dwarf_w4_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w5,    nullptr,    dwarf_w5_mips,       dwarf_w5_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w6,    nullptr,    dwarf_w6_mips,       dwarf_w6_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w7,    nullptr,    dwarf_w7_mips,       dwarf_w7_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w8,    nullptr,    dwarf_w8_mips,       dwarf_w8_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w9,    nullptr,    dwarf_w9_mips,       dwarf_w9_mips,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w10,   nullptr,    dwarf_w10_mips,      dwarf_w10_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w11,   nullptr,    dwarf_w11_mips,      dwarf_w11_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w12,   nullptr,    dwarf_w12_mips,      dwarf_w12_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w13,   nullptr,    dwarf_w13_mips,      dwarf_w13_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w14,   nullptr,    dwarf_w14_mips,      dwarf_w14_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w15,   nullptr,    dwarf_w15_mips,      dwarf_w15_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w16,   nullptr,    dwarf_w16_mips,      dwarf_w16_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w17,   nullptr,    dwarf_w17_mips,      dwarf_w17_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w18,   nullptr,    dwarf_w18_mips,      dwarf_w18_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w19,   nullptr,    dwarf_w19_mips,      dwarf_w19_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w20,   nullptr,    dwarf_w10_mips,      dwarf_w20_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w21,   nullptr,    dwarf_w21_mips,      dwarf_w21_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w22,   nullptr,    dwarf_w22_mips,      dwarf_w22_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w23,   nullptr,    dwarf_w23_mips,      dwarf_w23_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w24,   nullptr,    dwarf_w24_mips,      dwarf_w24_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w25,   nullptr,    dwarf_w25_mips,      dwarf_w25_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w26,   nullptr,    dwarf_w26_mips,      dwarf_w26_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w27,   nullptr,    dwarf_w27_mips,      dwarf_w27_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w28,   nullptr,    dwarf_w28_mips,      dwarf_w28_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w29,   nullptr,    dwarf_w29_mips,      dwarf_w29_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w30,   nullptr,    dwarf_w30_mips,      dwarf_w30_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w31,   nullptr,    dwarf_w31_mips,      dwarf_w31_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (mcsr,  nullptr,    dwarf_mcsr_mips,     dwarf_mcsr_mips, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (mir,   nullptr,    dwarf_mir_mips,      dwarf_mir_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (fcsr,  nullptr,    dwarf_fcsr_mips,     dwarf_fcsr_mips, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (fir,   nullptr,    dwarf_fir_mips,      dwarf_fir_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (config5, nullptr,    dwarf_config5_mips,      dwarf_config5_mips,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM)  }; +  static_assert((sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])) == k_num_registers_mips,      "g_register_infos_mips has wrong number of register infos"); diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/source/Plugins/Process/Utility/RegisterInfos_mips64.h index 101842e66d498..45853d7931ddb 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_mips64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_mips64.h @@ -1,15 +1,21 @@ -//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===// +//===-- RegisterInfos_mips64.h ----------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" +//===----------------------------------------------------------------------===// +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Compiler.h" + +// Project includes +  #ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT  // Computes the offset of the given GPR in the user data area. @@ -32,7 +38,7 @@       (LLVM_EXTENSION offsetof(UserArea, msa) + \        LLVM_EXTENSION offsetof(MSA_linux_mips, regname)) -// RegisterKind: GCC, DWARF, Generic, GDB, LLDB +// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB  // Note that the size and offset will be updated by platform-specific classes.  #ifdef LINUX_MIPS64 @@ -64,161 +70,160 @@  static RegisterInfo  g_register_infos_mips64[] =  { -    // General purpose registers.                 GCC,                  DWARF,              Generic,                GDB +    // General purpose registers.            EH_Frame,                  DWARF,              Generic,    Process Plugin  #ifndef LINUX_MIPS64 -    DEFINE_GPR(zero,     "r0",  gcc_dwarf_zero_mips64,  gcc_dwarf_zero_mips64,  LLDB_INVALID_REGNUM,    gdb_zero_mips64), -    DEFINE_GPR(r1,       NULL,  gcc_dwarf_r1_mips64,    gcc_dwarf_r1_mips64,    LLDB_INVALID_REGNUM,    gdb_r1_mips64), -    DEFINE_GPR(r2,       NULL,  gcc_dwarf_r2_mips64,    gcc_dwarf_r2_mips64,    LLDB_INVALID_REGNUM,    gdb_r2_mips64), -    DEFINE_GPR(r3,       NULL,  gcc_dwarf_r3_mips64,    gcc_dwarf_r3_mips64,    LLDB_INVALID_REGNUM,    gdb_r3_mips64), -    DEFINE_GPR(r4,       NULL,  gcc_dwarf_r4_mips64,    gcc_dwarf_r4_mips64,    LLDB_REGNUM_GENERIC_ARG1,    gdb_r4_mips64), -    DEFINE_GPR(r5,       NULL,  gcc_dwarf_r5_mips64,    gcc_dwarf_r5_mips64,    LLDB_REGNUM_GENERIC_ARG2,    gdb_r5_mips64), -    DEFINE_GPR(r6,       NULL,  gcc_dwarf_r6_mips64,    gcc_dwarf_r6_mips64,    LLDB_REGNUM_GENERIC_ARG3,    gdb_r6_mips64), -    DEFINE_GPR(r7,       NULL,  gcc_dwarf_r7_mips64,    gcc_dwarf_r7_mips64,    LLDB_REGNUM_GENERIC_ARG4,    gdb_r7_mips64), -    DEFINE_GPR(r8,       NULL,  gcc_dwarf_r8_mips64,    gcc_dwarf_r8_mips64,    LLDB_REGNUM_GENERIC_ARG5,    gdb_r8_mips64), -    DEFINE_GPR(r9,       NULL,  gcc_dwarf_r9_mips64,    gcc_dwarf_r9_mips64,    LLDB_REGNUM_GENERIC_ARG6,    gdb_r9_mips64), -    DEFINE_GPR(r10,      NULL,  gcc_dwarf_r10_mips64,   gcc_dwarf_r10_mips64,   LLDB_REGNUM_GENERIC_ARG7,    gdb_r10_mips64), -    DEFINE_GPR(r11,      NULL,  gcc_dwarf_r11_mips64,   gcc_dwarf_r11_mips64,   LLDB_REGNUM_GENERIC_ARG8,    gdb_r11_mips64), -    DEFINE_GPR(r12,      NULL,  gcc_dwarf_r12_mips64,   gcc_dwarf_r12_mips64,   LLDB_INVALID_REGNUM,    gdb_r12_mips64), -    DEFINE_GPR(r13,      NULL,  gcc_dwarf_r13_mips64,   gcc_dwarf_r13_mips64,   LLDB_INVALID_REGNUM,    gdb_r13_mips64), -    DEFINE_GPR(r14,      NULL,  gcc_dwarf_r14_mips64,   gcc_dwarf_r14_mips64,   LLDB_INVALID_REGNUM,    gdb_r14_mips64), -    DEFINE_GPR(r15,      NULL,  gcc_dwarf_r15_mips64,   gcc_dwarf_r15_mips64,   LLDB_INVALID_REGNUM,    gdb_r15_mips64), -    DEFINE_GPR(r16,      NULL,  gcc_dwarf_r16_mips64,   gcc_dwarf_r16_mips64,   LLDB_INVALID_REGNUM,    gdb_r16_mips64), -    DEFINE_GPR(r17,      NULL,  gcc_dwarf_r17_mips64,   gcc_dwarf_r17_mips64,   LLDB_INVALID_REGNUM,    gdb_r17_mips64), -    DEFINE_GPR(r18,      NULL,  gcc_dwarf_r18_mips64,   gcc_dwarf_r18_mips64,   LLDB_INVALID_REGNUM,    gdb_r18_mips64), -    DEFINE_GPR(r19,      NULL,  gcc_dwarf_r19_mips64,   gcc_dwarf_r19_mips64,   LLDB_INVALID_REGNUM,    gdb_r19_mips64), -    DEFINE_GPR(r20,      NULL,  gcc_dwarf_r20_mips64,   gcc_dwarf_r20_mips64,   LLDB_INVALID_REGNUM,    gdb_r20_mips64), -    DEFINE_GPR(r21,      NULL,  gcc_dwarf_r21_mips64,   gcc_dwarf_r21_mips64,   LLDB_INVALID_REGNUM,    gdb_r21_mips64), -    DEFINE_GPR(r22,      NULL,  gcc_dwarf_r22_mips64,   gcc_dwarf_r22_mips64,   LLDB_INVALID_REGNUM,    gdb_r22_mips64), -    DEFINE_GPR(r23,      NULL,  gcc_dwarf_r23_mips64,   gcc_dwarf_r23_mips64,   LLDB_INVALID_REGNUM,    gdb_r23_mips64), -    DEFINE_GPR(r24,      NULL,  gcc_dwarf_r24_mips64,   gcc_dwarf_r24_mips64,   LLDB_INVALID_REGNUM,    gdb_r24_mips64), -    DEFINE_GPR(r25,      NULL,  gcc_dwarf_r25_mips64,   gcc_dwarf_r25_mips64,   LLDB_INVALID_REGNUM,    gdb_r25_mips64), -    DEFINE_GPR(r26,      NULL,  gcc_dwarf_r26_mips64,   gcc_dwarf_r26_mips64,   LLDB_INVALID_REGNUM,    gdb_r26_mips64), -    DEFINE_GPR(r27,      NULL,  gcc_dwarf_r27_mips64,   gcc_dwarf_r27_mips64,   LLDB_INVALID_REGNUM,    gdb_r27_mips64), -    DEFINE_GPR(gp,       "r28", gcc_dwarf_gp_mips64,    gcc_dwarf_gp_mips64,    LLDB_INVALID_REGNUM,    gdb_gp_mips64), -    DEFINE_GPR(sp,       "r29", gcc_dwarf_sp_mips64,    gcc_dwarf_sp_mips64,    LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64), -    DEFINE_GPR(r30,      NULL,  gcc_dwarf_r30_mips64,   gcc_dwarf_r30_mips64,   LLDB_REGNUM_GENERIC_FP,    gdb_r30_mips64), -    DEFINE_GPR(ra,       "r31", gcc_dwarf_ra_mips64,    gcc_dwarf_ra_mips64,    LLDB_REGNUM_GENERIC_RA,    gdb_ra_mips64), -    DEFINE_GPR(sr,       NULL,  gcc_dwarf_sr_mips64,    gcc_dwarf_sr_mips64,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(mullo,    NULL,  gcc_dwarf_lo_mips64,    gcc_dwarf_lo_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(mulhi,    NULL,  gcc_dwarf_hi_mips64,    gcc_dwarf_hi_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(badvaddr, NULL,  gcc_dwarf_bad_mips64,   gcc_dwarf_bad_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(cause,    NULL,  gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(pc,       "pc",  gcc_dwarf_pc_mips64,    gcc_dwarf_pc_mips64,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), -    DEFINE_GPR(ic,       NULL,  gcc_dwarf_ic_mips64,    gcc_dwarf_ic_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(dummy,    NULL,  gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(zero,     "r0",      dwarf_zero_mips64,      dwarf_zero_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r1,       nullptr,   dwarf_r1_mips64,        dwarf_r1_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r2,       nullptr,   dwarf_r2_mips64,        dwarf_r2_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r3,       nullptr,   dwarf_r3_mips64,        dwarf_r3_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r4,       nullptr,   dwarf_r4_mips64,        dwarf_r4_mips64,    LLDB_REGNUM_GENERIC_ARG1,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r5,       nullptr,   dwarf_r5_mips64,        dwarf_r5_mips64,    LLDB_REGNUM_GENERIC_ARG2,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r6,       nullptr,   dwarf_r6_mips64,        dwarf_r6_mips64,    LLDB_REGNUM_GENERIC_ARG3,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r7,       nullptr,   dwarf_r7_mips64,        dwarf_r7_mips64,    LLDB_REGNUM_GENERIC_ARG4,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r8,       nullptr,   dwarf_r8_mips64,        dwarf_r8_mips64,    LLDB_REGNUM_GENERIC_ARG5,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r9,       nullptr,   dwarf_r9_mips64,        dwarf_r9_mips64,    LLDB_REGNUM_GENERIC_ARG6,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r10,      nullptr,   dwarf_r10_mips64,       dwarf_r10_mips64,   LLDB_REGNUM_GENERIC_ARG7,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r11,      nullptr,   dwarf_r11_mips64,       dwarf_r11_mips64,   LLDB_REGNUM_GENERIC_ARG8,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r12,      nullptr,   dwarf_r12_mips64,       dwarf_r12_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r13,      nullptr,   dwarf_r13_mips64,       dwarf_r13_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r14,      nullptr,   dwarf_r14_mips64,       dwarf_r14_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r15,      nullptr,   dwarf_r15_mips64,       dwarf_r15_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r16,      nullptr,   dwarf_r16_mips64,       dwarf_r16_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r17,      nullptr,   dwarf_r17_mips64,       dwarf_r17_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r18,      nullptr,   dwarf_r18_mips64,       dwarf_r18_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r19,      nullptr,   dwarf_r19_mips64,       dwarf_r19_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r20,      nullptr,   dwarf_r20_mips64,       dwarf_r20_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r21,      nullptr,   dwarf_r21_mips64,       dwarf_r21_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r22,      nullptr,   dwarf_r22_mips64,       dwarf_r22_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r23,      nullptr,   dwarf_r23_mips64,       dwarf_r23_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r24,      nullptr,   dwarf_r24_mips64,       dwarf_r24_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r25,      nullptr,   dwarf_r25_mips64,       dwarf_r25_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r26,      nullptr,   dwarf_r26_mips64,       dwarf_r26_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r27,      nullptr,   dwarf_r27_mips64,       dwarf_r27_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(gp,       "r28",     dwarf_gp_mips64,        dwarf_gp_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(sp,       "r29",     dwarf_sp_mips64,        dwarf_sp_mips64,    LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r30,      nullptr,   dwarf_r30_mips64,       dwarf_r30_mips64,   LLDB_REGNUM_GENERIC_FP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(ra,       "r31",     dwarf_ra_mips64,        dwarf_ra_mips64,    LLDB_REGNUM_GENERIC_RA,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(sr,       nullptr,   dwarf_sr_mips64,        dwarf_sr_mips64,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(mullo,    nullptr,   dwarf_lo_mips64,        dwarf_lo_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(mulhi,    nullptr,   dwarf_hi_mips64,        dwarf_hi_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(badvaddr, nullptr,   dwarf_bad_mips64,       dwarf_bad_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(cause,    nullptr,   dwarf_cause_mips64,     dwarf_cause_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(pc,       "pc",      dwarf_pc_mips64,        dwarf_pc_mips64,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), +    DEFINE_GPR(ic,       nullptr,   dwarf_ic_mips64,        dwarf_ic_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(dummy,    nullptr,   dwarf_dummy_mips64,     dwarf_dummy_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM),  #else - -    DEFINE_GPR(zero,     "r0",  gcc_dwarf_zero_mips64,  gcc_dwarf_zero_mips64,  LLDB_INVALID_REGNUM,    gdb_zero_mips64), -    DEFINE_GPR(r1,       NULL,  gcc_dwarf_r1_mips64,    gcc_dwarf_r1_mips64,    LLDB_INVALID_REGNUM,    gdb_r1_mips64), -    DEFINE_GPR(r2,       NULL,  gcc_dwarf_r2_mips64,    gcc_dwarf_r2_mips64,    LLDB_INVALID_REGNUM,    gdb_r2_mips64), -    DEFINE_GPR(r3,       NULL,  gcc_dwarf_r3_mips64,    gcc_dwarf_r3_mips64,    LLDB_INVALID_REGNUM,    gdb_r3_mips64), -    DEFINE_GPR(r4,       NULL,  gcc_dwarf_r4_mips64,    gcc_dwarf_r4_mips64,    LLDB_REGNUM_GENERIC_ARG1,    gdb_r4_mips64), -    DEFINE_GPR(r5,       NULL,  gcc_dwarf_r5_mips64,    gcc_dwarf_r5_mips64,    LLDB_REGNUM_GENERIC_ARG2,    gdb_r5_mips64), -    DEFINE_GPR(r6,       NULL,  gcc_dwarf_r6_mips64,    gcc_dwarf_r6_mips64,    LLDB_REGNUM_GENERIC_ARG3,    gdb_r6_mips64), -    DEFINE_GPR(r7,       NULL,  gcc_dwarf_r7_mips64,    gcc_dwarf_r7_mips64,    LLDB_REGNUM_GENERIC_ARG4,    gdb_r7_mips64), -    DEFINE_GPR(r8,       NULL,  gcc_dwarf_r8_mips64,    gcc_dwarf_r8_mips64,    LLDB_REGNUM_GENERIC_ARG5,    gdb_r8_mips64), -    DEFINE_GPR(r9,       NULL,  gcc_dwarf_r9_mips64,    gcc_dwarf_r9_mips64,    LLDB_REGNUM_GENERIC_ARG6,    gdb_r9_mips64), -    DEFINE_GPR(r10,      NULL,  gcc_dwarf_r10_mips64,   gcc_dwarf_r10_mips64,   LLDB_REGNUM_GENERIC_ARG7,    gdb_r10_mips64), -    DEFINE_GPR(r11,      NULL,  gcc_dwarf_r11_mips64,   gcc_dwarf_r11_mips64,   LLDB_REGNUM_GENERIC_ARG8,    gdb_r11_mips64), -    DEFINE_GPR(r12,      NULL,  gcc_dwarf_r12_mips64,   gcc_dwarf_r12_mips64,   LLDB_INVALID_REGNUM,    gdb_r12_mips64), -    DEFINE_GPR(r13,      NULL,  gcc_dwarf_r13_mips64,   gcc_dwarf_r13_mips64,   LLDB_INVALID_REGNUM,    gdb_r13_mips64), -    DEFINE_GPR(r14,      NULL,  gcc_dwarf_r14_mips64,   gcc_dwarf_r14_mips64,   LLDB_INVALID_REGNUM,    gdb_r14_mips64), -    DEFINE_GPR(r15,      NULL,  gcc_dwarf_r15_mips64,   gcc_dwarf_r15_mips64,   LLDB_INVALID_REGNUM,    gdb_r15_mips64), -    DEFINE_GPR(r16,      NULL,  gcc_dwarf_r16_mips64,   gcc_dwarf_r16_mips64,   LLDB_INVALID_REGNUM,    gdb_r16_mips64), -    DEFINE_GPR(r17,      NULL,  gcc_dwarf_r17_mips64,   gcc_dwarf_r17_mips64,   LLDB_INVALID_REGNUM,    gdb_r17_mips64), -    DEFINE_GPR(r18,      NULL,  gcc_dwarf_r18_mips64,   gcc_dwarf_r18_mips64,   LLDB_INVALID_REGNUM,    gdb_r18_mips64), -    DEFINE_GPR(r19,      NULL,  gcc_dwarf_r19_mips64,   gcc_dwarf_r19_mips64,   LLDB_INVALID_REGNUM,    gdb_r19_mips64), -    DEFINE_GPR(r20,      NULL,  gcc_dwarf_r20_mips64,   gcc_dwarf_r20_mips64,   LLDB_INVALID_REGNUM,    gdb_r20_mips64), -    DEFINE_GPR(r21,      NULL,  gcc_dwarf_r21_mips64,   gcc_dwarf_r21_mips64,   LLDB_INVALID_REGNUM,    gdb_r21_mips64), -    DEFINE_GPR(r22,      NULL,  gcc_dwarf_r22_mips64,   gcc_dwarf_r22_mips64,   LLDB_INVALID_REGNUM,    gdb_r22_mips64), -    DEFINE_GPR(r23,      NULL,  gcc_dwarf_r23_mips64,   gcc_dwarf_r23_mips64,   LLDB_INVALID_REGNUM,    gdb_r23_mips64), -    DEFINE_GPR(r24,      NULL,  gcc_dwarf_r24_mips64,   gcc_dwarf_r24_mips64,   LLDB_INVALID_REGNUM,    gdb_r24_mips64), -    DEFINE_GPR(r25,      NULL,  gcc_dwarf_r25_mips64,   gcc_dwarf_r25_mips64,   LLDB_INVALID_REGNUM,    gdb_r25_mips64), -    DEFINE_GPR(r26,      NULL,  gcc_dwarf_r26_mips64,   gcc_dwarf_r26_mips64,   LLDB_INVALID_REGNUM,    gdb_r26_mips64), -    DEFINE_GPR(r27,      NULL,  gcc_dwarf_r27_mips64,   gcc_dwarf_r27_mips64,   LLDB_INVALID_REGNUM,    gdb_r27_mips64), -    DEFINE_GPR(gp,       "r28", gcc_dwarf_gp_mips64,    gcc_dwarf_gp_mips64,    LLDB_INVALID_REGNUM,    gdb_gp_mips64), -    DEFINE_GPR(sp,       "r29", gcc_dwarf_sp_mips64,    gcc_dwarf_sp_mips64,    LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64), -    DEFINE_GPR(r30,      NULL,  gcc_dwarf_r30_mips64,   gcc_dwarf_r30_mips64,   LLDB_REGNUM_GENERIC_FP,    gdb_r30_mips64), -    DEFINE_GPR(ra,       "r31", gcc_dwarf_ra_mips64,    gcc_dwarf_ra_mips64,    LLDB_REGNUM_GENERIC_RA,    gdb_ra_mips64), -    DEFINE_GPR_INFO(sr,       NULL,  gcc_dwarf_sr_mips64,    gcc_dwarf_sr_mips64,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(mullo,    NULL,  gcc_dwarf_lo_mips64,    gcc_dwarf_lo_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(mulhi,    NULL,  gcc_dwarf_hi_mips64,    gcc_dwarf_hi_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(badvaddr, NULL,  gcc_dwarf_bad_mips64,   gcc_dwarf_bad_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR_INFO(cause,    NULL,  gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_GPR(pc,       "pc",  gcc_dwarf_pc_mips64,    gcc_dwarf_pc_mips64,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), -    DEFINE_GPR_INFO(config5,    NULL,  gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), -    DEFINE_FPR (f0,    NULL,   gcc_dwarf_f0_mips64,   gcc_dwarf_f0_mips64,   LLDB_INVALID_REGNUM,    gdb_f0_mips64), -    DEFINE_FPR (f1,    NULL,   gcc_dwarf_f1_mips64,   gcc_dwarf_f1_mips64,   LLDB_INVALID_REGNUM,    gdb_f1_mips64), -    DEFINE_FPR (f2,    NULL,   gcc_dwarf_f2_mips64,   gcc_dwarf_f2_mips64,   LLDB_INVALID_REGNUM,    gdb_f2_mips64), -    DEFINE_FPR (f3,    NULL,   gcc_dwarf_f3_mips64,   gcc_dwarf_f3_mips64,   LLDB_INVALID_REGNUM,    gdb_f3_mips64), -    DEFINE_FPR (f4,    NULL,   gcc_dwarf_f4_mips64,   gcc_dwarf_f4_mips64,   LLDB_INVALID_REGNUM,    gdb_f4_mips64), -    DEFINE_FPR (f5,    NULL,   gcc_dwarf_f5_mips64,   gcc_dwarf_f5_mips64,   LLDB_INVALID_REGNUM,    gdb_f5_mips64), -    DEFINE_FPR (f6,    NULL,   gcc_dwarf_f6_mips64,   gcc_dwarf_f6_mips64,   LLDB_INVALID_REGNUM,    gdb_f6_mips64), -    DEFINE_FPR (f7,    NULL,   gcc_dwarf_f7_mips64,   gcc_dwarf_f7_mips64,   LLDB_INVALID_REGNUM,    gdb_f7_mips64), -    DEFINE_FPR (f8,    NULL,   gcc_dwarf_f8_mips64,   gcc_dwarf_f8_mips64,   LLDB_INVALID_REGNUM,    gdb_f8_mips64), -    DEFINE_FPR (f9,    NULL,   gcc_dwarf_f9_mips64,   gcc_dwarf_f9_mips64,   LLDB_INVALID_REGNUM,    gdb_f9_mips64), -    DEFINE_FPR (f10,   NULL,   gcc_dwarf_f10_mips64,  gcc_dwarf_f10_mips64,  LLDB_INVALID_REGNUM,    gdb_f10_mips64), -    DEFINE_FPR (f11,   NULL,   gcc_dwarf_f11_mips64,  gcc_dwarf_f11_mips64,  LLDB_INVALID_REGNUM,    gdb_f11_mips64), -    DEFINE_FPR (f12,   NULL,   gcc_dwarf_f12_mips64,  gcc_dwarf_f12_mips64,  LLDB_INVALID_REGNUM,    gdb_f12_mips64), -    DEFINE_FPR (f13,   NULL,   gcc_dwarf_f13_mips64,  gcc_dwarf_f13_mips64,  LLDB_INVALID_REGNUM,    gdb_f13_mips64), -    DEFINE_FPR (f14,   NULL,   gcc_dwarf_f14_mips64,  gcc_dwarf_f14_mips64,  LLDB_INVALID_REGNUM,    gdb_f14_mips64), -    DEFINE_FPR (f15,   NULL,   gcc_dwarf_f15_mips64,  gcc_dwarf_f15_mips64,  LLDB_INVALID_REGNUM,    gdb_f15_mips64), -    DEFINE_FPR (f16,   NULL,   gcc_dwarf_f16_mips64,  gcc_dwarf_f16_mips64,  LLDB_INVALID_REGNUM,    gdb_f16_mips64), -    DEFINE_FPR (f17,   NULL,   gcc_dwarf_f17_mips64,  gcc_dwarf_f17_mips64,  LLDB_INVALID_REGNUM,    gdb_f17_mips64), -    DEFINE_FPR (f18,   NULL,   gcc_dwarf_f18_mips64,  gcc_dwarf_f18_mips64,  LLDB_INVALID_REGNUM,    gdb_f18_mips64), -    DEFINE_FPR (f19,   NULL,   gcc_dwarf_f19_mips64,  gcc_dwarf_f19_mips64,  LLDB_INVALID_REGNUM,    gdb_f19_mips64), -    DEFINE_FPR (f20,   NULL,   gcc_dwarf_f20_mips64,  gcc_dwarf_f20_mips64,  LLDB_INVALID_REGNUM,    gdb_f20_mips64), -    DEFINE_FPR (f21,   NULL,   gcc_dwarf_f21_mips64,  gcc_dwarf_f21_mips64,  LLDB_INVALID_REGNUM,    gdb_f21_mips64), -    DEFINE_FPR (f22,   NULL,   gcc_dwarf_f22_mips64,  gcc_dwarf_f22_mips64,  LLDB_INVALID_REGNUM,    gdb_f22_mips64), -    DEFINE_FPR (f23,   NULL,   gcc_dwarf_f23_mips64,  gcc_dwarf_f23_mips64,  LLDB_INVALID_REGNUM,    gdb_f23_mips64), -    DEFINE_FPR (f24,   NULL,   gcc_dwarf_f24_mips64,  gcc_dwarf_f24_mips64,  LLDB_INVALID_REGNUM,    gdb_f24_mips64), -    DEFINE_FPR (f25,   NULL,   gcc_dwarf_f25_mips64,  gcc_dwarf_f25_mips64,  LLDB_INVALID_REGNUM,    gdb_f25_mips64), -    DEFINE_FPR (f26,   NULL,   gcc_dwarf_f26_mips64,  gcc_dwarf_f26_mips64,  LLDB_INVALID_REGNUM,    gdb_f26_mips64), -    DEFINE_FPR (f27,   NULL,   gcc_dwarf_f27_mips64,  gcc_dwarf_f27_mips64,  LLDB_INVALID_REGNUM,    gdb_f27_mips64), -    DEFINE_FPR (f28,   NULL,   gcc_dwarf_f28_mips64,  gcc_dwarf_f28_mips64,  LLDB_INVALID_REGNUM,    gdb_f28_mips64), -    DEFINE_FPR (f29,   NULL,   gcc_dwarf_f29_mips64,  gcc_dwarf_f29_mips64,  LLDB_INVALID_REGNUM,    gdb_f29_mips64), -    DEFINE_FPR (f30,   NULL,   gcc_dwarf_f30_mips64,  gcc_dwarf_f30_mips64,  LLDB_INVALID_REGNUM,    gdb_f30_mips64), -    DEFINE_FPR (f31,   NULL,   gcc_dwarf_f31_mips64,  gcc_dwarf_f31_mips64,  LLDB_INVALID_REGNUM,    gdb_f31_mips64), -    DEFINE_FPR (fcsr,  NULL,   gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM,    gdb_fcsr_mips64), -    DEFINE_FPR (fir,   NULL,   gcc_dwarf_fir_mips64,  gcc_dwarf_fir_mips64,  LLDB_INVALID_REGNUM,    gdb_fir_mips64), -    DEFINE_FPR (config5,   NULL,   gcc_dwarf_config5_mips64,  gcc_dwarf_config5_mips64,  LLDB_INVALID_REGNUM,    gdb_config5_mips64), -    DEFINE_MSA (w0,    NULL,   gcc_dwarf_w0_mips64,   gcc_dwarf_w0_mips64,   LLDB_INVALID_REGNUM,    gdb_w0_mips64), -    DEFINE_MSA (w1,    NULL,   gcc_dwarf_w1_mips64,   gcc_dwarf_w1_mips64,   LLDB_INVALID_REGNUM,    gdb_w1_mips64), -    DEFINE_MSA (w2,    NULL,   gcc_dwarf_w2_mips64,   gcc_dwarf_w2_mips64,   LLDB_INVALID_REGNUM,    gdb_w2_mips64), -    DEFINE_MSA (w3,    NULL,   gcc_dwarf_w3_mips64,   gcc_dwarf_w3_mips64,   LLDB_INVALID_REGNUM,    gdb_w3_mips64), -    DEFINE_MSA (w4,    NULL,   gcc_dwarf_w4_mips64,   gcc_dwarf_w4_mips64,   LLDB_INVALID_REGNUM,    gdb_w4_mips64), -    DEFINE_MSA (w5,    NULL,   gcc_dwarf_w5_mips64,   gcc_dwarf_w5_mips64,   LLDB_INVALID_REGNUM,    gdb_w5_mips64), -    DEFINE_MSA (w6,    NULL,   gcc_dwarf_w6_mips64,   gcc_dwarf_w6_mips64,   LLDB_INVALID_REGNUM,    gdb_w6_mips64), -    DEFINE_MSA (w7,    NULL,   gcc_dwarf_w7_mips64,   gcc_dwarf_w7_mips64,   LLDB_INVALID_REGNUM,    gdb_w7_mips64), -    DEFINE_MSA (w8,    NULL,   gcc_dwarf_w8_mips64,   gcc_dwarf_w8_mips64,   LLDB_INVALID_REGNUM,    gdb_w8_mips64), -    DEFINE_MSA (w9,    NULL,   gcc_dwarf_w9_mips64,   gcc_dwarf_w9_mips64,   LLDB_INVALID_REGNUM,    gdb_w9_mips64), -    DEFINE_MSA (w10,   NULL,   gcc_dwarf_w10_mips64,  gcc_dwarf_w10_mips64,  LLDB_INVALID_REGNUM,    gdb_w10_mips64), -    DEFINE_MSA (w11,   NULL,   gcc_dwarf_w11_mips64,  gcc_dwarf_w11_mips64,  LLDB_INVALID_REGNUM,    gdb_w11_mips64), -    DEFINE_MSA (w12,   NULL,   gcc_dwarf_w12_mips64,  gcc_dwarf_w12_mips64,  LLDB_INVALID_REGNUM,    gdb_w12_mips64), -    DEFINE_MSA (w13,   NULL,   gcc_dwarf_w13_mips64,  gcc_dwarf_w13_mips64,  LLDB_INVALID_REGNUM,    gdb_w13_mips64), -    DEFINE_MSA (w14,   NULL,   gcc_dwarf_w14_mips64,  gcc_dwarf_w14_mips64,  LLDB_INVALID_REGNUM,    gdb_w14_mips64), -    DEFINE_MSA (w15,   NULL,   gcc_dwarf_w15_mips64,  gcc_dwarf_w15_mips64,  LLDB_INVALID_REGNUM,    gdb_w15_mips64), -    DEFINE_MSA (w16,   NULL,   gcc_dwarf_w16_mips64,  gcc_dwarf_w16_mips64,  LLDB_INVALID_REGNUM,    gdb_w16_mips64), -    DEFINE_MSA (w17,   NULL,   gcc_dwarf_w17_mips64,  gcc_dwarf_w17_mips64,  LLDB_INVALID_REGNUM,    gdb_w17_mips64), -    DEFINE_MSA (w18,   NULL,   gcc_dwarf_w18_mips64,  gcc_dwarf_w18_mips64,  LLDB_INVALID_REGNUM,    gdb_w18_mips64), -    DEFINE_MSA (w19,   NULL,   gcc_dwarf_w19_mips64,  gcc_dwarf_w19_mips64,  LLDB_INVALID_REGNUM,    gdb_w19_mips64), -    DEFINE_MSA (w20,   NULL,   gcc_dwarf_w10_mips64,  gcc_dwarf_w20_mips64,  LLDB_INVALID_REGNUM,    gdb_w20_mips64), -    DEFINE_MSA (w21,   NULL,   gcc_dwarf_w21_mips64,  gcc_dwarf_w21_mips64,  LLDB_INVALID_REGNUM,    gdb_w21_mips64), -    DEFINE_MSA (w22,   NULL,   gcc_dwarf_w22_mips64,  gcc_dwarf_w22_mips64,  LLDB_INVALID_REGNUM,    gdb_w22_mips64), -    DEFINE_MSA (w23,   NULL,   gcc_dwarf_w23_mips64,  gcc_dwarf_w23_mips64,  LLDB_INVALID_REGNUM,    gdb_w23_mips64), -    DEFINE_MSA (w24,   NULL,   gcc_dwarf_w24_mips64,  gcc_dwarf_w24_mips64,  LLDB_INVALID_REGNUM,    gdb_w24_mips64), -    DEFINE_MSA (w25,   NULL,   gcc_dwarf_w25_mips64,  gcc_dwarf_w25_mips64,  LLDB_INVALID_REGNUM,    gdb_w25_mips64), -    DEFINE_MSA (w26,   NULL,   gcc_dwarf_w26_mips64,  gcc_dwarf_w26_mips64,  LLDB_INVALID_REGNUM,    gdb_w26_mips64), -    DEFINE_MSA (w27,   NULL,   gcc_dwarf_w27_mips64,  gcc_dwarf_w27_mips64,  LLDB_INVALID_REGNUM,    gdb_w27_mips64), -    DEFINE_MSA (w28,   NULL,   gcc_dwarf_w28_mips64,  gcc_dwarf_w28_mips64,  LLDB_INVALID_REGNUM,    gdb_w28_mips64), -    DEFINE_MSA (w29,   NULL,   gcc_dwarf_w29_mips64,  gcc_dwarf_w29_mips64,  LLDB_INVALID_REGNUM,    gdb_w29_mips64), -    DEFINE_MSA (w30,   NULL,   gcc_dwarf_w30_mips64,  gcc_dwarf_w30_mips64,  LLDB_INVALID_REGNUM,    gdb_w30_mips64), -    DEFINE_MSA (w31,   NULL,   gcc_dwarf_w31_mips64,  gcc_dwarf_w31_mips64,  LLDB_INVALID_REGNUM,    gdb_w31_mips64), -    DEFINE_MSA_INFO (mcsr,  NULL,   gcc_dwarf_mcsr_mips64, gcc_dwarf_mcsr_mips64, LLDB_INVALID_REGNUM,    gdb_mcsr_mips64), -    DEFINE_MSA_INFO (mir,   NULL,   gcc_dwarf_mir_mips64,  gcc_dwarf_mir_mips64,  LLDB_INVALID_REGNUM,    gdb_mir_mips64), -    DEFINE_MSA_INFO (fcsr,  NULL,   gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM,    gdb_fcsr_mips64), -    DEFINE_MSA_INFO (fir,   NULL,   gcc_dwarf_fir_mips64,  gcc_dwarf_fir_mips64,  LLDB_INVALID_REGNUM,    gdb_fir_mips64), -    DEFINE_MSA_INFO (config5, NULL,   gcc_dwarf_config5_mips64,  gcc_dwarf_config5_mips64,  LLDB_INVALID_REGNUM,    gdb_config5_mips64) +    DEFINE_GPR(zero,     "r0",      dwarf_zero_mips64,      dwarf_zero_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r1,       nullptr,   dwarf_r1_mips64,        dwarf_r1_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r2,       nullptr,   dwarf_r2_mips64,        dwarf_r2_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r3,       nullptr,   dwarf_r3_mips64,        dwarf_r3_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r4,       nullptr,   dwarf_r4_mips64,        dwarf_r4_mips64,    LLDB_REGNUM_GENERIC_ARG1,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r5,       nullptr,   dwarf_r5_mips64,        dwarf_r5_mips64,    LLDB_REGNUM_GENERIC_ARG2,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r6,       nullptr,   dwarf_r6_mips64,        dwarf_r6_mips64,    LLDB_REGNUM_GENERIC_ARG3,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r7,       nullptr,   dwarf_r7_mips64,        dwarf_r7_mips64,    LLDB_REGNUM_GENERIC_ARG4,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r8,       nullptr,   dwarf_r8_mips64,        dwarf_r8_mips64,    LLDB_REGNUM_GENERIC_ARG5,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r9,       nullptr,   dwarf_r9_mips64,        dwarf_r9_mips64,    LLDB_REGNUM_GENERIC_ARG6,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r10,      nullptr,   dwarf_r10_mips64,       dwarf_r10_mips64,   LLDB_REGNUM_GENERIC_ARG7,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r11,      nullptr,   dwarf_r11_mips64,       dwarf_r11_mips64,   LLDB_REGNUM_GENERIC_ARG8,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r12,      nullptr,   dwarf_r12_mips64,       dwarf_r12_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r13,      nullptr,   dwarf_r13_mips64,       dwarf_r13_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r14,      nullptr,   dwarf_r14_mips64,       dwarf_r14_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r15,      nullptr,   dwarf_r15_mips64,       dwarf_r15_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r16,      nullptr,   dwarf_r16_mips64,       dwarf_r16_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r17,      nullptr,   dwarf_r17_mips64,       dwarf_r17_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r18,      nullptr,   dwarf_r18_mips64,       dwarf_r18_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r19,      nullptr,   dwarf_r19_mips64,       dwarf_r19_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r20,      nullptr,   dwarf_r20_mips64,       dwarf_r20_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r21,      nullptr,   dwarf_r21_mips64,       dwarf_r21_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r22,      nullptr,   dwarf_r22_mips64,       dwarf_r22_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r23,      nullptr,   dwarf_r23_mips64,       dwarf_r23_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r24,      nullptr,   dwarf_r24_mips64,       dwarf_r24_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r25,      nullptr,   dwarf_r25_mips64,       dwarf_r25_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r26,      nullptr,   dwarf_r26_mips64,       dwarf_r26_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r27,      nullptr,   dwarf_r27_mips64,       dwarf_r27_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(gp,       "r28",     dwarf_gp_mips64,        dwarf_gp_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(sp,       "r29",     dwarf_sp_mips64,        dwarf_sp_mips64,    LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), +    DEFINE_GPR(r30,      nullptr,   dwarf_r30_mips64,       dwarf_r30_mips64,   LLDB_REGNUM_GENERIC_FP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(ra,       "r31",     dwarf_ra_mips64,        dwarf_ra_mips64,    LLDB_REGNUM_GENERIC_RA,    LLDB_INVALID_REGNUM), +    DEFINE_GPR_INFO(sr,       nullptr,   dwarf_sr_mips64,        dwarf_sr_mips64,    LLDB_REGNUM_GENERIC_FLAGS,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(mullo,    nullptr,   dwarf_lo_mips64,        dwarf_lo_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(mulhi,    nullptr,   dwarf_hi_mips64,        dwarf_hi_mips64,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(badvaddr, nullptr,   dwarf_bad_mips64,       dwarf_bad_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR_INFO(cause,    nullptr,   dwarf_cause_mips64,     dwarf_cause_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(pc,       "pc",      dwarf_pc_mips64,        dwarf_pc_mips64,    LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), +    DEFINE_GPR_INFO(config5,    nullptr,   dwarf_config5_mips64,     dwarf_config5_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f0,    nullptr,    dwarf_f0_mips64,       dwarf_f0_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f1,    nullptr,    dwarf_f1_mips64,       dwarf_f1_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f2,    nullptr,    dwarf_f2_mips64,       dwarf_f2_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f3,    nullptr,    dwarf_f3_mips64,       dwarf_f3_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f4,    nullptr,    dwarf_f4_mips64,       dwarf_f4_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f5,    nullptr,    dwarf_f5_mips64,       dwarf_f5_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f6,    nullptr,    dwarf_f6_mips64,       dwarf_f6_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f7,    nullptr,    dwarf_f7_mips64,       dwarf_f7_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f8,    nullptr,    dwarf_f8_mips64,       dwarf_f8_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f9,    nullptr,    dwarf_f9_mips64,       dwarf_f9_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f10,   nullptr,    dwarf_f10_mips64,      dwarf_f10_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f11,   nullptr,    dwarf_f11_mips64,      dwarf_f11_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f12,   nullptr,    dwarf_f12_mips64,      dwarf_f12_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f13,   nullptr,    dwarf_f13_mips64,      dwarf_f13_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f14,   nullptr,    dwarf_f14_mips64,      dwarf_f14_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f15,   nullptr,    dwarf_f15_mips64,      dwarf_f15_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f16,   nullptr,    dwarf_f16_mips64,      dwarf_f16_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f17,   nullptr,    dwarf_f17_mips64,      dwarf_f17_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f18,   nullptr,    dwarf_f18_mips64,      dwarf_f18_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f19,   nullptr,    dwarf_f19_mips64,      dwarf_f19_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f20,   nullptr,    dwarf_f20_mips64,      dwarf_f20_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f21,   nullptr,    dwarf_f21_mips64,      dwarf_f21_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f22,   nullptr,    dwarf_f22_mips64,      dwarf_f22_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f23,   nullptr,    dwarf_f23_mips64,      dwarf_f23_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f24,   nullptr,    dwarf_f24_mips64,      dwarf_f24_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f25,   nullptr,    dwarf_f25_mips64,      dwarf_f25_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f26,   nullptr,    dwarf_f26_mips64,      dwarf_f26_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f27,   nullptr,    dwarf_f27_mips64,      dwarf_f27_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f28,   nullptr,    dwarf_f28_mips64,      dwarf_f28_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f29,   nullptr,    dwarf_f29_mips64,      dwarf_f29_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f30,   nullptr,    dwarf_f30_mips64,      dwarf_f30_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (f31,   nullptr,    dwarf_f31_mips64,      dwarf_f31_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (fcsr,  nullptr,    dwarf_fcsr_mips64,     dwarf_fcsr_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (fir,   nullptr,    dwarf_fir_mips64,      dwarf_fir_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_FPR (config5,   nullptr,    dwarf_config5_mips64,      dwarf_config5_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w0,    nullptr,    dwarf_w0_mips64,       dwarf_w0_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w1,    nullptr,    dwarf_w1_mips64,       dwarf_w1_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w2,    nullptr,    dwarf_w2_mips64,       dwarf_w2_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w3,    nullptr,    dwarf_w3_mips64,       dwarf_w3_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w4,    nullptr,    dwarf_w4_mips64,       dwarf_w4_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w5,    nullptr,    dwarf_w5_mips64,       dwarf_w5_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w6,    nullptr,    dwarf_w6_mips64,       dwarf_w6_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w7,    nullptr,    dwarf_w7_mips64,       dwarf_w7_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w8,    nullptr,    dwarf_w8_mips64,       dwarf_w8_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w9,    nullptr,    dwarf_w9_mips64,       dwarf_w9_mips64,   LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w10,   nullptr,    dwarf_w10_mips64,      dwarf_w10_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w11,   nullptr,    dwarf_w11_mips64,      dwarf_w11_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w12,   nullptr,    dwarf_w12_mips64,      dwarf_w12_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w13,   nullptr,    dwarf_w13_mips64,      dwarf_w13_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w14,   nullptr,    dwarf_w14_mips64,      dwarf_w14_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w15,   nullptr,    dwarf_w15_mips64,      dwarf_w15_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w16,   nullptr,    dwarf_w16_mips64,      dwarf_w16_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w17,   nullptr,    dwarf_w17_mips64,      dwarf_w17_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w18,   nullptr,    dwarf_w18_mips64,      dwarf_w18_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w19,   nullptr,    dwarf_w19_mips64,      dwarf_w19_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w20,   nullptr,    dwarf_w10_mips64,      dwarf_w20_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w21,   nullptr,    dwarf_w21_mips64,      dwarf_w21_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w22,   nullptr,    dwarf_w22_mips64,      dwarf_w22_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w23,   nullptr,    dwarf_w23_mips64,      dwarf_w23_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w24,   nullptr,    dwarf_w24_mips64,      dwarf_w24_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w25,   nullptr,    dwarf_w25_mips64,      dwarf_w25_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w26,   nullptr,    dwarf_w26_mips64,      dwarf_w26_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w27,   nullptr,    dwarf_w27_mips64,      dwarf_w27_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w28,   nullptr,    dwarf_w28_mips64,      dwarf_w28_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w29,   nullptr,    dwarf_w29_mips64,      dwarf_w29_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w30,   nullptr,    dwarf_w30_mips64,      dwarf_w30_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA (w31,   nullptr,    dwarf_w31_mips64,      dwarf_w31_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (mcsr,  nullptr,    dwarf_mcsr_mips64,     dwarf_mcsr_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (mir,   nullptr,    dwarf_mir_mips64,      dwarf_mir_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (fcsr,  nullptr,    dwarf_fcsr_mips64,     dwarf_fcsr_mips64, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (fir,   nullptr,    dwarf_fir_mips64,      dwarf_fir_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM), +    DEFINE_MSA_INFO (config5, nullptr,    dwarf_config5_mips64,      dwarf_config5_mips64,  LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM)  #endif  }; diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h index fe145e99588be..95347ae51592f 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h +++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h @@ -24,15 +24,15 @@  // Note that the size and offset will be updated by platform-specific classes.  #define DEFINE_GPR(reg, alt, lldb_kind)           \      { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ -      eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL } +      eFormatHex, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, gpr_##reg##_powerpc }, NULL, NULL }  #define DEFINE_FPR(reg, lldb_kind)           \      { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \ -      eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL } +      eFormatFloat, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, fpr_##reg##_powerpc }, NULL, NULL }  #define DEFINE_VMX(reg, lldb_kind)           \      { #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \ -      eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL } +      eFormatVectorOfUInt32, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, vmx_##reg##_powerpc }, NULL, NULL } -    // General purpose registers.                 GCC,                  DWARF,              Generic,                GDB +    // General purpose registers.            EH_Frame,                  DWARF,              Generic,                Process Plugin  #define POWERPC_REGS \      DEFINE_GPR(r0,       NULL,  LLDB_INVALID_REGNUM), \      DEFINE_GPR(r1,       "sp",  LLDB_REGNUM_GENERIC_SP), \ @@ -103,7 +103,7 @@      DEFINE_FPR(f29,      LLDB_INVALID_REGNUM), \      DEFINE_FPR(f30,      LLDB_INVALID_REGNUM), \      DEFINE_FPR(f31,      LLDB_INVALID_REGNUM), \ -    { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \ +    { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { dwarf_fpscr_powerpc, dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_fpscr_powerpc }, NULL, NULL }, \      DEFINE_VMX(v0,       LLDB_INVALID_REGNUM), \      DEFINE_VMX(v1,       LLDB_INVALID_REGNUM), \      DEFINE_VMX(v2,       LLDB_INVALID_REGNUM), \ @@ -136,8 +136,8 @@      DEFINE_VMX(v29,      LLDB_INVALID_REGNUM), \      DEFINE_VMX(v30,      LLDB_INVALID_REGNUM), \      DEFINE_VMX(v31,      LLDB_INVALID_REGNUM), \ -    { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \ -    { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL }, +    { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { dwarf_vrsave_powerpc, dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vrsave_powerpc }, NULL, NULL }, \ +    { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { dwarf_vscr_powerpc, dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_powerpc }, NULL, NULL },  static RegisterInfo  g_register_infos_powerpc64[] = diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h index 5da74ff834870..a393089dd129b 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h @@ -1,15 +1,21 @@ -//===-- RegisterInfos_x86_64.h ---------------------------------*- C++ -*-===// +//===-- RegisterInfos_x86_64.h ----------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// -#include "llvm/Support/Compiler.h" +//===----------------------------------------------------------------------===// +// C Includes  #include <stddef.h> +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Compiler.h" + +// Project includes +  // Computes the offset of the given GPR in the user data area.  #define GPR_OFFSET(regname) \      (LLVM_EXTENSION offsetof(GPR, regname)) @@ -44,7 +50,7 @@  #define DR_SIZE sizeof(((DBG*)NULL)->dr[0]) -// RegisterKind: GCC, DWARF, Generic, GDB, LLDB +// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB  // Note that the size and offset will be updated by platform-specific classes.  #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)    \ @@ -58,25 +64,25 @@  #define DEFINE_FP_ST(reg, i)                                       \      { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]),   \        eEncodingVector, eFormatVectorOfUInt8,                       \ -      { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_st##i##_x86_64 }, \ +      { dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \        NULL, NULL }  #define DEFINE_FP_MM(reg, i)                                                \      { #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]),   \        eEncodingUint, eFormatHex,                                            \ -      { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_mm##i##_x86_64 }, \ +      { dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_x86_64 }, \        NULL, NULL }  #define DEFINE_XMM(reg, i)                                         \      { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),   \        eEncodingVector, eFormatVectorOfUInt8,                       \ -      { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, lldb_##reg##i##_x86_64}, \ +      { dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64}, \        NULL, NULL }  #define DEFINE_YMM(reg, i)                                                          \      { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i),                         \        eEncodingVector, eFormatVectorOfUInt8,                                        \ -      { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, lldb_##reg##i##_x86_64 }, \ +      { dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64 }, \        NULL, NULL }  #define DEFINE_DR(reg, i)                                               \ @@ -100,31 +106,31 @@  static RegisterInfo  g_register_infos_x86_64[] =  { -    // General purpose registers.                GCC,                   DWARF,                Generic,                  GDB -    DEFINE_GPR(rax,    NULL,    gcc_dwarf_rax_x86_64,    gcc_dwarf_rax_x86_64,    LLDB_INVALID_REGNUM,       gdb_rax_x86_64), -    DEFINE_GPR(rbx,    NULL,    gcc_dwarf_rbx_x86_64,    gcc_dwarf_rbx_x86_64,    LLDB_INVALID_REGNUM,       gdb_rbx_x86_64), -    DEFINE_GPR(rcx,    "arg4",  gcc_dwarf_rcx_x86_64,    gcc_dwarf_rcx_x86_64,    LLDB_REGNUM_GENERIC_ARG4,  gdb_rcx_x86_64), -    DEFINE_GPR(rdx,    "arg3",  gcc_dwarf_rdx_x86_64,    gcc_dwarf_rdx_x86_64,    LLDB_REGNUM_GENERIC_ARG3,  gdb_rdx_x86_64), -    DEFINE_GPR(rdi,    "arg1",  gcc_dwarf_rdi_x86_64,    gcc_dwarf_rdi_x86_64,    LLDB_REGNUM_GENERIC_ARG1,  gdb_rdi_x86_64), -    DEFINE_GPR(rsi,    "arg2",  gcc_dwarf_rsi_x86_64,    gcc_dwarf_rsi_x86_64,    LLDB_REGNUM_GENERIC_ARG2,  gdb_rsi_x86_64), -    DEFINE_GPR(rbp,    "fp",    gcc_dwarf_rbp_x86_64,    gcc_dwarf_rbp_x86_64,    LLDB_REGNUM_GENERIC_FP,    gdb_rbp_x86_64), -    DEFINE_GPR(rsp,    "sp",    gcc_dwarf_rsp_x86_64,    gcc_dwarf_rsp_x86_64,    LLDB_REGNUM_GENERIC_SP,    gdb_rsp_x86_64), -    DEFINE_GPR(r8,     "arg5",  gcc_dwarf_r8_x86_64,     gcc_dwarf_r8_x86_64,     LLDB_REGNUM_GENERIC_ARG5,  gdb_r8_x86_64), -    DEFINE_GPR(r9,     "arg6",  gcc_dwarf_r9_x86_64,     gcc_dwarf_r9_x86_64,     LLDB_REGNUM_GENERIC_ARG6,  gdb_r9_x86_64), -    DEFINE_GPR(r10,    NULL,    gcc_dwarf_r10_x86_64,    gcc_dwarf_r10_x86_64,    LLDB_INVALID_REGNUM,       gdb_r10_x86_64), -    DEFINE_GPR(r11,    NULL,    gcc_dwarf_r11_x86_64,    gcc_dwarf_r11_x86_64,    LLDB_INVALID_REGNUM,       gdb_r11_x86_64), -    DEFINE_GPR(r12,    NULL,    gcc_dwarf_r12_x86_64,    gcc_dwarf_r12_x86_64,    LLDB_INVALID_REGNUM,       gdb_r12_x86_64), -    DEFINE_GPR(r13,    NULL,    gcc_dwarf_r13_x86_64,    gcc_dwarf_r13_x86_64,    LLDB_INVALID_REGNUM,       gdb_r13_x86_64), -    DEFINE_GPR(r14,    NULL,    gcc_dwarf_r14_x86_64,    gcc_dwarf_r14_x86_64,    LLDB_INVALID_REGNUM,       gdb_r14_x86_64), -    DEFINE_GPR(r15,    NULL,    gcc_dwarf_r15_x86_64,    gcc_dwarf_r15_x86_64,    LLDB_INVALID_REGNUM,       gdb_r15_x86_64), -    DEFINE_GPR(rip,    "pc",    gcc_dwarf_rip_x86_64,    gcc_dwarf_rip_x86_64,    LLDB_REGNUM_GENERIC_PC,    gdb_rip_x86_64), -    DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64), -    DEFINE_GPR(cs,     NULL,    gcc_dwarf_cs_x86_64,     gcc_dwarf_cs_x86_64,     LLDB_INVALID_REGNUM,       gdb_cs_x86_64), -    DEFINE_GPR(fs,     NULL,    gcc_dwarf_fs_x86_64,     gcc_dwarf_fs_x86_64,     LLDB_INVALID_REGNUM,       gdb_fs_x86_64), -    DEFINE_GPR(gs,     NULL,    gcc_dwarf_gs_x86_64,     gcc_dwarf_gs_x86_64,     LLDB_INVALID_REGNUM,       gdb_gs_x86_64), -    DEFINE_GPR(ss,     NULL,    gcc_dwarf_ss_x86_64,     gcc_dwarf_ss_x86_64,     LLDB_INVALID_REGNUM,       gdb_ss_x86_64), -    DEFINE_GPR(ds,     NULL,    gcc_dwarf_ds_x86_64,     gcc_dwarf_ds_x86_64,     LLDB_INVALID_REGNUM,       gdb_ds_x86_64), -    DEFINE_GPR(es,     NULL,    gcc_dwarf_es_x86_64,     gcc_dwarf_es_x86_64,     LLDB_INVALID_REGNUM,       gdb_es_x86_64), +    // General purpose registers.           EH_Frame,                   DWARF,                Generic,                Process Plugin +    DEFINE_GPR(rax,    nullptr,     dwarf_rax_x86_64,        dwarf_rax_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(rbx,    nullptr,     dwarf_rbx_x86_64,        dwarf_rbx_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(rcx,    "arg4",      dwarf_rcx_x86_64,        dwarf_rcx_x86_64,    LLDB_REGNUM_GENERIC_ARG4,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(rdx,    "arg3",      dwarf_rdx_x86_64,        dwarf_rdx_x86_64,    LLDB_REGNUM_GENERIC_ARG3,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(rdi,    "arg1",      dwarf_rdi_x86_64,        dwarf_rdi_x86_64,    LLDB_REGNUM_GENERIC_ARG1,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(rsi,    "arg2",      dwarf_rsi_x86_64,        dwarf_rsi_x86_64,    LLDB_REGNUM_GENERIC_ARG2,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(rbp,    "fp",        dwarf_rbp_x86_64,        dwarf_rbp_x86_64,    LLDB_REGNUM_GENERIC_FP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(rsp,    "sp",        dwarf_rsp_x86_64,        dwarf_rsp_x86_64,    LLDB_REGNUM_GENERIC_SP,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(r8,     "arg5",      dwarf_r8_x86_64,         dwarf_r8_x86_64,     LLDB_REGNUM_GENERIC_ARG5,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(r9,     "arg6",      dwarf_r9_x86_64,         dwarf_r9_x86_64,     LLDB_REGNUM_GENERIC_ARG6,  LLDB_INVALID_REGNUM), +    DEFINE_GPR(r10,    nullptr,     dwarf_r10_x86_64,        dwarf_r10_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(r11,    nullptr,     dwarf_r11_x86_64,        dwarf_r11_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(r12,    nullptr,     dwarf_r12_x86_64,        dwarf_r12_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(r13,    nullptr,     dwarf_r13_x86_64,        dwarf_r13_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(r14,    nullptr,     dwarf_r14_x86_64,        dwarf_r14_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(r15,    nullptr,     dwarf_r15_x86_64,        dwarf_r15_x86_64,    LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(rip,    "pc",        dwarf_rip_x86_64,        dwarf_rip_x86_64,    LLDB_REGNUM_GENERIC_PC,    LLDB_INVALID_REGNUM), +    DEFINE_GPR(rflags, "flags",     dwarf_rflags_x86_64,     dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), +    DEFINE_GPR(cs,     nullptr,     dwarf_cs_x86_64,         dwarf_cs_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(fs,     nullptr,     dwarf_fs_x86_64,         dwarf_fs_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(gs,     nullptr,     dwarf_gs_x86_64,         dwarf_gs_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ss,     nullptr,     dwarf_ss_x86_64,         dwarf_ss_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(ds,     nullptr,     dwarf_ds_x86_64,         dwarf_ds_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM), +    DEFINE_GPR(es,     nullptr,     dwarf_es_x86_64,         dwarf_es_x86_64,     LLDB_INVALID_REGNUM,       LLDB_INVALID_REGNUM),      DEFINE_GPR_PSEUDO_32(eax, rax),      DEFINE_GPR_PSEUDO_32(ebx, rbx), @@ -179,16 +185,16 @@ g_register_infos_x86_64[] =      DEFINE_GPR_PSEUDO_8L(r14l, r14),      DEFINE_GPR_PSEUDO_8L(r15l, r15), -    // i387 Floating point registers.     GCC,                                   DWARF,               Generic,            GDB -    DEFINE_FPR(fctrl,     fctrl,          gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_x86_64), -    DEFINE_FPR(fstat,     fstat,          gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64), -    DEFINE_FPR(ftag,      ftag,           LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_ftag_x86_64), -    DEFINE_FPR(fop,       fop,            LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_fop_x86_64), -    DEFINE_FPR(fiseg,     ptr.i386_.fiseg, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_fiseg_x86_64), -    DEFINE_FPR(fioff,     ptr.i386_.fioff, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_fioff_x86_64), -    DEFINE_FPR(foseg,     ptr.i386_.foseg, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_foseg_x86_64), -    DEFINE_FPR(fooff,     ptr.i386_.fooff, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, gdb_fooff_x86_64), -    DEFINE_FPR(mxcsr,     mxcsr,          gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64), +    // i387 Floating point registers. EH_frame,                                  DWARF,               Generic,          Process Plugin +    DEFINE_FPR(fctrl,     fctrl,              dwarf_fctrl_x86_64,     dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fstat,     fstat,              dwarf_fstat_x86_64,     dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(ftag,      ftag,           LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fop,       fop,            LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fiseg,     ptr.i386_.fiseg, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fioff,     ptr.i386_.fioff, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(foseg,     ptr.i386_.foseg, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(fooff,     ptr.i386_.fooff, LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), +    DEFINE_FPR(mxcsr,     mxcsr,              dwarf_mxcsr_x86_64,     dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),      DEFINE_FPR(mxcsrmask, mxcsrmask,      LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),      // FP registers. @@ -255,6 +261,7 @@ g_register_infos_x86_64[] =      DEFINE_DR(dr, 6),      DEFINE_DR(dr, 7)  }; +  static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64,      "g_register_infos_x86_64 has wrong number of register infos"); @@ -275,7 +282,6 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[  #endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT -  #ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS  #define UPDATE_GPR_INFO(reg, reg64)                                             \ diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 7c68d0d07821b..3bf766e875c90 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -58,6 +58,7 @@ StopInfoMachException::GetDescription ()                  }                  break;              case llvm::Triple::arm: +            case llvm::Triple::thumb:                  switch (m_exc_code)                  {                  case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; @@ -104,6 +105,7 @@ StopInfoMachException::GetDescription ()                  break;              case llvm::Triple::arm: +            case llvm::Triple::thumb:                  if (m_exc_code == 1)                      code_desc = "EXC_ARM_UNDEFINED";                  break; @@ -188,6 +190,7 @@ StopInfoMachException::GetDescription ()                      break;                  case llvm::Triple::arm: +                case llvm::Triple::thumb:                      switch (m_exc_code)                      {                      case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; @@ -408,6 +411,7 @@ StopInfoMachException::CreateStopReasonWithMachException                      break;                  case llvm::Triple::arm: +                case llvm::Triple::thumb:                      if (exc_code == 0x102) // EXC_ARM_DA_DEBUG                      {                          // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled diff --git a/source/Plugins/Process/Utility/StopInfoMachException.h b/source/Plugins/Process/Utility/StopInfoMachException.h index 130ee0b709b0a..25e05ecc1ec72 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.h +++ b/source/Plugins/Process/Utility/StopInfoMachException.h @@ -38,19 +38,16 @@ public:      {      } -    virtual ~StopInfoMachException() -    { -    } +    ~StopInfoMachException() override = default; - -    virtual lldb::StopReason -    GetStopReason () const +    lldb::StopReason +    GetStopReason() const override      {          return lldb::eStopReasonException;      } -    virtual const char * -    GetDescription (); +    const char * +    GetDescription() override;      // Since some mach exceptions will be reported as breakpoints, signals,      // or trace, we use this static accessor which will translate the mach @@ -71,7 +68,6 @@ protected:      uint64_t m_exc_subcode;  }; -  } // namespace lldb_private -#endif  // liblldb_StopInfoMachException_h_ +#endif // liblldb_StopInfoMachException_h_ diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h index 07eb45dcb431b..1e7cbfa448153 100644 --- a/source/Plugins/Process/Utility/ThreadMemory.h +++ b/source/Plugins/Process/Utility/ThreadMemory.h @@ -1,4 +1,4 @@ -//===-- ThreadMemory.h -----------------------------------------*- C++ -*-===// +//===-- ThreadMemory.h ------------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,13 +10,18 @@  #ifndef liblldb_ThreadMemory_h_  #define liblldb_ThreadMemory_h_ +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes  #include "lldb/Target/Thread.h"  class ThreadMemory :      public lldb_private::Thread  {  public: -      ThreadMemory (lldb_private::Process &process,                    lldb::tid_t tid,                    const lldb::ValueObjectSP &thread_info_valobj_sp); @@ -27,69 +32,65 @@ public:                    const char *queue,                    lldb::addr_t register_data_addr); -    virtual -    ~ThreadMemory(); +    ~ThreadMemory() override; -    //------------------------------------------------------------------ -    // lldb_private::Thread methods -    //------------------------------------------------------------------ -    virtual lldb::RegisterContextSP -    GetRegisterContext (); +    lldb::RegisterContextSP +    GetRegisterContext() override; -    virtual lldb::RegisterContextSP -    CreateRegisterContextForFrame (lldb_private::StackFrame *frame); +    lldb::RegisterContextSP +    CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; -    virtual bool -    CalculateStopInfo (); +    bool +    CalculateStopInfo() override; -    virtual const char * -    GetInfo () +    const char * +    GetInfo() override      {          if (m_backing_thread_sp)              m_backing_thread_sp->GetInfo(); -        return NULL; +        return nullptr;      } -    virtual const char * -    GetName () +    const char * +    GetName() override      {          if (!m_name.empty())              return m_name.c_str();          if (m_backing_thread_sp)              m_backing_thread_sp->GetName(); -        return NULL; +        return nullptr;      } -    virtual const char * -    GetQueueName () +    const char * +    GetQueueName() override      {          if (!m_queue.empty())              return m_queue.c_str();          if (m_backing_thread_sp)              m_backing_thread_sp->GetQueueName(); -        return NULL; +        return nullptr;      } -    virtual void -    WillResume (lldb::StateType resume_state); +    void +    WillResume(lldb::StateType resume_state) override; -    virtual void -    DidResume () +    void +    DidResume() override      {          if (m_backing_thread_sp)              m_backing_thread_sp->DidResume();      } -    virtual lldb::user_id_t -    GetProtocolID () const +    lldb::user_id_t +    GetProtocolID() const override      {          if (m_backing_thread_sp)              return m_backing_thread_sp->GetProtocolID();          return Thread::GetProtocolID();      } -    virtual void -    RefreshStateAfterStop(); +    void +    RefreshStateAfterStop() override;      lldb::ValueObjectSP &      GetValueObject () @@ -97,41 +98,36 @@ public:          return m_thread_info_valobj_sp;      } -    virtual void -    ClearStackFrames (); +    void +    ClearStackFrames() override; -    virtual void -    ClearBackingThread () +    void +    ClearBackingThread() override      {          m_backing_thread_sp.reset();      } -    virtual bool -    SetBackingThread (const lldb::ThreadSP &thread_sp) +    bool +    SetBackingThread(const lldb::ThreadSP &thread_sp) override      {          //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());          m_backing_thread_sp = thread_sp;          return (bool)thread_sp;      } -    virtual lldb::ThreadSP -    GetBackingThread () const +    lldb::ThreadSP +    GetBackingThread() const override      {          return m_backing_thread_sp;      }  protected: -     -    virtual bool -    IsOperatingSystemPluginThread () const +    bool +    IsOperatingSystemPluginThread() const override      {          return true;      } - -    //------------------------------------------------------------------ -    // For ThreadMemory and subclasses -    //------------------------------------------------------------------      // If this memory thread is actually represented by a thread from the      // lldb_private::Process subclass, then fill in the thread here and      // all APIs will be routed through this thread object. If m_backing_thread_sp @@ -142,11 +138,9 @@ protected:      std::string m_name;      std::string m_queue;      lldb::addr_t m_register_data_addr; +  private: -    //------------------------------------------------------------------ -    // For ThreadMemory only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (ThreadMemory);  }; -#endif  // liblldb_ThreadMemory_h_ +#endif // liblldb_ThreadMemory_h_ diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp index 1cdae9011673b..9be09c478a0ee 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -86,6 +86,9 @@ UnwindLLDB::AddFirstFrame ()      if (m_frames.size() > 0)          return true; +    ProcessSP process_sp (m_thread.GetProcess()); +    ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; +      // First, set up the 0th (initial) frame      CursorSP first_cursor_sp(new Cursor ());      RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread,  @@ -108,6 +111,10 @@ UnwindLLDB::AddFirstFrame ()      // cursor own it in its shared pointer      first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;      m_frames.push_back (first_cursor_sp); + +    // Update the Full Unwind Plan for this frame if not valid +    UpdateUnwindPlanForFirstFrameIfInvalid(abi); +      return true;  unwind_done: @@ -161,7 +168,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)          // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return          // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.          if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +        { +            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                return nullptr; +              return GetOneMoreFrame (abi); +        }          if (log)              log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.", @@ -175,7 +189,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)          // See if the regctx below this on the stack has a fallback unwind plan it can use.          // Subsequent calls to TryFallbackUnwindPlan() will return false.          if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +        { +            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                return nullptr; +              return GetOneMoreFrame (abi); +        }          if (log)              log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",  @@ -187,7 +208,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)          // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return          // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.          if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +        { +            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                return nullptr; +              return GetOneMoreFrame (abi); +        }          if (log)              log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk", @@ -212,7 +240,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)                  || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)              {                  if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +                { +                    // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +                    // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +                    if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                        return nullptr; +                      return GetOneMoreFrame (abi); +                }                  if (log)                      log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", @@ -232,7 +267,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)          // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return          // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.          if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +        { +            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                return nullptr; +              return GetOneMoreFrame (abi); +        }          if (log)              log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk", @@ -244,7 +286,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)          // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return          // true.  Subsequent calls to TryFallbackUnwindPlan() will return false.          if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) +        { +            // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of +            // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. +            if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) +                return nullptr; +              return GetOneMoreFrame (abi); +        }          if (log)              log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", @@ -263,6 +312,33 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)      return cursor_sp;  } +void +UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi) +{ +    // This function is called for First Frame only. +    assert (m_frames.size() == 1 && "No. of cursor frames are not 1"); + +    bool old_m_unwind_complete = m_unwind_complete; +    CursorSP old_m_candidate_frame = m_candidate_frame; + +    // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan +    // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also +    // update the cfa of Frame 0 (if required). +    AddOneMoreFrame(abi); + +    // Remove all the frames added by above function as the purpose of +    // using above function was just to check whether Unwinder of Frame 0 +    // works or not. +    for(uint32_t i=1; i<m_frames.size(); i++) +        m_frames.pop_back(); + +    // Restore status after calling AddOneMoreFrame +    m_unwind_complete = old_m_unwind_complete; +    m_candidate_frame = old_m_candidate_frame; +    return; +} + +  bool  UnwindLLDB::AddOneMoreFrame (ABI *abi)  { @@ -321,9 +397,17 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)      m_frames.push_back(new_frame_v2);      m_candidate_frame = GetOneMoreFrame(abi);      if (m_candidate_frame) +    { +        // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2]. +        // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that. +        // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan +        // call above. However, cfa field still needs to be updated. Hence updating it here and then returning. +        if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa))) +            return false;          return true; +    } -    // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind +    // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind      // plan is usually more reliable then the fallback one.      m_frames.pop_back();      m_frames.push_back(new_frame); diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h index ce897cd82423c..d3c07078759be 100644 --- a/source/Plugins/Process/Utility/UnwindLLDB.h +++ b/source/Plugins/Process/Utility/UnwindLLDB.h @@ -10,8 +10,12 @@  #ifndef lldb_UnwindLLDB_h_  #define lldb_UnwindLLDB_h_ +// C Includes +// C++ Includes  #include <vector> +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-public.h"  #include "lldb/Core/ConstString.h"  #include "lldb/Symbol/FuncUnwinders.h" @@ -27,9 +31,8 @@ class UnwindLLDB : public lldb_private::Unwind  {  public:       UnwindLLDB (lldb_private::Thread &thread); -     -    virtual -    ~UnwindLLDB() { } + +    ~UnwindLLDB() override = default;      enum RegisterSearchResult      { @@ -62,23 +65,23 @@ protected:      };      void -    DoClear() +    DoClear() override      {          m_frames.clear();          m_candidate_frame.reset();          m_unwind_complete = false;      } -    virtual uint32_t -    DoGetFrameCount(); +    uint32_t +    DoGetFrameCount() override;      bool -    DoGetFrameInfoAtIndex (uint32_t frame_idx, -                         lldb::addr_t& cfa,  -                         lldb::addr_t& start_pc); +    DoGetFrameInfoAtIndex(uint32_t frame_idx, +                          lldb::addr_t& cfa, +                          lldb::addr_t& start_pc) override;      lldb::RegisterContextSP -    DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame); +    DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;      typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP; @@ -112,7 +115,6 @@ protected:      }  private: -      struct Cursor      {          lldb::addr_t start_pc;  // The start address of the function/symbol for this frame - current pc if unknown @@ -134,6 +136,15 @@ private:      std::vector<ConstString> m_user_supplied_trap_handler_functions; +    //----------------------------------------------------------------- +    // Check if Full UnwindPlan of First frame is valid or not. +    // If not then try Fallback UnwindPlan of the frame. If Fallback +    // UnwindPlan succeeds then update the Full UnwindPlan with the +    // Fallback UnwindPlan. +    //----------------------------------------------------------------- +    void +    UpdateUnwindPlanForFirstFrameIfInvalid (ABI* abi); +      CursorSP      GetOneMoreFrame (ABI* abi); @@ -149,6 +160,6 @@ private:      DISALLOW_COPY_AND_ASSIGN (UnwindLLDB);  }; -}   // namespace lldb_private +} // namespace lldb_private -#endif  // lldb_UnwindLLDB_h_ +#endif // lldb_UnwindLLDB_h_ diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h index 2695376fd6e07..f195514ed1bab 100644 --- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h +++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h @@ -15,7 +15,6 @@  #include <vector>  // Other libraries and framework includes -  // Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/Unwind.h" @@ -24,29 +23,26 @@ class UnwindMacOSXFrameBackchain : public lldb_private::Unwind  {  public:       UnwindMacOSXFrameBackchain (lldb_private::Thread &thread); -     -    virtual -    ~UnwindMacOSXFrameBackchain() -    { -    } -     + +    ~UnwindMacOSXFrameBackchain() override = default; +  protected: -    virtual void -    DoClear() +    void +    DoClear() override      {          m_cursors.clear();      } -    virtual uint32_t -    DoGetFrameCount(); +    uint32_t +    DoGetFrameCount() override;      bool -    DoGetFrameInfoAtIndex (uint32_t frame_idx, -                         lldb::addr_t& cfa,  -                         lldb::addr_t& pc); +    DoGetFrameInfoAtIndex(uint32_t frame_idx, +                          lldb::addr_t& cfa, +                          lldb::addr_t& pc) override;      lldb::RegisterContextSP -    DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame); +    DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;      friend class RegisterContextMacOSXFrameBackchain; @@ -71,4 +67,4 @@ private:      DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain);  }; -#endif  // lldb_UnwindMacOSXFrameBackchain_h_ +#endif // lldb_UnwindMacOSXFrameBackchain_h_ diff --git a/source/Plugins/Process/Utility/lldb-arm-register-enums.h b/source/Plugins/Process/Utility/lldb-arm-register-enums.h index a617f6550f65d..4d82c10a78eac 100644 --- a/source/Plugins/Process/Utility/lldb-arm-register-enums.h +++ b/source/Plugins/Process/Utility/lldb-arm-register-enums.h @@ -74,7 +74,55 @@ namespace lldb_private          fpu_s30_arm,          fpu_s31_arm,          fpu_fpscr_arm, -        k_last_fpr_arm = fpu_fpscr_arm, +        fpu_d0_arm, +        fpu_d1_arm, +        fpu_d2_arm, +        fpu_d3_arm, +        fpu_d4_arm, +        fpu_d5_arm, +        fpu_d6_arm, +        fpu_d7_arm, +        fpu_d8_arm, +        fpu_d9_arm, +        fpu_d10_arm, +        fpu_d11_arm, +        fpu_d12_arm, +        fpu_d13_arm, +        fpu_d14_arm, +        fpu_d15_arm, +        fpu_d16_arm, +        fpu_d17_arm, +        fpu_d18_arm, +        fpu_d19_arm, +        fpu_d20_arm, +        fpu_d21_arm, +        fpu_d22_arm, +        fpu_d23_arm, +        fpu_d24_arm, +        fpu_d25_arm, +        fpu_d26_arm, +        fpu_d27_arm, +        fpu_d28_arm, +        fpu_d29_arm, +        fpu_d30_arm, +        fpu_d31_arm, +        fpu_q0_arm, +        fpu_q1_arm, +        fpu_q2_arm, +        fpu_q3_arm, +        fpu_q4_arm, +        fpu_q5_arm, +        fpu_q6_arm, +        fpu_q7_arm, +        fpu_q8_arm, +        fpu_q9_arm, +        fpu_q10_arm, +        fpu_q11_arm, +        fpu_q12_arm, +        fpu_q13_arm, +        fpu_q14_arm, +        fpu_q15_arm, +        k_last_fpr_arm = fpu_q15_arm,          exc_exception_arm,          exc_fsr_arm,          exc_far_arm, diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index bf5cad8e39c51..5b5d98a86d5e2 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -57,7 +57,7 @@ ProcessElfCore::Terminate()  lldb::ProcessSP -ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file) +ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file)  {      lldb::ProcessSP process_sp;      if (crash_file) @@ -75,7 +75,7 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp              if (elf_header.Parse(data, &data_offset))              {                  if (elf_header.e_type == llvm::ELF::ET_CORE) -                    process_sp.reset(new ProcessElfCore (target, listener, *crash_file)); +                    process_sp.reset(new ProcessElfCore (target_sp, listener, *crash_file));              }          }      } @@ -83,12 +83,12 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp  }  bool -ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name) +ProcessElfCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)  {      // For now we are just making sure the file exists for a given module      if (!m_core_module_sp && m_core_file.Exists())      { -        ModuleSpec core_module_spec(m_core_file, target.GetArchitecture()); +        ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());          Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,                                                    NULL, NULL, NULL));          if (m_core_module_sp) @@ -104,9 +104,9 @@ ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)  //----------------------------------------------------------------------  // ProcessElfCore constructor  //---------------------------------------------------------------------- -ProcessElfCore::ProcessElfCore(Target& target, Listener &listener, +ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, Listener &listener,                                 const FileSpec &core_file) : -    Process (target, listener), +    Process (target_sp, listener),      m_core_module_sp (),      m_core_file (core_file),      m_dyld_plugin_name (), @@ -233,10 +233,29 @@ ProcessElfCore::DoLoadCore ()      // it to match the core file which is always single arch.      ArchSpec arch (m_core_module_sp->GetArchitecture());      if (arch.IsValid()) -        m_target.SetArchitecture(arch); +        GetTarget().SetArchitecture(arch);      SetUnixSignals(UnixSignals::Create(GetArchitecture())); +    // Core files are useless without the main executable. See if we can locate the main +    // executable using data we found in the core file notes. +    lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); +    if (!exe_module_sp) +    { +        // The first entry in the NT_FILE might be our executable +        if (!m_nt_file_entries.empty()) +        { +            ModuleSpec exe_module_spec; +            exe_module_spec.GetArchitecture() = arch; +            exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false); +            if (exe_module_spec.GetFileSpec()) +            { +                exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); +                if (exe_module_sp) +                    GetTarget().SetExecutableModule(exe_module_sp, false); +            } +        } +    }      return error;  } @@ -258,7 +277,7 @@ ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_t      for (lldb::tid_t tid = 0; tid < num_threads; ++tid)      {          const ThreadData &td = m_thread_data[tid]; -        lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td)); +        lldb::ThreadSP thread_sp(new ThreadElfCore (*this, td));          new_thread_list.AddThread (thread_sp);      }      return new_thread_list.GetSize(false) > 0; @@ -352,8 +371,7 @@ ProcessElfCore::Clear()      m_thread_list.Clear();      m_os = llvm::Triple::UnknownOS; -    static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>(); -    SetUnixSignals(s_default_unix_signals_sp); +    SetUnixSignals(std::make_shared<UnixSignals>());  }  void @@ -371,12 +389,11 @@ ProcessElfCore::Initialize()  lldb::addr_t  ProcessElfCore::GetImageInfoAddress()  { -    Target *target = &GetTarget(); -    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); -    Address addr = obj_file->GetImageInfoAddress(target); +    ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); +    Address addr = obj_file->GetImageInfoAddress(&GetTarget());      if (addr.IsValid()) -        return addr.GetLoadAddress(target); +        return addr.GetLoadAddress(&GetTarget());      return LLDB_INVALID_ADDRESS;  } @@ -387,7 +404,8 @@ enum {      NT_PRPSINFO,      NT_TASKSTRUCT,      NT_PLATFORM, -    NT_AUXV +    NT_AUXV, +    NT_FILE = 0x46494c45  };  namespace FREEBSD { @@ -429,7 +447,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,          offset += 16;      thread_data.signo = data.GetU32(&offset); // pr_cursig -    offset += 4;        // pr_pid +    thread_data.tid = data.GetU32(&offset); // pr_pid      if (lp64)          offset += 4; @@ -503,6 +521,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *          // Store the NOTE information in the current thread          DataExtractor note_data (segment_data, note_start, note_size); +        note_data.SetAddressByteSize(m_core_module_sp->GetArchitecture().GetAddressByteSize());          if (note.n_name == "FreeBSD")          {              m_os = llvm::Triple::FreeBSD; @@ -532,7 +551,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *                      break;              }          } -        else +        else if (note.n_name == "CORE")          {              switch (note.n_type)              { @@ -543,6 +562,8 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *                      header_size = ELFLinuxPrStatus::GetSize(arch);                      len = note_data.GetByteSize() - header_size;                      thread_data->gpregset = DataExtractor(note_data, header_size, len); +                    // FIXME: Obtain actual tid on Linux +                    thread_data->tid = m_thread_data.size();                      break;                  case NT_FPREGSET:                      thread_data->fpregset = note_data; @@ -555,6 +576,28 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *                  case NT_AUXV:                      m_auxv = DataExtractor(note_data);                      break; +                case NT_FILE: +                    { +                        m_nt_file_entries.clear(); +                        lldb::offset_t offset = 0; +                        const uint64_t count = note_data.GetAddress(&offset); +                        note_data.GetAddress(&offset); // Skip page size +                        for (uint64_t i = 0; i<count; ++i) +                        { +                            NT_FILE_Entry entry; +                            entry.start = note_data.GetAddress(&offset); +                            entry.end = note_data.GetAddress(&offset); +                            entry.file_ofs = note_data.GetAddress(&offset); +                            m_nt_file_entries.push_back(entry); +                        } +                        for (uint64_t i = 0; i<count; ++i) +                        { +                            const char *path = note_data.GetCStr(&offset); +                            if (path && path[0]) +                                m_nt_file_entries[i].path.SetCString(path); +                        } +                    } +                    break;                  default:                      break;              } diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index 775d9e94dd8e9..12ce04c5ce38b 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -1,4 +1,4 @@ -//===-- ProcessElfCore.h ---------------------------------------*- C++ -*-===// +//===-- ProcessElfCore.h ----------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,18 +10,20 @@  //  2) The ELF file's PT_NOTE and PT_LOAD segments describes the program's  //     address space and thread contexts.  //  3) PT_NOTE segment contains note entries which describes a thread context. -//  4) PT_LOAD segment describes a valid contigous range of process address +//  4) PT_LOAD segment describes a valid contiguous range of process address  //     space.  //===----------------------------------------------------------------------===//  #ifndef liblldb_ProcessElfCore_h_  #define liblldb_ProcessElfCore_h_ +// C Includes  // C++ Includes  #include <list>  #include <vector>  // Other libraries and framework includes +// Project includes  #include "lldb/Core/ConstString.h"  #include "lldb/Core/Error.h"  #include "lldb/Target/Process.h" @@ -37,7 +39,7 @@ public:      // Constructors and Destructors      //------------------------------------------------------------------      static lldb::ProcessSP -    CreateInstance (lldb_private::Target& target, +    CreateInstance (lldb::TargetSP target_sp,                      lldb_private::Listener &listener,                      const lldb_private::FileSpec *crash_file_path); @@ -56,17 +58,16 @@ public:      //------------------------------------------------------------------      // Constructors and Destructors      //------------------------------------------------------------------ -    ProcessElfCore(lldb_private::Target& target, -                    lldb_private::Listener &listener, -                    const lldb_private::FileSpec &core_file); +    ProcessElfCore(lldb::TargetSP target_sp, +                   lldb_private::Listener &listener, +                   const lldb_private::FileSpec &core_file); -    virtual -    ~ProcessElfCore(); +    ~ProcessElfCore() override;      //------------------------------------------------------------------      // Check if a given Process      //------------------------------------------------------------------ -    bool CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override; +    bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;      //------------------------------------------------------------------      // Creating a new process, or attaching to an existing one @@ -118,6 +119,14 @@ protected:                            lldb_private::ThreadList &new_thread_list) override;  private: +    struct NT_FILE_Entry +    { +        lldb::addr_t start; +        lldb::addr_t end; +        lldb::addr_t file_ofs; +        lldb_private::ConstString path; +    }; +      //------------------------------------------------------------------      // For ProcessElfCore only      //------------------------------------------------------------------ @@ -143,6 +152,9 @@ private:      // Address ranges found in the core      VMRangeToFileOffset m_core_aranges; +    // NT_FILE entries found from the NOTE segment +    std::vector<NT_FILE_Entry> m_nt_file_entries; +      // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment      void      ParseThreadContextsFromNoteSegment (const elf::ELFProgramHeader *segment_header, @@ -157,4 +169,4 @@ private:      AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);  }; -#endif  // liblldb_ProcessElffCore_h_ +#endif // liblldb_ProcessElfCore_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp index f046c112d8b64..6778aeaaac007 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp @@ -10,7 +10,6 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h"  #include "RegisterContextPOSIXCore_arm.h"  using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h index 73e2ef7c3a93b..0e74897b5b5c0 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h @@ -1,15 +1,19 @@ -//===-- RegisterContextCorePOSIX_arm.h -----------------------*- C++ -*-===// +//===-- RegisterContextCorePOSIX_arm.h --------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_arm_H_ -#define liblldb_RegisterContextCorePOSIX_arm_H_ +#ifndef liblldb_RegisterContextCorePOSIX_arm_h_ +#define liblldb_RegisterContextCorePOSIX_arm_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/DataBufferHeap.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h" @@ -22,39 +26,41 @@ public:                                       const lldb_private::DataExtractor &gpregset,                                       const lldb_private::DataExtractor &fpregset); -    ~RegisterContextCorePOSIX_arm(); +    ~RegisterContextCorePOSIX_arm() override; -    virtual bool -    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override;      bool -    ReadAllRegisterValues(lldb::DataBufferSP &data_sp); +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;      bool -    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool -    HardwareSingleStep(bool enable); +    HardwareSingleStep(bool enable) override;  protected:      bool -    ReadGPR(); +    ReadGPR() override;      bool -    ReadFPR(); +    ReadFPR() override;      bool -    WriteGPR(); +    WriteGPR() override;      bool -    WriteFPR(); +    WriteFPR() override;  private:      lldb::DataBufferSP m_gpr_buffer;      lldb_private::DataExtractor m_gpr;  }; -#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm_H_ +#endif // liblldb_RegisterContextCorePOSIX_arm_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp index 53c0c83c264a2..7cfdd415ad5b0 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -10,7 +10,6 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h"  #include "RegisterContextPOSIXCore_arm64.h"  using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h index 2e1d6b4f9ca83..9b05edb1935fd 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -1,15 +1,19 @@ -//===-- RegisterContextCorePOSIX_arm64.h -----------------------*- C++ -*-===// +//===-- RegisterContextCorePOSIX_arm64.h ------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_arm64_H_ -#define liblldb_RegisterContextCorePOSIX_arm64_H_ +#ifndef liblldb_RegisterContextCorePOSIX_arm64_h_ +#define liblldb_RegisterContextCorePOSIX_arm64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/DataBufferHeap.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h" @@ -22,39 +26,41 @@ public:                                       const lldb_private::DataExtractor &gpregset,                                       const lldb_private::DataExtractor &fpregset); -    ~RegisterContextCorePOSIX_arm64(); +    ~RegisterContextCorePOSIX_arm64() override; -    virtual bool -    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override;      bool -    ReadAllRegisterValues(lldb::DataBufferSP &data_sp); +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;      bool -    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool -    HardwareSingleStep(bool enable); +    HardwareSingleStep(bool enable) override;  protected:      bool -    ReadGPR(); +    ReadGPR() override;      bool -    ReadFPR(); +    ReadFPR() override;      bool -    WriteGPR(); +    WriteGPR() override;      bool -    WriteFPR(); +    WriteFPR() override;  private:      lldb::DataBufferSP m_gpr_buffer;      lldb_private::DataExtractor m_gpr;  }; -#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm64_H_ +#endif // liblldb_RegisterContextCorePOSIX_arm64_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp index f0750a0cee18e..9d908e371a326 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp @@ -10,7 +10,6 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h"  #include "RegisterContextPOSIXCore_mips64.h"  using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h index ca29d4f0febd8..6cbfd504b7dbc 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h @@ -1,15 +1,19 @@ -//===-- RegisterContextCorePOSIX_mips64.h ----------------------*- C++ -*-===// +//===-- RegisterContextCorePOSIX_mips64.h -----------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_mips64_H_ -#define liblldb_RegisterContextCorePOSIX_mips64_H_ +#ifndef liblldb_RegisterContextCorePOSIX_mips64_h_ +#define liblldb_RegisterContextCorePOSIX_mips64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/DataBufferHeap.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h" @@ -22,39 +26,41 @@ public:                                       const lldb_private::DataExtractor &gpregset,                                       const lldb_private::DataExtractor &fpregset); -    ~RegisterContextCorePOSIX_mips64(); +    ~RegisterContextCorePOSIX_mips64() override; -    virtual bool -    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override;      bool -    ReadAllRegisterValues(lldb::DataBufferSP &data_sp); +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;      bool -    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool -    HardwareSingleStep(bool enable); +    HardwareSingleStep(bool enable) override;  protected:      bool -    ReadGPR(); +    ReadGPR() override;      bool -    ReadFPR(); +    ReadFPR() override;      bool -    WriteGPR(); +    WriteGPR() override;      bool -    WriteFPR(); +    WriteFPR() override;  private:      lldb::DataBufferSP m_gpr_buffer;      lldb_private::DataExtractor m_gpr;  }; -#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_ +#endif // liblldb_RegisterContextCorePOSIX_mips64_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp index d12df21a86646..9d8c97849ff8e 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp @@ -10,7 +10,6 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "RegisterContextPOSIX.h"  #include "RegisterContextPOSIXCore_powerpc.h"  using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h index a3590601fa7e6..0f587fd1459c1 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h @@ -5,11 +5,15 @@  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ -#define liblldb_RegisterContextCorePOSIX_powerpc_H_ +#ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_ +#define liblldb_RegisterContextCorePOSIX_powerpc_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/Core/DataBufferHeap.h"  #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" @@ -23,41 +27,43 @@ public:                                       const lldb_private::DataExtractor &fpregset,                                       const lldb_private::DataExtractor &vregset); -    ~RegisterContextCorePOSIX_powerpc(); +    ~RegisterContextCorePOSIX_powerpc() override; -    virtual bool -    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override;      bool -    ReadAllRegisterValues(lldb::DataBufferSP &data_sp); +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;      bool -    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool -    HardwareSingleStep(bool enable); +    HardwareSingleStep(bool enable) override;  protected:      bool -    ReadGPR(); +    ReadGPR() override;      bool -    ReadFPR(); +    ReadFPR() override;      bool -    ReadVMX(); +    ReadVMX() override;      bool -    WriteGPR(); +    WriteGPR() override;      bool -    WriteFPR(); +    WriteFPR() override;      bool -    WriteVMX(); +    WriteVMX() override;  private:      lldb::DataBufferSP m_gpr_buffer; @@ -68,4 +74,4 @@ private:      lldb_private::DataExtractor m_vec;  }; -#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_ +#endif // liblldb_RegisterContextCorePOSIX_powerpc_h_ diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp index 412c7ade82955..926c7aff36035 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp @@ -10,7 +10,6 @@  #include "lldb/Core/DataExtractor.h"  #include "lldb/Core/RegisterValue.h"  #include "lldb/Target/Thread.h" -#include "Plugins/Process/Utility/RegisterContextPOSIX.h"  #include "RegisterContextPOSIXCore_x86_64.h"  using namespace lldb_private; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h index ac0f49c3db52b..60f2ad33b4a5a 100644 --- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h @@ -1,15 +1,19 @@ -//===-- RegisterContextCorePOSIX_x86_64.h ----------------------*- C++ -*-===// +//===-- RegisterContextCorePOSIX_x86_64.h -----------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details.  // -//===---------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// -#ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_ -#define liblldb_RegisterContextCorePOSIX_x86_64_H_ +#ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_ +#define liblldb_RegisterContextCorePOSIX_x86_64_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"  class RegisterContextCorePOSIX_x86_64 : @@ -21,38 +25,40 @@ public:                                       const lldb_private::DataExtractor &gpregset,                                       const lldb_private::DataExtractor &fpregset); -    ~RegisterContextCorePOSIX_x86_64(); +    ~RegisterContextCorePOSIX_x86_64() override; -    virtual bool -    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value); +    bool +    ReadRegister(const lldb_private::RegisterInfo *reg_info, +                 lldb_private::RegisterValue &value) override; -    virtual bool -    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value); +    bool +    WriteRegister(const lldb_private::RegisterInfo *reg_info, +                  const lldb_private::RegisterValue &value) override;      bool -    ReadAllRegisterValues(lldb::DataBufferSP &data_sp); +    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;      bool -    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); +    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;      bool -    HardwareSingleStep(bool enable); +    HardwareSingleStep(bool enable) override;  protected:      bool -    ReadGPR(); +    ReadGPR() override;      bool -    ReadFPR(); +    ReadFPR() override;      bool -    WriteGPR(); +    WriteGPR() override;      bool -    WriteFPR(); +    WriteFPR() override;  private:      uint8_t *m_gpregset;  }; -#endif // #ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_ +#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_ diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 2abb6ba5decd9..9cc7829fc3913 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -37,9 +37,8 @@ using namespace lldb_private;  //----------------------------------------------------------------------  // Construct a Thread object with given data  //---------------------------------------------------------------------- -ThreadElfCore::ThreadElfCore (Process &process, tid_t tid, -                              const ThreadData &td) : -    Thread(process, tid), +ThreadElfCore::ThreadElfCore (Process &process, const ThreadData &td) : +    Thread(process, td.tid),      m_thread_name(td.name),      m_thread_reg_ctx_sp (),      m_signo(td.signo), diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index 50502c101daf9..d3a42e0eb54dd 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -1,4 +1,4 @@ -//===-- ThreadElfCore.h ----------------------------------------*- C++ -*-===// +//===-- ThreadElfCore.h -----------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,8 +10,12 @@  #ifndef liblldb_ThreadElfCore_h_  #define liblldb_ThreadElfCore_h_ +// C Includes +// C++ Includes  #include <string> +// Other libraries and framework includes +// Project includes  #include "lldb/Target/Thread.h"  #include "lldb/Core/DataExtractor.h" @@ -104,7 +108,6 @@ struct ELFLinuxPrPsInfo                  return 0;          }      } -  };  struct ThreadData @@ -112,6 +115,7 @@ struct ThreadData      lldb_private::DataExtractor gpregset;      lldb_private::DataExtractor fpregset;      lldb_private::DataExtractor vregset; +    lldb::tid_t tid;      int signo;      std::string name;  }; @@ -119,23 +123,21 @@ struct ThreadData  class ThreadElfCore : public lldb_private::Thread  {  public: -    ThreadElfCore (lldb_private::Process &process, lldb::tid_t tid, -                   const ThreadData &td); +    ThreadElfCore (lldb_private::Process &process, const ThreadData &td); -    virtual -    ~ThreadElfCore (); +    ~ThreadElfCore() override; -    virtual void -    RefreshStateAfterStop(); +    void +    RefreshStateAfterStop() override; -    virtual lldb::RegisterContextSP -    GetRegisterContext (); +    lldb::RegisterContextSP +    GetRegisterContext() override; -    virtual lldb::RegisterContextSP -    CreateRegisterContextForFrame (lldb_private::StackFrame *frame); +    lldb::RegisterContextSP +    CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; -    virtual void -    ClearStackFrames (); +    void +    ClearStackFrames() override;      static bool      ThreadIDIsValid (lldb::tid_t thread) @@ -143,8 +145,8 @@ public:          return thread != 0;      } -    virtual const char * -    GetName () +    const char * +    GetName() override      {          if (m_thread_name.empty())              return NULL; @@ -152,7 +154,7 @@ public:      }      void -    SetName (const char *name) +    SetName(const char *name) override      {          if (name && name[0])              m_thread_name.assign (name); @@ -173,8 +175,7 @@ protected:      lldb_private::DataExtractor m_fpregset_data;      lldb_private::DataExtractor m_vregset_data; -    virtual bool CalculateStopInfo(); - +    bool CalculateStopInfo() override;  }; -#endif  // liblldb_ThreadElfCore_h_ +#endif // liblldb_ThreadElfCore_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 9c263c8c40879..2ea1f206008a7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -30,6 +30,7 @@  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/ThreadLauncher.h"  #include "lldb/Host/TimeValue.h" +#include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "llvm/ADT/SmallString.h" @@ -574,15 +575,24 @@ GDBRemoteCommunication::DecompressPacket ()          return true;      if (m_bytes[1] != 'C' && m_bytes[1] != 'N')          return true; -    if (m_bytes[pkt_size - 3] != '#') + +    size_t hash_mark_idx = m_bytes.find ('#'); +    if (hash_mark_idx == std::string::npos) +        return true; +    if (hash_mark_idx + 2 >= m_bytes.size())          return true; -    if (!::isxdigit (m_bytes[pkt_size - 2]) || !::isxdigit (m_bytes[pkt_size - 1])) + +    if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2]))          return true; -    size_t content_length = pkt_size - 5;   // not counting '$', 'C' | 'N', '#', & the two hex checksum chars -    size_t content_start = 2;               // The first character of the compressed/not-compressed text of the packet -    size_t hash_mark_idx = pkt_size - 3;    // The '#' character marking the end of the packet -    size_t checksum_idx = pkt_size - 2;     // The first character of the two hex checksum characters +    size_t content_length = pkt_size - 5;    // not counting '$', 'C' | 'N', '#', & the two hex checksum chars +    size_t content_start = 2;                // The first character of the compressed/not-compressed text of the packet +    size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters + +    // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets. +    // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed +    // version of, leaving the rest of m_bytes unmodified. +    size_t size_of_first_packet = hash_mark_idx + 3;       // Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload,      // then a : and then the compressed data.  e.g. $C1024:<binary>#00 @@ -604,7 +614,7 @@ GDBRemoteCommunication::DecompressPacket ()              decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10);              if (errno != 0 || decompressed_bufsize == ULONG_MAX)              { -                m_bytes.erase (0, pkt_size); +                m_bytes.erase (0, size_of_first_packet);                  return false;              }          } @@ -633,7 +643,7 @@ GDBRemoteCommunication::DecompressPacket ()          if (!success)          {              SendNack(); -            m_bytes.erase (0, pkt_size); +            m_bytes.erase (0, size_of_first_packet);              return false;          }          else @@ -677,7 +687,7 @@ GDBRemoteCommunication::DecompressPacket ()          decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1);          if (decompressed_buffer == nullptr)          { -            m_bytes.erase (0, pkt_size); +            m_bytes.erase (0, size_of_first_packet);              return false;          } @@ -751,7 +761,7 @@ GDBRemoteCommunication::DecompressPacket ()      {          if (decompressed_buffer)              free (decompressed_buffer); -        m_bytes.erase (0, pkt_size); +        m_bytes.erase (0, size_of_first_packet);          return false;      } @@ -773,7 +783,7 @@ GDBRemoteCommunication::DecompressPacket ()          new_packet.push_back ('0');      } -    m_bytes = new_packet; +    m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size());      free (decompressed_buffer);      return true; @@ -927,8 +937,10 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri                  {                      for (size_t i=0; !binary && i<total_length; ++i)                      { -                        if (isprint(m_bytes[i]) == 0) +                        if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0) +                        {                              binary = true; +                        }                      }                  }                  if (binary) @@ -1100,16 +1112,16 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)  }  Error -GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, -                                                 uint16_t in_port, +GDBRemoteCommunication::StartDebugserverProcess (const char *url, +                                                 Platform *platform,                                                   ProcessLaunchInfo &launch_info, -                                                 uint16_t &out_port) +                                                 uint16_t *port, +                                                 const Args& inferior_args)  {      Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));      if (log) -        log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port); +        log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); -    out_port = in_port;      Error error;      // If we locate debugserver, keep that located version around      static FileSpec g_debugserver_file_spec; @@ -1146,11 +1158,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,              }              else              { -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); - +                debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME); +                if (debugserver_file_spec) +                { +                    // Platform::LocateExecutable() wouldn't return a path if it doesn't exist +                    debugserver_exists = true; +                } +                else +                { +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); +                } +                // Don't cache the platform specific GDB server binary as it could change +                // from platform to platform                  g_debugserver_file_spec.Clear(); -                debugserver_file_spec.Clear();              }          }      } @@ -1171,17 +1192,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          debugserver_args.AppendArgument("gdbserver");  #endif -        // If a host and port is supplied then use it -        char host_and_port[128]; -        if (hostname) -        { -            snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port); -            debugserver_args.AppendArgument(host_and_port); -        } -        else -        { -            host_and_port[0] = '\0'; -        } +        // If a url is supplied then use it +        if (url) +            debugserver_args.AppendArgument(url);          // use native registers, not the GDB registers          debugserver_args.AppendArgument("--native-regs"); @@ -1192,30 +1205,41 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          }          llvm::SmallString<PATH_MAX> named_pipe_path; -        Pipe port_pipe; - -        if (host_and_port[0] && in_port == 0) +        // socket_pipe is used by debug server to communicate back either +        // TCP port or domain socket name which it listens on. +        // The second purpose of the pipe to serve as a synchronization point - +        // once data is written to the pipe, debug server is up and running. +        Pipe socket_pipe; + +        // port is null when debug server should listen on domain socket - +        // we're not interested in port value but rather waiting for debug server +        // to become available. +        if ((port != nullptr && *port == 0) || port == nullptr)          { -            // Create a temporary file to get the stdout/stderr and redirect the -            // output of the command into this file. We will later read this file -            // if all goes well and fill the data into "command_output_ptr" - -            // Binding to port zero, we need to figure out what port it ends up -            // using using a named pipe... -            error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); -            if (error.Success()) +            if (url)              { +                // Create a temporary file to get the stdout/stderr and redirect the +                // output of the command into this file. We will later read this file +                // if all goes well and fill the data into "command_output_ptr" +     +#if defined(__APPLE__) +                // Binding to port zero, we need to figure out what port it ends up +                // using using a named pipe... +                error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf("GDBRemoteCommunication::%s() " +                                "named pipe creation failed: %s", +                                __FUNCTION__, error.AsCString()); +                    return error; +                }                  debugserver_args.AppendArgument("--named-pipe");                  debugserver_args.AppendArgument(named_pipe_path.c_str()); -            } -            else -            { -                if (log) -                    log->Printf("GDBRemoteCommunication::%s() " -                            "named pipe creation failed: %s", -                            __FUNCTION__, error.AsCString()); -                // let's try an unnamed pipe -                error = port_pipe.CreateNew(true); +#else +                // Binding to port zero, we need to figure out what port it ends up +                // using using an unnamed pipe... +                error = socket_pipe.CreateNew(true);                  if (error.Fail())                  {                      if (log) @@ -1224,42 +1248,43 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, error.AsCString());                      return error;                  } -                int write_fd = port_pipe.GetWriteFileDescriptor(); +                int write_fd = socket_pipe.GetWriteFileDescriptor();                  debugserver_args.AppendArgument("--pipe");                  debugserver_args.AppendArgument(std::to_string(write_fd).c_str()); -                launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor()); -            } -        } -        else -        { -            // No host and port given, so lets listen on our end and make the debugserver -            // connect to us.. -            error = StartListenThread ("127.0.0.1", 0); -            if (error.Fail()) -            { -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString()); -                return error; -            } - -            ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); -            // Wait for 10 seconds to resolve the bound port -            out_port = connection->GetListeningPort(10); -            if (out_port > 0) -            { -                char port_cstr[32]; -                snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port); -                // Send the host and port down that debugserver and specify an option -                // so that it connects back to the port we are listening to in this process -                debugserver_args.AppendArgument("--reverse-connect"); -                debugserver_args.AppendArgument(port_cstr); +                launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor()); +#endif              }              else              { -                error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); -                return error; +                // No host and port given, so lets listen on our end and make the debugserver +                // connect to us.. +                error = StartListenThread ("127.0.0.1", 0); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString()); +                    return error; +                } +     +                ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); +                // Wait for 10 seconds to resolve the bound port +                *port = connection->GetListeningPort(10); +                if (*port > 0) +                { +                    char port_cstr[32]; +                    snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port); +                    // Send the host and port down that debugserver and specify an option +                    // so that it connects back to the port we are listening to in this process +                    debugserver_args.AppendArgument("--reverse-connect"); +                    debugserver_args.AppendArgument(port_cstr); +                } +                else +                { +                    error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); +                    return error; +                }              }          } @@ -1304,6 +1329,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,              }          } while (has_env_var); +        if (inferior_args.GetArgumentCount() > 0) +        { +            debugserver_args.AppendArgument ("--"); +            debugserver_args.AppendArguments (inferior_args); +        } + +        // Copy the current environment to the gdbserver/debugserver instance +        StringList env; +        if (Host::GetEnvironment(env)) +        { +            for (size_t i = 0; i < env.GetSize(); ++i) +                launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str()); +        } +          // Close STDIN, STDOUT and STDERR.          launch_info.AppendCloseFileAction (STDIN_FILENO);          launch_info.AppendCloseFileAction (STDOUT_FILENO); @@ -1316,11 +1355,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          error = Host::LaunchProcess(launch_info); -        if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) +        if (error.Success() && +            launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)          {              if (named_pipe_path.size() > 0)              { -                error = port_pipe.OpenAsReader(named_pipe_path, false); +                error = socket_pipe.OpenAsReader(named_pipe_path, false);                  if (error.Fail())                      if (log)                          log->Printf("GDBRemoteCommunication::%s() " @@ -1328,24 +1368,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, named_pipe_path.c_str(), error.AsCString());              } -            if (port_pipe.CanWrite()) -                port_pipe.CloseWriteFileDescriptor(); -            if (port_pipe.CanRead()) +            if (socket_pipe.CanWrite()) +                socket_pipe.CloseWriteFileDescriptor(); +            if (socket_pipe.CanRead())              { -                char port_cstr[256]; +                char port_cstr[PATH_MAX] = {0};                  port_cstr[0] = '\0';                  size_t num_bytes = sizeof(port_cstr);                  // Read port from pipe with 10 second timeout. -                error = port_pipe.ReadWithTimeout(port_cstr, num_bytes, +                error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,                          std::chrono::seconds{10}, num_bytes); -                if (error.Success()) +                if (error.Success() && (port != nullptr))                  {                      assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); -                    out_port = StringConvert::ToUInt32(port_cstr, 0); +                    *port = StringConvert::ToUInt32(port_cstr, 0);                      if (log)                          log->Printf("GDBRemoteCommunication::%s() " -                                "debugserver listens %u port", -                                __FUNCTION__, out_port); +                                    "debugserver listens %u port", +                                    __FUNCTION__, *port);                  }                  else                  { @@ -1355,12 +1395,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, named_pipe_path.c_str(), error.AsCString());                  } -                port_pipe.Close(); +                socket_pipe.Close();              }              if (named_pipe_path.size() > 0)              { -                const auto err = port_pipe.Delete(named_pipe_path); +                const auto err = socket_pipe.Delete(named_pipe_path);                  if (err.Fail())                  {                      if (log) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 7379bb3aa09b1..2a01bcec260ca 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -12,9 +12,9 @@  // C Includes  // C++ Includes -#include <list>  #include <string>  #include <queue> +#include <vector>  // Other libraries and framework includes  // Project includes @@ -25,6 +25,7 @@  #include "lldb/Host/Mutex.h"  #include "lldb/Host/Predicate.h"  #include "lldb/Host/TimeValue.h" +#include "lldb/Interpreter/Args.h"  #include "Utility/StringExtractorGDBRemote.h" @@ -94,14 +95,10 @@ public:          uint32_t m_saved_timeout;      }; -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteCommunication(const char *comm_name,                              const char *listener_name); -    virtual -    ~GDBRemoteCommunication(); +    ~GDBRemoteCommunication() override;      PacketResult      GetAck (); @@ -117,12 +114,13 @@ public:                          size_t payload_length);      bool -    GetSequenceMutex (Mutex::Locker& locker, const char *failure_message = NULL); +    GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);      PacketType      CheckForPacket (const uint8_t *src,                       size_t src_len,                       StringExtractorGDBRemote &packet); +      bool      IsRunning() const      { @@ -162,21 +160,22 @@ public:      {          return m_packet_timeout * TimeValue::MicroSecPerSec;      } +      //------------------------------------------------------------------      // Start a debugserver instance on the current host using the      // supplied connection URL.      //------------------------------------------------------------------      Error -    StartDebugserverProcess (const char *hostname, -                             uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit -                             ProcessLaunchInfo &launch_info, -                             uint16_t &out_port); +    StartDebugserverProcess(const char *url, +                            Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located +                            ProcessLaunchInfo &launch_info, +                            uint16_t *port, +                            const Args& inferior_args = Args());      void      DumpHistory(Stream &strm);  protected: -      class History      {      public: @@ -223,6 +222,7 @@ protected:          AddPacket (char packet_char,                     PacketType type,                     uint32_t bytes_transmitted); +          void          AddPacket (const std::string &src,                     uint32_t src_len, @@ -241,7 +241,7 @@ protected:              return m_dumped_to_log;          } -protected: +    protected:          uint32_t          GetFirstSavedPacketIndex () const          { @@ -275,13 +275,30 @@ protected:              return i % m_packets.size();          } -                  std::vector<Entry> m_packets;          uint32_t m_curr_idx;          uint32_t m_total_packet_count;          mutable bool m_dumped_to_log;      }; +    uint32_t m_packet_timeout; +    uint32_t m_echo_number; +    LazyBool m_supports_qEcho; +#ifdef ENABLE_MUTEX_ERROR_CHECKING +    TrackingMutex m_sequence_mutex; +#else +    Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time +#endif +    Predicate<bool> m_public_is_running; +    Predicate<bool> m_private_is_running; +    History m_history; +    bool m_send_acks; +    bool m_is_platform; // Set to true if this class represents a platform, +                        // false if this class represents a debug session for +                        // a single process +     +    CompressionType m_compression_type; +      PacketResult      SendPacket (const char *payload,                  size_t payload_length); @@ -321,27 +338,6 @@ protected:      bool      DecompressPacket (); -    //------------------------------------------------------------------ -    // Classes that inherit from GDBRemoteCommunication can see and modify these -    //------------------------------------------------------------------ -    uint32_t m_packet_timeout; -    uint32_t m_echo_number; -    LazyBool m_supports_qEcho; -#ifdef ENABLE_MUTEX_ERROR_CHECKING -    TrackingMutex m_sequence_mutex; -#else -    Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time -#endif -    Predicate<bool> m_public_is_running; -    Predicate<bool> m_private_is_running; -    History m_history; -    bool m_send_acks; -    bool m_is_platform; // Set to true if this class represents a platform, -                        // false if this class represents a debug session for -                        // a single process -     -    CompressionType m_compression_type; -      Error      StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0); @@ -361,10 +357,12 @@ protected:      // This method is defined as part of communication.h      // when the read thread gets any bytes it will pass them on to this function -    virtual void AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status); +    void AppendBytesToCache(const uint8_t * bytes, +                            size_t len, +                            bool broadcast, +                            lldb::ConnectionStatus status) override;  private: -      std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue      lldb_private::Mutex m_packet_queue_mutex;            // Mutex for accessing queue      Condition m_condition_queue_not_empty;               // Condition variable to wait for packets @@ -372,13 +370,10 @@ private:      HostThread m_listen_thread;      std::string m_listen_url; -    //------------------------------------------------------------------ -    // For GDBRemoteCommunication only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunication_h_ +#endif // liblldb_GDBRemoteCommunication_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b8c67c593b1f2..5c7f6caca511f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -619,7 +619,6 @@ GDBRemoteCommunicationClient::GetThreadsInfo()      if (m_supports_jThreadsInfo)      {          StringExtractorGDBRemote response; -        m_supports_jThreadExtendedInfo = eLazyBoolNo;          if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success)          {              if (response.IsUnsupportedResponse()) @@ -782,7 +781,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse      Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));      // In order to stop async notifications from being processed in the middle of the -    // send/recieve sequence Hijack the broadcast. Then rebroadcast any events when we are done. +    // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done.      static Listener hijack_listener("lldb.NotifyHijacker");      HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify);     @@ -878,10 +877,10 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse          }      } -    // Remove our Hijacking listner from the broadcast. +    // Remove our Hijacking listener from the broadcast.      RestoreBroadcaster(); -    // If a notification event occured, rebroadcast since it can now be processed safely.   +    // If a notification event occurred, rebroadcast since it can now be processed safely.      EventSP event_sp;      if (hijack_listener.GetNextEvent(event_sp))          BroadcastEvent(event_sp); @@ -1050,7 +1049,6 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse      Mutex::Locker locker(m_sequence_mutex);      StateType state = eStateRunning; -    BroadcastEvent(eBroadcastBitRunPacketSent, NULL);      m_public_is_running.SetValue (true, eBroadcastNever);      // Set the starting continue packet into "continue_packet". This packet      // may change if we are interrupted and we continue after an async packet... @@ -1060,6 +1058,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse      const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");      bool got_async_packet = false; +    bool broadcast_sent = false;      while (state == eStateRunning)      { @@ -1072,6 +1071,12 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse              else                  m_interrupt_sent = false; +            if (! broadcast_sent) +            { +                BroadcastEvent(eBroadcastBitRunPacketSent, NULL); +                broadcast_sent = true; +            } +              m_private_is_running.SetValue (true, eBroadcastAlways);          } @@ -1133,10 +1138,10 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse                                  continue_after_async = false;                                  // We didn't get a SIGINT or SIGSTOP, so try for a -                                // very brief time (1 ms) to get another stop reply +                                // very brief time (0.1s) to get another stop reply                                  // packet to make sure it doesn't get in the way                                  StringExtractorGDBRemote extra_stop_reply_packet; -                                uint32_t timeout_usec = 1000; +                                uint32_t timeout_usec = 100000;                                  if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)                                  {                                      switch (extra_stop_reply_packet.GetChar()) @@ -1262,9 +1267,13 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse                          got_async_packet = true;                          std::string inferior_stdout;                          inferior_stdout.reserve(response.GetBytesLeft () / 2); -                        char ch; -                        while ((ch = response.GetHexU8()) != '\0') -                            inferior_stdout.append(1, ch); + +                        uint8_t ch; +                        while (response.GetHexU8Ex(ch)) +                        { +                            if (ch != 0) +                                inferior_stdout.append(1, (char)ch); +                        }                          process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());                      }                      break; @@ -1574,6 +1583,8 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu                  {                      case '$':                      case '#': +                    case '*': +                    case '}':                          send_hex_encoding = true;                          break;                      default: @@ -2308,7 +2319,8 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)              const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");              assert (packet_len < (int)sizeof(packet));              StringExtractorGDBRemote response; -            if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) +            if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success +                  && response.IsOKResponse())              {                  m_supports_detach_stay_stopped = eLazyBoolYes;                      } @@ -2326,7 +2338,7 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)          else          {              StringExtractorGDBRemote response; -            PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 1, response, false); +            PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false);              if (packet_result != PacketResult::Success)                  error.SetErrorString ("Sending extended disconnect packet failed.");          } @@ -3311,10 +3323,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t      return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)  == PacketResult::Success;  } -uint16_t -GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname) +bool +GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname, +                                               lldb::pid_t &pid, +                                               uint16_t &port, +                                               std::string &socket_name)  {      pid = LLDB_INVALID_PROCESS_ID; +    port = 0; +    socket_name.clear(); +      StringExtractorGDBRemote response;      StreamString stream;      stream.PutCString("qLaunchGDBServer;"); @@ -3339,22 +3357,67 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const      // give the process a few seconds to startup      GDBRemoteCommunication::ScopedTimeout timeout (*this, 10); -     +      if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)      {          std::string name;          std::string value; -        uint16_t port = 0; +        StringExtractor extractor;          while (response.GetNameColonValue(name, value))          {              if (name.compare("port") == 0)                  port = StringConvert::ToUInt32(value.c_str(), 0, 0);              else if (name.compare("pid") == 0)                  pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); +            else if (name.compare("socket_name") == 0) +            { +                extractor.GetStringRef().swap(value); +                extractor.SetFilePos(0); +                extractor.GetHexByteString(value); + +                socket_name = value; +            }          } -        return port; +        return true;      } -    return 0; +    return false; +} + +size_t +GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls) +{ +    connection_urls.clear(); + +    StringExtractorGDBRemote response; +    if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success) +        return 0; + +    StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef()); +    if (!data) +        return 0; + +    StructuredData::Array* array = data->GetAsArray(); +    if (!array) +        return 0; + +    for (size_t i = 0, count = array->GetSize(); i < count; ++i) +    { +        StructuredData::Dictionary* element = nullptr; +        if (!array->GetItemAtIndexAsDictionary(i, element)) +            continue; + +        uint16_t port = 0; +        if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port"))) +            port = port_osp->GetIntegerValue(0); + +        std::string socket_name; +        if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name"))) +            socket_name = socket_name_osp->GetStringValue(); + +        if (port != 0 || !socket_name.empty()) +            connection_urls.emplace_back(port, socket_name); +    } +    return connection_urls.size();  }  bool @@ -3395,6 +3458,17 @@ GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)              m_curr_tid = tid;              return true;          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet. +         * The reply from '?' packet could be as simple as 'S05'. There is no packet which can +         * give us pid and/or tid. Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && IsConnected()) +        { +            m_curr_tid = 1; +            return true; +        }      }      return false;  } @@ -3421,6 +3495,17 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)              m_curr_tid_run = tid;              return true;          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet. +         * The reply from '?' packet could be as simple as 'S05'. There is no packet which can +         * give us pid and/or tid. Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && IsConnected()) +        { +            m_curr_tid_run = 1; +            return true; +        }      }      return false;  } @@ -3546,6 +3631,17 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr                  } while (ch == ',');            // Make sure we got a comma separator              }          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for +         * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could +         * be as simple as 'S05'. There is no packet which can give us pid and/or tid. +         * Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected()) +        { +            thread_ids.push_back (1); +        }      }      else      { @@ -4347,100 +4443,97 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)          {              StreamString packet;              packet.PutCString ("qSymbol::"); -            while (1) +            StringExtractorGDBRemote response; +            while (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)              { -                StringExtractorGDBRemote response; -                if (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success) +                if (response.IsOKResponse())                  { -                    if (response.IsOKResponse()) -                    { -                        // We are done serving symbols requests -                        return; -                    } +                    // We are done serving symbols requests +                    return; +                } -                    if (response.IsUnsupportedResponse()) -                    { -                        // qSymbol is not supported by the current GDB server we are connected to -                        m_supports_qSymbol = false; -                        return; -                    } -                    else +                if (response.IsUnsupportedResponse()) +                { +                    // qSymbol is not supported by the current GDB server we are connected to +                    m_supports_qSymbol = false; +                    return; +                } +                else +                { +                    llvm::StringRef response_str(response.GetStringRef()); +                    if (response_str.startswith("qSymbol:"))                      { -                        llvm::StringRef response_str(response.GetStringRef()); -                        if (response_str.startswith("qSymbol:")) +                        response.SetFilePos(strlen("qSymbol:")); +                        std::string symbol_name; +                        if (response.GetHexByteString(symbol_name))                          { -                            response.SetFilePos(strlen("qSymbol:")); -                            std::string symbol_name; -                            if (response.GetHexByteString(symbol_name)) -                            { -                                if (symbol_name.empty()) -                                    return; +                            if (symbol_name.empty()) +                                return; -                                addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; -                                lldb_private::SymbolContextList sc_list; -                                if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) +                            addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; +                            lldb_private::SymbolContextList sc_list; +                            if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) +                            { +                                const size_t num_scs = sc_list.GetSize(); +                                for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)                                  { -                                    const size_t num_scs = sc_list.GetSize(); -                                    for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx) +                                    SymbolContext sc; +                                    if (sc_list.GetContextAtIndex(sc_idx, sc))                                      { -                                        SymbolContext sc; -                                        if (sc_list.GetContextAtIndex(sc_idx, sc)) +                                        if (sc.symbol)                                          { -                                            if (sc.symbol) +                                            switch (sc.symbol->GetType())                                              { -                                                switch (sc.symbol->GetType()) -                                                { -                                                case eSymbolTypeInvalid: -                                                case eSymbolTypeAbsolute: -                                                case eSymbolTypeUndefined: -                                                case eSymbolTypeSourceFile: -                                                case eSymbolTypeHeaderFile: -                                                case eSymbolTypeObjectFile: -                                                case eSymbolTypeCommonBlock: -                                                case eSymbolTypeBlock: -                                                case eSymbolTypeLocal: -                                                case eSymbolTypeParam: -                                                case eSymbolTypeVariable: -                                                case eSymbolTypeVariableType: -                                                case eSymbolTypeLineEntry: -                                                case eSymbolTypeLineHeader: -                                                case eSymbolTypeScopeBegin: -                                                case eSymbolTypeScopeEnd: -                                                case eSymbolTypeAdditional: -                                                case eSymbolTypeCompiler: -                                                case eSymbolTypeInstrumentation: -                                                case eSymbolTypeTrampoline: -                                                    break; - -                                                case eSymbolTypeCode: -                                                case eSymbolTypeResolver: -                                                case eSymbolTypeData: -                                                case eSymbolTypeRuntime: -                                                case eSymbolTypeException: -                                                case eSymbolTypeObjCClass: -                                                case eSymbolTypeObjCMetaClass: -                                                case eSymbolTypeObjCIVar: -                                                case eSymbolTypeReExported: -                                                    symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); -                                                    break; -                                                } +                                            case eSymbolTypeInvalid: +                                            case eSymbolTypeAbsolute: +                                            case eSymbolTypeUndefined: +                                            case eSymbolTypeSourceFile: +                                            case eSymbolTypeHeaderFile: +                                            case eSymbolTypeObjectFile: +                                            case eSymbolTypeCommonBlock: +                                            case eSymbolTypeBlock: +                                            case eSymbolTypeLocal: +                                            case eSymbolTypeParam: +                                            case eSymbolTypeVariable: +                                            case eSymbolTypeVariableType: +                                            case eSymbolTypeLineEntry: +                                            case eSymbolTypeLineHeader: +                                            case eSymbolTypeScopeBegin: +                                            case eSymbolTypeScopeEnd: +                                            case eSymbolTypeAdditional: +                                            case eSymbolTypeCompiler: +                                            case eSymbolTypeInstrumentation: +                                            case eSymbolTypeTrampoline: +                                                break; + +                                            case eSymbolTypeCode: +                                            case eSymbolTypeResolver: +                                            case eSymbolTypeData: +                                            case eSymbolTypeRuntime: +                                            case eSymbolTypeException: +                                            case eSymbolTypeObjCClass: +                                            case eSymbolTypeObjCMetaClass: +                                            case eSymbolTypeObjCIVar: +                                            case eSymbolTypeReExported: +                                                symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); +                                                break;                                              }                                          }                                      }                                  } -                                // This is the normal path where our symbol lookup was successful and we want -                                // to send a packet with the new symbol value and see if another lookup needs to be -                                // done. - -                                // Change "packet" to contain the requested symbol value and name -                                packet.Clear(); -                                packet.PutCString("qSymbol:"); -                                if (symbol_load_addr != LLDB_INVALID_ADDRESS) -                                    packet.Printf("%" PRIx64, symbol_load_addr); -                                packet.PutCString(":"); -                                packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); -                                continue; // go back to the while loop and send "packet" and wait for another response                              } +                            // This is the normal path where our symbol lookup was successful and we want +                            // to send a packet with the new symbol value and see if another lookup needs to be +                            // done. + +                            // Change "packet" to contain the requested symbol value and name +                            packet.Clear(); +                            packet.PutCString("qSymbol:"); +                            if (symbol_load_addr != LLDB_INVALID_ADDRESS) +                                packet.Printf("%" PRIx64, symbol_load_addr); +                            packet.PutCString(":"); +                            packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); +                            continue; // go back to the while loop and send "packet" and wait for another response                          }                      }                  } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index b08ff0647797c..d2df214d0dbad 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -12,6 +12,8 @@  // C Includes  // C++ Includes +#include <map> +#include <string>  #include <vector>  // Other libraries and framework includes @@ -28,12 +30,9 @@ namespace process_gdb_remote {  class GDBRemoteCommunicationClient : public GDBRemoteCommunication  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteCommunicationClient(); -    ~GDBRemoteCommunicationClient(); +    ~GDBRemoteCommunicationClient() override;      //------------------------------------------------------------------      // After connecting, send the handshake to the server to make sure @@ -79,6 +78,7 @@ public:                                            const char *packet_payload,                                            size_t packet_length,                                            StringExtractorGDBRemote &response); +      bool      SendvContPacket (ProcessGDBRemote *process,                       const char *payload, @@ -114,9 +114,15 @@ public:      bool      GetLaunchSuccess (std::string &error_str); -    uint16_t -    LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname); -     +    bool +    LaunchGDBServer (const char *remote_accept_hostname, +                     lldb::pid_t &pid, +                     uint16_t &port, +                     std::string &socket_name); + +    size_t +    QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls); +      bool      KillSpawnedProcess (lldb::pid_t pid); @@ -161,7 +167,7 @@ public:      SendLaunchArchPacket (const char *arch);      int -    SendLaunchEventDataPacket (const char *data, bool *was_supported = NULL); +    SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr);      //------------------------------------------------------------------      /// Sends a "vAttach:PID" where PID is in hex.  @@ -182,7 +188,6 @@ public:      SendAttach (lldb::pid_t pid,                   StringExtractorGDBRemote& response); -      //------------------------------------------------------------------      /// Sends a GDB remote protocol 'I' packet that delivers stdin      /// data to the remote process. @@ -396,6 +401,7 @@ public:          default:                    return false;          }      } +      uint8_t      SendGDBStoppointTypePacket (GDBStoppointType type,   // Type of breakpoint or watchpoint                                  bool insert,              // Insert or remove? @@ -505,11 +511,11 @@ public:      GetFileExists (const FileSpec& file_spec);      Error -    RunShellCommand(const char *command,           // Shouldn't be NULL +    RunShellCommand(const char *command,           // Shouldn't be nullptr                      const FileSpec &working_dir,   // Pass empty FileSpec to use the current working directory -                    int *status_ptr,               // Pass NULL if you don't want the process exit status -                    int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit -                    std::string *command_output,   // Pass NULL if you don't want the command output +                    int *status_ptr,               // Pass nullptr if you don't want the process exit status +                    int *signo_ptr,                // Pass nullptr if you don't want the signal that caused the process to exit +                    std::string *command_output,   // Pass nullptr if you don't want the command output                      uint32_t timeout_sec);         // Timeout in seconds to wait for shell program to finish      bool @@ -567,26 +573,6 @@ public:      ServeSymbolLookups(lldb_private::Process *process);  protected: - -    PacketResult -    SendPacketAndWaitForResponseNoLock (const char *payload, -                                        size_t payload_length, -                                        StringExtractorGDBRemote &response); - -    bool -    GetCurrentProcessInfo (bool allow_lazy_pid = true); - -    bool -    GetGDBServerVersion(); - -    // Given the list of compression types that the remote debug stub can support, -    // possibly enable compression if we find an encoding we can handle. -    void -    MaybeEnableCompression (std::vector<std::string> supported_compressions); - -    //------------------------------------------------------------------ -    // Classes that inherit from GDBRemoteCommunicationClient can see and modify these -    //------------------------------------------------------------------      LazyBool m_supports_not_sending_acks;      LazyBool m_supports_thread_suffix;      LazyBool m_supports_threads_in_stop_reply; @@ -639,7 +625,6 @@ protected:      lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations      lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc -      uint32_t m_num_supported_hardware_watchpoints;      // If we need to send a packet while the target is running, the m_async_XXX @@ -667,18 +652,31 @@ protected:      uint32_t m_default_packet_timeout;      uint64_t m_max_packet_size;  // as returned by qSupported -     +    PacketResult +    SendPacketAndWaitForResponseNoLock (const char *payload, +                                        size_t payload_length, +                                        StringExtractorGDBRemote &response); + +    bool +    GetCurrentProcessInfo (bool allow_lazy_pid = true); + +    bool +    GetGDBServerVersion(); + +    // Given the list of compression types that the remote debug stub can support, +    // possibly enable compression if we find an encoding we can handle. +    void +    MaybeEnableCompression (std::vector<std::string> supported_compressions); +      bool      DecodeProcessInfoResponse (StringExtractorGDBRemote &response,                                  ProcessInstanceInfo &process_info); +  private: -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationClient only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationClient_h_ +#endif // liblldb_GDBRemoteCommunicationClient_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 44c0f6a32f5b7..1d512bf1de595 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -39,8 +39,7 @@ public:      GDBRemoteCommunicationServer(const char *comm_name,                                   const char *listener_name); -    virtual -    ~GDBRemoteCommunicationServer(); +    ~GDBRemoteCommunicationServer() override;      void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,                                 PacketHandler handler); @@ -73,13 +72,10 @@ protected:      SendOKResponse ();  private: -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationServer only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServer_h_ +#endif // liblldb_GDBRemoteCommunicationServer_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 698854e5dfbd7..7f876fb393d9d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -58,8 +58,6 @@ using namespace lldb_private::process_gdb_remote;  //----------------------------------------------------------------------  GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :      GDBRemoteCommunicationServer (comm_name, listener_name), -    m_spawned_pids (), -    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),      m_process_launch_info (),      m_process_launch_error (),      m_proc_infos (), @@ -79,8 +77,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const cha                                    &GDBRemoteCommunicationServerCommon::Handle_qGroupName);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,                                    &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); -    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, -                                  &GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,                                    &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, @@ -185,14 +181,20 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &      else          response.Printf("watchpoint_exceptions_received:after;");  #else -    if (host_arch.GetMachine() == llvm::Triple::mips64 || -        host_arch.GetMachine() == llvm::Triple::mips64el) +    if (host_arch.GetMachine() == llvm::Triple::aarch64 || +        host_arch.GetMachine() == llvm::Triple::aarch64_be || +        host_arch.GetMachine() == llvm::Triple::arm || +        host_arch.GetMachine() == llvm::Triple::armeb || +        host_arch.GetMachine() == llvm::Triple::mips64 || +        host_arch.GetMachine() == llvm::Triple::mips64el || +        host_arch.GetMachine() == llvm::Triple::mips || +        host_arch.GetMachine() == llvm::Triple::mipsel)          response.Printf("watchpoint_exceptions_received:before;");      else          response.Printf("watchpoint_exceptions_received:after;");  #endif -    switch (lldb::endian::InlHostByteOrder()) +    switch (endian::InlHostByteOrder())      {      case eByteOrderBig:     response.PutCString ("endian:big;"); break;      case eByteOrderLittle:  response.PutCString ("endian:little;"); break; @@ -485,94 +487,6 @@ GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) -{ -    packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); - -    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); - -    // verify that we know anything about this pid. -    // Scope for locker -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -        { -            // not a pid we know about -            return SendErrorResponse (10); -        } -    } - -    // go ahead and attempt to kill the spawned process -    if (KillSpawnedProcess (pid)) -        return SendOKResponse (); -    else -        return SendErrorResponse (11); -} - -bool -GDBRemoteCommunicationServerCommon::KillSpawnedProcess (lldb::pid_t pid) -{ -    // make sure we know about this process -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return false; -    } - -    // first try a SIGTERM (standard kill) -    Host::Kill (pid, SIGTERM); - -    // check if that worked -    for (size_t i=0; i<10; ++i) -    { -        { -            Mutex::Locker locker (m_spawned_pids_mutex); -            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            { -                // it is now killed -                return true; -            } -        } -        usleep (10000); -    } - -    // check one more time after the final usleep -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return true; -    } - -    // the launched process still lives.  Now try killing it again, -    // this time with an unblockable signal. -    Host::Kill (pid, SIGKILL); - -    for (size_t i=0; i<10; ++i) -    { -        { -            Mutex::Locker locker (m_spawned_pids_mutex); -            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            { -                // it is now killed -                return true; -            } -        } -        usleep (10000); -    } - -    // check one more time after the final usleep -    // Scope for locker -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return true; -    } - -    // no luck - the process still lives -    return false; -} - -GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:open:")); @@ -1299,6 +1213,7 @@ GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (              switch (proc_triple.getArch ())              {                  case llvm::Triple::arm: +                case llvm::Triple::thumb:                  case llvm::Triple::aarch64:                      ostype = "ios";                      break; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 62b129bb18b9a..f55b2eb3f4dc7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -12,14 +12,14 @@  // C Includes  // C++ Includes -#include <set> +#include <string>  // Other libraries and framework includes +// Project includes  #include "lldb/lldb-private-forward.h"  #include "lldb/Host/Mutex.h"  #include "lldb/Target/Process.h" -// Project includes  #include "GDBRemoteCommunicationServer.h"  #include "GDBRemoteCommunicationServerCommon.h" @@ -36,12 +36,9 @@ class GDBRemoteCommunicationServerCommon :  public:      GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name); -    virtual -    ~GDBRemoteCommunicationServerCommon(); +    ~GDBRemoteCommunicationServerCommon() override;  protected: -    std::set<lldb::pid_t> m_spawned_pids; -    Mutex m_spawned_pids_mutex;      ProcessLaunchInfo m_process_launch_info;      Error m_process_launch_error;      ProcessInstanceInfoList m_proc_infos; @@ -74,9 +71,6 @@ protected:      Handle_qSpeedTest (StringExtractorGDBRemote &packet);      PacketResult -    Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); - -    PacketResult      Handle_vFile_Open (StringExtractorGDBRemote &packet);      PacketResult @@ -160,9 +154,6 @@ protected:      PacketResult      Handle_QLaunchArch (StringExtractorGDBRemote &packet); -    bool -    KillSpawnedProcess (lldb::pid_t pid); -      static void      CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,                                 StreamString &response); @@ -213,4 +204,4 @@ protected:  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServerCommon_h_ +#endif // liblldb_GDBRemoteCommunicationServerCommon_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index c4523252f1908..921369c7ef21c 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -43,6 +43,8 @@  #include "lldb/Host/common/NativeRegisterContext.h"  #include "lldb/Host/common/NativeProcessProtocol.h"  #include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Utility/JSON.h" +#include "lldb/Utility/LLDBAssert.h"  // Project includes  #include "Utility/StringExtractorGDBRemote.h" @@ -96,20 +98,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(      RegisterPacketHandlers();  } -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS() -{ -    Mutex::Locker locker (m_debugged_process_mutex); - -    if (m_debugged_process_sp) -    { -        m_debugged_process_sp->Terminate (); -        m_debugged_process_sp.reset (); -    } -} -  void  GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()  { @@ -126,7 +114,7 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,                                    &GDBRemoteCommunicationServerLLGS::Handle_interrupt);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m, -                                  &GDBRemoteCommunicationServerLLGS::Handle_m); +                                  &GDBRemoteCommunicationServerLLGS::Handle_memory_read);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,                                    &GDBRemoteCommunicationServerLLGS::Handle_M);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, @@ -161,6 +149,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()                                    &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,                                    &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, +                                  &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,                                    &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, @@ -175,6 +165,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()                                    &GDBRemoteCommunicationServerLLGS::Handle_vCont);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions,                                    &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x, +                                  &GDBRemoteCommunicationServerLLGS::Handle_memory_read);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,                                    &GDBRemoteCommunicationServerLLGS::Handle_Z);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, @@ -223,6 +215,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()          error = NativeProcessProtocol::Launch(              m_process_launch_info,              *this, +            m_mainloop,              m_debugged_process_sp);      } @@ -274,17 +267,6 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()      printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ()); -    // Add to list of spawned processes. -    lldb::pid_t pid; -    if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID) -    { -        // add to spawned pids -        Mutex::Locker locker (m_spawned_pids_mutex); -        // On an lldb-gdbserver, we would expect there to be only one. -        assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); -        m_spawned_pids.insert (pid); -    } -      return error;  } @@ -297,48 +279,37 @@ GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)      if (log)          log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid); -    // Scope for mutex locker. +    // Before we try to attach, make sure we aren't already monitoring something else. +    if (m_debugged_process_sp  && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) +        return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID()); + +    // Try to attach. +    error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp); +    if (!error.Success ())      { -        // Before we try to attach, make sure we aren't already monitoring something else. -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (!m_spawned_pids.empty ()) -        { -            error.SetErrorStringWithFormat ("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, *m_spawned_pids.begin()); -            return error; -        } +        fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ()); +        return error; +    } -        // Try to attach. -        error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp); -        if (!error.Success ()) -        { -            fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ()); +    // Setup stdout/stderr mapping from inferior. +    auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); +    if (terminal_fd >= 0) +    { +        if (log) +            log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); +        error = SetSTDIOFileDescriptor (terminal_fd); +        if (error.Fail ())              return error; -        } - -        // Setup stdout/stderr mapping from inferior. -        auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); -        if (terminal_fd >= 0) -        { -            if (log) -                log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); -            error = SetSTDIOFileDescriptor (terminal_fd); -            if (error.Fail ()) -                return error; -        } -        else -        { -            if (log) -                log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); -        } - -        printf ("Attached to process %" PRIu64 "...\n", pid); +    } +    else +    { +        if (log) +            log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); +    } -        // Add to list of spawned processes. -        assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); -        m_spawned_pids.insert (pid); +    printf ("Attached to process %" PRIu64 "...\n", pid); -        return error; -    } +    return error;  }  void @@ -455,6 +426,178 @@ WriteRegisterValueInHexFixedWidth (StreamString &response,      }  } +static JSONObject::SP +GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD)); + +    NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext (); +    if (! reg_ctx_sp) +        return nullptr; + +    JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); + +#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET +    // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers. +    const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); +    if (! reg_set_p) +        return nullptr; +    for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) +    { +        uint32_t reg_num = *reg_num_p; +#else +    // Expedite only a couple of registers until we figure out why sending registers is +    // expensive. +    static const uint32_t k_expedited_registers[] = { +        LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM +    }; +    static const uint32_t k_abridged_expedited_registers[] = { +        LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM +    }; + +    for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers; +         *generic_reg_p != LLDB_INVALID_REGNUM; +         ++generic_reg_p) +    { +        uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p); +        if (reg_num == LLDB_INVALID_REGNUM) +            continue; // Target does not support the given register. +#endif + +        const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); +        if (reg_info_p == nullptr) +        { +            if (log) +                log->Printf("%s failed to get register info for register index %" PRIu32, +                        __FUNCTION__, reg_num); +            continue; +        } + +        if (reg_info_p->value_regs != nullptr) +            continue; // Only expedite registers that are not contained in other registers. + +        RegisterValue reg_value; +        Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); +        if (error.Fail()) +        { +            if (log) +                log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, +                        reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num, +                        error.AsCString ()); +            continue; +        } + +        StreamString stream; +        WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, ®_value); + +        register_object_sp->SetObject(std::to_string(reg_num), +                std::make_shared<JSONString>(stream.GetString())); +    } + +    return register_object_sp; +} + +static const char * +GetStopReasonString(StopReason stop_reason) +{ +    switch (stop_reason) +    { +    case eStopReasonTrace: +        return "trace"; +    case eStopReasonBreakpoint: +        return "breakpoint"; +    case eStopReasonWatchpoint: +        return "watchpoint"; +    case eStopReasonSignal: +        return "signal"; +    case eStopReasonException: +        return "exception"; +    case eStopReasonExec: +        return "exec"; +    case eStopReasonInstrumentation: +    case eStopReasonInvalid: +    case eStopReasonPlanComplete: +    case eStopReasonThreadExiting: +    case eStopReasonNone: +        break; // ignored +    } +    return nullptr; +} + +static JSONArray::SP +GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + +    JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + +    // Ensure we can get info on the given thread. +    uint32_t thread_idx = 0; +    for ( NativeThreadProtocolSP thread_sp; +          (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; +          ++thread_idx) +    { + +        lldb::tid_t tid = thread_sp->GetID(); + +        // Grab the reason this thread stopped. +        struct ThreadStopInfo tid_stop_info; +        std::string description; +        if (!thread_sp->GetStopReason (tid_stop_info, description)) +            return nullptr; + +        const int signum = tid_stop_info.details.signal.signo; +        if (log) +        { +            log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, +                    __FUNCTION__, +                    process.GetID (), +                    tid, +                    signum, +                    tid_stop_info.reason, +                    tid_stop_info.details.exception.type); +        } + +        JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); +        threads_array_sp->AppendObject(thread_obj_sp); + +        if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged)) +            thread_obj_sp->SetObject("registers", registers_sp); + +        thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); +        if (signum != 0) +            thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); + +        const std::string thread_name = thread_sp->GetName (); +        if (! thread_name.empty()) +            thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); + +        if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) +            thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str)); + +        if (! description.empty()) +            thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description)); + +        if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) +        { +            thread_obj_sp->SetObject("metype", +                    std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); + +            JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); +            for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) +            { +                medata_array_sp->AppendObject(std::make_shared<JSONNumber>( +                            tid_stop_info.details.exception.data[i])); +            } +            thread_obj_sp->SetObject("medata", medata_array_sp); +        } + +        // TODO: Expedite interesting regions of inferior memory +    } + +    return threads_array_sp; +} +  GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)  { @@ -548,6 +691,31 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)              response.Printf ("%" PRIx64, listed_thread_sp->GetID ());          }          response.PutChar (';'); + +        // Include JSON info that describes the stop reason for any threads +        // that actually have stop reasons. We use the new "jstopinfo" key +        // whose values is hex ascii JSON that contains the thread IDs +        // thread stop info only for threads that have stop reasons. Only send +        // this if we have more than one thread otherwise this packet has all +        // the info it needs. +        if (thread_index > 0) +        { +            const bool threads_with_valid_stop_info_only = true; +            JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp, +                                                               threads_with_valid_stop_info_only); +            if (threads_info_sp) +            { +                response.PutCString("jstopinfo:"); +                StreamString unescaped_response; +                threads_info_sp->Write(unescaped_response); +                response.PutCStringAsRawHex8(unescaped_response.GetData()); +                response.PutChar(';'); +            } +            else if (log) +                log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64, +                        __FUNCTION__, m_debugged_process_sp->GetID()); + +        }      }      // @@ -595,34 +763,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)          }      } -    const char* reason_str = nullptr; -    switch (tid_stop_info.reason) -    { -    case eStopReasonTrace: -        reason_str = "trace"; -        break; -    case eStopReasonBreakpoint: -        reason_str = "breakpoint"; -        break; -    case eStopReasonWatchpoint: -        reason_str = "watchpoint"; -        break; -    case eStopReasonSignal: -        reason_str = "signal"; -        break; -    case eStopReasonException: -        reason_str = "exception"; -        break; -    case eStopReasonExec: -        reason_str = "exec"; -        break; -    case eStopReasonInstrumentation: -    case eStopReasonInvalid: -    case eStopReasonPlanComplete: -    case eStopReasonThreadExiting: -    case eStopReasonNone: -        break; -    } +    const char* reason_str = GetStopReasonString(tid_stop_info.reason);      if (reason_str != nullptr)      {          response.Printf ("reason:%s;", reason_str); @@ -663,43 +804,15 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProto      if (log)          log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); -    // Send the exit result, and don't flush output. -    // Note: flushing output here would join the inferior stdio reflection thread, which -    // would gunk up the waitpid monitor thread that is calling this. -    PacketResult result = SendStopReasonForState (StateType::eStateExited, false); +    PacketResult result = SendStopReasonForState(StateType::eStateExited);      if (result != PacketResult::Success)      {          if (log)              log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());      } -    // Remove the process from the list of spawned pids. -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.erase (process->GetID ()) < 1) -        { -            if (log) -                log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to remove PID %" PRIu64 " from the spawned pids list", __FUNCTION__, process->GetID ()); - -        } -    } - -    // FIXME can't do this yet - since process state propagation is currently -    // synchronous, it is running off the NativeProcessProtocol's innards and -    // will tear down the NPP while it still has code to execute. -#if 0 -    // Clear the NativeProcessProtocol pointer. -    { -        Mutex::Locker locker (m_debugged_process_mutex); -        m_debugged_process_sp.reset(); -    } -#endif -      // Close the pipe to the inferior terminal i/o if we launched it -    // and set one up.  Otherwise, 'k' and its flush of stdio could -    // end up waiting on a thread join that will never end.  Consider -    // adding a timeout to the connection thread join call so we -    // can avoid that scenario altogether. +    // and set one up.      MaybeCloseInferiorTerminalConnection ();      // We are ready to exit the debug monitor. @@ -725,7 +838,7 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProt              break;          default:              // In all other cases, send the stop reason. -            PacketResult result = SendStopReasonForState (StateType::eStateStopped, false); +            PacketResult result = SendStopReasonForState(StateType::eStateStopped);              if (result != PacketResult::Success)              {                  if (log) @@ -748,21 +861,30 @@ GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *pr                  StateAsCString (state));      } -    // Make sure we get all of the pending stdout/stderr from the inferior -    // and send it to the lldb host before we send the state change -    // notification -    m_stdio_communication.SynchronizeWithReadThread(); -      switch (state)      { -    case StateType::eStateExited: -        HandleInferiorState_Exited (process); +    case StateType::eStateRunning: +        StartSTDIOForwarding();          break;      case StateType::eStateStopped: +        // Make sure we get all of the pending stdout/stderr from the inferior +        // and send it to the lldb host before we send the state change +        // notification +        SendProcessOutput(); +        // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not +        // interfere with our protocol. +        StopSTDIOForwarding();          HandleInferiorState_Stopped (process);          break; +    case StateType::eStateExited: +        // Same as above +        SendProcessOutput(); +        StopSTDIOForwarding(); +        HandleInferiorState_Exited (process); +        break; +      default:          if (log)          { @@ -796,7 +918,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()              if(log)                  log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",                          __FUNCTION__); -            m_read_handle_up.reset();              m_mainloop.RequestTermination();              return;          } @@ -817,7 +938,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()              if(log)                  log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",                          __FUNCTION__, error.AsCString()); -            m_read_handle_up.reset();              m_mainloop.RequestTermination();              break;          } @@ -831,7 +951,7 @@ GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connecti      GDBRemoteCommunicationServer::SetConnection(connection.release());      Error error; -    m_read_handle_up = m_mainloop.RegisterReadObject(read_object_sp, +    m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp,              [this] (MainLoopBase &) { DataAvailableCallback(); }, error);      return error;  } @@ -857,7 +977,7 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)  {      Error error; -    // Set up the Read Thread for reading/handling process I/O +    // Set up the reading/handling of process I/O      std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));      if (!conn_up)      { @@ -873,29 +993,73 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)          return error;      } +    return Error(); +} + +void +GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() +{ +    // Don't forward if not connected (e.g. when attaching). +    if (! m_stdio_communication.IsConnected()) +        return; +      // llgs local-process debugging may specify PTY paths, which will make these      // file actions non-null      // process launch -e/o will also make these file actions non-null      // nullptr means that the traffic is expected to flow over gdb-remote protocol -    if ( -        m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || -        m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr -        ) +    if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) && +         m_process_launch_info.GetFileActionForFD(STDERR_FILENO)) +        return; + +    Error error; +    lldbassert(! m_stdio_handle_up); +    m_stdio_handle_up = m_mainloop.RegisterReadObject( +            m_stdio_communication.GetConnection()->GetReadObject(), +            [this] (MainLoopBase &) { SendProcessOutput(); }, error); + +    if (! m_stdio_handle_up)      { -        // output from the process must be forwarded over gdb-remote -        // create a thread to read the handle and send the data -        m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this); -        m_stdio_communication.StartReadThread(); +        // Not much we can do about the failure. Log it and continue without forwarding. +        if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) +            log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s", +                        __FUNCTION__, error.AsCString());      } +} -    return error; +void +GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() +{ +    m_stdio_handle_up.reset();  }  void -GDBRemoteCommunicationServerLLGS::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len) +GDBRemoteCommunicationServerLLGS::SendProcessOutput()  { -    GDBRemoteCommunicationServerLLGS *server = reinterpret_cast<GDBRemoteCommunicationServerLLGS*> (baton); -    static_cast<void> (server->SendONotification (static_cast<const char *>(src), src_len)); +    char buffer[1024]; +    ConnectionStatus status; +    Error error; +    while (true) +    { +        size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error); +        switch (status) +        { +        case eConnectionStatusSuccess: +            SendONotification(buffer, bytes_read); +            break; +        case eConnectionStatusLostConnection: +        case eConnectionStatusEndOfFile: +        case eConnectionStatusError: +        case eConnectionStatusNoConnection: +            if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) +                log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString()); +            m_stdio_handle_up.reset(); +            return; + +        case eConnectionStatusInterrupted: +        case eConnectionStatusTimedOut: +            return; +        } +    }  }  GDBRemoteCommunication::PacketResult @@ -941,49 +1105,24 @@ GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet)      return SendPacketNoLock (response.GetData(), response.GetSize());  } -bool -GDBRemoteCommunicationServerLLGS::DebuggedProcessReaped (lldb::pid_t pid) -{ -    // reap a process that we were debugging (but not debugserver) -    Mutex::Locker locker (m_spawned_pids_mutex); -    return m_spawned_pids.erase(pid) > 0; -} - -bool -GDBRemoteCommunicationServerLLGS::ReapDebuggedProcess (void *callback_baton, -                                        lldb::pid_t pid, -                                        bool exited, -                                        int signal,    // Zero for no signal -                                        int status)    // Exit value of process if signal is zero -{ -    GDBRemoteCommunicationServerLLGS *server = (GDBRemoteCommunicationServerLLGS *)callback_baton; -    server->DebuggedProcessReaped (pid); -    return true; -} -  GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet)  { -    // shutdown all spawned processes -    std::set<lldb::pid_t> spawned_pids_copy; +    Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); -    // copy pids -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ()); -    } +    StopSTDIOForwarding(); -    // nuke the spawned processes -    for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it) +    if (! m_debugged_process_sp)      { -        lldb::pid_t spawned_pid = *it; -        if (!KillSpawnedProcess (spawned_pid)) -        { -            fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid); -        } +        if (log) +            log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__); +        return PacketResult::Success;      } -    FlushInferiorOutput (); +    Error error = m_debugged_process_sp->Kill(); +    if (error.Fail() && log) +        log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s", +                __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());      // No OK response for kill packet.      // return SendOKResponse (); @@ -1316,11 +1455,11 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &      if (!m_debugged_process_sp)          return SendErrorResponse (02); -    return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +    return SendStopReasonForState (m_debugged_process_sp->GetState());  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit) +GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state)  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -1349,8 +1488,6 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType proces          case eStateInvalid:          case eStateUnloaded:          case eStateExited: -            if (flush_on_exit) -                FlushInferiorOutput ();              return SendWResponse(m_debugged_process_sp.get());          default: @@ -1448,8 +1585,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote          response.PutChar (';');      } -    if (reg_info->kinds[RegisterKind::eRegisterKindGCC] != LLDB_INVALID_REGNUM) -        response.Printf ("gcc:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindGCC]); +    if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) +        response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);      if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)          response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]); @@ -1856,7 +1993,7 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &pa  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet)  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -1889,7 +2026,7 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)      {          if (log)              log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__); -        return PacketResult::Success; +        return SendOKResponse();      }      // Allocate the response buffer. @@ -1916,8 +2053,16 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)      }      StreamGDBRemote response; -    for (size_t i = 0; i < bytes_read; ++i) -        response.PutHex8(buf[i]); +    packet.SetFilePos(0); +    char kind = packet.GetChar('?'); +    if (kind == 'x') +        response.PutEscapedBytes(buf.data(), byte_count); +    else +    { +        assert(kind == 'm'); +        for (size_t i = 0; i < bytes_read; ++i) +            response.PutHex8(buf[i]); +    }      return SendPacketNoLock(response.GetData(), response.GetSize());  } @@ -2108,6 +2253,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)      bool want_breakpoint = true;      bool want_hardware = false; +    uint32_t watch_flags = 0;      const GDBStoppointType stoppoint_type =          GDBStoppointType(packet.GetS32 (eStoppointInvalid)); @@ -2118,10 +2264,13 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)          case eBreakpointHardware:              want_hardware = true;  want_breakpoint = true;  break;          case eWatchpointWrite: +            watch_flags = 1;              want_hardware = true;  want_breakpoint = false; break;          case eWatchpointRead: +            watch_flags = 2;              want_hardware = true;  want_breakpoint = false; break;          case eWatchpointReadWrite: +            watch_flags = 3;              want_hardware = true;  want_breakpoint = false; break;          case eStoppointInvalid:              return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); @@ -2161,11 +2310,6 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)      }      else      { -        uint32_t watch_flags = -            stoppoint_type == eWatchpointWrite -            ? 0x1  // Write -            : 0x3; // ReadWrite -          // Try to set the watchpoint.          const Error error = m_debugged_process_sp->SetWatchpoint (                  addr, size, watch_flags, want_hardware); @@ -2555,7 +2699,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &pack      }      // Notify we attached by sending a stop packet. -    return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +    return SendStopReasonForState (m_debugged_process_sp->GetState ());  }  GDBRemoteCommunication::PacketResult @@ -2563,8 +2707,7 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)  {      Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); -    // Scope for mutex locker. -    Mutex::Locker locker (m_spawned_pids_mutex); +    StopSTDIOForwarding();      // Fail if we don't have a current process.      if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) @@ -2574,14 +2717,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendErrorResponse (0x15);      } -    if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end()) -    { -        if (log) -            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to find PID %" PRIu64 " in spawned pids list", -                         __FUNCTION__, m_debugged_process_sp->GetID ()); -        return SendErrorResponse (0x1); -    } -      lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;      // Consume the ';' after D. @@ -2603,11 +2738,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendIllFormedResponse (packet, "Invalid pid");      } -    if (m_stdio_communication.IsConnected ()) -    { -        m_stdio_communication.StopReadThread (); -    } -      const Error error = m_debugged_process_sp->Detach ();      if (error.Fail ())      { @@ -2617,7 +2747,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendErrorResponse (0x01);      } -    m_spawned_pids.erase (m_debugged_process_sp->GetID ());      return SendOKResponse ();  } @@ -2638,6 +2767,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemo  }  GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + +    // Ensure we have a debugged process. +    if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) +        return SendErrorResponse (50); + +    if (log) +        log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64, +                __FUNCTION__, m_debugged_process_sp->GetID()); + + +    StreamString response; +    const bool threads_with_valid_stop_info_only = false; +    JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp, +                                                        threads_with_valid_stop_info_only); +    if (! threads_array_sp) +    { +        if (log) +            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64, +                    __FUNCTION__, m_debugged_process_sp->GetID()); +        return SendErrorResponse(52); +    } + +    threads_array_sp->Write(response); +    StreamGDBRemote escaped_response; +    escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); +    return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize()); +} + +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)  {      // Fail if we don't have a current process. @@ -2686,21 +2847,6 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRem  }  void -GDBRemoteCommunicationServerLLGS::FlushInferiorOutput () -{ -    // If we're not monitoring an inferior's terminal, ignore this. -    if (!m_stdio_communication.IsConnected()) -        return; - -    Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); -    if (log) -        log->Printf ("GDBRemoteCommunicationServerLLGS::%s() called", __FUNCTION__); - -    // FIXME implement a timeout on the join. -    m_stdio_communication.JoinReadThread(); -} - -void  GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection ()  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 29f3fdebcfb0c..f16057781ddc4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -42,9 +42,6 @@ public:      //------------------------------------------------------------------      GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop); -    virtual -    ~GDBRemoteCommunicationServerLLGS(); -      //------------------------------------------------------------------      /// Specify the program to launch and its arguments.      /// @@ -119,12 +116,15 @@ public:  protected:      lldb::PlatformSP m_platform_sp;      MainLoop &m_mainloop; -    MainLoop::ReadHandleUP m_read_handle_up; +    MainLoop::ReadHandleUP m_network_handle_up;      lldb::tid_t m_current_tid;      lldb::tid_t m_continue_tid;      Mutex m_debugged_process_mutex;      NativeProcessProtocolSP m_debugged_process_sp; +      Communication m_stdio_communication; +    MainLoop::ReadHandleUP m_stdio_handle_up; +      lldb::StateType m_inferior_prev_state;      lldb::DataBufferSP m_active_auxv_buffer_sp;      Mutex m_saved_registers_mutex; @@ -142,7 +142,7 @@ protected:      SendStopReplyPacketForThread (lldb::tid_t tid);      PacketResult -    SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit); +    SendStopReasonForState (lldb::StateType process_state);      PacketResult      Handle_k (StringExtractorGDBRemote &packet); @@ -201,8 +201,9 @@ protected:      PacketResult      Handle_interrupt (StringExtractorGDBRemote &packet); +    // Handles $m and $x packets.      PacketResult -    Handle_m (StringExtractorGDBRemote &packet); +    Handle_memory_read (StringExtractorGDBRemote &packet);      PacketResult      Handle_M (StringExtractorGDBRemote &packet); @@ -241,6 +242,9 @@ protected:      Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);      PacketResult +    Handle_jThreadsInfo (StringExtractorGDBRemote &packet); + +    PacketResult      Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);      PacketResult @@ -261,32 +265,16 @@ protected:      Error      SetSTDIOFileDescriptor (int fd); -    static void -    STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); -      FileSpec      FindModuleFile (const std::string& module_path, const ArchSpec& arch) override;  private: -    bool -    DebuggedProcessReaped (lldb::pid_t pid); - -    static bool -    ReapDebuggedProcess (void *callback_baton, -                         lldb::pid_t pid, -                         bool exited, -                         int signal, -                         int status); -      void      HandleInferiorState_Exited (NativeProcessProtocol *process);      void      HandleInferiorState_Stopped (NativeProcessProtocol *process); -    void -    FlushInferiorOutput (); -      NativeThreadProtocolSP      GetThreadFromSuffix (StringExtractorGDBRemote &packet); @@ -305,6 +293,15 @@ private:      void      DataAvailableCallback (); +    void +    SendProcessOutput (); + +    void +    StartSTDIOForwarding(); + +    void +    StopSTDIOForwarding(); +      //------------------------------------------------------------------      // For GDBRemoteCommunicationServerLLGS only      //------------------------------------------------------------------ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 1205049db3fb8..f88ac12475260 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -15,19 +15,26 @@  // C++ Includes  #include <cstring>  #include <chrono> +#include <mutex> +#include <sstream>  // Other libraries and framework includes +#include "llvm/Support/FileSystem.h" +  #include "lldb/Core/Log.h" +#include "lldb/Core/StreamGDBRemote.h"  #include "lldb/Core/StreamString.h"  #include "lldb/Core/StructuredData.h"  #include "lldb/Host/Config.h"  #include "lldb/Host/ConnectionFileDescriptor.h"  #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Target/FileAction.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/JSON.h"  // Project includes  #include "Utility/StringExtractorGDBRemote.h" @@ -40,18 +47,29 @@ using namespace lldb_private::process_gdb_remote;  //----------------------------------------------------------------------  // GDBRemoteCommunicationServerPlatform constructor  //---------------------------------------------------------------------- -GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() : +GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, +                                                                           const char* socket_scheme) :      GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), +    m_socket_protocol(socket_protocol), +    m_socket_scheme(socket_scheme), +    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),      m_platform_sp (Platform::GetHostPlatform ()),      m_port_map (),      m_port_offset(0)  { +    m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; +    m_pending_gdb_server.port = 0; +      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,                                    &GDBRemoteCommunicationServerPlatform::Handle_qC);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,                                    &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,                                    &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, +                                  &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, +                                  &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,                                    &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, @@ -78,38 +96,16 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()  {  } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) +Error +GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args, +                                                      std::string hostname, +                                                      lldb::pid_t& pid, +                                                      uint16_t& port, +                                                      std::string& socket_name)  { -#ifdef _WIN32 -    return SendErrorResponse(9); -#else -    // Spawn a local debugserver as a platform so we can then attach or launch -    // a process... - -    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); -    if (log) -        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); - -    // Sleep and wait a bit for debugserver to start to listen... -    ConnectionFileDescriptor file_conn; -    std::string hostname; -    // TODO: /tmp/ should not be hardcoded. User might want to override /tmp -    // with the TMPDIR environment variable -    packet.SetFilePos(::strlen ("qLaunchGDBServer;")); -    std::string name; -    std::string value; -    uint16_t port = UINT16_MAX; -    while (packet.GetNameColonValue(name, value)) -    { -        if (name.compare ("host") == 0) -            hostname.swap(value); -        else if (name.compare ("port") == 0) -            port = StringConvert::ToUInt32(value.c_str(), 0, 0); -    }      if (port == UINT16_MAX)          port = GetNextAvailablePort(); - +          // Spawn a new thread to accept the port that gets bound after      // binding to port 0 (zero). @@ -120,6 +116,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD      ProcessLaunchInfo debugserver_launch_info;      if (hostname.empty())          hostname = "127.0.0.1"; + +    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));      if (log)          log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); @@ -133,53 +131,210 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD      int platform_port;      std::string platform_path;      bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); +    UNUSED_IF_ASSERT_DISABLED(ok);      assert(ok); -    Error error = StartDebugserverProcess ( -                                     platform_ip.c_str(), -                                     port, -                                     debugserver_launch_info, -                                     port); -    lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); +    std::ostringstream url; +    uint16_t* port_ptr = &port; +    if (m_socket_protocol == Socket::ProtocolTcp) +        url << platform_ip << ":" << port; +    else +    { +        socket_name = GetDomainSocketPath("gdbserver").GetPath(); +        url << socket_name; +        port_ptr = nullptr; +    } +    Error error = StartDebugserverProcess (url.str().c_str(), +                                           nullptr, +                                           debugserver_launch_info, +                                           port_ptr, +                                           args); -    if (debugserver_pid != LLDB_INVALID_PROCESS_ID) +    pid = debugserver_launch_info.GetProcessID(); +    if (pid != LLDB_INVALID_PROCESS_ID)      {          Mutex::Locker locker (m_spawned_pids_mutex); -        m_spawned_pids.insert(debugserver_pid); +        m_spawned_pids.insert(pid);          if (port > 0) -            AssociatePortWithProcess(port, debugserver_pid); +            AssociatePortWithProcess(port, pid);      }      else      {          if (port > 0) -            FreePort (port); +            FreePort(port); +    } +    return error; +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) +{ +#ifdef _WIN32 +    return SendErrorResponse(9); +#else +    // Spawn a local debugserver as a platform so we can then attach or launch +    // a process... + +    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); +    if (log) +        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); + +    ConnectionFileDescriptor file_conn; +    std::string hostname; +    packet.SetFilePos(::strlen ("qLaunchGDBServer;")); +    std::string name; +    std::string value; +    uint16_t port = UINT16_MAX; +    while (packet.GetNameColonValue(name, value)) +    { +        if (name.compare ("host") == 0) +            hostname.swap(value); +        else if (name.compare ("port") == 0) +            port = StringConvert::ToUInt32(value.c_str(), 0, 0);      } -    if (error.Success()) +    lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; +    std::string socket_name; +    Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); +    if (error.Fail())      {          if (log) -            log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); +            log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); +        return SendErrorResponse(9); +    } -        char response[256]; -        const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); -        assert (response_len < (int)sizeof(response)); -        PacketResult packet_result = SendPacketNoLock (response, response_len); +    if (log) +        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); -        if (packet_result != PacketResult::Success) +    StreamGDBRemote response; +    response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); +    if (!socket_name.empty()) +    { +        response.PutCString("socket_name:"); +        response.PutCStringAsRawHex8(socket_name.c_str()); +        response.PutChar(';'); +    } + +    PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize()); +    if (packet_result != PacketResult::Success) +    { +        if (debugserver_pid != LLDB_INVALID_PROCESS_ID) +            ::kill (debugserver_pid, SIGINT); +    } +    return packet_result; +#endif +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet) +{ +    if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) +        return SendErrorResponse(4); + +    JSONObject::SP server_sp = std::make_shared<JSONObject>(); +    server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port)); +    if (!m_pending_gdb_server.socket_name.empty()) +        server_sp->SetObject("socket_name", +                             std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); + +    JSONArray server_list; +    server_list.AppendObject(server_sp); + +    StreamGDBRemote response; +    server_list.Write(response); + +    StreamGDBRemote escaped_response; +    escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); +    return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +{ +    packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); + +    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); + +    // verify that we know anything about this pid. +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end())          { -            if (debugserver_pid != LLDB_INVALID_PROCESS_ID) -                ::kill (debugserver_pid, SIGINT); +            // not a pid we know about +            return SendErrorResponse (10);          } -        return packet_result;      } + +    // go ahead and attempt to kill the spawned process +    if (KillSpawnedProcess (pid)) +        return SendOKResponse ();      else +        return SendErrorResponse (11); +} + +bool +GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) +{ +    // make sure we know about this process      { -        if (log) -            log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return false;      } -    return SendErrorResponse (9); -#endif + +    // first try a SIGTERM (standard kill) +    Host::Kill (pid, SIGTERM); + +    // check if that worked +    for (size_t i=0; i<10; ++i) +    { +        { +            Mutex::Locker locker (m_spawned_pids_mutex); +            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            { +                // it is now killed +                return true; +            } +        } +        usleep (10000); +    } + +    // check one more time after the final usleep +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // the launched process still lives.  Now try killing it again, +    // this time with an unblockable signal. +    Host::Kill (pid, SIGKILL); + +    for (size_t i=0; i<10; ++i) +    { +        { +            Mutex::Locker locker (m_spawned_pids_mutex); +            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            { +                // it is now killed +                return true; +            } +        } +        usleep (10000); +    } + +    // check one more time after the final usleep +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // no luck - the process still lives +    return false;  }  GDBRemoteCommunication::PacketResult @@ -402,8 +557,48 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)      return false;  } +const FileSpec& +GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() +{ +    static FileSpec g_domainsocket_dir; +    static std::once_flag g_once_flag; + +    std::call_once(g_once_flag, []() { +        const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); +        if (domainsocket_dir_env != nullptr) +            g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); +        else +            HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir); +    }); + +    return g_domainsocket_dir; +} + +FileSpec +GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix) +{ +    llvm::SmallString<PATH_MAX> socket_path; +    llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str()); + +    FileSpec socket_path_spec(GetDomainSocketDir()); +    socket_path_spec.AppendPathComponent(socket_name.c_str()); + +    llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); +    return FileSpec(socket_path.c_str(), false); +} +  void -GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset) +GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)  {      m_port_offset = port_offset;  } + +void +GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid, +                                                          uint16_t port, +                                                          const std::string& socket_name) +{ +    m_pending_gdb_server.pid = pid; +    m_pending_gdb_server.port = port; +    m_pending_gdb_server.socket_name = socket_name; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 5c011371a3ebe..1fe7207d2bc2e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -10,7 +10,15 @@  #ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_  #define liblldb_GDBRemoteCommunicationServerPlatform_h_ +// C Includes +// C++ Includes +#include <map> +#include <set> + +// Other libraries and framework includes +// Project includes  #include "GDBRemoteCommunicationServerCommon.h" +#include "lldb/Host/Socket.h"  namespace lldb_private {  namespace process_gdb_remote { @@ -21,10 +29,10 @@ class GDBRemoteCommunicationServerPlatform :  public:      typedef std::map<uint16_t, lldb::pid_t> PortMap; -    GDBRemoteCommunicationServerPlatform(); +    GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, +                                         const char* socket_scheme); -    virtual -    ~GDBRemoteCommunicationServerPlatform(); +    ~GDBRemoteCommunicationServerPlatform() override;      Error      LaunchProcess () override; @@ -58,16 +66,40 @@ public:      void      SetPortOffset (uint16_t port_offset); +    void +    SetInferiorArguments (const lldb_private::Args& args); + +    Error +    LaunchGDBServer(const lldb_private::Args& args, +                    std::string hostname, +                    lldb::pid_t& pid, +                    uint16_t& port, +                    std::string& socket_name); + +    void +    SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name); +  protected: +    const Socket::SocketProtocol m_socket_protocol; +    const std::string m_socket_scheme; +    Mutex m_spawned_pids_mutex; +    std::set<lldb::pid_t> m_spawned_pids;      lldb::PlatformSP m_platform_sp;      PortMap m_port_map;      uint16_t m_port_offset; +    struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server;      PacketResult      Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);      PacketResult +    Handle_qQueryGDBServer (StringExtractorGDBRemote &packet); + +    PacketResult +    Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); + +    PacketResult      Handle_qProcessInfo (StringExtractorGDBRemote &packet);      PacketResult @@ -84,6 +116,9 @@ protected:  private:      bool +    KillSpawnedProcess (lldb::pid_t pid); + +    bool      DebugserverProcessReaped (lldb::pid_t pid);      static bool @@ -93,13 +128,16 @@ private:                              int signal,                              int status); -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationServerPlatform only -    //------------------------------------------------------------------ +    static const FileSpec& +    GetDomainSocketDir(); + +    static FileSpec +    GetDomainSocketPath(const char* prefix); +      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServerPlatform_h_ +#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index f5f134e80d6ab..b0a1eaaeb79c0 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -17,9 +17,6 @@  #include "lldb/Core/RegisterValue.h"  #include "lldb/Core/Scalar.h"  #include "lldb/Core/StreamString.h" -#ifndef LLDB_DISABLE_PYTHON -#include "lldb/Interpreter/PythonDataObjects.h" -#endif  #include "lldb/Target/ExecutionContext.h"  #include "lldb/Target/Target.h"  #include "lldb/Utility/Utils.h" @@ -28,8 +25,8 @@  #include "ProcessGDBRemote.h"  #include "ProcessGDBRemoteLog.h"  #include "ThreadGDBRemote.h" -#include "Utility/ARM_GCC_Registers.h"  #include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  using namespace lldb;  using namespace lldb_private; @@ -150,6 +147,52 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor      return success;  } +bool +GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val) +{ +    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); +    if (reg_info == NULL) +        return false; + +    // Early in process startup, we can get a thread that has an invalid byte order +    // because the process hasn't been completely set up yet (see the ctor where the +    // byte order is setfrom the process).  If that's the case, we can't set the +    // value here. +    if (m_reg_data.GetByteOrder() == eByteOrderInvalid) +    { +        return false; +    } + +    // Invalidate if needed +    InvalidateIfNeeded (false); + +    DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val))); +    DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*)); + +    // If our register context and our register info disagree, which should never happen, don't +    // overwrite past the end of the buffer. +    if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) +        return false; + +    // Grab a pointer to where we are going to put this register +    uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); + +    if (dst == NULL) +        return false; + + +    if (data.CopyByteOrderedData (0,                            // src offset +                                  reg_info->byte_size,          // src length +                                  dst,                          // dst +                                  reg_info->byte_size,          // dst length +                                  m_reg_data.GetByteOrder()))   // dst byte order +    { +        SetRegisterIsValid (reg, true); +        return true; +    } +    return false; +} +  // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().  bool  GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info, @@ -186,7 +229,8 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE              if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))                  return false;              if (response.IsNormalResponse()) -                if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize()) +                if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())), +                                         m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())                      SetAllRegisterValid (true);          }          else if (reg_info->value_regs) @@ -275,8 +319,8 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,      packet.Printf ("P%x=", reg);      packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),                                reg_info->byte_size, -                              lldb::endian::InlHostByteOrder(), -                              lldb::endian::InlHostByteOrder()); +                              endian::InlHostByteOrder(), +                              endian::InlHostByteOrder());      if (gdb_comm.GetThreadSuffixSupported())          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -372,8 +416,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data                      packet.PutChar ('G');                      packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),                                                m_reg_data.GetByteSize(), -                                              lldb::endian::InlHostByteOrder(), -                                              lldb::endian::InlHostByteOrder()); +                                              endian::InlHostByteOrder(), +                                              endian::InlHostByteOrder());                      if (thread_suffix_supported)                          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -772,8 +816,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                                  packet.Printf ("P%x=", reg);                                  packet.PutBytesAsRawHex8 (restore_src,                                                            reg_byte_size, -                                                          lldb::endian::InlHostByteOrder(), -                                                          lldb::endian::InlHostByteOrder()); +                                                          endian::InlHostByteOrder(), +                                                          endian::InlHostByteOrder());                                  if (thread_suffix_supported)                                      packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -795,8 +839,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                                      packet.Printf ("P%x=", reg);                                      packet.PutBytesAsRawHex8 (restore_src,                                                                reg_byte_size, -                                                              lldb::endian::InlHostByteOrder(), -                                                              lldb::endian::InlHostByteOrder()); +                                                              endian::InlHostByteOrder(), +                                                              endian::InlHostByteOrder());                                      if (thread_suffix_supported)                                          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -851,7 +895,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                      }                      StreamString packet;                      packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]); -                    packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +                    packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder());                      if (thread_suffix_supported)                          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -941,115 +985,115 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)      };      static RegisterInfo g_register_infos[] = { -//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          COMPILER             DWARF                GENERIC                 GDB    LLDB      VALUE REGS    INVALIDATE REGS -//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  ===    ====      ==========    =============== -    { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r0,              dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,      0 },        NULL,              NULL}, -    { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r1,              dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,      1 },        NULL,              NULL}, -    { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r2,              dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,      2 },        NULL,              NULL}, -    { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r3,              dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,      3 },        NULL,              NULL}, -    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r4,              dwarf_r4,            LLDB_INVALID_REGNUM,     4,      4 },        NULL,              NULL}, -    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r5,              dwarf_r5,            LLDB_INVALID_REGNUM,     5,      5 },        NULL,              NULL}, -    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r6,              dwarf_r6,            LLDB_INVALID_REGNUM,     6,      6 },        NULL,              NULL}, -    { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r7,              dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,      7 },        NULL,              NULL}, -    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r8,              dwarf_r8,            LLDB_INVALID_REGNUM,     8,      8 },        NULL,              NULL}, -    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r9,              dwarf_r9,            LLDB_INVALID_REGNUM,     9,      9 },        NULL,              NULL}, -    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r10,             dwarf_r10,           LLDB_INVALID_REGNUM,    10,     10 },        NULL,              NULL}, -    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r11,             dwarf_r11,           LLDB_INVALID_REGNUM,    11,     11 },        NULL,              NULL}, -    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r12,             dwarf_r12,           LLDB_INVALID_REGNUM,    12,     12 },        NULL,              NULL}, -    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { gcc_sp,              dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,     13 },        NULL,              NULL}, -    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { gcc_lr,              dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,     14 },        NULL,              NULL}, -    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { gcc_pc,              dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,     15 },        NULL,              NULL}, -    { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,     16 },        NULL,              NULL}, -    { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,     17 },        NULL,              NULL}, -    { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,     18 },        NULL,              NULL}, -    { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,     19 },        NULL,              NULL}, -    { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,     20 },        NULL,              NULL}, -    { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,     21 },        NULL,              NULL}, -    { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,     22 },        NULL,              NULL}, -    { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,     23 },        NULL,              NULL}, -    { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,     24 },        NULL,              NULL}, -    { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { gcc_cpsr,            dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,     25 },        NULL,              NULL}, -    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,     26 },        NULL,              NULL}, -    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,     27 },        NULL,              NULL}, -    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,     28 },        NULL,              NULL}, -    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,     29 },        NULL,              NULL}, -    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,     30 },        NULL,              NULL}, -    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,     31 },        NULL,              NULL}, -    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,     32 },        NULL,              NULL}, -    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,     33 },        NULL,              NULL}, -    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,     34 },        NULL,              NULL}, -    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,     35 },        NULL,              NULL}, -    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,     36 },        NULL,              NULL}, -    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,     37 },        NULL,              NULL}, -    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,     38 },        NULL,              NULL}, -    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,     39 },        NULL,              NULL}, -    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,     40 },        NULL,              NULL}, -    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,     41 },        NULL,              NULL}, -    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,     42 },        NULL,              NULL}, -    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,     43 },        NULL,              NULL}, -    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,     44 },        NULL,              NULL}, -    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,     45 },        NULL,              NULL}, -    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,     46 },        NULL,              NULL}, -    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,     47 },        NULL,              NULL}, -    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,     48 },        NULL,              NULL}, -    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,     49 },        NULL,              NULL}, -    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,     50 },        NULL,              NULL}, -    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,     51 },        NULL,              NULL}, -    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,     52 },        NULL,              NULL}, -    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,     53 },        NULL,              NULL}, -    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,     54 },        NULL,              NULL}, -    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,     55 },        NULL,              NULL}, -    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,     56 },        NULL,              NULL}, -    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,     57 },        NULL,              NULL}, -    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,     58 },        NULL,              NULL}, -    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,     59 },        NULL,              NULL}, -    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,     60 },        NULL,              NULL}, -    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,     61 },        NULL,              NULL}, -    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,     62 },        NULL,              NULL}, -    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,     63 },        NULL,              NULL}, -    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,     64 },        NULL,              NULL}, -    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,     65 },        NULL,              NULL}, -    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,     66 },        NULL,              NULL}, -    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,     67 },        NULL,              NULL}, -    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,     68 },        NULL,              NULL}, -    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,     69 },        NULL,              NULL}, -    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,     70 },        NULL,              NULL}, -    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,     71 },        NULL,              NULL}, -    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,     72 },        NULL,              NULL}, -    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,     73 },        NULL,              NULL}, -    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,     74 },        NULL,              NULL}, -    { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,     75 },   g_d0_regs,              NULL}, -    { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,     76 },   g_d1_regs,              NULL}, -    { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,     77 },   g_d2_regs,              NULL}, -    { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,     78 },   g_d3_regs,              NULL}, -    { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,     79 },   g_d4_regs,              NULL}, -    { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,     80 },   g_d5_regs,              NULL}, -    { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,     81 },   g_d6_regs,              NULL}, -    { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,     82 },   g_d7_regs,              NULL}, -    { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,     83 },   g_d8_regs,              NULL}, -    { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,     84 },   g_d9_regs,              NULL}, -    { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,     85 },  g_d10_regs,              NULL}, -    { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,     86 },  g_d11_regs,              NULL}, -    { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,     87 },  g_d12_regs,              NULL}, -    { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,     88 },  g_d13_regs,              NULL}, -    { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,     89 },  g_d14_regs,              NULL}, -    { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,     90 },  g_d15_regs,              NULL}, -    { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,     91 },   g_q0_regs,              NULL}, -    { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,     92 },   g_q1_regs,              NULL}, -    { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,     93 },   g_q2_regs,              NULL}, -    { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,     94 },   g_q3_regs,              NULL}, -    { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,     95 },   g_q4_regs,              NULL}, -    { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,     96 },   g_q5_regs,              NULL}, -    { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,     97 },   g_q6_regs,              NULL}, -    { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,     98 },   g_q7_regs,              NULL}, -    { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,     99 },   g_q8_regs,              NULL}, -    { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,    100 },   g_q9_regs,              NULL}, -    { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,    101 },  g_q10_regs,              NULL}, -    { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,    102 },  g_q11_regs,              NULL}, -    { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,    103 },  g_q12_regs,              NULL}, -    { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,    104 },  g_q13_regs,              NULL}, -    { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,    105 },  g_q14_regs,              NULL}, -    { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,    106 },  g_q15_regs,              NULL} +//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          EH_FRAME             DWARF                GENERIC                 PROCESS PLUGIN  LLDB      VALUE REGS    INVALIDATE REGS +//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  =============   ====      ==========    =============== +    { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r0,          dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,               0 },        NULL,              NULL}, +    { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r1,          dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,               1 },        NULL,              NULL}, +    { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r2,          dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,               2 },        NULL,              NULL}, +    { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r3,          dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,               3 },        NULL,              NULL}, +    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r4,          dwarf_r4,            LLDB_INVALID_REGNUM,     4,               4 },        NULL,              NULL}, +    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r5,          dwarf_r5,            LLDB_INVALID_REGNUM,     5,               5 },        NULL,              NULL}, +    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r6,          dwarf_r6,            LLDB_INVALID_REGNUM,     6,               6 },        NULL,              NULL}, +    { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r7,          dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,               7 },        NULL,              NULL}, +    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r8,          dwarf_r8,            LLDB_INVALID_REGNUM,     8,               8 },        NULL,              NULL}, +    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r9,          dwarf_r9,            LLDB_INVALID_REGNUM,     9,               9 },        NULL,              NULL}, +    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r10,         dwarf_r10,           LLDB_INVALID_REGNUM,    10,              10 },        NULL,              NULL}, +    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r11,         dwarf_r11,           LLDB_INVALID_REGNUM,    11,              11 },        NULL,              NULL}, +    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r12,         dwarf_r12,           LLDB_INVALID_REGNUM,    12,              12 },        NULL,              NULL}, +    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_sp,          dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,              13 },        NULL,              NULL}, +    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_lr,          dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,              14 },        NULL,              NULL}, +    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_pc,          dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,              15 },        NULL,              NULL}, +    { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,              16 },        NULL,              NULL}, +    { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,              17 },        NULL,              NULL}, +    { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,              18 },        NULL,              NULL}, +    { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,              19 },        NULL,              NULL}, +    { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,              20 },        NULL,              NULL}, +    { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,              21 },        NULL,              NULL}, +    { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,              22 },        NULL,              NULL}, +    { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,              23 },        NULL,              NULL}, +    { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,              24 },        NULL,              NULL}, +    { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { ehframe_cpsr,        dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,              25 },        NULL,              NULL}, +    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,              26 },        NULL,              NULL}, +    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,              27 },        NULL,              NULL}, +    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,              28 },        NULL,              NULL}, +    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,              29 },        NULL,              NULL}, +    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,              30 },        NULL,              NULL}, +    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,              31 },        NULL,              NULL}, +    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,              32 },        NULL,              NULL}, +    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,              33 },        NULL,              NULL}, +    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,              34 },        NULL,              NULL}, +    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,              35 },        NULL,              NULL}, +    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,              36 },        NULL,              NULL}, +    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,              37 },        NULL,              NULL}, +    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,              38 },        NULL,              NULL}, +    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,              39 },        NULL,              NULL}, +    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,              40 },        NULL,              NULL}, +    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,              41 },        NULL,              NULL}, +    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,              42 },        NULL,              NULL}, +    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,              43 },        NULL,              NULL}, +    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,              44 },        NULL,              NULL}, +    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,              45 },        NULL,              NULL}, +    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,              46 },        NULL,              NULL}, +    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,              47 },        NULL,              NULL}, +    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,              48 },        NULL,              NULL}, +    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,              49 },        NULL,              NULL}, +    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,              50 },        NULL,              NULL}, +    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,              51 },        NULL,              NULL}, +    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,              52 },        NULL,              NULL}, +    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,              53 },        NULL,              NULL}, +    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,              54 },        NULL,              NULL}, +    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,              55 },        NULL,              NULL}, +    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,              56 },        NULL,              NULL}, +    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,              57 },        NULL,              NULL}, +    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,              58 },        NULL,              NULL}, +    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,              59 },        NULL,              NULL}, +    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,              60 },        NULL,              NULL}, +    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,              61 },        NULL,              NULL}, +    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,              62 },        NULL,              NULL}, +    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,              63 },        NULL,              NULL}, +    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,              64 },        NULL,              NULL}, +    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,              65 },        NULL,              NULL}, +    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,              66 },        NULL,              NULL}, +    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,              67 },        NULL,              NULL}, +    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,              68 },        NULL,              NULL}, +    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,              69 },        NULL,              NULL}, +    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,              70 },        NULL,              NULL}, +    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,              71 },        NULL,              NULL}, +    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,              72 },        NULL,              NULL}, +    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,              73 },        NULL,              NULL}, +    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,              74 },        NULL,              NULL}, +    { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,              75 },   g_d0_regs,              NULL}, +    { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,              76 },   g_d1_regs,              NULL}, +    { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,              77 },   g_d2_regs,              NULL}, +    { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,              78 },   g_d3_regs,              NULL}, +    { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,              79 },   g_d4_regs,              NULL}, +    { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,              80 },   g_d5_regs,              NULL}, +    { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,              81 },   g_d6_regs,              NULL}, +    { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,              82 },   g_d7_regs,              NULL}, +    { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,              83 },   g_d8_regs,              NULL}, +    { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,              84 },   g_d9_regs,              NULL}, +    { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,              85 },  g_d10_regs,              NULL}, +    { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,              86 },  g_d11_regs,              NULL}, +    { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,              87 },  g_d12_regs,              NULL}, +    { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,              88 },  g_d13_regs,              NULL}, +    { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,              89 },  g_d14_regs,              NULL}, +    { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,              90 },  g_d15_regs,              NULL}, +    { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,              91 },   g_q0_regs,              NULL}, +    { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,              92 },   g_q1_regs,              NULL}, +    { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,              93 },   g_q2_regs,              NULL}, +    { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,              94 },   g_q3_regs,              NULL}, +    { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,              95 },   g_q4_regs,              NULL}, +    { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,              96 },   g_q5_regs,              NULL}, +    { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,              97 },   g_q6_regs,              NULL}, +    { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,              98 },   g_q7_regs,              NULL}, +    { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,              99 },   g_q8_regs,              NULL}, +    { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,             100 },   g_q9_regs,              NULL}, +    { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,             101 },  g_q10_regs,              NULL}, +    { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,             102 },  g_q11_regs,              NULL}, +    { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,             103 },  g_q12_regs,              NULL}, +    { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,             104 },  g_q13_regs,              NULL}, +    { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,             105 },  g_q14_regs,              NULL}, +    { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,             106 },  g_q15_regs,              NULL}      };      static const uint32_t num_registers = llvm::array_lengthof(g_register_infos); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 117d280cc547a..0e26c69eb2a9f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -42,32 +42,22 @@ public:      {      } -    ~GDBRemoteDynamicRegisterInfo () -    { -    } +    ~GDBRemoteDynamicRegisterInfo() override = default;      void      HardcodeARMRegisters(bool from_scratch); -  };  class GDBRemoteRegisterContext : public RegisterContext  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteRegisterContext (ThreadGDBRemote &thread,                                uint32_t concrete_frame_idx,                                GDBRemoteDynamicRegisterInfo ®_info,                                bool read_all_at_once); -    virtual -    ~GDBRemoteRegisterContext (); +    ~GDBRemoteRegisterContext() override; -    //------------------------------------------------------------------ -    // Subclasses must override these functions -    //------------------------------------------------------------------      void      InvalidateAllRegisters () override; @@ -119,6 +109,9 @@ protected:      bool      PrivateSetRegisterValue (uint32_t reg, StringExtractor &response); +    bool +    PrivateSetRegisterValue (uint32_t reg, uint64_t val); +      void      SetAllRegisterValid (bool b); @@ -166,13 +159,10 @@ private:      bool SetPrimordialRegister(const RegisterInfo *reg_info,                                 GDBRemoteCommunicationClient &gdb_comm); -    //------------------------------------------------------------------ -    // For GDBRemoteRegisterContext only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // lldb_GDBRemoteRegisterContext_h_ +#endif // lldb_GDBRemoteRegisterContext_h_ diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 1e150b1dda9fd..2e7a5b5384f46 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -40,6 +40,7 @@  #include "lldb/Core/Timer.h"  #include "lldb/Core/Value.h"  #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/FileSystem.h"  #include "lldb/Host/HostThread.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/Symbols.h" @@ -56,6 +57,7 @@  #include "lldb/Interpreter/OptionGroupUInt64.h"  #include "lldb/Interpreter/Property.h"  #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/ABI.h"  #include "lldb/Target/DynamicLoader.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/TargetList.h" @@ -192,7 +194,7 @@ public:          {              for (uint32_t i = 0; i < e_num; ++i)                  m_has[i] = false; -        }; +        }          void set_name (const std::string & name)          { @@ -216,6 +218,16 @@ public:              return m_has[e_has_base];          } +        void set_base_is_offset (bool is_offset) +        { +            m_base_is_offset = is_offset; +        } +        bool get_base_is_offset(bool & out) const +        { +            out = m_base_is_offset; +            return m_has[e_has_base]; +        } +          void set_link_map (const lldb::addr_t addr)          {              m_link_map = addr; @@ -250,6 +262,7 @@ public:          std::string m_name;          lldb::addr_t m_link_map;          lldb::addr_t m_base; +        bool m_base_is_offset;          lldb::addr_t m_dynamic;      }; @@ -322,22 +335,22 @@ ProcessGDBRemote::Terminate()  lldb::ProcessSP -ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path) +ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path)  {      lldb::ProcessSP process_sp;      if (crash_file_path == NULL) -        process_sp.reset (new ProcessGDBRemote (target, listener)); +        process_sp.reset (new ProcessGDBRemote (target_sp, listener));      return process_sp;  }  bool -ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name) +ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)  {      if (plugin_specified_by_name)          return true;      // For now we are just making sure the file exists for a given module -    Module *exe_module = target.GetExecutableModulePointer(); +    Module *exe_module = target_sp->GetExecutableModulePointer();      if (exe_module)      {          ObjectFile *exe_objfile = exe_module->GetObjectFile(); @@ -366,17 +379,20 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)  //----------------------------------------------------------------------  // ProcessGDBRemote constructor  //---------------------------------------------------------------------- -ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : -    Process (target, listener), +ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener) : +    Process (target_sp, listener),      m_flags (0),      m_gdb_comm (),      m_debugserver_pid (LLDB_INVALID_PROCESS_ID),      m_last_stop_packet_mutex (Mutex::eMutexTypeRecursive),      m_register_info (),      m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), +    m_async_listener("lldb.process.gdb-remote.async-listener"),      m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),      m_thread_ids (), -    m_threads_info_sp (), +    m_thread_pcs (), +    m_jstopinfo_sp (), +    m_jthreadsinfo_sp (),      m_continue_c_tids (),      m_continue_C_tids (),      m_continue_s_tids (), @@ -394,6 +410,25 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :      m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");      m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");      m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit,      "async thread did exit"); + +    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC)); + +    const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; + +    if (m_async_listener.StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask) +    { +        if (log) +            log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__); +    } + +    const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit | +                                    GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; +    if (m_async_listener.StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask) +    { +        if (log) +            log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__); +    } +      const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();      if (timeout_seconds > 0)          m_gdb_comm.SetPacketTimeout(timeout_seconds); @@ -481,6 +516,40 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_      return false;  } +// If the remote stub didn't give us eh_frame or DWARF register numbers for a register, +// see if the ABI can provide them. +// DWARF and eh_frame register numbers are defined as a part of the ABI. +static void +AugmentRegisterInfoViaABI (RegisterInfo ®_info, ConstString reg_name, ABISP abi_sp) +{ +    if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM +        || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) +    { +        if (abi_sp) +        { +            RegisterInfo abi_reg_info; +            if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info)) +            { +                if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame]; +                } +                if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF]; +                } +                if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric]; +                } +            } +        } +    } +} +  static size_t  SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> ®nums, int base)  { @@ -524,11 +593,23 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      //     3 - Fall back on the qRegisterInfo packets.      FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile (); +    if (!target_definition_fspec.Exists()) +    { +        // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it. +        target_definition_fspec.ResolvePath(); +    }      if (target_definition_fspec)      {          // See if we can get register definitions from a python file          if (ParsePythonTargetDefinition (target_definition_fspec)) +        {              return; +        } +        else +        { +            StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); +            stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str()); +        }      }      if (GetGDBServerRegisterInfo ()) @@ -561,12 +642,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      0,                    // byte size                      reg_offset,           // offset                      eEncodingUint,        // encoding -                    eFormatHex,           // formate +                    eFormatHex,           // format                      { -                        LLDB_INVALID_REGNUM, // GCC reg num +                        LLDB_INVALID_REGNUM, // eh_frame reg num                          LLDB_INVALID_REGNUM, // DWARF reg num                          LLDB_INVALID_REGNUM, // generic reg num -                        reg_num,             // GDB reg num +                        reg_num,             // process plugin reg num                          reg_num           // native register number                      },                      NULL, @@ -635,9 +716,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      {                          set_name.SetCString(value.c_str());                      } -                    else if (name.compare("gcc") == 0) +                    else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)                      { -                        reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); +                        reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);                      }                      else if (name.compare("dwarf") == 0)                      { @@ -671,6 +752,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      reg_info.invalidate_regs = invalidate_regs.data();                  } +                AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ()); +                  m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);              }              else @@ -711,11 +794,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      if (!target_arch.IsValid())      {          if (remote_arch.IsValid() -              && remote_arch.GetMachine() == llvm::Triple::arm +              && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb)                && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)              m_register_info.HardcodeARMRegisters(from_scratch);      } -    else if (target_arch.GetMachine() == llvm::Triple::arm) +    else if (target_arch.GetMachine() == llvm::Triple::arm +            || target_arch.GetMachine() == llvm::Triple::thumb)      {          m_register_info.HardcodeARMRegisters(from_scratch);      } @@ -779,20 +863,21 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)              if (GetTarget().GetNonStopModeEnabled())                  HandleStopReplySequence(); -            if (!m_target.GetArchitecture().IsValid())  +            Target &target = GetTarget(); +            if (!target.GetArchitecture().IsValid())               {                  if (m_gdb_comm.GetProcessArchitecture().IsValid())                  { -                    m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());                  }                  else                  { -                    m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetHostArchitecture());                  }              }              const StateType state = SetThreadStopInfo (response); -            if (state == eStateStopped) +            if (state != eStateInvalid)              {                  SetPrivateState (state);              } @@ -910,27 +995,22 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)      ObjectFile * object_file = exe_module->GetObjectFile();      if (object_file)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (launch_info); -        } -         +        error = EstablishConnectionIfNeeded (launch_info);          if (error.Success())          {              lldb_utility::PseudoTerminal pty;              const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; -            PlatformSP platform_sp (m_target.GetPlatform()); +            PlatformSP platform_sp (GetTarget().GetPlatform());              if (disable_stdio)              {                  // set to /dev/null unless redirected to a file above                  if (!stdin_file_spec) -                    stdin_file_spec.SetFile("/dev/null", false); +                    stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stdout_file_spec) -                    stdout_file_spec.SetFile("/dev/null", false); +                    stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stderr_file_spec) -                    stderr_file_spec.SetFile("/dev/null", false); +                    stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);              }              else if (platform_sp && platform_sp->IsHost())              { @@ -977,7 +1057,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)              m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);              m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError); -            m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName()); +            m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());              const char * launch_event_data = launch_info.GetLaunchEventData();              if (launch_event_data != NULL && *launch_event_data != '\0') @@ -1044,13 +1124,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)                  if (process_arch.IsValid())                  { -                    m_target.MergeArchitecture(process_arch); +                    GetTarget().MergeArchitecture(process_arch);                  }                  else                  {                      const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();                      if (host_arch.IsValid()) -                        m_target.MergeArchitecture(host_arch); +                        GetTarget().MergeArchitecture(host_arch);                  }                  SetPrivateState (SetThreadStopInfo (response)); @@ -1226,8 +1306,8 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)                  // it has, so we really need to take the remote host architecture as our                  // defacto architecture in this case. -                if (process_arch.GetMachine() == llvm::Triple::arm && -                    process_arch.GetTriple().getVendor() == llvm::Triple::Apple) +                if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb) +                    && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)                  {                      GetTarget().SetArchitecture (process_arch);                      if (log) @@ -1295,21 +1375,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process      Clear();      if (attach_pid != LLDB_INVALID_PROCESS_ID)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); -             -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } -     +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); @@ -1319,6 +1385,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process              SetID (attach_pid);                          m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));          } +        else +            SetExitStatus (-1, error.AsCString());      }      return error; @@ -1333,21 +1401,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro      if (process_name && process_name[0])      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); - -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } - +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              StreamString packet; @@ -1371,11 +1425,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro              else                  packet.PutCString("vAttachName");              packet.PutChar(';'); -            packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +            packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());              m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));          } +        else +            SetExitStatus (-1, error.AsCString());      }      return error;  } @@ -1403,6 +1459,8 @@ ProcessGDBRemote::WillResume ()      m_continue_C_tids.clear();      m_continue_s_tids.clear();      m_continue_S_tids.clear(); +    m_jstopinfo_sp.reset(); +    m_jthreadsinfo_sp.reset();      return Error();  } @@ -1694,12 +1752,14 @@ ProcessGDBRemote::ClearThreadIDList ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex());      m_thread_ids.clear(); +    m_thread_pcs.clear();  }  size_t  ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)  {      m_thread_ids.clear(); +    m_thread_pcs.clear();      size_t comma_pos;      lldb::tid_t tid;      while ((comma_pos = value.find(',')) != std::string::npos) @@ -1717,18 +1777,39 @@ ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)      return m_thread_ids.size();  } +size_t +ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value) +{ +    m_thread_pcs.clear(); +    size_t comma_pos; +    lldb::addr_t pc; +    while ((comma_pos = value.find(',')) != std::string::npos) +    { +        value[comma_pos] = '\0'; +        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +        if (pc != LLDB_INVALID_ADDRESS) +            m_thread_pcs.push_back (pc); +        value.erase(0, comma_pos + 1); +    } +    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +    if (pc != LLDB_INVALID_THREAD_ID) +        m_thread_pcs.push_back (pc); +    return m_thread_pcs.size(); +} +  bool  ProcessGDBRemote::UpdateThreadIDList ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex()); -    if (m_threads_info_sp) +    if (m_jthreadsinfo_sp)      {          // If we have the JSON threads info, we can get the thread list from that -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();          if (thread_infos && thread_infos->GetSize() > 0)          {              m_thread_ids.clear(); +            m_thread_pcs.clear();              thread_infos->ForEach([this](StructuredData::Object* object) -> bool {                  StructuredData::Dictionary *thread_dict = object->GetAsDictionary();                  if (thread_dict) @@ -1751,25 +1832,43 @@ ProcessGDBRemote::UpdateThreadIDList ()          // that might contain a "threads" key/value pair          // Lock the thread stack while we access it -        Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); -        // Get the number of stop packets on the stack -        int nItems = m_stop_packet_stack.size(); -        // Iterate over them -        for (int i = 0; i < nItems; i++) +        //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); +        Mutex::Locker stop_stack_lock; +        if (stop_stack_lock.TryLock(m_last_stop_packet_mutex))          { -            // Get the thread stop info -            StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; -            const std::string &stop_info_str = stop_info.GetStringRef(); -            const size_t threads_pos = stop_info_str.find(";threads:"); -            if (threads_pos != std::string::npos) +            // Get the number of stop packets on the stack +            int nItems = m_stop_packet_stack.size(); +            // Iterate over them +            for (int i = 0; i < nItems; i++)              { -                const size_t start = threads_pos + strlen(";threads:"); -                const size_t end = stop_info_str.find(';', start); -                if (end != std::string::npos) +                // Get the thread stop info +                StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; +                const std::string &stop_info_str = stop_info.GetStringRef(); + +                m_thread_pcs.clear(); +                const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); +                if (thread_pcs_pos != std::string::npos) +                { +                    const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); +                    const size_t end = stop_info_str.find(';', start); +                    if (end != std::string::npos) +                    { +                        std::string value = stop_info_str.substr(start, end - start); +                        UpdateThreadPCsFromStopReplyThreadsValue(value); +                    } +                } + +                const size_t threads_pos = stop_info_str.find(";threads:"); +                if (threads_pos != std::string::npos)                  { -                    std::string value = stop_info_str.substr(start, end - start); -                    if (UpdateThreadIDsFromStopReplyThreadsValue(value)) -                        return true; +                    const size_t start = threads_pos + strlen(";threads:"); +                    const size_t end = stop_info_str.find(';', start); +                    if (end != std::string::npos) +                    { +                        std::string value = stop_info_str.substr(start, end - start); +                        if (UpdateThreadIDsFromStopReplyThreadsValue(value)) +                            return true; +                    }                  }              }          } @@ -1826,6 +1925,25 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new                             __FUNCTION__, static_cast<void*>(thread_sp.get()),                             thread_sp->GetID());              } +            // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most +            // of the register read/write packets in gdb-remote protocol.   +            // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these; +            // they are a performance improvement over fetching thread register values individually, the +            // method we will fall back to if needed. +            if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid) +            { +                ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); +                RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext()); +                if (reg_ctx_sp) +                { +                    uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber  +                                                                   (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); +                    if (pc_regnum != LLDB_INVALID_REGNUM) +                    { +                        gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]); +                    } +                } +            }              new_thread_list.AddThread(thread_sp);          }      } @@ -1846,13 +1964,14 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new      return true;  } +  bool -ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) +ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)  {      // See if we got thread stop infos for all threads via the "jThreadsInfo" packet -    if (m_threads_info_sp) +    if (thread_infos_sp)      { -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();          if (thread_infos)          {              lldb::tid_t tid; @@ -1865,12 +1984,36 @@ ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)                      if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))                      {                          if (tid == thread->GetID()) -                            return SetThreadStopInfo(thread_dict); +                            return (bool)SetThreadStopInfo(thread_dict);                      }                  }              }          }      } +    return false; +} + +bool +ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) +{ +    // See if we got thread stop infos for all threads via the "jThreadsInfo" packet +    if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp)) +        return true; + +    // See if we got thread stop info for any threads valid stop info reasons threads +    // via the "jstopinfo" packet stop reply packet key/value pair? +    if (m_jstopinfo_sp) +    { +        // If we have "jstopinfo" then we have stop descriptions for all threads +        // that have stop reasons, and if there is no entry for a thread, then +        // it has no stop reason. +        thread->GetRegisterContext()->InvalidateIfNeeded(true); +        if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp)) +        { +            thread->SetStopInfo (StopInfoSP()); +        } +        return true; +    }      // Fall back to using the qThreadStopInfo packet      StringExtractorGDBRemote stop_packet; @@ -1926,8 +2069,6 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,                  gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);              } -            // Clear the stop info just in case we don't set it to anything -            thread_sp->SetStopInfo (StopInfoSP());              thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());              gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); @@ -1937,145 +2078,159 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,              else                  gdb_thread->ClearQueueInfo(); - -            if (exc_type != 0) -            { -                const size_t exc_data_size = exc_data.size(); - -                thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, -                                                                                                  exc_type, -                                                                                                  exc_data_size, -                                                                                                  exc_data_size >= 1 ? exc_data[0] : 0, -                                                                                                  exc_data_size >= 2 ? exc_data[1] : 0, -                                                                                                  exc_data_size >= 3 ? exc_data[2] : 0)); -            } -            else +            // Make sure we update our thread stop reason just once +            if (!thread_sp->StopInfoIsUpToDate())              { -                bool handled = false; -                bool did_exec = false; -                if (!reason.empty()) +                thread_sp->SetStopInfo (StopInfoSP()); +                // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo. +                ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID()); +                if (memory_thread_sp) +                    thread_sp = memory_thread_sp; + +                if (exc_type != 0)                  { -                    if (reason.compare("trace") == 0) -                    { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); -                        handled = true; -                    } -                    else if (reason.compare("breakpoint") == 0) +                    const size_t exc_data_size = exc_data.size(); + +                    thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, +                                                                                                      exc_type, +                                                                                                      exc_data_size, +                                                                                                      exc_data_size >= 1 ? exc_data[0] : 0, +                                                                                                      exc_data_size >= 2 ? exc_data[1] : 0, +                                                                                                      exc_data_size >= 3 ? exc_data[2] : 0)); +                } +                else +                { +                    bool handled = false; +                    bool did_exec = false; +                    if (!reason.empty())                      { -                        addr_t pc = thread_sp->GetRegisterContext()->GetPC(); -                        lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); -                        if (bp_site_sp) +                        if (reason.compare("trace") == 0)                          { -                            // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, -                            // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that -                            // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));                              handled = true; -                            if (bp_site_sp->ValidForThisThread (thread_sp.get())) -                            { -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); -                            } -                            else +                        } +                        else if (reason.compare("breakpoint") == 0) +                        { +                            addr_t pc = thread_sp->GetRegisterContext()->GetPC(); +                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); +                            if (bp_site_sp)                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_sp); +                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, +                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that +                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                                handled = true; +                                if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                                { +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                } +                                else +                                { +                                    StopInfoSP invalid_stop_info_sp; +                                    thread_sp->SetStopInfo (invalid_stop_info_sp); +                                }                              }                          } -                    } -                    else if (reason.compare("trap") == 0) -                    { -                        // Let the trap just use the standard signal stop reason below... -                    } -                    else if (reason.compare("watchpoint") == 0) -                    { -                        StringExtractor desc_extractor(description.c_str()); -                        addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); -                        uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); -                        addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); -                        watch_id_t watch_id = LLDB_INVALID_WATCH_ID; -                        if (wp_addr != LLDB_INVALID_ADDRESS) +                        else if (reason.compare("trap") == 0)                          { -                            WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); -                            if (wp_sp) +                            // Let the trap just use the standard signal stop reason below... +                        } +                        else if (reason.compare("watchpoint") == 0) +                        { +                            StringExtractor desc_extractor(description.c_str()); +                            addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); +                            uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); +                            addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); +                            watch_id_t watch_id = LLDB_INVALID_WATCH_ID; +                            if (wp_addr != LLDB_INVALID_ADDRESS) +                            { +                                WatchpointSP wp_sp; +                                ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); +                                if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) +                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); +                                if (!wp_sp) +                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); +                                if (wp_sp) +                                { +                                    wp_sp->SetHardwareIndex(wp_index); +                                    watch_id = wp_sp->GetID(); +                                } +                            } +                            if (watch_id == LLDB_INVALID_WATCH_ID)                              { -                                wp_sp->SetHardwareIndex(wp_index); -                                watch_id = wp_sp->GetID(); +                                Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); +                                if (log) log->Printf ("failed to find watchpoint");                              } +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr)); +                            handled = true;                          } -                        if (watch_id == LLDB_INVALID_WATCH_ID) +                        else if (reason.compare("exception") == 0)                          { -                            Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); -                            if (log) log->Printf ("failed to find watchpoint"); +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); +                            handled = true; +                        } +                        else if (reason.compare("exec") == 0) +                        { +                            did_exec = true; +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); +                            handled = true;                          } -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr)); -                        handled = true; -                    } -                    else if (reason.compare("exception") == 0) -                    { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); -                        handled = true; -                    } -                    else if (reason.compare("exec") == 0) -                    { -                        did_exec = true; -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); -                        handled = true;                      } -                } -                if (!handled && signo && did_exec == false) -                { -                    if (signo == SIGTRAP) +                    if (!handled && signo && did_exec == false)                      { -                        // Currently we are going to assume SIGTRAP means we are either -                        // hitting a breakpoint or hardware single stepping. -                        handled = true; -                        addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; -                        lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - -                        if (bp_site_sp) +                        if (signo == SIGTRAP)                          { -                            // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, -                            // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that -                            // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. -                            if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                            // Currently we are going to assume SIGTRAP means we are either +                            // hitting a breakpoint or hardware single stepping. +                            handled = true; +                            addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; +                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + +                            if (bp_site_sp)                              { -                                if(m_breakpoint_pc_offset != 0) -                                    thread_sp->GetRegisterContext()->SetPC(pc); -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, +                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that +                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                                if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                                { +                                    if(m_breakpoint_pc_offset != 0) +                                        thread_sp->GetRegisterContext()->SetPC(pc); +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                } +                                else +                                { +                                    StopInfoSP invalid_stop_info_sp; +                                    thread_sp->SetStopInfo (invalid_stop_info_sp); +                                }                              }                              else                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_sp); +                                // If we were stepping then assume the stop was the result of the trace.  If we were +                                // not stepping then report the SIGTRAP. +                                // FIXME: We are still missing the case where we single step over a trap instruction. +                                if (thread_sp->GetTemporaryResumeState() == eStateStepping) +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); +                                else +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));                              }                          } -                        else -                        { -                            // If we were stepping then assume the stop was the result of the trace.  If we were -                            // not stepping then report the SIGTRAP. -                            // FIXME: We are still missing the case where we single step over a trap instruction. -                            if (thread_sp->GetTemporaryResumeState() == eStateStepping) -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); -                            else -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str())); -                        } +                        if (!handled) +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));                      } -                    if (!handled) -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str())); -                } -                if (!description.empty()) -                { -                    lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); -                    if (stop_info_sp) -                    { -                        const char *stop_info_desc = stop_info_sp->GetDescription(); -                        if (!stop_info_desc || !stop_info_desc[0]) -                            stop_info_sp->SetDescription (description.c_str()); -                    } -                    else +                    if (!description.empty())                      { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); +                        lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); +                        if (stop_info_sp) +                        { +                            const char *stop_info_desc = stop_info_sp->GetDescription(); +                            if (!stop_info_desc || !stop_info_desc[0]) +                                stop_info_sp->SetDescription (description.c_str()); +                        } +                        else +                        { +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); +                        }                      }                  }              } @@ -2084,7 +2239,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,      return thread_sp;  } -StateType +lldb::ThreadSP  ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)  {      static ConstString g_key_tid("tid"); @@ -2101,6 +2256,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)      static ConstString g_key_address("address");      static ConstString g_key_bytes("bytes");      static ConstString g_key_description("description"); +    static ConstString g_key_signal("signal");      // Stop with signal and thread info      lldb::tid_t tid = LLDB_INVALID_THREAD_ID; @@ -2159,7 +2315,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_name)          { -            thread_name = std::move(object->GetStringValue()); +            thread_name = object->GetStringValue();          }          else if (key == g_key_qaddr)          { @@ -2168,7 +2324,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          else if (key == g_key_queue_name)          {              queue_vars_valid = true; -            queue_name = std::move(object->GetStringValue()); +            queue_name = object->GetStringValue();          }          else if (key == g_key_queue_kind)          { @@ -2192,11 +2348,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_reason)          { -            reason = std::move(object->GetStringValue()); +            reason = object->GetStringValue();          }          else if (key == g_key_description)          { -            description = std::move(object->GetStringValue()); +            description = object->GetStringValue();          }          else if (key == g_key_registers)          { @@ -2207,7 +2363,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)                  registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {                      const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);                      if (reg != UINT32_MAX) -                        expedited_register_map[reg] = std::move(object->GetStringValue()); +                        expedited_register_map[reg] = object->GetStringValue();                      return true; // Keep iterating through all array items                  });              } @@ -2245,24 +2401,24 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)              }          } +        else if (key == g_key_signal) +            signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);          return true; // Keep iterating through all dictionary key/value pairs      }); -    SetThreadStopInfo (tid, -                       expedited_register_map, -                       signo, -                       thread_name, -                       reason, -                       description, -                       exc_type, -                       exc_data, -                       thread_dispatch_qaddr, -                       queue_vars_valid, -                       queue_name, -                       queue_kind, -                       queue_serial); - -    return eStateExited; +    return SetThreadStopInfo (tid, +                              expedited_register_map, +                              signo, +                              thread_name, +                              reason, +                              description, +                              exc_type, +                              exc_data, +                              thread_dispatch_qaddr, +                              queue_vars_valid, +                              queue_name, +                              queue_kind, +                              queue_serial);  }  StateType @@ -2348,6 +2504,39 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      if (tid != LLDB_INVALID_THREAD_ID)                          m_thread_ids.push_back (tid);                  } +                else if (key.compare("thread-pcs") == 0) +                { +                    m_thread_pcs.clear(); +                    // A comma separated list of all threads in the current +                    // process that includes the thread for this stop reply +                    // packet +                    size_t comma_pos; +                    lldb::addr_t pc; +                    while ((comma_pos = value.find(',')) != std::string::npos) +                    { +                        value[comma_pos] = '\0'; +                        // thread in big endian hex +                        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +                        if (pc != LLDB_INVALID_ADDRESS) +                            m_thread_pcs.push_back (pc); +                        value.erase(0, comma_pos + 1); +                    } +                    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +                    if (pc != LLDB_INVALID_ADDRESS) +                        m_thread_pcs.push_back (pc); +                } +                else if (key.compare("jstopinfo") == 0) +                { +                    StringExtractor json_extractor; +                    // Swap "value" over into "name_extractor" +                    json_extractor.GetStringRef().swap(value); +                    // Now convert the HEX bytes into a string value +                    json_extractor.GetHexByteString (value); + +                    // This JSON contains thread IDs and thread stop info for all threads. +                    // It doesn't contain expedited registers, memory or queue info. +                    m_jstopinfo_sp = StructuredData::ParseJSON (value); +                }                  else if (key.compare("hexname") == 0)                  {                      StringExtractor name_extractor; @@ -2431,7 +2620,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                          if (mem_cache_addr != LLDB_INVALID_ADDRESS)                          {                              StringExtractor bytes; -                            bytes.GetStringRef() = std::move(pair.second.str()); +                            bytes.GetStringRef() = pair.second.str();                              const size_t byte_size = bytes.GetStringRef().size()/2;                              DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));                              const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0); @@ -2455,6 +2644,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);                      description = ostr.GetString().c_str();                  } +                else if (key.compare("library") == 0) +                { +                    LoadModules(); +                }                  else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))                  {                      uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16); @@ -2509,6 +2702,7 @@ ProcessGDBRemote::RefreshStateAfterStop ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex());      m_thread_ids.clear(); +    m_thread_pcs.clear();      // Set the thread stop info. It might have a "threads" key whose value is      // a list of all thread IDs in the current process, so m_thread_ids might      // get set. @@ -2545,11 +2739,6 @@ ProcessGDBRemote::RefreshStateAfterStop ()          m_initial_tid = LLDB_INVALID_THREAD_ID;      } -    // Fetch the threads via an efficient packet that gets stop infos for all threads -    // only if we have more than one thread -    if (m_thread_ids.size() > 1) -        m_threads_info_sp = m_gdb_comm.GetThreadsInfo(); -      // Let all threads recover from stopping and do any clean up based      // on the previous thread state (if any).      m_thread_list_real.RefreshStateAfterStop(); @@ -2824,6 +3013,12 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      {          // Lock the thread stack while we access it          Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + +        // We are are not using non-stop mode, there can only be one last stop +        // reply packet, so clear the list. +        if (GetTarget().GetNonStopModeEnabled() == false) +            m_stop_packet_stack.clear(); +          // Add this stop packet to the stop packet stack          // This stack will get popped and examined when we switch to the          // Stopped state @@ -2831,6 +3026,11 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      }  } +void +ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) +{ +    Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); +}  //------------------------------------------------------------------  // Process Queries @@ -2839,7 +3039,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)  bool  ProcessGDBRemote::IsAlive ()  { -    return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited; +    return m_gdb_comm.IsConnected() && Process::IsAlive();  }  addr_t @@ -2859,6 +3059,35 @@ ProcessGDBRemote::GetImageInfoAddress()      return addr;  } +void +ProcessGDBRemote::WillPublicStop () +{ +    // See if the GDB remote client supports the JSON threads info. +    // If so, we gather stop info for all threads, expedited registers, +    // expedited memory, runtime queue information (iOS and MacOSX only), +    // and more. Expediting memory will help stack backtracing be much +    // faster. Expediting registers will make sure we don't have to read +    // the thread registers for GPRs. +    m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); + +    if (m_jthreadsinfo_sp) +    { +        // Now set the stop info for each thread and also expedite any registers +        // and memory that was in the jThreadsInfo response. +        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); +        if (thread_infos) +        { +            const size_t n = thread_infos->GetSize(); +            for (size_t i=0; i<n; ++i) +            { +                StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); +                if (thread_dict) +                    SetThreadStopInfo(thread_dict); +            } +        } +    } +} +  //------------------------------------------------------------------  // Process Memory  //------------------------------------------------------------------ @@ -2877,14 +3106,8 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro      char packet[64];      int packet_len;      bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); -    if (binary_memory_read) -    { -        packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } -    else -    { -        packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } +    packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, +                            binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);      assert (packet_len + 1 < (int)sizeof(packet));      StringExtractorGDBRemote response;      if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success) @@ -2940,7 +3163,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro      StreamString packet;      packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); -    packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +    packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());      StringExtractorGDBRemote response;      if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)      { @@ -3377,6 +3600,27 @@ ProcessGDBRemote::DoSignal (int signo)  }  Error +ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info) +{ +    // Make sure we aren't already connected? +    if (m_gdb_comm.IsConnected()) +        return Error(); + +    PlatformSP platform_sp (GetTarget ().GetPlatform ()); +    if (platform_sp && !platform_sp->IsHost ()) +        return Error("Lost debug server connection"); + +    auto error = LaunchAndConnectToDebugserver (process_info); +    if (error.Fail()) +    { +        const char *error_string = error.AsCString(); +        if (error_string == nullptr) +            error_string = "unable to launch " DEBUGSERVER_BASENAME; +    } +    return error; +} + +Error  ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)  {      Error error; @@ -3401,14 +3645,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info          // Set hostname being NULL to do the reverse connect where debugserver          // will bind to port zero and it will communicate back to us the port          // that we will connect to -        const char *hostname = NULL; +        const char *hostname = nullptr;          uint16_t port = 0;  #endif -        error = m_gdb_comm.StartDebugserverProcess (hostname, -                                                    port, +        StreamString url_str; +        const char* url = nullptr; +        if (hostname != nullptr) +        { +            url_str.Printf("%s:%u", hostname, port); +            url = url_str.GetData(); +        } + +        error = m_gdb_comm.StartDebugserverProcess (url, +                                                    GetTarget().GetPlatform().get(),                                                      debugserver_launch_info, -                                                    port); +                                                    &port);          if (error.Success ())              m_debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -3653,164 +3905,174 @@ ProcessGDBRemote::AsyncThread (void *arg)      if (log)          log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID()); -    Listener listener ("ProcessGDBRemote::AsyncThread");      EventSP event_sp; -    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | -                                        eBroadcastBitAsyncThreadShouldExit; - -    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) +    bool done = false; +    while (!done)      { -        listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit | -                                                                GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify); - -        bool done = false; -        while (!done) +        if (log) +            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); +        if (process->m_async_listener.WaitForEvent (NULL, event_sp))          { -            if (log) -                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); -            if (listener.WaitForEvent (NULL, event_sp)) +            const uint32_t event_type = event_sp->GetType(); +            if (event_sp->BroadcasterIs (&process->m_async_broadcaster))              { -                const uint32_t event_type = event_sp->GetType(); -                if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) +                if (log) +                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); + +                switch (event_type)                  { -                    if (log) -                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); +                    case eBroadcastBitAsyncContinue: +                        { +                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); -                    switch (event_type) -                    { -                        case eBroadcastBitAsyncContinue: +                            if (continue_packet)                              { -                                const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); +                                const char *continue_cstr = (const char *)continue_packet->GetBytes (); +                                const size_t continue_cstr_len = continue_packet->GetByteSize (); +                                if (log) +                                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); -                                if (continue_packet) +                                if (::strstr (continue_cstr, "vAttach") == NULL) +                                    process->SetPrivateState(eStateRunning); +                                StringExtractorGDBRemote response; + +                                // If in Non-Stop-Mode +                                if (process->GetTarget().GetNonStopModeEnabled())                                  { -                                    const char *continue_cstr = (const char *)continue_packet->GetBytes (); -                                    const size_t continue_cstr_len = continue_packet->GetByteSize (); -                                    if (log) -                                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); - -                                    if (::strstr (continue_cstr, "vAttach") == NULL) -                                        process->SetPrivateState(eStateRunning); -                                    StringExtractorGDBRemote response; -   -                                    // If in Non-Stop-Mode -                                    if (process->GetTarget().GetNonStopModeEnabled()) +                                    // send the vCont packet +                                    if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))                                      { -                                        // send the vCont packet -                                        if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response)) -                                        { -                                            // Something went wrong -                                            done = true; -                                            break; -                                        } +                                        // Something went wrong +                                        done = true; +                                        break;                                      } -                                    // If in All-Stop-Mode -                                    else -                                    { -                                        StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); - -                                        // We need to immediately clear the thread ID list so we are sure to get a valid list of threads. -                                        // The thread ID list might be contained within the "response", or the stop reply packet that -                                        // caused the stop. So clear it now before we give the stop reply packet to the process -                                        // using the process->SetLastStopPacket()... -                                        process->ClearThreadIDList (); +                                } +                                // If in All-Stop-Mode +                                else +                                { +                                    StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); -                                        switch (stop_state) -                                        { -                                        case eStateStopped: -                                        case eStateCrashed: -                                        case eStateSuspended: -                                            process->SetLastStopPacket (response); -                                            process->SetPrivateState (stop_state); -                                            break; +                                    // We need to immediately clear the thread ID list so we are sure to get a valid list of threads. +                                    // The thread ID list might be contained within the "response", or the stop reply packet that +                                    // caused the stop. So clear it now before we give the stop reply packet to the process +                                    // using the process->SetLastStopPacket()... +                                    process->ClearThreadIDList (); -                                        case eStateExited: +                                    switch (stop_state) +                                    { +                                    case eStateStopped: +                                    case eStateCrashed: +                                    case eStateSuspended: +                                        process->SetLastStopPacket (response); +                                        process->SetPrivateState (stop_state); +                                        break; + +                                    case eStateExited: +                                    { +                                        process->SetLastStopPacket (response); +                                        process->ClearThreadIDList(); +                                        response.SetFilePos(1); +                                         +                                        int exit_status = response.GetHexU8(); +                                        const char *desc_cstr = NULL; +                                        StringExtractor extractor; +                                        std::string desc_string; +                                        if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')                                          { -                                            process->SetLastStopPacket (response); -                                            process->ClearThreadIDList(); -                                            response.SetFilePos(1); -                                             -                                            int exit_status = response.GetHexU8(); -                                            const char *desc_cstr = NULL; -                                            StringExtractor extractor; -                                            std::string desc_string; -                                            if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') +                                            std::string desc_token; +                                            while (response.GetNameColonValue (desc_token, desc_string))                                              { -                                                std::string desc_token; -                                                while (response.GetNameColonValue (desc_token, desc_string)) +                                                if (desc_token == "description")                                                  { -                                                    if (desc_token == "description") -                                                    { -                                                        extractor.GetStringRef().swap(desc_string); -                                                        extractor.SetFilePos(0); -                                                        extractor.GetHexByteString (desc_string); -                                                        desc_cstr = desc_string.c_str(); -                                                    } +                                                    extractor.GetStringRef().swap(desc_string); +                                                    extractor.SetFilePos(0); +                                                    extractor.GetHexByteString (desc_string); +                                                    desc_cstr = desc_string.c_str();                                                  }                                              } -                                            process->SetExitStatus(exit_status, desc_cstr); -                                            done = true; -                                            break;                                          } -                                        case eStateInvalid: +                                        process->SetExitStatus(exit_status, desc_cstr); +                                        done = true; +                                        break; +                                    } +                                    case eStateInvalid: +                                    { +                                        // Check to see if we were trying to attach and if we got back +                                        // the "E87" error code from debugserver -- this indicates that +                                        // the process is not debuggable.  Return a slightly more helpful +                                        // error message about why the attach failed. +                                        if (::strstr (continue_cstr, "vAttach") != NULL +                                            && response.GetError() == 0x87) +                                        { +                                            process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection"); +                                        } +                                        // E01 code from vAttach means that the attach failed +                                        if (::strstr (continue_cstr, "vAttach") != NULL +                                            && response.GetError() == 0x1) +                                        { +                                            process->SetExitStatus(-1, "unable to attach"); +                                        } +                                        else +                                        {                                              process->SetExitStatus(-1, "lost connection"); +                                        }                                              break; +                                    } -                                        default: -                                            process->SetPrivateState (stop_state); -                                            break; -                                        } // switch(stop_state) -                                    } // else // if in All-stop-mode -                                } // if (continue_packet) -                            } // case eBroadcastBitAysncContinue -                            break; +                                    default: +                                        process->SetPrivateState (stop_state); +                                        break; +                                    } // switch(stop_state) +                                } // else // if in All-stop-mode +                            } // if (continue_packet) +                        } // case eBroadcastBitAysncContinue +                        break; -                        case eBroadcastBitAsyncThreadShouldExit: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); -                            done = true; -                            break; +                    case eBroadcastBitAsyncThreadShouldExit: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); +                        done = true; +                        break; -                        default: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); -                            done = true; -                            break; -                    } +                    default: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); +                        done = true; +                        break;                  } -                else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) +            } +            else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) +            { +                switch (event_type)                  { -                    switch (event_type) -                    { -                        case Communication::eBroadcastBitReadThreadDidExit: -                            process->SetExitStatus (-1, "lost connection"); -                            done = true; -                            break; - -                        case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: -                        { -                            lldb_private::Event *event = event_sp.get(); -                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); -                            StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes()); -                            // Hand this over to the process to handle -                            process->HandleNotifyPacket(notify); -                            break; -                        } +                    case Communication::eBroadcastBitReadThreadDidExit: +                        process->SetExitStatus (-1, "lost connection"); +                        done = true; +                        break; -                        default: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); -                            done = true; -                            break; +                    case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: +                    { +                        lldb_private::Event *event = event_sp.get(); +                        const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); +                        StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes()); +                        // Hand this over to the process to handle +                        process->HandleNotifyPacket(notify); +                        break;                      } + +                    default: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); +                        done = true; +                        break;                  }              } -            else -            { -                if (log) -                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); -                done = true; -            } +        } +        else +        { +            if (log) +                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); +            done = true;          }      } @@ -3864,10 +4126,10 @@ ProcessGDBRemote::StartNoticingNewThreads()      }      else      { -        PlatformSP platform_sp (m_target.GetPlatform()); +        PlatformSP platform_sp (GetTarget().GetPlatform());          if (platform_sp)          { -            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target); +            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());              if (m_thread_create_bp_sp)              {                  if (log && log->GetVerbose()) @@ -3986,6 +4248,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())      { +        // Scope for the scoped timeout object +        GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10); +          StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());          args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);          args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count); @@ -4009,8 +4274,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres              {                  if (!response.Empty())                  { -                    // The packet has already had the 0x7d xor quoting stripped out at the -                    // GDBRemoteCommunication packet receive level.                      object_sp = StructuredData::ParseJSON (response.GetStringRef());                  }              } @@ -4019,7 +4282,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      return object_sp;  } -  // Establish the largest memory read/write payloads we should use.  // If the remote stub has a max packet size, stay under that size.  //  @@ -4113,6 +4375,18 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,      return true;  } +bool +ProcessGDBRemote::GetHostOSVersion(uint32_t &major, +                                   uint32_t &minor, +                                   uint32_t &update) +{ +    if (m_gdb_comm.GetOSVersion(major, minor, update)) +        return true; +    // We failed to get the host OS version, defer to the base +    // implementation to correctly invalidate the arguments. +    return Process::GetHostOSVersion(major, minor, update); +} +  namespace {  typedef std::vector<std::string> stringVec; @@ -4135,15 +4409,15 @@ struct GdbServerTargetInfo  };  bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info) +ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)  {      if (!feature_node)          return false; -    uint32_t prev_reg_num = 0; +    uint32_t cur_reg_num = 0;      uint32_t reg_offset = 0; -    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, ®_offset](const XMLNode ®_node) -> bool { +    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool {          std::string gdb_group;          std::string gdb_type;          ConstString reg_name; @@ -4158,19 +4432,19 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              0,                    // byte size              reg_offset,           // offset              eEncodingUint,        // encoding -            eFormatHex,           // formate +            eFormatHex,           // format              { -                LLDB_INVALID_REGNUM, // GCC reg num +                LLDB_INVALID_REGNUM, // eh_frame reg num                  LLDB_INVALID_REGNUM, // DWARF reg num                  LLDB_INVALID_REGNUM, // generic reg num -                prev_reg_num,        // GDB reg num -                prev_reg_num         // native register number +                cur_reg_num,        // process plugin reg num +                cur_reg_num         // native register number              },              NULL,              NULL          }; -        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &prev_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { +        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {              if (name == "name")              {                  reg_name.SetString(value); @@ -4192,9 +4466,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);                  if (regnum != LLDB_INVALID_REGNUM)                  { -                    reg_info.kinds[eRegisterKindGDB] = regnum; -                    reg_info.kinds[eRegisterKindLLDB] = regnum; -                    prev_reg_num = regnum; +                    reg_info.kinds[eRegisterKindProcessPlugin] = regnum;                  }              }              else if (name == "offset") @@ -4240,9 +4512,9 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  if (pos != target_info.reg_set_map.end())                      set_name = pos->second.name;              } -            else if (name == "gcc_regnum") +            else if (name == "gcc_regnum" || name == "ehframe_regnum")              { -                reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); +                reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);              }              else if (name == "dwarf_regnum")              { @@ -4305,7 +4577,8 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              reg_info.invalidate_regs = invalidate_regs.data();          } -        ++prev_reg_num; +        ++cur_reg_num; +        AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);          dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);          return true; // Keep iterating through all "reg" elements @@ -4401,7 +4674,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()              if (feature_node)              { -                ParseRegisters(feature_node, target_info, this->m_register_info); +                ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());              }              for (const auto &include : target_info.includes) @@ -4419,7 +4692,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()                  XMLNode include_feature_node = include_xml_document.GetRootElement("feature");                  if (include_feature_node)                  { -                    ParseRegisters(include_feature_node, target_info, this->m_register_info); +                    ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());                  }              }              this->m_register_info.Finalize(GetTarget().GetArchitecture()); @@ -4489,7 +4762,8 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)                  {                      // the displacement as read from the field 'l_addr' of the link_map struct.                      module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0)); -                     +                    // base address is always a displacement, not an absolute value. +                    module.set_base_is_offset(true);                  }                  else if (name == "l_ld")                  { @@ -4504,13 +4778,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              {                  std::string name;                  lldb::addr_t lm=0, base=0, ld=0; +                bool base_is_offset;                  module.get_name (name);                  module.get_link_map (lm);                  module.get_base (base); +                module.get_base_is_offset (base_is_offset);                  module.get_dynamic (ld); -                log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str()); +                log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());              }              list.add (module); @@ -4552,15 +4828,19 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              const XMLNode §ion = library.FindFirstChildElementWithName("section");              llvm::StringRef address = section.GetAttributeValue("address");              module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0)); +            // These addresses are absolute values. +            module.set_base_is_offset(false);              if (log)              {                  std::string name;                  lldb::addr_t base = 0; +                bool base_is_offset;                  module.get_name (name);                  module.get_base (base); +                module.get_base_is_offset (base_is_offset); -                log->Printf ("found (base:0x%" PRIx64 ", name:'%s')", base, name.c_str()); +                log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());              }              list.add (module); @@ -4577,7 +4857,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)  }  lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr) +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset)  {      Target &target = m_process->GetTarget();      ModuleList &modules = target.GetImages(); @@ -4588,11 +4868,11 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a      ModuleSpec module_spec (file, target.GetArchitecture());      if ((module_sp = modules.FindFirstModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      else if ((module_sp = target.GetSharedModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      return module_sp; @@ -4615,10 +4895,12 @@ ProcessGDBRemote::LoadModules ()      {          std::string  mod_name;          lldb::addr_t mod_base; +        bool         mod_base_is_offset;          bool valid = true;          valid &= modInfo.get_name (mod_name);          valid &= modInfo.get_base (mod_base); +        valid &= modInfo.get_base_is_offset (mod_base_is_offset);          if (!valid)              continue; @@ -4630,7 +4912,7 @@ ProcessGDBRemote::LoadModules ()              marker += 1;          FileSpec file (mod_name.c_str()+marker, true); -        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base); +        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset);          if (module_sp.get())              new_modules.Append (module_sp); @@ -4638,7 +4920,7 @@ ProcessGDBRemote::LoadModules ()      if (new_modules.GetSize() > 0)      { -        Target & target = m_target; +        Target &target = GetTarget();          new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool          { diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 45c74ea64ee50..54749827d6ac6 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -11,12 +11,14 @@  #define liblldb_ProcessGDBRemote_h_  // C Includes -  // C++ Includes -#include <list> +#include <atomic> +#include <map> +#include <string>  #include <vector>  // Other libraries and framework includes +// Project includes  #include "lldb/Core/ArchSpec.h"  #include "lldb/Core/Broadcaster.h"  #include "lldb/Core/ConstString.h" @@ -42,11 +44,12 @@ class ThreadGDBRemote;  class ProcessGDBRemote : public Process  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ +    ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener); + +    ~ProcessGDBRemote() override; +      static lldb::ProcessSP -    CreateInstance (Target& target,  +    CreateInstance (lldb::TargetSP target_sp,                      Listener &listener,                      const FileSpec *crash_file_path); @@ -66,18 +69,10 @@ public:      GetPluginDescriptionStatic();      //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ -    ProcessGDBRemote(Target& target, Listener &listener); - -    virtual -    ~ProcessGDBRemote(); - -    //------------------------------------------------------------------      // Check if a given Process      //------------------------------------------------------------------      bool -    CanDebug (Target &target, bool plugin_specified_by_name) override; +    CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;      CommandObject *      GetPluginCommandObject() override; @@ -152,6 +147,9 @@ public:      void      RefreshStateAfterStop() override; +    void +    SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); +      //------------------------------------------------------------------      // Process Queries      //------------------------------------------------------------------ @@ -161,6 +159,9 @@ public:      lldb::addr_t      GetImageInfoAddress() override; +    void +    WillPublicStop () override; +      //------------------------------------------------------------------      // Process Memory      //------------------------------------------------------------------ @@ -238,6 +239,11 @@ public:                    const ArchSpec& arch,                    ModuleSpec &module_spec) override; +    bool +    GetHostOSVersion(uint32_t &major, +                     uint32_t &minor, +                     uint32_t &update) override; +      size_t      LoadModules() override; @@ -257,20 +263,63 @@ protected:      class GDBLoadedModuleInfoList; +    //------------------------------------------------------------------ +    /// Broadcaster event bits definitions. +    //------------------------------------------------------------------ +    enum +    { +        eBroadcastBitAsyncContinue                  = (1 << 0), +        eBroadcastBitAsyncThreadShouldExit          = (1 << 1), +        eBroadcastBitAsyncThreadDidExit             = (1 << 2) +    }; +     +    Flags m_flags;            // Process specific flags (see eFlags enums) +    GDBRemoteCommunicationClient m_gdb_comm; +    std::atomic<lldb::pid_t> m_debugserver_pid; +    std::vector<StringExtractorGDBRemote> m_stop_packet_stack;  // The stop packet stack replaces the last stop packet variable +    Mutex m_last_stop_packet_mutex; +    GDBRemoteDynamicRegisterInfo m_register_info; +    Broadcaster m_async_broadcaster; +    Listener m_async_listener; +    HostThread m_async_thread; +    Mutex m_async_thread_state_mutex; +    typedef std::vector<lldb::tid_t> tid_collection; +    typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection; +    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; +    typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; +    tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping +    std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads. +    StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos +    StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported +    tid_collection m_continue_c_tids;                  // 'c' for continue +    tid_sig_collection m_continue_C_tids; // 'C' for continue with signal +    tid_collection m_continue_s_tids;                  // 's' for step +    tid_sig_collection m_continue_S_tids; // 'S' for step with signal +    uint64_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory +    uint64_t m_remote_stub_max_memory_size;    // The maximum memory size the remote gdb stub can handle +    MMapMap m_addr_to_mmap_size; +    lldb::BreakpointSP m_thread_create_bp_sp; +    bool m_waiting_for_attach; +    bool m_destroy_tried_resuming; +    lldb::CommandObjectSP m_command_sp; +    int64_t m_breakpoint_pc_offset; +    lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach +      //----------------------------------------------------------------------      // Accessors      //----------------------------------------------------------------------      bool      IsRunning ( lldb::StateType state )      { -        return    state == lldb::eStateRunning || IsStepping(state); +        return state == lldb::eStateRunning || IsStepping(state);      }      bool      IsStepping ( lldb::StateType state)      { -        return    state == lldb::eStateStepping; +        return state == lldb::eStateStepping;      } +      bool      CanResume ( lldb::StateType state)      { @@ -306,6 +355,9 @@ protected:                        ThreadList &new_thread_list) override;      Error +    EstablishConnectionIfNeeded (const ProcessInfo &process_info); + +    Error      LaunchAndConnectToDebugserver (const ProcessInfo &process_info);      void @@ -333,46 +385,10 @@ protected:      CalculateThreadStopInfo (ThreadGDBRemote *thread);      size_t -    UpdateThreadIDsFromStopReplyThreadsValue (std::string &value); +    UpdateThreadPCsFromStopReplyThreadsValue (std::string &value); -    //------------------------------------------------------------------ -    /// Broadcaster event bits definitions. -    //------------------------------------------------------------------ -    enum -    { -        eBroadcastBitAsyncContinue                  = (1 << 0), -        eBroadcastBitAsyncThreadShouldExit          = (1 << 1), -        eBroadcastBitAsyncThreadDidExit             = (1 << 2) -    }; -     -    Flags m_flags;            // Process specific flags (see eFlags enums) -    GDBRemoteCommunicationClient m_gdb_comm; -    std::atomic<lldb::pid_t> m_debugserver_pid; -    std::vector<StringExtractorGDBRemote> m_stop_packet_stack;  // The stop packet stack replaces the last stop packet variable -    Mutex m_last_stop_packet_mutex; -    GDBRemoteDynamicRegisterInfo m_register_info; -    Broadcaster m_async_broadcaster; -    HostThread m_async_thread; -    Mutex m_async_thread_state_mutex; -    typedef std::vector<lldb::tid_t> tid_collection; -    typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection; -    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; -    typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; -    tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping -    StructuredData::ObjectSP m_threads_info_sp; // Stop info for all threads if "jThreadsInfo" packet is supported -    tid_collection m_continue_c_tids;                  // 'c' for continue -    tid_sig_collection m_continue_C_tids; // 'C' for continue with signal -    tid_collection m_continue_s_tids;                  // 's' for step -    tid_sig_collection m_continue_S_tids; // 'S' for step with signal -    uint64_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory -    uint64_t m_remote_stub_max_memory_size;    // The maximum memory size the remote gdb stub can handle -    MMapMap m_addr_to_mmap_size; -    lldb::BreakpointSP m_thread_create_bp_sp; -    bool m_waiting_for_attach; -    bool m_destroy_tried_resuming; -    lldb::CommandObjectSP m_command_sp; -    int64_t m_breakpoint_pc_offset; -    lldb::tid_t m_initial_tid; // The inital thread ID, given by stub on attach +    size_t +    UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);      bool      HandleNotifyPacket(StringExtractorGDBRemote &packet); @@ -396,7 +412,10 @@ protected:      lldb::StateType      SetThreadStopInfo (StringExtractor& stop_packet); -    lldb::StateType +    bool +    GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp); + +    lldb::ThreadSP      SetThreadStopInfo (StructuredData::Dictionary *thread_dict);      lldb::ThreadSP @@ -445,7 +464,7 @@ protected:      GetLoadedModuleList (GDBLoadedModuleInfoList &);      lldb::ModuleSP -    LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr); +    LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset);  private:      //------------------------------------------------------------------ @@ -458,10 +477,9 @@ private:                           lldb::user_id_t break_loc_id);      DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote); -  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_ProcessGDBRemote_h_ +#endif // liblldb_ProcessGDBRemote_h_ diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index d2a6503caf8e0..9b410d8b5b8c2 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -313,6 +313,14 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons  }  bool +ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval) +{ +    GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get()); +    assert (gdb_reg_ctx); +    return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval); +} + +bool  ThreadGDBRemote::CalculateStopInfo ()  {      ProcessSP process_sp (GetProcess()); diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 175433a3e20c1..24693ba891ccb 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -10,8 +10,12 @@  #ifndef liblldb_ThreadGDBRemote_h_  #define liblldb_ThreadGDBRemote_h_ +// C Includes +// C++ Includes  #include <string> +// Other libraries and framework includes +// Project includes  #include "lldb/Core/StructuredData.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/Thread.h" @@ -28,8 +32,7 @@ class ThreadGDBRemote : public Thread  public:      ThreadGDBRemote (Process &process, lldb::tid_t tid); -    virtual -    ~ThreadGDBRemote (); +    ~ThreadGDBRemote() override;      void      WillResume (lldb::StateType resume_state) override; @@ -101,30 +104,27 @@ public:      FetchThreadExtendedInfo () override;  protected: -          friend class ProcessGDBRemote; +    std::string m_thread_name; +    std::string m_dispatch_queue_name; +    lldb::addr_t m_thread_dispatch_qaddr; +    lldb::QueueKind m_queue_kind;     // Queue info from stop reply/stop info for thread +    uint64_t m_queue_serial;    // Queue info from stop reply/stop info for thread +      bool      PrivateSetRegisterValue (uint32_t reg,                                StringExtractor &response);      bool +    PrivateSetRegisterValue (uint32_t reg,  +                             uint64_t regval); + +    bool      CachedQueueInfoIsValid() const      {          return m_queue_kind != lldb::eQueueKindUnknown;      } -    //------------------------------------------------------------------ -    // Member variables. -    //------------------------------------------------------------------ -    std::string m_thread_name; -    std::string m_dispatch_queue_name; -    lldb::addr_t m_thread_dispatch_qaddr; -    lldb::QueueKind m_queue_kind;     // Queue info from stop reply/stop info for thread -    uint64_t m_queue_serial;    // Queue info from stop reply/stop info for thread -    //------------------------------------------------------------------ -    // Member variables. -    //------------------------------------------------------------------ -      void      SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id); @@ -135,4 +135,4 @@ protected:  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_ThreadGDBRemote_h_ +#endif // liblldb_ThreadGDBRemote_h_ diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp new file mode 100644 index 0000000000000..1a352fa1987fd --- /dev/null +++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp @@ -0,0 +1,93 @@ +//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ScriptInterpreterNone.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StringList.h" +#include "lldb/Interpreter/CommandInterpreter.h" + +#include <mutex> + +using namespace lldb; +using namespace lldb_private; + +ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter) +    : ScriptInterpreter(interpreter, eScriptLanguageNone) +{ +} + +ScriptInterpreterNone::~ScriptInterpreterNone() +{ +} + +bool +ScriptInterpreterNone::ExecuteOneLine(const char *command, CommandReturnObject *, const ExecuteScriptOptions &) +{ +    m_interpreter.GetDebugger().GetErrorFile()->PutCString( +        "error: there is no embedded script interpreter in this mode.\n"); +    return false; +} + +void +ScriptInterpreterNone::ExecuteInterpreterLoop() +{ +    m_interpreter.GetDebugger().GetErrorFile()->PutCString( +        "error: there is no embedded script interpreter in this mode.\n"); +} + +void +ScriptInterpreterNone::Initialize() +{ +    static std::once_flag g_once_flag; + +    std::call_once(g_once_flag, []() +                   { +                       PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), +                                                     lldb::eScriptLanguageNone, CreateInstance); +                   }); +} + +void +ScriptInterpreterNone::Terminate() +{ +} + +lldb::ScriptInterpreterSP +ScriptInterpreterNone::CreateInstance(CommandInterpreter &interpreter) +{ +    return std::make_shared<ScriptInterpreterNone>(interpreter); +} + +lldb_private::ConstString +ScriptInterpreterNone::GetPluginNameStatic() +{ +    static ConstString g_name("script-none"); +    return g_name; +} + +const char * +ScriptInterpreterNone::GetPluginDescriptionStatic() +{ +    return "Null script interpreter"; +} + +lldb_private::ConstString +ScriptInterpreterNone::GetPluginName() +{ +    return GetPluginNameStatic(); +} + +uint32_t +ScriptInterpreterNone::GetPluginVersion() +{ +    return 1; +} diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h new file mode 100644 index 0000000000000..49fd4fabfbc5d --- /dev/null +++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h @@ -0,0 +1,66 @@ +//===-- ScriptInterpreterNone.h ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ScriptInterpreterNone_h_ +#define liblldb_ScriptInterpreterNone_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/ScriptInterpreter.h" + +namespace lldb_private +{ + +class ScriptInterpreterNone : public ScriptInterpreter +{ +  public: +    ScriptInterpreterNone(CommandInterpreter &interpreter); + +    ~ScriptInterpreterNone() override; + +    bool +    ExecuteOneLine(const char *command, CommandReturnObject *result, +                   const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + +    void +    ExecuteInterpreterLoop() override; + +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void +    Initialize(); + +    static void +    Terminate(); + +    static lldb::ScriptInterpreterSP +    CreateInstance(CommandInterpreter &interpreter); + +    static lldb_private::ConstString +    GetPluginNameStatic(); + +    static const char * +    GetPluginDescriptionStatic(); + +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    lldb_private::ConstString +    GetPluginName() override; + +    uint32_t +    GetPluginVersion() override; +}; + +} // namespace lldb_private + +#endif // liblldb_ScriptInterpreterNone_h_ diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp new file mode 100644 index 0000000000000..3107677ee9480 --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -0,0 +1,1069 @@ +//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +#include "lldb-python.h" +#include "PythonDataObjects.h" +#include "ScriptInterpreterPython.h" + +#include "lldb/Core/Stream.h" +#include "lldb/Host/File.h" +#include "lldb/Interpreter/ScriptInterpreter.h" + +#include <stdio.h> + +using namespace lldb_private; +using namespace lldb; + +void +StructuredPythonObject::Dump(Stream &s) const +{ +    s << "Python Obj: 0x" << GetValue(); +} + +//---------------------------------------------------------------------- +// PythonObject +//---------------------------------------------------------------------- + +void +PythonObject::Dump(Stream &strm) const +{ +    if (m_py_obj) +    { +        FILE *file = ::tmpfile(); +        if (file) +        { +            ::PyObject_Print (m_py_obj, file, 0); +            const long length = ftell (file); +            if (length) +            { +                ::rewind(file); +                std::vector<char> file_contents (length,'\0'); +                const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file); +                if (length_read > 0) +                    strm.Write (file_contents.data(), length_read); +            } +            ::fclose (file); +        } +    } +    else +        strm.PutCString ("NULL"); +} + +PyObjectType +PythonObject::GetObjectType() const +{ +    if (!IsAllocated()) +        return PyObjectType::None; + +    if (PythonModule::Check(m_py_obj)) +        return PyObjectType::Module; +    if (PythonList::Check(m_py_obj)) +        return PyObjectType::List; +    if (PythonTuple::Check(m_py_obj)) +        return PyObjectType::Tuple; +    if (PythonDictionary::Check(m_py_obj)) +        return PyObjectType::Dictionary; +    if (PythonString::Check(m_py_obj)) +        return PyObjectType::String; +    if (PythonInteger::Check(m_py_obj)) +        return PyObjectType::Integer; +    if (PythonFile::Check(m_py_obj)) +        return PyObjectType::File; +    if (PythonCallable::Check(m_py_obj)) +        return PyObjectType::Callable; +    return PyObjectType::Unknown; +} + +PythonString +PythonObject::Repr() const +{ +    if (!m_py_obj) +        return PythonString(); +    PyObject *repr = PyObject_Repr(m_py_obj); +    if (!repr) +        return PythonString(); +    return PythonString(PyRefType::Owned, repr); +} + +PythonString +PythonObject::Str() const +{ +    if (!m_py_obj) +        return PythonString(); +    PyObject *str = PyObject_Str(m_py_obj); +    if (!str) +        return PythonString(); +    return PythonString(PyRefType::Owned, str); +} + +PythonObject +PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) +{ +    size_t dot_pos = name.find_first_of('.'); +    llvm::StringRef piece = name.substr(0, dot_pos); +    PythonObject result = dict.GetItemForKey(PythonString(piece)); +    if (dot_pos == llvm::StringRef::npos) +    { +        // There was no dot, we're done. +        return result; +    } + +    // There was a dot.  The remaining portion of the name should be looked up in +    // the context of the object that was found in the dictionary. +    return result.ResolveName(name.substr(dot_pos + 1)); +} + +PythonObject +PythonObject::ResolveName(llvm::StringRef name) const +{ +    // Resolve the name in the context of the specified object.  If, +    // for example, `this` refers to a PyModule, then this will look for +    // `name` in this module.  If `this` refers to a PyType, then it will +    // resolve `name` as an attribute of that type.  If `this` refers to +    // an instance of an object, then it will resolve `name` as the value +    // of the specified field. +    // +    // This function handles dotted names so that, for example, if `m_py_obj` +    // refers to the `sys` module, and `name` == "path.append", then it +    // will find the function `sys.path.append`. + +    size_t dot_pos = name.find_first_of('.'); +    if (dot_pos == llvm::StringRef::npos) +    { +        // No dots in the name, we should be able to find the value immediately +        // as an attribute of `m_py_obj`. +        return GetAttributeValue(name); +    } + +    // Look up the first piece of the name, and resolve the rest as a child of that. +    PythonObject parent = ResolveName(name.substr(0, dot_pos)); +    if (!parent.IsAllocated()) +        return PythonObject(); + +    // Tail recursion.. should be optimized by the compiler +    return parent.ResolveName(name.substr(dot_pos + 1)); +} + +bool +PythonObject::HasAttribute(llvm::StringRef attr) const +{ +    if (!IsValid()) +        return false; +    PythonString py_attr(attr); +    return !!PyObject_HasAttr(m_py_obj, py_attr.get()); +} + +PythonObject +PythonObject::GetAttributeValue(llvm::StringRef attr) const +{ +    if (!IsValid()) +        return PythonObject(); + +    PythonString py_attr(attr); +    if (!PyObject_HasAttr(m_py_obj, py_attr.get())) +        return PythonObject(); + +    return PythonObject(PyRefType::Owned, +        PyObject_GetAttr(m_py_obj, py_attr.get())); +} + +bool +PythonObject::IsNone() const +{ +    return m_py_obj == Py_None; +} + +bool +PythonObject::IsValid() const +{ +    return m_py_obj != nullptr; +} + +bool +PythonObject::IsAllocated() const +{ +    return IsValid() && !IsNone(); +} + +StructuredData::ObjectSP +PythonObject::CreateStructuredObject() const +{ +    switch (GetObjectType()) +    { +        case PyObjectType::Dictionary: +            return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary(); +        case PyObjectType::Integer: +            return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); +        case PyObjectType::List: +            return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); +        case PyObjectType::String: +            return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); +        case PyObjectType::None: +            return StructuredData::ObjectSP(); +        default: +            return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj)); +    } +} + +//---------------------------------------------------------------------- +// PythonString +//---------------------------------------------------------------------- + +PythonString::PythonString(PyRefType type, PyObject *py_obj) +    : PythonObject() +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string +} + +PythonString::PythonString(const PythonString &object) +    : PythonObject(object) +{ +} + +PythonString::PythonString(llvm::StringRef string) +    : PythonObject() +{ +    SetString(string); +} + +PythonString::PythonString(const char *string) +    : PythonObject() +{ +    SetString(llvm::StringRef(string)); +} + +PythonString::PythonString() +    : PythonObject() +{ +} + +PythonString::~PythonString () +{ +} + +bool +PythonString::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; + +    if (PyUnicode_Check(py_obj)) +        return true; +#if PY_MAJOR_VERSION < 3 +    if (PyString_Check(py_obj)) +        return true; +#endif +    return false; +} + +void +PythonString::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonString::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } +#if PY_MAJOR_VERSION < 3 +    // In Python 2, Don't store PyUnicode objects directly, because we need +    // access to their underlying character buffers which Python 2 doesn't +    // provide. +    if (PyUnicode_Check(py_obj)) +        result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get())); +#endif +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +llvm::StringRef +PythonString::GetString() const +{ +    if (!IsValid()) +        return llvm::StringRef(); + +    Py_ssize_t size; +    char *c; + +#if PY_MAJOR_VERSION >= 3 +    c = PyUnicode_AsUTF8AndSize(m_py_obj, &size); +#else +    PyString_AsStringAndSize(m_py_obj, &c, &size); +#endif +    return llvm::StringRef(c, size); +} + +size_t +PythonString::GetSize() const +{ +    if (IsValid()) +    { +#if PY_MAJOR_VERSION >= 3 +        return PyUnicode_GetSize(m_py_obj); +#else +        return PyString_Size(m_py_obj); +#endif +    } +    return 0; +} + +void +PythonString::SetString (llvm::StringRef string) +{ +#if PY_MAJOR_VERSION >= 3 +    PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size()); +    PythonObject::Reset(PyRefType::Owned, unicode); +#else +    PyObject *str = PyString_FromStringAndSize(string.data(), string.size()); +    PythonObject::Reset(PyRefType::Owned, str); +#endif +} + +StructuredData::StringSP +PythonString::CreateStructuredString() const +{ +    StructuredData::StringSP result(new StructuredData::String); +    result->SetValue(GetString()); +    return result; +} + +//---------------------------------------------------------------------- +// PythonInteger +//---------------------------------------------------------------------- + +PythonInteger::PythonInteger() +    : PythonObject() +{ + +} + +PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj) +    : PythonObject() +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type +} + +PythonInteger::PythonInteger(const PythonInteger &object) +    : PythonObject(object) +{ +} + +PythonInteger::PythonInteger(int64_t value) +    : PythonObject() +{ +    SetInteger(value); +} + + +PythonInteger::~PythonInteger () +{ +} + +bool +PythonInteger::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; + +#if PY_MAJOR_VERSION >= 3 +    // Python 3 does not have PyInt_Check.  There is only one type of +    // integral value, long. +    return PyLong_Check(py_obj); +#else +    return PyLong_Check(py_obj) || PyInt_Check(py_obj); +#endif +} + +void +PythonInteger::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonInteger::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +#if PY_MAJOR_VERSION < 3 +    // Always store this as a PyLong, which makes interoperability between +    // Python 2.x and Python 3.x easier.  This is only necessary in 2.x, +    // since 3.x doesn't even have a PyInt. +    if (PyInt_Check(py_obj)) +    { +        // Since we converted the original object to a different type, the new +        // object is an owned object regardless of the ownership semantics requested +        // by the user. +        result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj))); +    } +#endif + +    assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject"); + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +int64_t +PythonInteger::GetInteger() const +{ +    if (m_py_obj) +    { +        assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong"); + +        return PyLong_AsLongLong(m_py_obj); +    } +    return UINT64_MAX; +} + +void +PythonInteger::SetInteger(int64_t value) +{ +    PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value)); +} + +StructuredData::IntegerSP +PythonInteger::CreateStructuredInteger() const +{ +    StructuredData::IntegerSP result(new StructuredData::Integer); +    result->SetValue(GetInteger()); +    return result; +} + +//---------------------------------------------------------------------- +// PythonList +//---------------------------------------------------------------------- + +PythonList::PythonList(PyInitialValue value) +    : PythonObject() +{ +    if (value == PyInitialValue::Empty) +        Reset(PyRefType::Owned, PyList_New(0)); +} + +PythonList::PythonList(int list_size) +    : PythonObject() +{ +    Reset(PyRefType::Owned, PyList_New(list_size)); +} + +PythonList::PythonList(PyRefType type, PyObject *py_obj) +    : PythonObject() +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list +} + +PythonList::PythonList(const PythonList &list) +    : PythonObject(list) +{ +} + +PythonList::~PythonList () +{ +} + +bool +PythonList::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; +    return PyList_Check(py_obj); +} + +void +PythonList::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonList::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +uint32_t +PythonList::GetSize() const +{ +    if (IsValid()) +        return PyList_GET_SIZE(m_py_obj); +    return 0; +} + +PythonObject +PythonList::GetItemAtIndex(uint32_t index) const +{ +    if (IsValid()) +        return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index)); +    return PythonObject(); +} + +void +PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object) +{ +    if (IsAllocated() && object.IsValid()) +    { +        // PyList_SetItem is documented to "steal" a reference, so we need to +        // convert it to an owned reference by incrementing it. +        Py_INCREF(object.get()); +        PyList_SetItem(m_py_obj, index, object.get()); +    } +} + +void +PythonList::AppendItem(const PythonObject &object) +{ +    if (IsAllocated() && object.IsValid()) +    { +        // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF` +        // here like we do with `PyList_SetItem`. +        PyList_Append(m_py_obj, object.get()); +    } +} + +StructuredData::ArraySP +PythonList::CreateStructuredArray() const +{ +    StructuredData::ArraySP result(new StructuredData::Array); +    uint32_t count = GetSize(); +    for (uint32_t i = 0; i < count; ++i) +    { +        PythonObject obj = GetItemAtIndex(i); +        result->AddItem(obj.CreateStructuredObject()); +    } +    return result; +} + +//---------------------------------------------------------------------- +// PythonTuple +//---------------------------------------------------------------------- + +PythonTuple::PythonTuple(PyInitialValue value) +    : PythonObject() +{ +    if (value == PyInitialValue::Empty) +        Reset(PyRefType::Owned, PyTuple_New(0)); +} + +PythonTuple::PythonTuple(int tuple_size) +    : PythonObject() +{ +    Reset(PyRefType::Owned, PyTuple_New(tuple_size)); +} + +PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj) +    : PythonObject() +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple +} + +PythonTuple::PythonTuple(const PythonTuple &tuple) +    : PythonObject(tuple) +{ +} + +PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects) +{ +    m_py_obj = PyTuple_New(objects.size()); + +    uint32_t idx = 0; +    for (auto object : objects) +    { +        if (object.IsValid()) +            SetItemAtIndex(idx, object); +        idx++; +    } +} + +PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects) +{ +    m_py_obj = PyTuple_New(objects.size()); + +    uint32_t idx = 0; +    for (auto py_object : objects) +    { +        PythonObject object(PyRefType::Borrowed, py_object); +        if (object.IsValid()) +            SetItemAtIndex(idx, object); +        idx++; +    } +} + +PythonTuple::~PythonTuple() +{ +} + +bool +PythonTuple::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; +    return PyTuple_Check(py_obj); +} + +void +PythonTuple::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonTuple::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +uint32_t +PythonTuple::GetSize() const +{ +    if (IsValid()) +        return PyTuple_GET_SIZE(m_py_obj); +    return 0; +} + +PythonObject +PythonTuple::GetItemAtIndex(uint32_t index) const +{ +    if (IsValid()) +        return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index)); +    return PythonObject(); +} + +void +PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object) +{ +    if (IsAllocated() && object.IsValid()) +    { +        // PyTuple_SetItem is documented to "steal" a reference, so we need to +        // convert it to an owned reference by incrementing it. +        Py_INCREF(object.get()); +        PyTuple_SetItem(m_py_obj, index, object.get()); +    } +} + +StructuredData::ArraySP +PythonTuple::CreateStructuredArray() const +{ +    StructuredData::ArraySP result(new StructuredData::Array); +    uint32_t count = GetSize(); +    for (uint32_t i = 0; i < count; ++i) +    { +        PythonObject obj = GetItemAtIndex(i); +        result->AddItem(obj.CreateStructuredObject()); +    } +    return result; +} + +//---------------------------------------------------------------------- +// PythonDictionary +//---------------------------------------------------------------------- + +PythonDictionary::PythonDictionary(PyInitialValue value) +    : PythonObject() +{ +    if (value == PyInitialValue::Empty) +        Reset(PyRefType::Owned, PyDict_New()); +} + +PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj) +    : PythonObject() +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary +} + +PythonDictionary::PythonDictionary(const PythonDictionary &object) +    : PythonObject(object) +{ +} + +PythonDictionary::~PythonDictionary () +{ +} + +bool +PythonDictionary::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; + +    return PyDict_Check(py_obj); +} + +void +PythonDictionary::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonDictionary::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +uint32_t +PythonDictionary::GetSize() const +{ +    if (IsValid()) +        return PyDict_Size(m_py_obj); +    return 0; +} + +PythonList +PythonDictionary::GetKeys() const +{ +    if (IsValid()) +        return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj)); +    return PythonList(PyInitialValue::Invalid); +} + +PythonObject +PythonDictionary::GetItemForKey(const PythonObject &key) const +{ +    if (IsAllocated() && key.IsValid()) +        return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get())); +    return PythonObject(); +} + +void +PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value) +{ +    if (IsAllocated() && key.IsValid() && value.IsValid()) +        PyDict_SetItem(m_py_obj, key.get(), value.get()); +} + +StructuredData::DictionarySP +PythonDictionary::CreateStructuredDictionary() const +{ +    StructuredData::DictionarySP result(new StructuredData::Dictionary); +    PythonList keys(GetKeys()); +    uint32_t num_keys = keys.GetSize(); +    for (uint32_t i = 0; i < num_keys; ++i) +    { +        PythonObject key = keys.GetItemAtIndex(i); +        PythonObject value = GetItemForKey(key); +        StructuredData::ObjectSP structured_value = value.CreateStructuredObject(); +        result->AddItem(key.Str().GetString(), structured_value); +    } +    return result; +} + +PythonModule::PythonModule() : PythonObject() +{ +} + +PythonModule::PythonModule(PyRefType type, PyObject *py_obj) +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module +} + +PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict) +{ +} + +PythonModule::~PythonModule() +{ +} + +PythonModule +PythonModule::BuiltinsModule() +{ +#if PY_MAJOR_VERSION >= 3 +    return AddModule("builtins"); +#else +    return AddModule("__builtin__"); +#endif +} + +PythonModule +PythonModule::MainModule() +{ +    return AddModule("__main__"); +} + +PythonModule +PythonModule::AddModule(llvm::StringRef module) +{ +    std::string str = module.str(); +    return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str())); +} + + +PythonModule +PythonModule::ImportModule(llvm::StringRef module) +{ +    std::string str = module.str(); +    return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str())); +} + +bool +PythonModule::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; + +    return PyModule_Check(py_obj); +} + +void +PythonModule::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonModule::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +PythonDictionary +PythonModule::GetDictionary() const +{ +    return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj)); +} + +PythonCallable::PythonCallable() : PythonObject() +{ +} + +PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj) +{ +    Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable +} + +PythonCallable::PythonCallable(const PythonCallable &callable) +    : PythonObject(callable) +{ +} + +PythonCallable::~PythonCallable() +{ +} + +bool +PythonCallable::Check(PyObject *py_obj) +{ +    if (!py_obj) +        return false; + +    return PyCallable_Check(py_obj); +} + +void +PythonCallable::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonCallable::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls +    // back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + + +PythonCallable::ArgInfo +PythonCallable::GetNumArguments() const +{ +    ArgInfo result = { 0, false, false }; +    if (!IsValid()) +        return result; + +    PyObject *py_func_obj = m_py_obj; +    if (PyMethod_Check(py_func_obj)) +        py_func_obj = PyMethod_GET_FUNCTION(py_func_obj); + +    if (!py_func_obj) +        return result; + +    PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); +    if (!code) +        return result; + +    result.count = code->co_argcount; +    result.has_varargs = !!(code->co_flags & CO_VARARGS); +    result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS); +    return result; +} + +PythonObject +PythonCallable::operator ()() +{ +    return PythonObject(PyRefType::Owned, +        PyObject_CallObject(m_py_obj, nullptr)); +} + +PythonObject +PythonCallable::operator ()(std::initializer_list<PyObject*> args) +{ +    PythonTuple arg_tuple(args); +    return PythonObject(PyRefType::Owned, +        PyObject_CallObject(m_py_obj, arg_tuple.get())); +} + +PythonObject +PythonCallable::operator ()(std::initializer_list<PythonObject> args) +{ +    PythonTuple arg_tuple(args); +    return PythonObject(PyRefType::Owned, +        PyObject_CallObject(m_py_obj, arg_tuple.get())); +} + +PythonFile::PythonFile() +    : PythonObject() +{ +} + +PythonFile::PythonFile(File &file, const char *mode) +{ +    Reset(file, mode); +} + +PythonFile::PythonFile(const char *path, const char *mode) +{ +    FILE *fp = nullptr; +    fp = fopen(path, mode); +    lldb_private::File file(fp, true); +    Reset(file, mode); +} + +PythonFile::PythonFile(PyRefType type, PyObject *o) +{ +    Reset(type, o); +} + +PythonFile::~PythonFile() +{ +} + +bool +PythonFile::Check(PyObject *py_obj) +{ +#if PY_MAJOR_VERSION < 3 +    return PyFile_Check(py_obj); +#else +    // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a +    // first-class object type anymore.  `PyFile_FromFd` is just a thin wrapper +    // over `io.open()`, which returns some object derived from `io.IOBase`. +    // As a result, the only way to detect a file in Python 3 is to check whether +    // it inherits from `io.IOBase`.  Since it is possible for non-files to also +    // inherit from `io.IOBase`, we additionally verify that it has the `fileno` +    // attribute, which should guarantee that it is backed by the file system. +    PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io")); +    PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get())); +    PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase")); + +    PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj)); + +    if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get())) +        return false; +    if (!object_type.HasAttribute("fileno")) +        return false; + +    return true; +#endif +} + +void +PythonFile::Reset(PyRefType type, PyObject *py_obj) +{ +    // Grab the desired reference type so that if we end up rejecting +    // `py_obj` it still gets decremented if necessary. +    PythonObject result(type, py_obj); + +    if (!PythonFile::Check(py_obj)) +    { +        PythonObject::Reset(); +        return; +    } + +    // Calling PythonObject::Reset(const PythonObject&) will lead to stack +    // overflow since it calls back into the virtual implementation. +    PythonObject::Reset(PyRefType::Borrowed, result.get()); +} + +void +PythonFile::Reset(File &file, const char *mode) +{ +    if (!file.IsValid()) +    { +        Reset(); +        return; +    } + +    char *cmode = const_cast<char *>(mode); +#if PY_MAJOR_VERSION >= 3 +    Reset(PyRefType::Owned, +        PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0)); +#else +    // Read through the Python source, doesn't seem to modify these strings +    Reset(PyRefType::Owned, +        PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr)); +#endif +} + +bool +PythonFile::GetUnderlyingFile(File &file) const +{ +    if (!IsValid()) +        return false; + +    file.Close(); +    // We don't own the file descriptor returned by this function, make sure the +    // File object knows about that. +    file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false); +    return file.IsValid(); +} + + +#endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h new file mode 100644 index 0000000000000..c9d17c0f0fad4 --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -0,0 +1,498 @@ +//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H + +#ifndef LLDB_DISABLE_PYTHON + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-defines.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/StructuredData.h" +#include "lldb/Core/Flags.h" +#include "lldb/Host/File.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class PythonString; +class PythonList; +class PythonDictionary; +class PythonInteger; + +class StructuredPythonObject : public StructuredData::Generic +{ +public: +    StructuredPythonObject() +        : StructuredData::Generic() +    { +    } + +    StructuredPythonObject(void *obj) +        : StructuredData::Generic(obj) +    { +        Py_XINCREF(GetValue()); +    } + +    ~StructuredPythonObject() override +    { +        if (Py_IsInitialized()) +            Py_XDECREF(GetValue()); +        SetValue(nullptr); +    } + +    bool +    IsValid() const override +    { +        return GetValue() && GetValue() != Py_None; +    } + +    void Dump(Stream &s) const override; + +private: +    DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject); +}; + +enum class PyObjectType +{ +    Unknown, +    None, +    Integer, +    Dictionary, +    List, +    String, +    Module, +    Callable, +    Tuple, +    File +}; + +enum class PyRefType +{ +    Borrowed, // We are not given ownership of the incoming PyObject. +              // We cannot safely hold it without calling Py_INCREF. +    Owned     // We have ownership of the incoming PyObject.  We should +              // not call Py_INCREF. +}; + +enum class PyInitialValue +{ +    Invalid, +    Empty +}; + +class PythonObject +{ +public: +    PythonObject() +        : m_py_obj(nullptr) +    { +    } + +    PythonObject(PyRefType type, PyObject *py_obj) +        : m_py_obj(nullptr) +    { +        Reset(type, py_obj); +    } + +    PythonObject(const PythonObject &rhs) +        : m_py_obj(nullptr) +    { +        Reset(rhs); +    } + +    virtual ~PythonObject() +    { +        Reset(); +    } + +    void +    Reset() +    { +        // Avoid calling the virtual method since it's not necessary +        // to actually validate the type of the PyObject if we're +        // just setting to null. +        if (Py_IsInitialized()) +            Py_XDECREF(m_py_obj); +        m_py_obj = nullptr; +    } + +    void +    Reset(const PythonObject &rhs) +    { +        // Avoid calling the virtual method if it's not necessary +        // to actually validate the type of the PyObject. +        if (!rhs.IsValid()) +            Reset(); +        else +            Reset(PyRefType::Borrowed, rhs.m_py_obj); +    } + +    // PythonObject is implicitly convertible to PyObject *, which will call the +    // wrong overload.  We want to explicitly disallow this, since a PyObject +    // *always* owns its reference.  Therefore the overload which takes a +    // PyRefType doesn't make sense, and the copy constructor should be used. +    void +    Reset(PyRefType type, const PythonObject &ref) = delete; + +    virtual void +    Reset(PyRefType type, PyObject *py_obj) +    { +        if (py_obj == m_py_obj) +            return; + +        if (Py_IsInitialized()) +            Py_XDECREF(m_py_obj); + +        m_py_obj = py_obj; + +        // If this is a borrowed reference, we need to convert it to +        // an owned reference by incrementing it.  If it is an owned +        // reference (for example the caller allocated it with PyDict_New() +        // then we must *not* increment it. +        if (Py_IsInitialized() && type == PyRefType::Borrowed) +            Py_XINCREF(m_py_obj); +    } +         +    void +    Dump () const +    { +        if (m_py_obj) +            _PyObject_Dump (m_py_obj); +        else +            puts ("NULL"); +    } +         +    void +    Dump (Stream &strm) const; + +    PyObject* +    get() const +    { +        return m_py_obj; +    } + +    PyObject* +    release() +    { +        PyObject *result = m_py_obj; +        m_py_obj = nullptr; +        return result; +    } + +    PythonObject & +    operator=(const PythonObject &other) +    { +        Reset(PyRefType::Borrowed, other.get()); +        return *this; +    } + +    PyObjectType +    GetObjectType() const; + +    PythonString +    Repr() const; + +    PythonString +    Str() const; + +    static PythonObject +    ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict); + +    template<typename T> +    static T +    ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) +    { +        return ResolveNameWithDictionary(name, dict).AsType<T>(); +    } + +    PythonObject +    ResolveName(llvm::StringRef name) const; + +    template<typename T> +    T +    ResolveName(llvm::StringRef name) const +    { +        return ResolveName(name).AsType<T>(); +    } + +    bool +    HasAttribute(llvm::StringRef attribute) const; + +    PythonObject +    GetAttributeValue(llvm::StringRef attribute) const; + +    bool +    IsValid() const; + +    bool +    IsAllocated() const; + +    bool +    IsNone() const; + +    template<typename T> +    T AsType() const +    { +        if (!T::Check(m_py_obj)) +            return T(); +        return T(PyRefType::Borrowed, m_py_obj); +    } + +    StructuredData::ObjectSP +    CreateStructuredObject() const; + +protected: +    PyObject* m_py_obj; +}; + +class PythonString : public PythonObject +{ +public: +    PythonString(); +    explicit PythonString(llvm::StringRef string); +    explicit PythonString(const char *string); +    PythonString(PyRefType type, PyObject *o); +    PythonString(const PythonString &object); + +    ~PythonString() override; + +    static bool Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    llvm::StringRef +    GetString() const; + +    size_t +    GetSize() const; + +    void SetString(llvm::StringRef string); + +    StructuredData::StringSP CreateStructuredString() const; +}; + +class PythonInteger : public PythonObject +{ +public: +    PythonInteger(); +    explicit PythonInteger(int64_t value); +    PythonInteger(PyRefType type, PyObject *o); +    PythonInteger(const PythonInteger &object); + +    ~PythonInteger() override; + +    static bool Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    int64_t GetInteger() const; + +    void +    SetInteger (int64_t value); + +    StructuredData::IntegerSP CreateStructuredInteger() const; +}; + +class PythonList : public PythonObject +{ +public: +    PythonList() {} +    explicit PythonList(PyInitialValue value); +    explicit PythonList(int list_size); +    PythonList(PyRefType type, PyObject *o); +    PythonList(const PythonList &list); + +    ~PythonList() override; + +    static bool Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    uint32_t GetSize() const; + +    PythonObject GetItemAtIndex(uint32_t index) const; + +    void SetItemAtIndex(uint32_t index, const PythonObject &object); + +    void AppendItem(const PythonObject &object); + +    StructuredData::ArraySP CreateStructuredArray() const; +}; + +class PythonTuple : public PythonObject +{ +public: +    PythonTuple() {} +    explicit PythonTuple(PyInitialValue value); +    explicit PythonTuple(int tuple_size); +    PythonTuple(PyRefType type, PyObject *o); +    PythonTuple(const PythonTuple &tuple); +    PythonTuple(std::initializer_list<PythonObject> objects); +    PythonTuple(std::initializer_list<PyObject*> objects); + +    ~PythonTuple() override; + +    static bool Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    uint32_t GetSize() const; + +    PythonObject GetItemAtIndex(uint32_t index) const; + +    void SetItemAtIndex(uint32_t index, const PythonObject &object); + +    StructuredData::ArraySP CreateStructuredArray() const; +}; + +class PythonDictionary : public PythonObject +{ +public: +    PythonDictionary() {} +    explicit PythonDictionary(PyInitialValue value); +    PythonDictionary(PyRefType type, PyObject *o); +    PythonDictionary(const PythonDictionary &dict); + +    ~PythonDictionary() override; + +    static bool Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    uint32_t GetSize() const; + +    PythonList GetKeys() const; + +    PythonObject GetItemForKey(const PythonObject &key) const; +    void SetItemForKey(const PythonObject &key, const PythonObject &value); + +    StructuredData::DictionarySP CreateStructuredDictionary() const; +}; + +class PythonModule : public PythonObject +{ +  public: +    PythonModule(); +    PythonModule(PyRefType type, PyObject *o); +    PythonModule(const PythonModule &dict); + +    ~PythonModule() override; + +    static bool Check(PyObject *py_obj); + +    static PythonModule +    BuiltinsModule(); + +    static PythonModule +    MainModule(); + +    static PythonModule +    AddModule(llvm::StringRef module); + +    static PythonModule +    ImportModule(llvm::StringRef module); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; + +    PythonDictionary GetDictionary() const; +}; + +class PythonCallable : public PythonObject +{ +public: +    struct ArgInfo { +        size_t count; +        bool has_varargs : 1; +        bool has_kwargs : 1; +    }; + +    PythonCallable(); +    PythonCallable(PyRefType type, PyObject *o); +    PythonCallable(const PythonCallable &dict); + +    ~PythonCallable() override; + +    static bool +    Check(PyObject *py_obj); + +    // Bring in the no-argument base class version +    using PythonObject::Reset; + +    void +    Reset(PyRefType type, PyObject *py_obj) override; + +    ArgInfo +    GetNumArguments() const; + +    PythonObject +    operator ()(); + +    PythonObject +    operator ()(std::initializer_list<PyObject*> args); + +    PythonObject +    operator ()(std::initializer_list<PythonObject> args); + +    template<typename Arg, typename... Args> +    PythonObject +    operator ()(const Arg &arg, Args... args) +    { +        return operator()({ arg, args... }); +    } +}; + + +class PythonFile : public PythonObject +{ +  public: +    PythonFile(); +    PythonFile(File &file, const char *mode); +    PythonFile(const char *path, const char *mode); +    PythonFile(PyRefType type, PyObject *o); + +    ~PythonFile() override; + +    static bool Check(PyObject *py_obj); + +    using PythonObject::Reset; + +    void Reset(PyRefType type, PyObject *py_obj) override; +    void Reset(File &file, const char *mode); + +    bool GetUnderlyingFile(File &file) const; +}; + +} // namespace lldb_private + +#endif + +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp new file mode 100644 index 0000000000000..2cbd85bfa11ef --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp @@ -0,0 +1,201 @@ +//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_DISABLE_PYTHON + +#include "lldb-python.h" +#include "PythonExceptionState.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +using namespace lldb_private; + +PythonExceptionState::PythonExceptionState(bool restore_on_exit) +    : m_restore_on_exit(restore_on_exit) +{ +    Acquire(restore_on_exit); +} + +PythonExceptionState::~PythonExceptionState() +{ +    if (m_restore_on_exit) +        Restore(); +} + +void +PythonExceptionState::Acquire(bool restore_on_exit) +{ +    // If a state is already acquired, the user needs to decide whether they +    // want to discard or restore it.  Don't allow the potential silent +    // loss of a valid state. +    assert(!IsError()); + +    if (!HasErrorOccurred()) +        return; + +    PyObject *py_type = nullptr; +    PyObject *py_value = nullptr; +    PyObject *py_traceback = nullptr; +    PyErr_Fetch(&py_type, &py_value, &py_traceback); +    // PyErr_Fetch clears the error flag. +    assert(!HasErrorOccurred()); + +    // Ownership of the objects returned by `PyErr_Fetch` is transferred +    // to us. +    m_type.Reset(PyRefType::Owned, py_type); +    m_value.Reset(PyRefType::Owned, py_value); +    m_traceback.Reset(PyRefType::Owned, py_traceback); +    m_restore_on_exit = restore_on_exit; +} + +void +PythonExceptionState::Restore() +{ +    if (m_type.IsValid()) +    { +        // The documentation for PyErr_Restore says "Do not pass a null type and +        // non-null value or traceback.  So only restore if type was non-null +        // to begin with.  In this case we're passing ownership back to Python +        // so release them all. +        PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release()); +    } + +    // After we restore, we should not hold onto the exception state.  Demand that +    // it be re-acquired. +    Discard(); +} + +void +PythonExceptionState::Discard() +{ +    m_type.Reset(); +    m_value.Reset(); +    m_traceback.Reset(); +} + +void +PythonExceptionState::Reset() +{ +    if (m_restore_on_exit) +        Restore(); +    else +        Discard(); +} + +bool +PythonExceptionState::HasErrorOccurred() +{ +    return PyErr_Occurred(); +} + +bool +PythonExceptionState::IsError() const +{ +    return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid(); +} + +PythonObject +PythonExceptionState::GetType() const +{ +    return m_type; +} + +PythonObject +PythonExceptionState::GetValue() const +{ +    return m_value; +} + +PythonObject +PythonExceptionState::GetTraceback() const +{ +    return m_traceback; +} + +std::string +PythonExceptionState::Format() const +{ +    // Don't allow this function to modify the error state. +    PythonExceptionState state(true); + +    std::string backtrace = ReadBacktrace(); +    if (!IsError()) +        return std::string(); + +    // It's possible that ReadPythonBacktrace generated another exception. +    // If this happens we have to clear the exception, because otherwise +    // PyObject_Str() will assert below.  That's why we needed to do the +    // save / restore at the beginning of this function. +    PythonExceptionState bt_error_state(false); + +    std::string error_string; +    llvm::raw_string_ostream error_stream(error_string); +    error_stream << m_value.Str().GetString() << "\n"; + +    if (!bt_error_state.IsError()) +    { +        // If we were able to read the backtrace, just append it. +        error_stream << backtrace << "\n"; +    } +    else +    { +        // Otherwise, append some information about why we were unable to +        // obtain the backtrace. +        PythonString bt_error = bt_error_state.GetValue().Str(); +        error_stream << "An error occurred while retrieving the backtrace: " << bt_error.GetString() << "\n"; +    } +    return error_stream.str(); +} + +std::string +PythonExceptionState::ReadBacktrace() const +{ +    std::string retval("backtrace unavailable"); + +    auto traceback_module = PythonModule::ImportModule("traceback"); +#if PY_MAJOR_VERSION >= 3 +    auto stringIO_module = PythonModule::ImportModule("io"); +#else +    auto stringIO_module = PythonModule::ImportModule("StringIO"); +#endif +    if (!m_traceback.IsAllocated()) +        return retval; + +    if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated()) +        return retval; + +    auto stringIO_builder = stringIO_module.ResolveName<PythonCallable>("StringIO"); +    if (!stringIO_builder.IsAllocated()) +        return retval; + +    auto stringIO_buffer = stringIO_builder(); +    if (!stringIO_buffer.IsAllocated()) +        return retval; + +    auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb"); +    if (!printTB.IsAllocated()) +        return retval; + +    auto printTB_result = printTB(m_traceback.get(), Py_None, stringIO_buffer.get()); +    auto stringIO_getvalue = stringIO_buffer.ResolveName<PythonCallable>("getvalue"); +    if (!stringIO_getvalue.IsAllocated()) +        return retval; + +    auto printTB_string = stringIO_getvalue().AsType<PythonString>(); +    if (!printTB_string.IsAllocated()) +        return retval; + +    llvm::StringRef string_data(printTB_string.GetString()); +    retval.assign(string_data.data(), string_data.size()); + +    return retval; +} + +#endif diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h new file mode 100644 index 0000000000000..c74e52b9ef560 --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h @@ -0,0 +1,70 @@ +//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H + +#ifndef LLDB_DISABLE_PYTHON + +#include "PythonDataObjects.h" + +namespace lldb_private +{ + +class PythonExceptionState +{ +  public: +    explicit PythonExceptionState(bool restore_on_exit); +    ~PythonExceptionState(); + +    void +    Acquire(bool restore_on_exit); + +    void +    Restore(); + +    void +    Discard(); + +    void +    Reset(); + +    static bool +    HasErrorOccurred(); + +    bool +    IsError() const; + +    PythonObject +    GetType() const; + +    PythonObject +    GetValue() const; + +    PythonObject +    GetTraceback() const; + +    std::string +    Format() const; + +  private: +    std::string +    ReadBacktrace() const; + +    bool m_restore_on_exit; + +    PythonObject m_type; +    PythonObject m_value; +    PythonObject m_traceback; +}; +} + +#endif + +#endif diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp new file mode 100644 index 0000000000000..b1dd34b46f69e --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -0,0 +1,3172 @@ +//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +#include "lldb-python.h" +#include "ScriptInterpreterPython.h" +#include "PythonDataObjects.h" +#include "PythonExceptionState.h" + +#include <stdlib.h> +#include <stdio.h> + +#include <mutex> +#include <string> + +#include "lldb/API/SBValue.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Breakpoint/WatchpointOptions.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Timer.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/Pipe.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +#if defined(_WIN32) +#include "lldb/Host/windows/ConnectionGenericFileWindows.h" +#endif + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" + +using namespace lldb; +using namespace lldb_private; + +static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr; +static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr; +static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr; +static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr; +static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr; +static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr; +static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr; +static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue  = nullptr; +static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr; +static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr; +static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr; +static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr; +static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr; +static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr; +static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr; +static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr; +static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr; + +static bool g_initialized = false; + +namespace +{ + +// Initializing Python is not a straightforward process.  We cannot control what +// external code may have done before getting to this point in LLDB, including +// potentially having already initialized Python, so we need to do a lot of work +// to ensure that the existing state of the system is maintained across our +// initialization.  We do this by using an RAII pattern where we save off initial +// state at the beginning, and restore it at the end  +struct InitializePythonRAII +{ +public: +    InitializePythonRAII() : +        m_gil_state(PyGILState_UNLOCKED), +        m_was_already_initialized(false) +    { +        // Python will muck with STDIN terminal state, so save off any current TTY +        // settings so we can restore them. +        m_stdin_tty_state.Save(STDIN_FILENO, false); + +        InitializePythonHome(); + +        // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for +        // calling `Py_Initialize` and `PyEval_InitThreads`.  < 3.2 requires that you +        // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last. +#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3) +        Py_InitializeEx(0); +        InitializeThreadsPrivate(); +#else +        InitializeThreadsPrivate(); +        Py_InitializeEx(0); +#endif +    } + +    ~InitializePythonRAII() +    { +        if (m_was_already_initialized) +        { +            Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); + +            if (log) +            { +                log->Printf("Releasing PyGILState. Returning to state = %slocked\n", +                    m_was_already_initialized == PyGILState_UNLOCKED ? "un" : ""); +            } +            PyGILState_Release(m_gil_state); +        } +        else +        { +            // We initialized the threads in this function, just unlock the GIL. +            PyEval_SaveThread(); +        } + +        m_stdin_tty_state.Restore(); +    } + +private: +    void InitializePythonHome() +    { +#if defined(LLDB_PYTHON_HOME) +#if PY_MAJOR_VERSION >= 3 +        size_t size = 0; +        static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size); +#else +        static char *g_python_home = LLDB_PYTHON_HOME; +#endif +        Py_SetPythonHome(g_python_home); +#endif +    } + +    void InitializeThreadsPrivate() +    { +        if (PyEval_ThreadsInitialized()) +        { +            Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); + +            m_was_already_initialized = true; +            m_gil_state = PyGILState_Ensure(); +            if (log) +            { +                log->Printf("Ensured PyGILState. Previous state = %slocked\n", +                    m_gil_state == PyGILState_UNLOCKED ? "un" : ""); +            } +            return; +        } + +        // InitThreads acquires the GIL if it hasn't been called before. +        PyEval_InitThreads(); +    } + +    TerminalState m_stdin_tty_state; +    PyGILState_STATE m_gil_state; +    bool m_was_already_initialized; +}; + +} + +ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter, +                                         uint16_t on_entry, +                                         uint16_t on_leave, +                                         FILE *in, +                                         FILE *out, +                                         FILE *err) : +    ScriptInterpreterLocker (), +    m_teardown_session( (on_leave & TearDownSession) == TearDownSession ), +    m_python_interpreter(py_interpreter) +{ +    DoAcquireLock(); +    if ((on_entry & InitSession) == InitSession) +    { +        if (DoInitSession(on_entry, in, out, err) == false) +        { +            // Don't teardown the session if we didn't init it. +            m_teardown_session = false; +        } +    } +} + +bool +ScriptInterpreterPython::Locker::DoAcquireLock() +{ +    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); +    m_GILState = PyGILState_Ensure(); +    if (log) +        log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); + +    // we need to save the thread state when we first start the command +    // because we might decide to interrupt it while some action is taking +    // place outside of Python (e.g. printing to screen, waiting for the network, ...) +    // in that case, _PyThreadState_Current will be NULL - and we would be unable +    // to set the asynchronous exception - not a desirable situation +    m_python_interpreter->SetThreadState(PyThreadState_Get()); +    m_python_interpreter->IncrementLockCount(); +    return true; +} + +bool +ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err) +{ +    if (!m_python_interpreter) +        return false; +    return m_python_interpreter->EnterSession (on_entry_flags, in, out, err); +} + +bool +ScriptInterpreterPython::Locker::DoFreeLock() +{ +    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE)); +    if (log) +        log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : ""); +    PyGILState_Release(m_GILState); +    m_python_interpreter->DecrementLockCount(); +    return true; +} + +bool +ScriptInterpreterPython::Locker::DoTearDownSession() +{ +    if (!m_python_interpreter) +        return false; +    m_python_interpreter->LeaveSession (); +    return true; +} + +ScriptInterpreterPython::Locker::~Locker() +{ +    if (m_teardown_session) +        DoTearDownSession(); +    DoFreeLock(); +} + +ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter) : +    ScriptInterpreter(interpreter, eScriptLanguagePython), +    IOHandlerDelegateMultiline("DONE"), +    m_saved_stdin(), +    m_saved_stdout(), +    m_saved_stderr(), +    m_main_module(), +    m_lldb_module(), +    m_session_dict(PyInitialValue::Invalid), +    m_sys_module_dict(PyInitialValue::Invalid), +    m_run_one_line_function(), +    m_run_one_line_str_global(), +    m_dictionary_name(interpreter.GetDebugger().GetInstanceName().AsCString()), +    m_terminal_state(), +    m_active_io_handler(eIOHandlerNone), +    m_session_is_active(false), +    m_pty_slave_is_open(false), +    m_valid_session(true), +    m_lock_count(0), +    m_command_thread_state(nullptr) +{ +    assert(g_initialized && "ScriptInterpreterPython created but InitializePrivate has not been called!"); + +    m_dictionary_name.append("_dict"); +    StreamString run_string; +    run_string.Printf ("%s = dict()", m_dictionary_name.c_str()); + +    Locker locker(this, +                  ScriptInterpreterPython::Locker::AcquireLock, +                  ScriptInterpreterPython::Locker::FreeAcquiredLock); +    PyRun_SimpleString (run_string.GetData()); + +    run_string.Clear(); +    run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str()); +    PyRun_SimpleString (run_string.GetData()); + +    // Reloading modules requires a different syntax in Python 2 and Python 3.  This provides +    // a consistent syntax no matter what version of Python. +    run_string.Clear(); +    run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", m_dictionary_name.c_str()); +    PyRun_SimpleString(run_string.GetData()); + +    // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set +    // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task +    run_string.Clear(); +    run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str()); +    PyRun_SimpleString (run_string.GetData()); +    run_string.Clear(); + +    run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str()); +    PyRun_SimpleString (run_string.GetData()); +    run_string.Clear(); +     +    run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(), +                       interpreter.GetDebugger().GetID()); +    PyRun_SimpleString (run_string.GetData()); +} + +ScriptInterpreterPython::~ScriptInterpreterPython () +{ +    // the session dictionary may hold objects with complex state +    // which means that they may need to be torn down with some level of smarts +    // and that, in turn, requires a valid thread state +    // force Python to procure itself such a thread state, nuke the session dictionary +    // and then release it for others to use and proceed with the rest of the shutdown +    auto gil_state = PyGILState_Ensure(); +    m_session_dict.Reset(); +    PyGILState_Release(gil_state); +} + +void +ScriptInterpreterPython::Initialize() +{ +    static std::once_flag g_once_flag; + +    std::call_once(g_once_flag, []() +    { +        InitializePrivate(); + +        PluginManager::RegisterPlugin(GetPluginNameStatic(), +                                      GetPluginDescriptionStatic(), +                                      lldb::eScriptLanguagePython, +                                      CreateInstance); +    }); +} +     +void +ScriptInterpreterPython::Terminate() +{ + +} +     +lldb::ScriptInterpreterSP +ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter) +{ +    return std::make_shared<ScriptInterpreterPython>(interpreter); +} +     +lldb_private::ConstString +ScriptInterpreterPython::GetPluginNameStatic() +{ +    static ConstString g_name("script-python"); +    return g_name; +} + +const char * +ScriptInterpreterPython::GetPluginDescriptionStatic() +{ +    return "Embedded Python interpreter"; +} +     +lldb_private::ConstString +ScriptInterpreterPython::GetPluginName() +{ +    return GetPluginNameStatic(); +} +     +uint32_t +ScriptInterpreterPython::GetPluginVersion() +{ +    return 1; +} + +void +ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler) +{ +    const char *instructions = nullptr; +     +    switch (m_active_io_handler) +    { +    case eIOHandlerNone: +            break; +    case eIOHandlerBreakpoint: +            instructions = R"(Enter your Python command(s). Type 'DONE' to end. +def function (frame, bp_loc, internal_dict): +    """frame: the lldb.SBFrame for the location at which you stopped +       bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information +       internal_dict: an LLDB support object not to be used""" +)"; +            break; +    case eIOHandlerWatchpoint: +            instructions = "Enter your Python command(s). Type 'DONE' to end.\n"; +            break; +    } +     +    if (instructions) +    { +        StreamFileSP output_sp(io_handler.GetOutputStreamFile()); +        if (output_sp) +        { +            output_sp->PutCString(instructions); +            output_sp->Flush(); +        } +    } +} + +void +ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data) +{ +    io_handler.SetIsDone(true); +    bool batch_mode = m_interpreter.GetBatchCommandMode(); + +    switch (m_active_io_handler) +    { +    case eIOHandlerNone: +        break; +    case eIOHandlerBreakpoint: +        { +            std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData(); +            for (auto bp_options : *bp_options_vec) +            { +                if (!bp_options) +                    continue; +                     +                std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); +                if (data_ap.get()) +                { +                    data_ap->user_source.SplitIntoLines(data); +                     +                    if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success()) +                    { +                        BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); +                        bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); +                    } +                    else if (!batch_mode) +                    { +                        StreamFileSP error_sp = io_handler.GetErrorStreamFile(); +                        if (error_sp) +                        { +                            error_sp->Printf ("Warning: No command attached to breakpoint.\n"); +                            error_sp->Flush(); +                        } +                    } +                } +            } +            m_active_io_handler = eIOHandlerNone; +        } +        break; +    case eIOHandlerWatchpoint: +        { +            WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData(); +            std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); +            if (data_ap.get()) +            { +                data_ap->user_source.SplitIntoLines(data); +                 +                if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) +                { +                    BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); +                    wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); +                } +                else if (!batch_mode) +                { +                    StreamFileSP error_sp = io_handler.GetErrorStreamFile(); +                    if (error_sp) +                    { +                        error_sp->Printf ("Warning: No command attached to breakpoint.\n"); +                        error_sp->Flush(); +                    } +                } +            } +            m_active_io_handler = eIOHandlerNone; +        } +        break; +    } +} + + +void +ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) +{ +} + +void +ScriptInterpreterPython::SaveTerminalState (int fd) +{ +    // Python mucks with the terminal state of STDIN. If we can possibly avoid +    // this by setting the file handles up correctly prior to entering the +    // interpreter we should. For now we save and restore the terminal state +    // on the input file handle. +    m_terminal_state.Save (fd, false); +} + +void +ScriptInterpreterPython::RestoreTerminalState () +{ +    // Python mucks with the terminal state of STDIN. If we can possibly avoid +    // this by setting the file handles up correctly prior to entering the +    // interpreter we should. For now we save and restore the terminal state +    // on the input file handle. +    m_terminal_state.Restore(); +} + +void +ScriptInterpreterPython::LeaveSession () +{ +    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); +    if (log) +        log->PutCString("ScriptInterpreterPython::LeaveSession()"); + +    // checking that we have a valid thread state - since we use our own threading and locking +    // in some (rare) cases during cleanup Python may end up believing we have no thread state +    // and PyImport_AddModule will crash if that is the case - since that seems to only happen +    // when destroying the SBDebugger, we can make do without clearing up stdout and stderr + +    // rdar://problem/11292882 +    // When the current thread state is NULL, PyThreadState_Get() issues a fatal error. +    if (PyThreadState_GetDict()) +    { +        PythonDictionary &sys_module_dict = GetSysModuleDictionary (); +        if (sys_module_dict.IsValid()) +        { +            if (m_saved_stdin.IsValid()) +            { +                sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin); +                m_saved_stdin.Reset (); +            } +            if (m_saved_stdout.IsValid()) +            { +                sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout); +                m_saved_stdout.Reset (); +            } +            if (m_saved_stderr.IsValid()) +            { +                sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr); +                m_saved_stderr.Reset (); +            } +        } +    } + +    m_session_is_active = false; +} + +bool +ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, +                                       FILE *in, +                                       FILE *out, +                                       FILE *err) +{ +    // If we have already entered the session, without having officially 'left' it, then there is no need to  +    // 'enter' it again. +    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); +    if (m_session_is_active) +    { +        if (log) +            log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags); +        return false; +    } + +    if (log) +        log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags); +     + +    m_session_is_active = true; + +    StreamString run_string; + +    if (on_entry_flags & Locker::InitGlobals) +    { +        run_string.Printf (    "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); +        run_string.Printf (    "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); +        run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()"); +        run_string.PutCString ("; lldb.process = lldb.target.GetProcess()"); +        run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()"); +        run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()"); +        run_string.PutCString ("')"); +    } +    else +    { +        // If we aren't initing the globals, we should still always set the debugger (since that is always unique.) +        run_string.Printf (    "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID()); +        run_string.Printf (    "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID()); +        run_string.PutCString ("')"); +    } + +    PyRun_SimpleString (run_string.GetData()); +    run_string.Clear(); + +    PythonDictionary &sys_module_dict = GetSysModuleDictionary (); +    if (sys_module_dict.IsValid()) +    { +        File in_file(in, false); +        File out_file(out, false); +        File err_file(err, false); + +        lldb::StreamFileSP in_sp; +        lldb::StreamFileSP out_sp; +        lldb::StreamFileSP err_sp; +        if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid()) +            m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp); + +        m_saved_stdin.Reset(); + +        if ((on_entry_flags & Locker::NoSTDIN) == 0) +        { +            // STDIN is enabled +            if (!in_file.IsValid() && in_sp) +                in_file = in_sp->GetFile(); +            if (in_file.IsValid()) +            { +                // Flush the file before giving it to python to avoid interleaved output. +                in_file.Flush(); + +                m_saved_stdin = sys_module_dict.GetItemForKey(PythonString("stdin")).AsType<PythonFile>(); +                // This call can deadlock your process if the file is locked +                PythonFile new_file(in_file, "r"); +                sys_module_dict.SetItemForKey (PythonString("stdin"), new_file); +            } +        } + +        if (!out_file.IsValid() && out_sp) +            out_file = out_sp->GetFile(); +        if (out_file.IsValid()) +        { +            // Flush the file before giving it to python to avoid interleaved output. +            out_file.Flush(); + +            m_saved_stdout = sys_module_dict.GetItemForKey(PythonString("stdout")).AsType<PythonFile>(); + +            PythonFile new_file(out_file, "w"); +            sys_module_dict.SetItemForKey (PythonString("stdout"), new_file); +        } +        else +            m_saved_stdout.Reset(); + +        if (!err_file.IsValid() && err_sp) +            err_file = err_sp->GetFile(); +        if (err_file.IsValid()) +        { +            // Flush the file before giving it to python to avoid interleaved output. +            err_file.Flush(); + +            m_saved_stderr = sys_module_dict.GetItemForKey(PythonString("stderr")).AsType<PythonFile>(); + +            PythonFile new_file(err_file, "w"); +            sys_module_dict.SetItemForKey (PythonString("stderr"), new_file); +        } +        else +            m_saved_stderr.Reset(); +    } + +    if (PyErr_Occurred()) +        PyErr_Clear (); +     +    return true; +} + +PythonObject & +ScriptInterpreterPython::GetMainModule() +{ +    if (!m_main_module.IsValid()) +        m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__")); +    return m_main_module; +} + +PythonDictionary & +ScriptInterpreterPython::GetSessionDictionary () +{ +    if (m_session_dict.IsValid()) +        return m_session_dict; + +    PythonObject &main_module = GetMainModule(); +    if (!main_module.IsValid()) +        return m_session_dict; + +    PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); +    if (!main_dict.IsValid()) +        return m_session_dict; + +    PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name)); +    m_session_dict.Reset(PyRefType::Borrowed, item.get()); +    return m_session_dict; +} + +PythonDictionary & +ScriptInterpreterPython::GetSysModuleDictionary () +{ +    if (m_sys_module_dict.IsValid()) +        return m_sys_module_dict; + +    PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys")); +    if (sys_module.IsValid()) +        m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get())); +    return m_sys_module_dict; +} + +static std::string +GenerateUniqueName (const char* base_name_wanted, +                    uint32_t& functions_counter, +                    const void* name_token = nullptr) +{ +    StreamString sstr; +     +    if (!base_name_wanted) +        return std::string(); +     +    if (!name_token) +        sstr.Printf ("%s_%d", base_name_wanted, functions_counter++); +    else +        sstr.Printf ("%s_%p", base_name_wanted, name_token); +     +    return sstr.GetString(); +} + +bool +ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects () +{ +    if (m_run_one_line_function.IsValid()) +        return true; + +    PythonObject module(PyRefType::Borrowed, PyImport_AddModule ("lldb.embedded_interpreter")); +    if (!module.IsValid()) +        return false; + +    PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get())); +    if (!module_dict.IsValid()) +        return false; + +    m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line")); +    m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str")); +    return m_run_one_line_function.IsValid(); +} + +static void +ReadThreadBytesReceived(void *baton, const void *src, size_t src_len) +{ +    if (src && src_len) +    { +        Stream *strm = (Stream *)baton; +        strm->Write(src, src_len); +        strm->Flush(); +    } +} + +bool +ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options) +{ +    if (!m_valid_session) +        return false; +     +    if (command && command[0]) +    { +        // We want to call run_one_line, passing in the dictionary and the command string.  We cannot do this through +        // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside +        // another string to pass to PyRun_SimpleString messes up the escaping.  So we use the following more complicated +        // method to pass the command string directly down to Python. +        Debugger &debugger = m_interpreter.GetDebugger(); +         +        StreamFileSP input_file_sp; +        StreamFileSP output_file_sp; +        StreamFileSP error_file_sp; +        Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm"); +        bool join_read_thread = false; +        if (options.GetEnableIO()) +        { +            if (result) +            { +                input_file_sp = debugger.GetInputFile(); +                // Set output to a temporary file so we can forward the results on to the result object +                 +                Pipe pipe; +                Error pipe_result = pipe.CreateNew(false); +                if (pipe_result.Success()) +                { +#if defined(_WIN32) +                    lldb::file_t read_file = pipe.GetReadNativeHandle(); +                    pipe.ReleaseReadFileDescriptor(); +                    std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true)); +#else +                    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true)); +#endif +                    if (conn_ap->IsConnected()) +                    { +                        output_comm.SetConnection(conn_ap.release()); +                        output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream()); +                        output_comm.StartReadThread(); +                        join_read_thread = true; +                        FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w"); +                        output_file_sp.reset(new StreamFile(outfile_handle, true)); +                        error_file_sp = output_file_sp; +                        if (outfile_handle) +                            ::setbuf (outfile_handle, nullptr); +                         +                        result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream()); +                        result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream()); +                    } +                } +            } +            if (!input_file_sp || !output_file_sp || !error_file_sp) +                debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp); +        } +        else +        { +            input_file_sp.reset (new StreamFile ()); +            input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead); +            output_file_sp.reset (new StreamFile ()); +            output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite); +            error_file_sp = output_file_sp; +        } + +        FILE *in_file = input_file_sp->GetFile().GetStream(); +        FILE *out_file = output_file_sp->GetFile().GetStream(); +        FILE *err_file = error_file_sp->GetFile().GetStream(); +        bool success = false; +        { +            // WARNING!  It's imperative that this RAII scope be as tight as possible.  In particular, the +            // scope must end *before* we try to join the read thread.  The reason for this is that a +            // pre-requisite for joining the read thread is that we close the write handle (to break the +            // pipe and cause it to wake up and exit).  But acquiring the GIL as below will redirect Python's +            // stdio to use this same handle.  If we close the handle while Python is still using it, bad +            // things will happen. +            Locker locker(this, +                          ScriptInterpreterPython::Locker::AcquireLock | +                          ScriptInterpreterPython::Locker::InitSession | +                          (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | +                          ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN), +                          ScriptInterpreterPython::Locker::FreeAcquiredLock | +                          ScriptInterpreterPython::Locker::TearDownSession, +                          in_file, +                          out_file, +                          err_file); +         +            // Find the correct script interpreter dictionary in the main module. +            PythonDictionary &session_dict = GetSessionDictionary (); +            if (session_dict.IsValid()) +            { +                if (GetEmbeddedInterpreterModuleObjects ()) +                { +                    if (PyCallable_Check(m_run_one_line_function.get())) +                    { +                        PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command)); +                        if (pargs.IsValid()) +                        { +                            PythonObject return_value(PyRefType::Owned, +                                PyObject_CallObject(m_run_one_line_function.get(), pargs.get())); +                            if (return_value.IsValid()) +                                success = true; +                            else if (options.GetMaskoutErrors() && PyErr_Occurred ()) +                            { +                                PyErr_Print(); +                                PyErr_Clear(); +                            } +                        } +                    } +                } +            } + +            // Flush our output and error file handles +            ::fflush (out_file); +            if (out_file != err_file) +                ::fflush (err_file); +        } +         +        if (join_read_thread) +        { +            // Close the write end of the pipe since we are done with our +            // one line script. This should cause the read thread that +            // output_comm is using to exit +            output_file_sp->GetFile().Close(); +            // The close above should cause this thread to exit when it gets +            // to the end of file, so let it get all its data +            output_comm.JoinReadThread(); +            // Now we can close the read end of the pipe +            output_comm.Disconnect(); +        } +         +         +        if (success) +            return true; + +        // The one-liner failed.  Append the error message. +        if (result) +            result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command); +        return false; +    } + +    if (result) +        result->AppendError ("empty command passed to python\n"); +    return false; +} + + +class IOHandlerPythonInterpreter : +    public IOHandler +{ +public: +     +    IOHandlerPythonInterpreter (Debugger &debugger, +                                ScriptInterpreterPython *python) : +        IOHandler (debugger, IOHandler::Type::PythonInterpreter), +        m_python(python) +    { +         +    } +     +    ~IOHandlerPythonInterpreter() override +    { +         +    } +     +    ConstString +    GetControlSequence (char ch) override +    { +        if (ch == 'd') +            return ConstString("quit()\n"); +        return ConstString(); +    } + +    void +    Run () override +    { +        if (m_python) +        { +            int stdin_fd = GetInputFD(); +            if (stdin_fd >= 0) +            { +                Terminal terminal(stdin_fd); +                TerminalState terminal_state; +                const bool is_a_tty = terminal.IsATerminal(); +                 +                if (is_a_tty) +                { +                    terminal_state.Save (stdin_fd, false); +                    terminal.SetCanonical(false); +                    terminal.SetEcho(true); +                } +                 +                ScriptInterpreterPython::Locker locker (m_python, +                                                        ScriptInterpreterPython::Locker::AcquireLock | +                                                        ScriptInterpreterPython::Locker::InitSession | +                                                        ScriptInterpreterPython::Locker::InitGlobals, +                                                        ScriptInterpreterPython::Locker::FreeAcquiredLock | +                                                        ScriptInterpreterPython::Locker::TearDownSession); + +                // The following call drops into the embedded interpreter loop and stays there until the +                // user chooses to exit from the Python interpreter. +                // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before +                // a system call that can hang, and lock it when the syscall has returned. +                 +                // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and +                // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want +                // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off, +                // and things could hang (it's happened before). +                 +                StreamString run_string; +                run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ()); +                PyRun_SimpleString (run_string.GetData()); +                 +                if (is_a_tty) +                    terminal_state.Restore(); +            } +        } +        SetIsDone(true); +    } + +    void +    Cancel () override +    { +         +    } + +    bool +    Interrupt () override +    { +        return m_python->Interrupt(); +    } +     +    void +    GotEOF() override +    { +         +    } +protected: +    ScriptInterpreterPython *m_python; +}; + + +void +ScriptInterpreterPython::ExecuteInterpreterLoop () +{ +    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); + +    Debugger &debugger = GetCommandInterpreter().GetDebugger(); + +    // At the moment, the only time the debugger does not have an input file handle is when this is called +    // directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to +    // try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't +    // do it. + +    if (!debugger.GetInputFile()->GetFile().IsValid()) +        return; + +    IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this)); +    if (io_handler_sp) +    { +        debugger.PushIOHandler(io_handler_sp); +    } +} + +bool +ScriptInterpreterPython::Interrupt() +{ +    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); + +    if (IsExecutingPython()) +    { +        PyThreadState *state = PyThreadState_Get(); +        if (!state) +            state = GetThreadState(); +        if (state) +        { +            long tid = state->thread_id; +            PyThreadState_Swap(state); +            int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); +            if (log) +                log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads); +            return true; +        } +    } +    if (log) +        log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt"); +    return false; + +} +bool +ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, +                                                   ScriptInterpreter::ScriptReturnType return_type, +                                                   void *ret_value, +                                                   const ExecuteScriptOptions &options) +{ + +    Locker locker(this, +                  ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, +                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); + +    PythonObject py_return; +    PythonObject &main_module = GetMainModule(); +    PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); +    PythonObject py_error; +    bool ret_success = false; +    int success; +     +    PythonDictionary locals = GetSessionDictionary (); +     +    if (!locals.IsValid()) +    { +        locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); +    } +         +    if (!locals.IsValid()) +        locals = globals; + +    py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); +    if (py_error.IsValid()) +        PyErr_Clear(); +     +    if (in_string != nullptr) +    { +        { // scope for PythonInputReaderManager +            //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL); +            py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get())); +            if (!py_return.IsValid()) +            { +                py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); +                if (py_error.IsValid()) +                    PyErr_Clear(); + +                py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get())); +            } +        } + +        if (py_return.IsValid()) +        { +            switch (return_type) +            { +                case eScriptReturnTypeCharPtr: // "char *" +                { +                    const char format[3] = "s#"; +                    success = PyArg_Parse (py_return.get(), format, (char **) ret_value); +                    break; +                } +                case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None +                { +                    const char format[3] = "z"; +                    success = PyArg_Parse (py_return.get(), format, (char **) ret_value); +                    break; +                } +                case eScriptReturnTypeBool: +                { +                    const char format[2] = "b"; +                    success = PyArg_Parse (py_return.get(), format, (bool *) ret_value); +                    break; +                } +                case eScriptReturnTypeShortInt: +                { +                    const char format[2] = "h"; +                    success = PyArg_Parse (py_return.get(), format, (short *) ret_value); +                    break; +                } +                case eScriptReturnTypeShortIntUnsigned: +                { +                    const char format[2] = "H"; +                    success = PyArg_Parse (py_return.get(), format, (unsigned short *) ret_value); +                    break; +                } +                case eScriptReturnTypeInt: +                { +                    const char format[2] = "i"; +                    success = PyArg_Parse (py_return.get(), format, (int *) ret_value); +                    break; +                } +                case eScriptReturnTypeIntUnsigned: +                { +                    const char format[2] = "I"; +                    success = PyArg_Parse (py_return.get(), format, (unsigned int *) ret_value); +                    break; +                } +                case eScriptReturnTypeLongInt: +                { +                    const char format[2] = "l"; +                    success = PyArg_Parse (py_return.get(), format, (long *) ret_value); +                    break; +                } +                case eScriptReturnTypeLongIntUnsigned: +                { +                    const char format[2] = "k"; +                    success = PyArg_Parse (py_return.get(), format, (unsigned long *) ret_value); +                    break; +                } +                case eScriptReturnTypeLongLong: +                { +                    const char format[2] = "L"; +                    success = PyArg_Parse (py_return.get(), format, (long long *) ret_value); +                    break; +                } +                case eScriptReturnTypeLongLongUnsigned: +                { +                    const char format[2] = "K"; +                    success = PyArg_Parse (py_return.get(), format, (unsigned long long *) ret_value); +                    break; +                } +                case eScriptReturnTypeFloat: +                { +                    const char format[2] = "f"; +                    success = PyArg_Parse (py_return.get(), format, (float *) ret_value); +                    break; +                } +                case eScriptReturnTypeDouble: +                { +                    const char format[2] = "d"; +                    success = PyArg_Parse (py_return.get(), format, (double *) ret_value); +                    break; +                } +                case eScriptReturnTypeChar: +                { +                    const char format[2] = "c"; +                    success = PyArg_Parse (py_return.get(), format, (char *) ret_value); +                    break; +                } +                case eScriptReturnTypeOpaqueObject: +                { +                    success = true; +                    PyObject *saved_value = py_return.get(); +                    Py_XINCREF(saved_value); +                    *((PyObject **)ret_value) = saved_value; +                    break; +                } +            } + +            if (success) +                ret_success = true; +            else +                ret_success = false; +        } +    } + +    py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); +    if (py_error.IsValid()) +    { +        ret_success = false; +        if (options.GetMaskoutErrors()) +        { +            if (PyErr_GivenExceptionMatches (py_error.get(), PyExc_SyntaxError)) +                PyErr_Print (); +            PyErr_Clear(); +        } +    } + +    return ret_success; +} + +Error +ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options) +{ +    Error error; +     +    Locker locker(this, +                  ScriptInterpreterPython::Locker::AcquireLock      | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN, +                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); + +    PythonObject return_value; +    PythonObject &main_module = GetMainModule(); +    PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get())); +    PythonObject py_error; + +    PythonDictionary locals = GetSessionDictionary(); + +    if (!locals.IsValid()) +        locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str())); + +    if (!locals.IsValid()) +        locals = globals; + +    py_error.Reset(PyRefType::Borrowed, PyErr_Occurred()); +    if (py_error.IsValid()) +        PyErr_Clear(); +     +    if (in_string != nullptr) +    { +        PythonObject code_object; +        code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input)); + +        if (code_object.IsValid()) +        { +            // In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it takes +            // a PyObject.  They are convertible (hence the function PyCode_Check(PyObject*), so +            // we have to do the cast for Python 2.x +#if PY_MAJOR_VERSION >= 3 +            PyObject *py_code_obj = code_object.get(); +#else +            PyCodeObject *py_code_obj = reinterpret_cast<PyCodeObject *>(code_object.get()); +#endif +            return_value.Reset(PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get())); +        } +    } + +    PythonExceptionState exception_state(!options.GetMaskoutErrors()); +    if (exception_state.IsError()) +        error.SetErrorString(exception_state.Format().c_str()); + +    return error; +} + + +void +ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, +                                                                  CommandReturnObject &result) +{ +    m_active_io_handler = eIOHandlerBreakpoint; +    m_interpreter.GetPythonCommandsFromIOHandler ("    ", *this, true, &bp_options_vec); +} + +void +ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, +                                                                  CommandReturnObject &result) +{ +    m_active_io_handler = eIOHandlerWatchpoint; +    m_interpreter.GetPythonCommandsFromIOHandler ("    ", *this, true, wp_options); +} + +void +ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, +                                                               const char *function_name) +{ +    // For now just cons up a oneliner that calls the provided function. +    std::string oneliner("return "); +    oneliner += function_name; +    oneliner += "(frame, bp_loc, internal_dict)"; +    m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options, +                                                                        oneliner.c_str()); +} + +// Set a Python one-liner as the callback for the breakpoint. +Error +ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options, +                                                       const char *command_body_text) +{ +    std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData()); + +    // Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData.  That will +    // wrap the body in an auto-generated function, and return the function name in script_source.  That is what +    // the callback will actually invoke. +     +    data_ap->user_source.SplitIntoLines(command_body_text); +    Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source); +    if (error.Success()) +    { +        BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release())); +        bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp); +        return error; +    } +    else +        return error; +} + +// Set a Python one-liner as the callback for the watchpoint. +void +ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options, +                                                       const char *oneliner) +{ +    std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData()); + +    // It's necessary to set both user_source and script_source to the oneliner. +    // The former is used to generate callback description (as in watchpoint command list) +    // while the latter is used for Python to interpret during the actual callback. + +    data_ap->user_source.AppendString (oneliner); +    data_ap->script_source.assign (oneliner); + +    if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source)) +    { +        BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release())); +        wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp); +    } +     +    return; +} + +Error +ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def) +{ +    // Convert StringList to one long, newline delimited, const char *. +    std::string function_def_string(function_def.CopyList()); + +    Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)); +    return error; +} + +Error +ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input) +{ +    Error error; +    int num_lines = input.GetSize (); +    if (num_lines == 0) +    { +        error.SetErrorString ("No input data."); +        return error; +    } +     +    if (!signature || *signature == 0) +    { +        error.SetErrorString("No output function name."); +        return error; +    } + +    StreamString sstr; +    StringList auto_generated_function; +    auto_generated_function.AppendString (signature); +    auto_generated_function.AppendString ("     global_dict = globals()");   // Grab the global dictionary +    auto_generated_function.AppendString ("     new_keys = internal_dict.keys()");    // Make a list of keys in the session dict +    auto_generated_function.AppendString ("     old_keys = global_dict.keys()"); // Save list of keys in global dict +    auto_generated_function.AppendString ("     global_dict.update (internal_dict)"); // Add the session dictionary to the  +    // global dictionary. +     +    // Wrap everything up inside the function, increasing the indentation. +     +    auto_generated_function.AppendString("     if True:"); +    for (int i = 0; i < num_lines; ++i) +    { +        sstr.Clear (); +        sstr.Printf ("       %s", input.GetStringAtIndex (i)); +        auto_generated_function.AppendString (sstr.GetData()); +    } +    auto_generated_function.AppendString ("     for key in new_keys:");  // Iterate over all the keys from session dict +    auto_generated_function.AppendString ("         internal_dict[key] = global_dict[key]");  // Update session dict values +    auto_generated_function.AppendString ("         if key not in old_keys:");       // If key was not originally in global dict +    auto_generated_function.AppendString ("             del global_dict[key]");      //  ...then remove key/value from global dict +     +    // Verify that the results are valid Python. +     +    error = ExportFunctionDefinitionToInterpreter (auto_generated_function); +     +    return error; +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token) +{ +    static uint32_t num_created_functions = 0; +    user_input.RemoveBlankLines (); +    StreamString sstr; +     +    // Check to see if we have any data; if not, just return. +    if (user_input.GetSize() == 0) +        return false; +     +    // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the +    // ValueObject as parameter to the function. +     +    std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token)); +    sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); +     +    if (!GenerateFunction(sstr.GetData(), user_input).Success()) +        return false; + +    // Store the name of the auto-generated function to be called. +    output.assign(auto_generated_function_name); +    return true; +} + +bool +ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output) +{ +    static uint32_t num_created_functions = 0; +    user_input.RemoveBlankLines (); +    StreamString sstr; +     +    // Check to see if we have any data; if not, just return. +    if (user_input.GetSize() == 0) +        return false; +     +    std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions)); + +    sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str()); +     +    if (!GenerateFunction(sstr.GetData(),user_input).Success()) +        return false; +     +    // Store the name of the auto-generated function to be called. +    output.assign(auto_generated_function_name); +    return true; +} + + +bool +ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token) +{ +    static uint32_t num_created_classes = 0; +    user_input.RemoveBlankLines (); +    int num_lines = user_input.GetSize (); +    StreamString sstr; +     +    // Check to see if we have any data; if not, just return. +    if (user_input.GetSize() == 0) +        return false; +     +    // Wrap all user input into a Python class +     +    std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token)); +     +    StringList auto_generated_class; +     +    // Create the function name & definition string. +     +    sstr.Printf ("class %s:", auto_generated_class_name.c_str()); +    auto_generated_class.AppendString (sstr.GetData()); +         +    // Wrap everything up inside the class, increasing the indentation. +    // we don't need to play any fancy indentation tricks here because there is no +    // surrounding code whose indentation we need to honor +    for (int i = 0; i < num_lines; ++i) +    { +        sstr.Clear (); +        sstr.Printf ("     %s", user_input.GetStringAtIndex (i)); +        auto_generated_class.AppendString (sstr.GetData()); +    } +     +     +    // Verify that the results are valid Python. +    // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported) +    // (TODO: rename that method to ExportDefinitionToInterpreter) +    if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success()) +        return false; +     +    // Store the name of the auto-generated class +     +    output.assign(auto_generated_class_name); +    return true; +} + +StructuredData::GenericSP +ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) +{ +    if (class_name == nullptr || class_name[0] == '\0') +        return StructuredData::GenericSP(); + +    if (!process_sp) +        return StructuredData::GenericSP(); + +    void* ret_val; +     +    { +        Locker py_lock  (this, +                         Locker::AcquireLock | Locker::NoSTDIN, +                         Locker::FreeLock); +        ret_val = g_swig_create_os_plugin    (class_name, +                                              m_dictionary_name.c_str(), +                                              process_sp); +    } + +    return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); +} + +StructuredData::DictionarySP +ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) +{ +    Locker py_lock(this, +                   Locker::AcquireLock | Locker::NoSTDIN, +                   Locker::FreeLock); +     +    static char callee_name[] = "get_register_info"; +     +    if (!os_plugin_object_sp) +        return StructuredData::DictionarySP(); + +    StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); +    if (!generic) +        return nullptr; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); + +    if (!implementor.IsAllocated()) +        return StructuredData::DictionarySP(); + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return StructuredData::DictionarySP(); +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +         +        return StructuredData::DictionarySP(); +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } +    assert(PythonDictionary::Check(py_return.get()) && "get_register_info returned unknown object type!"); + +    PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); +    return result_dict.CreateStructuredDictionary(); +} + +StructuredData::ArraySP +ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) +{ +    Locker py_lock (this, +                    Locker::AcquireLock | Locker::NoSTDIN, +                    Locker::FreeLock); + +    static char callee_name[] = "get_thread_info"; + +    if (!os_plugin_object_sp) +        return StructuredData::ArraySP(); + +    StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); +    if (!generic) +        return nullptr; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); + +    if (!implementor.IsAllocated()) +        return StructuredData::ArraySP(); + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return StructuredData::ArraySP(); +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +         +        return StructuredData::ArraySP(); +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    assert(PythonList::Check(py_return.get()) && "get_thread_info returned unknown object type!"); + +    PythonList result_list(PyRefType::Borrowed, py_return.get()); +    return result_list.CreateStructuredArray(); +} + +// GetPythonValueFormatString provides a system independent type safe way to +// convert a variable's type into a python value format. Python value formats +// are defined in terms of builtin C types and could change from system to +// as the underlying typedef for uint* types, size_t, off_t and other values +// change. + +template <typename T> +const char *GetPythonValueFormatString(T t) +{ +    assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type."); +    return nullptr; +} +template <> const char *GetPythonValueFormatString (char *)             { return "s"; } +template <> const char *GetPythonValueFormatString (char)               { return "b"; } +template <> const char *GetPythonValueFormatString (unsigned char)      { return "B"; } +template <> const char *GetPythonValueFormatString (short)              { return "h"; } +template <> const char *GetPythonValueFormatString (unsigned short)     { return "H"; } +template <> const char *GetPythonValueFormatString (int)                { return "i"; } +template <> const char *GetPythonValueFormatString (unsigned int)       { return "I"; } +template <> const char *GetPythonValueFormatString (long)               { return "l"; } +template <> const char *GetPythonValueFormatString (unsigned long)      { return "k"; } +template <> const char *GetPythonValueFormatString (long long)          { return "L"; } +template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; } +template <> const char *GetPythonValueFormatString (float t)            { return "f"; } +template <> const char *GetPythonValueFormatString (double t)           { return "d"; } + +StructuredData::StringSP +ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) +{ +    Locker py_lock (this, +                    Locker::AcquireLock | Locker::NoSTDIN, +                    Locker::FreeLock); + +    static char callee_name[] = "get_register_data"; +    static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid)); +     +    if (!os_plugin_object_sp) +        return StructuredData::StringSP(); + +    StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); +    if (!generic) +        return nullptr; +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); + +    if (!implementor.IsAllocated()) +        return StructuredData::StringSP(); + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return StructuredData::StringSP(); +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +        return StructuredData::StringSP(); +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, tid)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    assert(PythonString::Check(py_return.get()) && "get_register_data returned unknown object type!"); + +    PythonString result_string(PyRefType::Borrowed, py_return.get()); +    return result_string.CreateStructuredString(); +} + +StructuredData::DictionarySP +ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context) +{ +    Locker py_lock(this, +                   Locker::AcquireLock | Locker::NoSTDIN, +                   Locker::FreeLock); +     +    static char callee_name[] = "create_thread"; +    std::string param_format; +    param_format += GetPythonValueFormatString(tid); +    param_format += GetPythonValueFormatString(context); +     +    if (!os_plugin_object_sp) +        return StructuredData::DictionarySP(); + +    StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); +    if (!generic) +        return nullptr; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); + +    if (!implementor.IsAllocated()) +        return StructuredData::DictionarySP(); + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return StructuredData::DictionarySP(); +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +        return StructuredData::DictionarySP(); +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, ¶m_format[0], tid, context)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    assert(PythonDictionary::Check(py_return.get()) && "create_thread returned unknown object type!"); + +    PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); +    return result_dict.CreateStructuredDictionary(); +} + +StructuredData::ObjectSP +ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp) +{ +    if (class_name == nullptr || class_name[0] == '\0') +        return StructuredData::ObjectSP(); + +    if (!thread_plan_sp.get()) +        return StructuredData::ObjectSP(); + +    Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger(); +    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); +    ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter); +     +    if (!script_interpreter) +        return StructuredData::ObjectSP(); + +    void* ret_val; + +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +         +        ret_val = g_swig_thread_plan_script (class_name, +                                             python_interpreter->m_dictionary_name.c_str(), +                                             thread_plan_sp); +    } + +    return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) +{ +    bool explains_stop = true; +    StructuredData::Generic *generic = nullptr; +    if (implementor_sp) +        generic = implementor_sp->GetAsGeneric(); +    if (generic) +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error); +        if (script_error) +            return true; +    } +    return explains_stop; +} + +bool +ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) +{ +    bool should_stop = true; +    StructuredData::Generic *generic = nullptr; +    if (implementor_sp) +        generic = implementor_sp->GetAsGeneric(); +    if (generic) +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error); +        if (script_error) +            return true; +    } +    return should_stop; +} + +lldb::StateType +ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) +{ +    bool should_step = false; +    StructuredData::Generic *generic = nullptr; +    if (implementor_sp) +        generic = implementor_sp->GetAsGeneric(); +    if (generic) +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error); +        if (script_error) +            should_step = true; +    } +    if (should_step) +        return lldb::eStateStepping; +    else +        return lldb::eStateRunning; +} + +StructuredData::ObjectSP +ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) +{ +    if (!file_spec.Exists()) +    { +        error.SetErrorString("no such file"); +        return StructuredData::ObjectSP(); +    } + +    StructuredData::ObjectSP module_sp; + +    if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp)) +        return module_sp; + +    return StructuredData::ObjectSP(); +} + +StructuredData::DictionarySP +ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, +                                            lldb_private::Error &error) +{ +    if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get) +        return StructuredData::DictionarySP(); +    StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric(); +    if (!generic) +        return StructuredData::DictionarySP(); + +    PythonObject reply_pyobj; +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        TargetSP target_sp(target->shared_from_this()); +        reply_pyobj.Reset(PyRefType::Owned, +                          (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp)); +    } + +    PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get()); +    return py_dict.CreateStructuredDictionary(); +} + +StructuredData::ObjectSP +ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) +{ +    if (class_name == nullptr || class_name[0] == '\0') +        return StructuredData::ObjectSP(); + +    if (!valobj.get()) +        return StructuredData::ObjectSP(); + +    ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); +    Target *target = exe_ctx.GetTargetPtr(); +     +    if (!target) +        return StructuredData::ObjectSP(); + +    Debugger &debugger = target->GetDebugger(); +    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); +    ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; +     +    if (!script_interpreter) +        return StructuredData::ObjectSP(); + +    void *ret_val = nullptr; + +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_synthetic_script (class_name, +                                           python_interpreter->m_dictionary_name.c_str(), +                                           valobj); +    } + +    return StructuredData::ObjectSP(new StructuredPythonObject(ret_val)); +} + +StructuredData::GenericSP +ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name) +{ +    DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this()); +     +    if (class_name == nullptr || class_name[0] == '\0') +        return StructuredData::GenericSP(); +     +    if (!debugger_sp.get()) +        return StructuredData::GenericSP(); +     +    void* ret_val; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_create_cmd (class_name, +                                     m_dictionary_name.c_str(), +                                     debugger_sp); +    } +     +    return StructuredData::GenericSP(new StructuredPythonObject(ret_val)); +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token) +{ +    StringList input; +    input.SplitIntoLines(oneliner, strlen(oneliner)); +    return GenerateTypeScriptFunction(input, output, name_token); +} + +bool +ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token) +{ +    StringList input; +    input.SplitIntoLines(oneliner, strlen(oneliner)); +    return GenerateTypeSynthClass(input, output, name_token); +} + + +Error +ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output) +{ +    static uint32_t num_created_functions = 0; +    user_input.RemoveBlankLines (); +    StreamString sstr; +    Error error; +    if (user_input.GetSize() == 0) +    { +        error.SetErrorString("No input data."); +        return error; +    } + +    std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions)); +    sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); +     +    error = GenerateFunction(sstr.GetData(), user_input); +    if (!error.Success()) +        return error; +     +    // Store the name of the auto-generated function to be called. +    output.assign(auto_generated_function_name); +    return error; +} + +bool +ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output) +{ +    static uint32_t num_created_functions = 0; +    user_input.RemoveBlankLines (); +    StreamString sstr; + +    if (user_input.GetSize() == 0) +        return false; + +    std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions)); +    sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); +     +    if (!GenerateFunction(sstr.GetData(), user_input).Success()) +        return false; +     +    // Store the name of the auto-generated function to be called. +    output.assign(auto_generated_function_name); +    return true; +} + +bool +ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj, +                                            StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options, +                                            std::string &retval) +{ +     +    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); +     +    if (!valobj.get()) +    { +        retval.assign("<no object>"); +        return false; +    } + +    void *old_callee = nullptr; +    StructuredData::Generic *generic = nullptr; +    if (callee_wrapper_sp) +    { +        generic = callee_wrapper_sp->GetAsGeneric(); +        if (generic) +            old_callee = generic->GetValue(); +    } +    void* new_callee = old_callee; +     +    bool ret_val; +    if (python_function_name && *python_function_name) +    { +        { +            Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +            { +                TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options)); +                 +                Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback"); +                ret_val = g_swig_typescript_callback (python_function_name, +                                                      GetSessionDictionary().get(), +                                                      valobj, +                                                      &new_callee, +                                                      options_sp, +                                                      retval); +            } +        } +    } +    else +    { +        retval.assign("<no function name>"); +        return false; +    } +     +    if (new_callee && old_callee != new_callee) +        callee_wrapper_sp.reset(new StructuredPythonObject(new_callee)); + +    return ret_val; +} + +void +ScriptInterpreterPython::Clear () +{ +    // Release any global variables that might have strong references to +    // LLDB objects when clearing the python script interpreter. +    Locker locker(this, +                  ScriptInterpreterPython::Locker::AcquireLock, +                  ScriptInterpreterPython::Locker::FreeAcquiredLock); + +    // This may be called as part of Py_Finalize.  In that case the modules are destroyed in random +    // order and we can't guarantee that we can access these. +    if (Py_IsInitialized()) +        PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None"); +} + +bool +ScriptInterpreterPython::BreakpointCallbackFunction  +( +    void *baton, +    StoppointCallbackContext *context, +    user_id_t break_id, +    user_id_t break_loc_id +) +{ +    BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton; +    const char *python_function_name = bp_option_data->script_source.c_str(); + +    if (!context) +        return true; +         +    ExecutionContext exe_ctx (context->exe_ctx_ref); +    Target *target = exe_ctx.GetTargetPtr(); +     +    if (!target) +        return true; +         +    Debugger &debugger = target->GetDebugger(); +    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); +    ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; +     +    if (!script_interpreter) +        return true; +     +    if (python_function_name && python_function_name[0]) +    { +        const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); +        BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id); +        if (breakpoint_sp) +        { +            const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id)); + +            if (stop_frame_sp && bp_loc_sp) +            { +                bool ret_val = true; +                { +                    Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +                    ret_val = g_swig_breakpoint_callback (python_function_name, +                                                          python_interpreter->m_dictionary_name.c_str(), +                                                          stop_frame_sp,  +                                                          bp_loc_sp); +                } +                return ret_val; +            } +        } +    } +    // We currently always true so we stop in case anything goes wrong when +    // trying to call the script function +    return true; +} + +bool +ScriptInterpreterPython::WatchpointCallbackFunction  +( +    void *baton, +    StoppointCallbackContext *context, +    user_id_t watch_id +) +{ +    WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton; +    const char *python_function_name = wp_option_data->script_source.c_str(); + +    if (!context) +        return true; +         +    ExecutionContext exe_ctx (context->exe_ctx_ref); +    Target *target = exe_ctx.GetTargetPtr(); +     +    if (!target) +        return true; +         +    Debugger &debugger = target->GetDebugger(); +    ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); +    ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; +     +    if (!script_interpreter) +        return true; +     +    if (python_function_name && python_function_name[0]) +    { +        const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP()); +        WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id); +        if (wp_sp) +        { +            if (stop_frame_sp && wp_sp) +            { +                bool ret_val = true; +                { +                    Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +                    ret_val = g_swig_watchpoint_callback (python_function_name, +                                                          python_interpreter->m_dictionary_name.c_str(), +                                                          stop_frame_sp,  +                                                          wp_sp); +                } +                return ret_val; +            } +        } +    } +    // We currently always true so we stop in case anything goes wrong when +    // trying to call the script function +    return true; +} + +size_t +ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp, uint32_t max) +{ +    if (!implementor_sp) +        return 0; +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return 0; +    void *implementor = generic->GetValue(); +    if (!implementor) +        return 0; +     +    if (!g_swig_calc_children) +        return 0; + +    size_t ret_val = 0; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_calc_children (implementor, max); +    } +     +    return ret_val; +} + +lldb::ValueObjectSP +ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx) +{ +    if (!implementor_sp) +        return lldb::ValueObjectSP(); + +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return lldb::ValueObjectSP(); +    void *implementor = generic->GetValue(); +    if (!implementor) +        return lldb::ValueObjectSP(); +     +    if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) +        return lldb::ValueObjectSP(); +     +    lldb::ValueObjectSP ret_val; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        void* child_ptr = g_swig_get_child_index (implementor,idx); +        if (child_ptr != nullptr && child_ptr != Py_None) +        { +            lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); +            if (sb_value_ptr == nullptr) +                Py_XDECREF(child_ptr); +            else +                ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); +        } +        else +        { +            Py_XDECREF(child_ptr); +        } +    } +     +    return ret_val; +} + +int +ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name) +{ +    if (!implementor_sp) +        return UINT32_MAX; + +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return UINT32_MAX; +    void *implementor = generic->GetValue(); +    if (!implementor) +        return UINT32_MAX; +     +    if (!g_swig_get_index_child) +        return UINT32_MAX; +     +    int ret_val = UINT32_MAX; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_get_index_child (implementor, child_name); +    } +     +    return ret_val; +} + +bool +ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) +{ +    bool ret_val = false; +     +    if (!implementor_sp) +        return ret_val; + +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return ret_val; +    void *implementor = generic->GetValue(); +    if (!implementor) +        return ret_val; +     +    if (!g_swig_update_provider) +        return ret_val; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_update_provider (implementor); +    } +     +    return ret_val; +} + +bool +ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp) +{ +    bool ret_val = false; +     +    if (!implementor_sp) +        return ret_val; + +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return ret_val; +    void *implementor = generic->GetValue(); +    if (!implementor) +        return ret_val; +     +    if (!g_swig_mighthavechildren_provider) +        return ret_val; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_mighthavechildren_provider (implementor); +    } +     +    return ret_val; +} + +lldb::ValueObjectSP +ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp) +{ +    lldb::ValueObjectSP ret_val(nullptr); +     +    if (!implementor_sp) +        return ret_val; + +    StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); +    if (!generic) +        return ret_val; +    void *implementor = generic->GetValue(); +    if (!implementor) +        return ret_val; +     +    if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue) +        return ret_val; +     +    { +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        void* child_ptr = g_swig_getvalue_provider (implementor); +        if (child_ptr != nullptr && child_ptr != Py_None) +        { +            lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); +            if (sb_value_ptr == nullptr) +                Py_XDECREF(child_ptr); +            else +                ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr); +        } +        else +        { +            Py_XDECREF(child_ptr); +        } +    } +     +    return ret_val; +} + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, +                                                 Process* process, +                                                 std::string& output, +                                                 Error& error) +{ +    bool ret_val; +    if (!process) +    { +        error.SetErrorString("no process"); +        return false; +    } +    if (!impl_function || !impl_function[0]) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +    if (!g_swig_run_script_keyword_process) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +    { +        ProcessSP process_sp(process->shared_from_this()); +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output); +        if (!ret_val) +            error.SetErrorString("python script evaluation failed"); +    } +    return ret_val; +} + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, +                                                 Thread* thread, +                                                 std::string& output, +                                                 Error& error) +{ +    bool ret_val; +    if (!thread) +    { +        error.SetErrorString("no thread"); +        return false; +    } +    if (!impl_function || !impl_function[0]) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +    if (!g_swig_run_script_keyword_thread) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +    { +        ThreadSP thread_sp(thread->shared_from_this()); +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output); +        if (!ret_val) +            error.SetErrorString("python script evaluation failed"); +    } +    return ret_val; +} + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, +                                                 Target* target, +                                                 std::string& output, +                                                 Error& error) +{ +    bool ret_val; +    if (!target) +    { +        error.SetErrorString("no thread"); +        return false; +    } +    if (!impl_function || !impl_function[0]) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +    if (!g_swig_run_script_keyword_target) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +    { +        TargetSP target_sp(target->shared_from_this()); +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output); +        if (!ret_val) +            error.SetErrorString("python script evaluation failed"); +    } +    return ret_val; +} + +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, +                                                 StackFrame* frame, +                                                 std::string& output, +                                                 Error& error) +{ +    bool ret_val; +    if (!frame) +    { +        error.SetErrorString("no frame"); +        return false; +    } +    if (!impl_function || !impl_function[0]) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +    if (!g_swig_run_script_keyword_frame) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +    { +        StackFrameSP frame_sp(frame->shared_from_this()); +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output); +        if (!ret_val) +            error.SetErrorString("python script evaluation failed"); +    } +    return ret_val; +} +     +bool +ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, +                                                 ValueObject *value, +                                                 std::string& output, +                                                 Error& error) +{ +    bool ret_val; +    if (!value) +    { +        error.SetErrorString("no value"); +        return false; +    } +    if (!impl_function || !impl_function[0]) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +    if (!g_swig_run_script_keyword_value) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +    { +        ValueObjectSP value_sp(value->GetSP()); +        Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); +        ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output); +        if (!ret_val) +            error.SetErrorString("python script evaluation failed"); +    } +    return ret_val; +} + +uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr) +{ +    size_t pos = 0; +    uint64_t matches = 0; +    while((pos = str.find(oldStr, pos)) != std::string::npos) +    { +        matches++; +        str.replace(pos, oldStr.length(), newStr); +        pos += newStr.length(); +    } +    return matches; +} + +bool +ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error, +                                             StructuredData::ObjectSP *module_sp) +{ +    if (!pathname || !pathname[0]) +    { +        error.SetErrorString("invalid pathname"); +        return false; +    } +     +    if (!g_swig_call_module_init) +    { +        error.SetErrorString("internal helper function missing"); +        return false; +    } +     +    lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); + +    { +        FileSpec target_file(pathname, true); +        std::string basename(target_file.GetFilename().GetCString()); +         +        StreamString command_stream; + +        // Before executing Pyton code, lock the GIL. +        Locker py_lock (this, +                        Locker::AcquireLock      | (init_session ? Locker::InitSession     : 0) | Locker::NoSTDIN, +                        Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); +         +        if (target_file.GetFileType() == FileSpec::eFileTypeInvalid || +            target_file.GetFileType() == FileSpec::eFileTypeUnknown) +        { +            // if not a valid file of any sort, check if it might be a filename still +            // dot can't be used but / and \ can, and if either is found, reject +            if (strchr(pathname,'\\') || strchr(pathname,'/')) +            { +                error.SetErrorString("invalid pathname"); +                return false; +            } +            basename = pathname; // not a filename, probably a package of some sort, let it go through +        } +        else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory || +                 target_file.GetFileType() == FileSpec::eFileTypeRegular || +                 target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink) +        { +            std::string directory(target_file.GetDirectory().GetCString()); +            replace_all(directory,"'","\\'"); +             +            // now make sure that Python has "directory" in the search path +            StreamString command_stream; +            command_stream.Printf("if not (sys.path.__contains__('%s')):\n    sys.path.insert(1,'%s');\n\n", +                                  directory.c_str(), +                                  directory.c_str()); +            bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success(); +            if (!syspath_retval) +            { +                error.SetErrorString("Python sys.path handling failed"); +                return false; +            } +             +            // strip .py or .pyc extension +            ConstString extension = target_file.GetFileNameExtension(); +            if (extension) +            { +                if (::strcmp(extension.GetCString(), "py") == 0) +                    basename.resize(basename.length()-3); +                else if(::strcmp(extension.GetCString(), "pyc") == 0) +                    basename.resize(basename.length()-4); +            } +        } +        else +        { +            error.SetErrorString("no known way to import this module specification"); +            return false; +        } +         +        // check if the module is already import-ed +        command_stream.Clear(); +        command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str()); +        bool does_contain = false; +        // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process +        // in which this LLDB framework is living +        bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(), +                                                               ScriptInterpreterPython::eScriptReturnTypeBool, +                                                               &does_contain, +                                                               ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain); +        // this call will fail if the module was not imported in this Debugger before +        command_stream.Clear(); +        command_stream.Printf("sys.getrefcount(%s)",basename.c_str()); +        bool was_imported_locally = GetSessionDictionary().GetItemForKey(PythonString(basename)).IsAllocated(); +         +        bool was_imported = (was_imported_globally || was_imported_locally); +         +        if (was_imported == true && can_reload == false) +        { +            error.SetErrorString("module already imported"); +            return false; +        } + +        // now actually do the import +        command_stream.Clear(); +         +        if (was_imported) +        { +            if (!was_imported_locally) +                command_stream.Printf("import %s ; reload_module(%s)",basename.c_str(),basename.c_str()); +            else +                command_stream.Printf("reload_module(%s)",basename.c_str()); +        } +        else +            command_stream.Printf("import %s",basename.c_str()); +         +        error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)); +        if (error.Fail()) +            return false; +         +        // if we are here, everything worked +        // call __lldb_init_module(debugger,dict) +        if (!g_swig_call_module_init (basename.c_str(), +                                      m_dictionary_name.c_str(), +                                      debugger_sp)) +        { +            error.SetErrorString("calling __lldb_init_module failed"); +            return false; +        } +         +        if (module_sp) +        { +            // everything went just great, now set the module object +            command_stream.Clear(); +            command_stream.Printf("%s",basename.c_str()); +            void* module_pyobj = nullptr; +            if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj) +                module_sp->reset(new StructuredPythonObject(module_pyobj)); +        } +         +        return true; +    } +} + +bool +ScriptInterpreterPython::IsReservedWord (const char* word) +{ +    if (!word || !word[0]) +        return false; +     +    llvm::StringRef word_sr(word); + +    // filter out a few characters that would just confuse us +    // and that are clearly not keyword material anyway +    if (word_sr.find_first_of("'\"") != llvm::StringRef::npos) +        return false; +     +    StreamString command_stream; +    command_stream.Printf("keyword.iskeyword('%s')", word); +    bool result; +    ExecuteScriptOptions options; +    options.SetEnableIO(false); +    options.SetMaskoutErrors(true); +    options.SetSetLLDBGlobals(false); +    if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options)) +        return result; +    return false; +} + +ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp, +                                                                     ScriptedCommandSynchronicity synchro) : +    m_debugger_sp(debugger_sp), +    m_synch_wanted(synchro), +    m_old_asynch(debugger_sp->GetAsyncExecution()) +{ +    if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous) +        m_debugger_sp->SetAsyncExecution(false); +    else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous) +        m_debugger_sp->SetAsyncExecution(true); +} + +ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() +{ +    if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue) +        m_debugger_sp->SetAsyncExecution(m_old_asynch); +} + +bool +ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, +                                               const char* args, +                                               ScriptedCommandSynchronicity synchronicity, +                                               lldb_private::CommandReturnObject& cmd_retobj, +                                               Error& error, +                                               const lldb_private::ExecutionContext& exe_ctx) +{ +    if (!impl_function) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +     +    if (!g_swig_call_command) +    { +        error.SetErrorString("no helper function to run scripted commands"); +        return false; +    } +     +    lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); +    lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); +     +    if (!debugger_sp.get()) +    { +        error.SetErrorString("invalid Debugger pointer"); +        return false; +   } +     +    bool ret_val = false; +     +    std::string err_msg; + +    { +        Locker py_lock(this, +                       Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), +                       Locker::FreeLock    | Locker::TearDownSession); +         +        SynchronicityHandler synch_handler(debugger_sp, +                                           synchronicity); +         +        ret_val = g_swig_call_command       (impl_function, +                                             m_dictionary_name.c_str(), +                                             debugger_sp, +                                             args, +                                             cmd_retobj, +                                             exe_ctx_ref_sp); +    } +     +    if (!ret_val) +        error.SetErrorString("unable to execute script function"); +    else +        error.Clear(); +     +    return ret_val; +} + +bool +ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, +                                                const char* args, +                                                ScriptedCommandSynchronicity synchronicity, +                                                lldb_private::CommandReturnObject& cmd_retobj, +                                                Error& error, +                                                const lldb_private::ExecutionContext& exe_ctx) +{ +    if (!impl_obj_sp || !impl_obj_sp->IsValid()) +    { +        error.SetErrorString("no function to execute"); +        return false; +    } +     +    if (!g_swig_call_command_object) +    { +        error.SetErrorString("no helper function to run scripted commands"); +        return false; +    } +     +    lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this(); +    lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); +     +    if (!debugger_sp.get()) +    { +        error.SetErrorString("invalid Debugger pointer"); +        return false; +    } +     +    bool ret_val = false; +     +    std::string err_msg; +     +    { +        Locker py_lock(this, +                       Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), +                       Locker::FreeLock    | Locker::TearDownSession); +         +        SynchronicityHandler synch_handler(debugger_sp, +                                           synchronicity); +         +        ret_val = g_swig_call_command_object      (impl_obj_sp->GetValue(), +                                                   debugger_sp, +                                                   args, +                                                   cmd_retobj, +                                                   exe_ctx_ref_sp); +    } +     +    if (!ret_val) +        error.SetErrorString("unable to execute script function"); +    else +        error.Clear(); + +    return ret_val; +} + +// in Python, a special attribute __doc__ contains the docstring +// for an object (function, method, class, ...) if any is defined +// Otherwise, the attribute's value is None +bool +ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest) +{ +	dest.clear(); +	if (!item || !*item) +		return false; +    std::string command(item); +    command += ".__doc__"; +     +    char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully +     +    if (ExecuteOneLineWithReturn (command.c_str(), +                                  ScriptInterpreter::eScriptReturnTypeCharStrOrNone, +                                  &result_ptr, +                                  ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) +    { +        if (result_ptr) +            dest.assign(result_ptr); +        return true; +    } +    else +    { +        StreamString str_stream; +        str_stream.Printf("Function %s was not found. Containing module might be missing.",item); +        dest.assign(str_stream.GetData()); +        return false; +    } +} + +bool +ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, +                                                       std::string& dest) +{ +    bool got_string = false; +    dest.clear(); +     +    Locker py_lock (this, +                    Locker::AcquireLock | Locker::NoSTDIN, +                    Locker::FreeLock); +     +    static char callee_name[] = "get_short_help"; +     +    if (!cmd_obj_sp) +        return false; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); + +    if (!implementor.IsAllocated()) +        return false; + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return false; +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +        return false; +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    if (py_return.IsAllocated() && PythonString::Check(py_return.get())) +    { +        PythonString py_string(PyRefType::Borrowed, py_return.get()); +        llvm::StringRef return_data(py_string.GetString()); +        dest.assign(return_data.data(), return_data.size()); +        got_string = true; +    } +    return got_string; +} + +uint32_t +ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) +{ +    uint32_t result = 0; +     +    Locker py_lock (this, +                    Locker::AcquireLock | Locker::NoSTDIN, +                    Locker::FreeLock); +     +    static char callee_name[] = "get_flags"; +     +    if (!cmd_obj_sp) +        return result; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); + +    if (!implementor.IsAllocated()) +        return result; + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return result; +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +        return result; +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    if (py_return.IsAllocated() && PythonInteger::Check(py_return.get())) +    { +        PythonInteger int_value(PyRefType::Borrowed, py_return.get()); +        result = int_value.GetInteger(); +    } +     +    return result; +} + +bool +ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp, +                                                      std::string& dest) +{ +    bool got_string = false; +    dest.clear(); +     +    Locker py_lock (this, +                    Locker::AcquireLock | Locker::NoSTDIN, +                    Locker::FreeLock); +     +    static char callee_name[] = "get_long_help"; +     +    if (!cmd_obj_sp) +        return false; + +    PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue()); + +    if (!implementor.IsAllocated()) +        return false; + +    PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + +    if (PyErr_Occurred()) +        PyErr_Clear(); + +    if (!pmeth.IsAllocated()) +        return false; +     +    if (PyCallable_Check(pmeth.get()) == 0) +    { +        if (PyErr_Occurred()) +            PyErr_Clear(); +         +        return false; +    } +     +    if (PyErr_Occurred()) +        PyErr_Clear(); +     +    // right now we know this function exists and is callable.. +    PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr)); + +    // if it fails, print the error but otherwise go on +    if (PyErr_Occurred()) +    { +        PyErr_Print(); +        PyErr_Clear(); +    } + +    if (py_return.IsAllocated() && PythonString::Check(py_return.get())) +    { +        PythonString str(PyRefType::Borrowed, py_return.get()); +        llvm::StringRef str_data(str.GetString()); +        dest.assign(str_data.data(), str_data.size()); +        got_string = true; +    } +     +    return got_string; +} + +std::unique_ptr<ScriptInterpreterLocker> +ScriptInterpreterPython::AcquireInterpreterLock () +{ +    std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this, +                                                                Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN, +                                                                Locker::FreeLock | Locker::TearDownSession)); +    return py_lock; +} + +void +ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback, +                                                SWIGBreakpointCallbackFunction swig_breakpoint_callback, +                                                SWIGWatchpointCallbackFunction swig_watchpoint_callback, +                                                SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, +                                                SWIGPythonCreateSyntheticProvider swig_synthetic_script, +                                                SWIGPythonCreateCommandObject swig_create_cmd, +                                                SWIGPythonCalculateNumChildren swig_calc_children, +                                                SWIGPythonGetChildAtIndex swig_get_child_index, +                                                SWIGPythonGetIndexOfChildWithName swig_get_index_child, +                                                SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , +                                                SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, +                                                SWIGPythonUpdateSynthProviderInstance swig_update_provider, +                                                SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, +                                                SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, +                                                SWIGPythonCallCommand swig_call_command, +                                                SWIGPythonCallCommandObject swig_call_command_object, +                                                SWIGPythonCallModuleInit swig_call_module_init, +                                                SWIGPythonCreateOSPlugin swig_create_os_plugin, +                                                SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, +                                                SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, +                                                SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, +                                                SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, +                                                SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, +                                                SWIGPython_GetDynamicSetting swig_plugin_get, +                                                SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, +                                                SWIGPythonCallThreadPlan swig_call_thread_plan) +{ +    g_swig_init_callback = swig_init_callback; +    g_swig_breakpoint_callback = swig_breakpoint_callback; +    g_swig_watchpoint_callback = swig_watchpoint_callback; +    g_swig_typescript_callback = swig_typescript_callback; +    g_swig_synthetic_script = swig_synthetic_script; +    g_swig_create_cmd = swig_create_cmd; +    g_swig_calc_children = swig_calc_children; +    g_swig_get_child_index = swig_get_child_index; +    g_swig_get_index_child = swig_get_index_child; +    g_swig_cast_to_sbvalue = swig_cast_to_sbvalue; +    g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue; +    g_swig_update_provider = swig_update_provider; +    g_swig_mighthavechildren_provider = swig_mighthavechildren_provider; +    g_swig_getvalue_provider = swig_getvalue_provider; +    g_swig_call_command = swig_call_command; +    g_swig_call_command_object = swig_call_command_object; +    g_swig_call_module_init = swig_call_module_init; +    g_swig_create_os_plugin = swig_create_os_plugin; +    g_swig_run_script_keyword_process = swig_run_script_keyword_process; +    g_swig_run_script_keyword_thread = swig_run_script_keyword_thread; +    g_swig_run_script_keyword_target = swig_run_script_keyword_target; +    g_swig_run_script_keyword_frame = swig_run_script_keyword_frame; +    g_swig_run_script_keyword_value = swig_run_script_keyword_value; +    g_swig_plugin_get = swig_plugin_get; +    g_swig_thread_plan_script = swig_thread_plan_script; +    g_swig_call_thread_plan = swig_call_thread_plan; +} + +void +ScriptInterpreterPython::InitializePrivate () +{ +    assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!"); +    g_initialized = true; + +    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); + +    // RAII-based initialization which correctly handles multiple-initialization, version- +    // specific differences among Python 2 and Python 3, and saving and restoring various +    // other pieces of state that can get mucked with during initialization. +    InitializePythonRAII initialize_guard; + +    if (g_swig_init_callback) +        g_swig_init_callback (); + +    // Update the path python uses to search for modules to include the current directory. + +    PyRun_SimpleString ("import sys"); +    AddToSysPath(AddLocation::End, "."); + +    FileSpec file_spec; +    // Don't denormalize paths when calling file_spec.GetPath().  On platforms that use +    // a backslash as the path separator, this will result in executing python code containing +    // paths with unescaped backslashes.  But Python also accepts forward slashes, so to make +    // life easier we just use that. +    if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec)) +        AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); +    if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec)) +        AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false)); + +    PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line"); +} + +void +ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path) +{ +    std::string path_copy; + +    std::string statement; +    if (location == AddLocation::Beginning) +    { +        statement.assign("sys.path.insert(0,\""); +        statement.append (path); +        statement.append ("\")"); +    } +    else +    { +        statement.assign("sys.path.append(\""); +        statement.append(path); +        statement.append("\")"); +    } +    PyRun_SimpleString (statement.c_str()); +} + + +//void +//ScriptInterpreterPython::Terminate () +//{ +//    // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it).  Calling +//    // Py_Finalize here causes test suite runs to seg fault:  The test suite runs in Python.  It registers  +//    // SBDebugger::Terminate to be called 'at_exit'.  When the test suite Python harness finishes up, it calls  +//    // Py_Finalize, which calls all the 'at_exit' registered functions.  SBDebugger::Terminate calls Debugger::Terminate, +//    // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls  +//    // ScriptInterpreterPython::Terminate.  So if we call Py_Finalize here, we end up with Py_Finalize being called from +//    // within Py_Finalize, which results in a seg fault. +//    // +//    // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't +//    // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the +//    // process exits). +//    // +////    Py_Finalize (); +//} + +#endif // #ifdef LLDB_DISABLE_PYTHON diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h new file mode 100644 index 0000000000000..4c6eb39498986 --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -0,0 +1,607 @@ +//===-- ScriptInterpreterPython.h -------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +// C Includes +// C++ Includes +#include <memory> +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "PythonDataObjects.h" +#include "lldb/Core/IOHandler.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Host/Terminal.h" + +class IOHandlerPythonInterpreter; + +namespace lldb_private { +     +class ScriptInterpreterPython : +    public ScriptInterpreter, +    public IOHandlerDelegateMultiline +{ +public: +#if PY_MAJOR_VERSION >= 3 +    typedef PyObject*(*SWIGInitCallback) (void); +#else +    typedef void(*SWIGInitCallback) (void); +#endif + +    typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name, +                                                    const char *session_dictionary_name, +                                                    const lldb::StackFrameSP& frame_sp, +                                                    const lldb::BreakpointLocationSP &bp_loc_sp); +     +    typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name, +                                                    const char *session_dictionary_name, +                                                    const lldb::StackFrameSP& frame_sp, +                                                    const lldb::WatchpointSP &wp_sp); +     +    typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, +                                                          void *session_dictionary, +                                                          const lldb::ValueObjectSP& valobj_sp, +                                                          void** pyfunct_wrapper, +                                                          const lldb::TypeSummaryOptionsSP& options, +                                                          std::string& retval); +     +    typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, +                                                        const char *session_dictionary_name, +                                                        const lldb::ValueObjectSP& valobj_sp); + +    typedef void* (*SWIGPythonCreateCommandObject) (const char *python_class_name, +                                                    const char *session_dictionary_name, +                                                    const lldb::DebuggerSP debugger_sp); +     +    typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name, +                                                        const char *session_dictionary_name, +                                                        const lldb::ThreadPlanSP& thread_plan_sp); + +    typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error); + +    typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, +                                               const char *session_dictionary_name, +                                               const lldb::ProcessSP& process_sp); +     +    typedef size_t          (*SWIGPythonCalculateNumChildren)                   (void *implementor, uint32_t max); + +    typedef void*           (*SWIGPythonGetChildAtIndex)                        (void *implementor, uint32_t idx); + +    typedef int             (*SWIGPythonGetIndexOfChildWithName)                (void *implementor, const char* child_name); + +    typedef void*           (*SWIGPythonCastPyObjectToSBValue)                  (void* data); + +    typedef lldb::ValueObjectSP  (*SWIGPythonGetValueObjectSPFromSBValue)       (void* data); + +    typedef bool            (*SWIGPythonUpdateSynthProviderInstance)            (void* data); + +    typedef bool            (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); + +    typedef void*           (*SWIGPythonGetValueSynthProviderInstance)          (void *implementor); +     +    typedef bool            (*SWIGPythonCallCommand)            (const char *python_function_name, +                                                                 const char *session_dictionary_name, +                                                                 lldb::DebuggerSP& debugger, +                                                                 const char* args, +                                                                 lldb_private::CommandReturnObject& cmd_retobj, +                                                                 lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +    typedef bool            (*SWIGPythonCallCommandObject)        (void *implementor, +                                                                   lldb::DebuggerSP& debugger, +                                                                   const char* args, +                                                                   lldb_private::CommandReturnObject& cmd_retobj, +                                                                   lldb::ExecutionContextRefSP exe_ctx_ref_sp); + +    typedef bool            (*SWIGPythonCallModuleInit)         (const char *python_module_name, +                                                                 const char *session_dictionary_name, +                                                                 lldb::DebuggerSP& debugger); +     +    typedef bool            (*SWIGPythonScriptKeyword_Process)  (const char* python_function_name, +                                                                 const char* session_dictionary_name, +                                                                 lldb::ProcessSP& process, +                                                                 std::string& output); + +    typedef bool            (*SWIGPythonScriptKeyword_Thread)   (const char* python_function_name, +                                                                 const char* session_dictionary_name, +                                                                 lldb::ThreadSP& thread, +                                                                 std::string& output); +     +    typedef bool            (*SWIGPythonScriptKeyword_Target)   (const char* python_function_name, +                                                                 const char* session_dictionary_name, +                                                                 lldb::TargetSP& target, +                                                                 std::string& output); + +    typedef bool            (*SWIGPythonScriptKeyword_Frame)    (const char* python_function_name, +                                                                 const char* session_dictionary_name, +                                                                 lldb::StackFrameSP& frame, +                                                                 std::string& output); + +    typedef bool            (*SWIGPythonScriptKeyword_Value)    (const char* python_function_name, +                                                                 const char* session_dictionary_name, +                                                                 lldb::ValueObjectSP& value, +                                                                 std::string& output); +     +    typedef void*           (*SWIGPython_GetDynamicSetting)     (void* module, +                                                                 const char* setting, +                                                                 const lldb::TargetSP& target_sp); + +    friend class ::IOHandlerPythonInterpreter; + +    ScriptInterpreterPython (CommandInterpreter &interpreter); + +    ~ScriptInterpreterPython() override; + +    bool +    Interrupt() override; + +    bool +    ExecuteOneLine (const char *command, +                    CommandReturnObject *result, +                    const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + +    void +    ExecuteInterpreterLoop () override; + +    bool +    ExecuteOneLineWithReturn (const char *in_string,  +                              ScriptInterpreter::ScriptReturnType return_type, +                              void *ret_value, +                              const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + +    lldb_private::Error +    ExecuteMultipleLines (const char *in_string, +                          const ExecuteScriptOptions &options = ExecuteScriptOptions()) override; + +    Error +    ExportFunctionDefinitionToInterpreter (StringList &function_def) override; + +    bool +    GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr) override; +     +    bool +    GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr) override; +     +    bool +    GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr) override; +     +    // use this if the function code is just a one-liner script +    bool +    GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr) override; +     +    bool +    GenerateScriptAliasFunction (StringList &input, std::string& output) override; + +    StructuredData::ObjectSP CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override; + +    StructuredData::GenericSP CreateScriptCommandObject (const char *class_name) override; + +    StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override; + +    bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; + +    bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; + +    lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override; + +    StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override; + +    StructuredData::DictionarySP OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + +    StructuredData::ArraySP OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override; + +    StructuredData::StringSP OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) override; + +    StructuredData::DictionarySP OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, +                                                       lldb::addr_t context) override; + +    StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) override; + +    StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, +                                                    lldb_private::Error &error) override; + +    size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) override; + +    lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override; + +    int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) override; + +    bool UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; + +    bool MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) override; + +    lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; + +    bool +    RunScriptBasedCommand(const char* impl_function, +                          const char* args, +                          ScriptedCommandSynchronicity synchronicity, +                          lldb_private::CommandReturnObject& cmd_retobj, +                          Error& error, +                          const lldb_private::ExecutionContext& exe_ctx) override; +     +    bool +    RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp, +                           const char* args, +                           ScriptedCommandSynchronicity synchronicity, +                           lldb_private::CommandReturnObject& cmd_retobj, +                           Error& error, +                           const lldb_private::ExecutionContext& exe_ctx) override; +     +    Error +    GenerateFunction(const char *signature, const StringList &input) override; +     +    Error +    GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) override; + +    bool +    GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) override; + +//    static size_t +//    GenerateBreakpointOptionsCommandCallback (void *baton,  +//                                              InputReader &reader,  +//                                              lldb::InputReaderAction notification, +//                                              const char *bytes,  +//                                              size_t bytes_len); +//     +//    static size_t +//    GenerateWatchpointOptionsCommandCallback (void *baton,  +//                                              InputReader &reader,  +//                                              lldb::InputReaderAction notification, +//                                              const char *bytes,  +//                                              size_t bytes_len); +     +    static bool +    BreakpointCallbackFunction (void *baton,  +                                StoppointCallbackContext *context,  +                                lldb::user_id_t break_id, +                                lldb::user_id_t break_loc_id); +     +    static bool +    WatchpointCallbackFunction (void *baton,  +                                StoppointCallbackContext *context,  +                                lldb::user_id_t watch_id); + +    bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, +                            const TypeSummaryOptions &options, std::string &retval) override; + +    void +    Clear () override; + +    bool +    GetDocumentationForItem (const char* item, std::string& dest) override; +     +    bool +    GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; +     +    uint32_t +    GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) override; +     +    bool +    GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override; +     +    bool +    CheckObjectExists (const char* name) override +    { +        if (!name || !name[0]) +            return false; +        std::string temp; +        return GetDocumentationForItem (name,temp); +    } +     +    bool +    RunScriptFormatKeyword (const char* impl_function, +                            Process* process, +                            std::string& output, +                            Error& error) override; + +    bool +    RunScriptFormatKeyword (const char* impl_function, +                            Thread* thread, +                            std::string& output, +                            Error& error) override; +     +    bool +    RunScriptFormatKeyword (const char* impl_function, +                            Target* target, +                            std::string& output, +                            Error& error) override; +     +    bool +    RunScriptFormatKeyword (const char* impl_function, +                            StackFrame* frame, +                            std::string& output, +                            Error& error) override; +     +    bool +    RunScriptFormatKeyword (const char* impl_function, +                            ValueObject* value, +                            std::string& output, +                            Error& error) override; + +    bool LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error, +                             StructuredData::ObjectSP *module_sp = nullptr) override; + +    bool +    IsReservedWord (const char* word) override; + +    std::unique_ptr<ScriptInterpreterLocker> +    AcquireInterpreterLock () override; +     +    void +    CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec, +                                             CommandReturnObject &result) override; + +    void  +    CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, +                                             CommandReturnObject &result) override; + +    /// Set the callback body text into the callback for the breakpoint. +    Error +    SetBreakpointCommandCallback (BreakpointOptions *bp_options, +                                  const char *callback_body) override; + +    void  +    SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options, +                                          const char *function_name) override; + +    /// Set a one-liner as the callback for the watchpoint. +    void  +    SetWatchpointCommandCallback (WatchpointOptions *wp_options, +                                  const char *oneliner) override; + +    StringList +    ReadCommandInputFromUser (FILE *in_file); + +    void ResetOutputFileHandle(FILE *new_fh) override; + +    static void +    InitializePrivate (); + +    static void +    InitializeInterpreter (SWIGInitCallback python_swig_init_callback, +                           SWIGBreakpointCallbackFunction swig_breakpoint_callback, +                           SWIGWatchpointCallbackFunction swig_watchpoint_callback, +                           SWIGPythonTypeScriptCallbackFunction swig_typescript_callback, +                           SWIGPythonCreateSyntheticProvider swig_synthetic_script, +                           SWIGPythonCreateCommandObject swig_create_cmd, +                           SWIGPythonCalculateNumChildren swig_calc_children, +                           SWIGPythonGetChildAtIndex swig_get_child_index, +                           SWIGPythonGetIndexOfChildWithName swig_get_index_child, +                           SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue , +                           SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue, +                           SWIGPythonUpdateSynthProviderInstance swig_update_provider, +                           SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider, +                           SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider, +                           SWIGPythonCallCommand swig_call_command, +                           SWIGPythonCallCommandObject swig_call_command_object, +                           SWIGPythonCallModuleInit swig_call_module_init, +                           SWIGPythonCreateOSPlugin swig_create_os_plugin, +                           SWIGPythonScriptKeyword_Process swig_run_script_keyword_process, +                           SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread, +                           SWIGPythonScriptKeyword_Target swig_run_script_keyword_target, +                           SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame, +                           SWIGPythonScriptKeyword_Value swig_run_script_keyword_value, +                           SWIGPython_GetDynamicSetting swig_plugin_get, +                           SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script, +                           SWIGPythonCallThreadPlan swig_call_thread_plan); + +    const char * +    GetDictionaryName () +    { +        return m_dictionary_name.c_str(); +    } + +    PyThreadState * +    GetThreadState() +    { +        return m_command_thread_state; +    } + +    void +    SetThreadState (PyThreadState *s) +    { +        if (s) +            m_command_thread_state = s; +    } + +    //---------------------------------------------------------------------- +    // IOHandlerDelegate +    //---------------------------------------------------------------------- +    void +    IOHandlerActivated (IOHandler &io_handler) override; + +    void +    IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override; + +    //------------------------------------------------------------------ +    // Static Functions +    //------------------------------------------------------------------ +    static void +    Initialize(); +     +    static void +    Terminate(); +     +    static lldb::ScriptInterpreterSP +    CreateInstance(CommandInterpreter &interpreter); +     +    static lldb_private::ConstString +    GetPluginNameStatic(); +     +    static const char * +    GetPluginDescriptionStatic(); +     +    //------------------------------------------------------------------ +    // PluginInterface protocol +    //------------------------------------------------------------------ +    lldb_private::ConstString +    GetPluginName() override; +     +    uint32_t +    GetPluginVersion() override; + +    class Locker : public ScriptInterpreterLocker +    { +    public: +        enum OnEntry +        { +            AcquireLock         = 0x0001, +            InitSession         = 0x0002, +            InitGlobals         = 0x0004, +            NoSTDIN             = 0x0008 +        }; +         +        enum OnLeave +        { +            FreeLock            = 0x0001, +            FreeAcquiredLock    = 0x0002,    // do not free the lock if we already held it when calling constructor +            TearDownSession     = 0x0004 +        }; +         +        Locker(ScriptInterpreterPython *py_interpreter = nullptr, +               uint16_t on_entry = AcquireLock | InitSession, +               uint16_t on_leave = FreeLock | TearDownSession, +               FILE *in = nullptr, +               FILE *out = nullptr, +               FILE *err = nullptr); +         +        ~Locker () override; + +    private: +        bool +        DoAcquireLock (); +         +        bool +        DoInitSession (uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err); +         +        bool +        DoFreeLock (); +         +        bool +        DoTearDownSession (); + +        static void +        ReleasePythonLock (); +         +    	bool                     m_teardown_session; +    	ScriptInterpreterPython *m_python_interpreter; +//    	FILE*                    m_tmp_fh; +        PyGILState_STATE         m_GILState; +    }; + +protected: +    class SynchronicityHandler +    { +    private: +        lldb::DebuggerSP             m_debugger_sp; +        ScriptedCommandSynchronicity m_synch_wanted; +        bool                         m_old_asynch; + +    public: +        SynchronicityHandler(lldb::DebuggerSP, +                             ScriptedCommandSynchronicity); + +        ~SynchronicityHandler(); +    }; +     +    enum class AddLocation +    { +        Beginning, +        End +    }; + +    static void AddToSysPath(AddLocation location, std::string path); + +    bool +    EnterSession(uint16_t on_entry_flags, +                 FILE *in, +                 FILE *out, +                 FILE *err); + +    void +    LeaveSession(); + +    void +    SaveTerminalState(int fd); + +    void +    RestoreTerminalState(); + +    uint32_t +    IsExecutingPython () const +    { +        return m_lock_count > 0; +    } + +    uint32_t +    IncrementLockCount() +    { +        return ++m_lock_count; +    } + +    uint32_t +    DecrementLockCount() +    { +        if (m_lock_count > 0) +            --m_lock_count; +        return m_lock_count; +    } + +    enum ActiveIOHandler { +        eIOHandlerNone, +        eIOHandlerBreakpoint, +        eIOHandlerWatchpoint +    }; + +    PythonObject &GetMainModule(); + +    PythonDictionary & +    GetSessionDictionary (); +     +    PythonDictionary & +    GetSysModuleDictionary (); + +    bool +    GetEmbeddedInterpreterModuleObjects (); + +    PythonFile m_saved_stdin; +    PythonFile m_saved_stdout; +    PythonFile m_saved_stderr; +    PythonObject m_main_module; +    PythonObject m_lldb_module; +    PythonDictionary m_session_dict; +    PythonDictionary m_sys_module_dict; +    PythonObject m_run_one_line_function; +    PythonObject m_run_one_line_str_global; +    std::string m_dictionary_name; +    TerminalState m_terminal_state; +    ActiveIOHandler m_active_io_handler; +    bool m_session_is_active; +    bool m_pty_slave_is_open; +    bool m_valid_session; +    uint32_t m_lock_count; +    PyThreadState *m_command_thread_state; +}; + +} // namespace lldb_private + +#endif // LLDB_DISABLE_PYTHON + +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H diff --git a/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/source/Plugins/ScriptInterpreter/Python/lldb-python.h new file mode 100644 index 0000000000000..013492c39bf80 --- /dev/null +++ b/source/Plugins/ScriptInterpreter/Python/lldb-python.h @@ -0,0 +1,31 @@ +//===-- lldb-python.h --------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H + +// Python.h needs to be included before any system headers in order to avoid redefinition of macros + +#ifdef LLDB_DISABLE_PYTHON +// Python is disabled in this build +#else +#if defined(__linux__) +// features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined.  This value +// may be different from the value that Python defines it to be which results +// in a warning.  Undefine _POSIX_C_SOURCE before including Python.h  The same +// holds for _XOPEN_SOURCE. +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE +#endif + +// Include python for non windows machines +#include <Python.h> +#endif // LLDB_DISABLE_PYTHON + +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp new file mode 100644 index 0000000000000..c0754a1fdd542 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -0,0 +1,56 @@ +//===-- DIERef.cpp ----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DIERef.h" +#include "DWARFCompileUnit.h" +#include "DWARFFormValue.h" + +DIERef::DIERef() : +    cu_offset(DW_INVALID_OFFSET), +    die_offset(DW_INVALID_OFFSET) +{} + +DIERef::DIERef(dw_offset_t d) : +    cu_offset(DW_INVALID_OFFSET), +    die_offset(d) +{} + +DIERef::DIERef(dw_offset_t c, dw_offset_t d) : +    cu_offset(c), +    die_offset(d) +{} + +DIERef::DIERef(lldb::user_id_t uid) : +    cu_offset(uid>>32), +    die_offset(uid&0xffffffff) +{} + +DIERef::DIERef(const DWARFFormValue& form_value) : +    cu_offset(DW_INVALID_OFFSET), +    die_offset(DW_INVALID_OFFSET) +{ +    if (form_value.IsValid()) +    { +        const DWARFCompileUnit* dwarf_cu = form_value.GetCompileUnit(); +        if (dwarf_cu) +        { +            if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) +                cu_offset = dwarf_cu->GetBaseObjOffset(); +            else +                cu_offset = dwarf_cu->GetOffset(); +        } +        die_offset = form_value.Reference(); +    } +} + +lldb::user_id_t +DIERef::GetUID() const +{ +    return ((lldb::user_id_t)cu_offset) << 32 | die_offset; +} diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.h b/source/Plugins/SymbolFile/DWARF/DIERef.h new file mode 100644 index 0000000000000..a5484db6bd6c9 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -0,0 +1,42 @@ +//===-- DIERef.h ------------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DIERef_h_ +#define SymbolFileDWARF_DIERef_h_ + +#include "lldb/Core/dwarf.h" +#include "lldb/lldb-defines.h" + +class DWARFFormValue; + +struct DIERef +{ +    DIERef(); + +    explicit +    DIERef(dw_offset_t d); + +    DIERef(dw_offset_t c, dw_offset_t d); + +    explicit +    DIERef(lldb::user_id_t uid); + +    explicit +    DIERef(const DWARFFormValue& form_value); + +    lldb::user_id_t +    GetUID() const; + +    dw_offset_t cu_offset; +    dw_offset_t die_offset; +}; + +typedef std::vector<DIERef> DIEArray; + +#endif  // SymbolFileDWARF_DIERef_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h new file mode 100644 index 0000000000000..ab20844bfcfde --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -0,0 +1,65 @@ +//===-- DWARFASTParser.h ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParser_h_ +#define SymbolFileDWARF_DWARFASTParser_h_ + +#include "DWARFDefines.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" + +class DWARFDIE; + +class DWARFASTParser +{ +public: +    virtual ~DWARFASTParser() {} + +    virtual lldb::TypeSP +    ParseTypeFromDWARF (const lldb_private::SymbolContext& sc, +                        const DWARFDIE &die, +                        lldb_private::Log *log, +                        bool *type_is_new_ptr) = 0; + +    virtual lldb_private::Function * +    ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc, +                            const DWARFDIE &die) = 0; + +    virtual bool +    CanCompleteType (const lldb_private::CompilerType &compiler_type) +    { +        return false; +    } + +    virtual bool +    CompleteType (const lldb_private::CompilerType &compiler_type) +    { +        return false; +    } + +    virtual bool +    CompleteTypeFromDWARF (const DWARFDIE &die, +                           lldb_private::Type *type, +                           lldb_private::CompilerType &compiler_type) = 0; + +    virtual lldb_private::CompilerDecl +    GetDeclForUIDFromDWARF (const DWARFDIE &die) = 0; + +    virtual lldb_private::CompilerDeclContext +    GetDeclContextForUIDFromDWARF (const DWARFDIE &die) = 0; + +    virtual lldb_private::CompilerDeclContext +    GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0; + +    virtual std::vector<DWARFDIE> +    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0; +}; + +#endif  // SymbolFileDWARF_DWARFASTParser_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp new file mode 100644 index 0000000000000..68a0285b69dfe --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -0,0 +1,4034 @@ +//===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserClang.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" +#include "DWARFDeclContext.h" +#include "DWARFDefines.h" +#include "DWARFDIE.h" +#include "DWARFDIECollection.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDebugMap.h" +#include "UniqueDWARFASTType.h" + +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Value.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/TypeMap.h" +#include "lldb/Target/Language.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +#include <map> +#include <vector> + +//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN + +#ifdef ENABLE_DEBUG_PRINTF +#include <stdio.h> +#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + + +using namespace lldb; +using namespace lldb_private; +DWARFASTParserClang::DWARFASTParserClang (ClangASTContext &ast) : +    m_ast (ast), +    m_die_to_decl_ctx (), +    m_decl_ctx_to_die () +{ +} + +DWARFASTParserClang::~DWARFASTParserClang () +{ +} + + +static AccessType +DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility) +{ +    switch (dwarf_accessibility) +    { +        case DW_ACCESS_public:      return eAccessPublic; +        case DW_ACCESS_private:     return eAccessPrivate; +        case DW_ACCESS_protected:   return eAccessProtected; +        default:                    break; +    } +    return eAccessNone; +} + +static bool +DeclKindIsCXXClass (clang::Decl::Kind decl_kind) +{ +    switch (decl_kind) +    { +        case clang::Decl::CXXRecord: +        case clang::Decl::ClassTemplateSpecialization: +            return true; +        default: +            break; +    } +    return false; +} + +struct BitfieldInfo +{ +    uint64_t bit_size; +    uint64_t bit_offset; + +    BitfieldInfo () : +    bit_size (LLDB_INVALID_ADDRESS), +    bit_offset (LLDB_INVALID_ADDRESS) +    { +    } + +    void +    Clear() +    { +        bit_size = LLDB_INVALID_ADDRESS; +        bit_offset = LLDB_INVALID_ADDRESS; +    } + +    bool IsValid () +    { +        return (bit_size != LLDB_INVALID_ADDRESS) && +        (bit_offset != LLDB_INVALID_ADDRESS); +    } +}; + + +ClangASTImporter & +DWARFASTParserClang::GetClangASTImporter() +{ +    if (!m_clang_ast_importer_ap) +    { +        m_clang_ast_importer_ap.reset (new ClangASTImporter); +    } +    return *m_clang_ast_importer_ap; +} + + +TypeSP +DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log) +{ +    ModuleSP dwo_module_sp = die.GetContainingDWOModule(); +    if (dwo_module_sp) +    { +        // This type comes from an external DWO module +        std::vector<CompilerContext> dwo_context; +        die.GetDWOContext(dwo_context); +        TypeMap dwo_types; +        if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types)) +        { +            const size_t num_dwo_types = dwo_types.GetSize(); +            if (num_dwo_types == 1) +            { +                // We found a real definition for this type elsewhere +                // so lets use it and cache the fact that we found +                // a complete type for this die +                TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0); +                if (dwo_type_sp) +                { +                    lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType(); + +                    lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type); + +                    //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString()); +                    if (type) +                    { +                        SymbolFileDWARF *dwarf = die.GetDWARF(); +                        TypeSP type_sp (new Type (die.GetID(), +                                                  dwarf, +                                                  dwo_type_sp->GetName(), +                                                  dwo_type_sp->GetByteSize(), +                                                  NULL, +                                                  LLDB_INVALID_UID, +                                                  Type::eEncodingInvalid, +                                                  &dwo_type_sp->GetDeclaration(), +                                                  type, +                                                  Type::eResolveStateForward)); + +                        dwarf->GetTypeList()->Insert(type_sp); +                        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                        clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type); +                        if (tag_decl) +                            LinkDeclContextToDIE(tag_decl, die); +                        else +                        { +                            clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die); +                            if (defn_decl_ctx) +                                LinkDeclContextToDIE(defn_decl_ctx, die); +                        } +                        return type_sp; +                    } +                } +            } +        } +    } +    return TypeSP(); +} + +TypeSP +DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, +                                         const DWARFDIE &die, +                                         Log *log, +                                         bool *type_is_new_ptr) +{ +    TypeSP type_sp; + +    if (type_is_new_ptr) +        *type_is_new_ptr = false; + +    AccessType accessibility = eAccessNone; +    if (die) +    { +        SymbolFileDWARF *dwarf = die.GetDWARF(); +        if (log) +        { +            DWARFDIE context_die; +            clang::DeclContext *context = GetClangDeclContextContainingDIE (die, &context_die); + +            dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')", +                                                             die.GetOffset(), +                                                             static_cast<void*>(context), +                                                             context_die.GetOffset(), +                                                             die.GetTagAsCString(), +                                                             die.GetName()); + +        } +        // +        //        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); +        //        if (log && dwarf_cu) +        //        { +        //            StreamString s; +        //            die->DumpLocation (this, dwarf_cu, s); +        //            dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); +        // +        //        } + +        Type *type_ptr = dwarf->GetDIEToType().lookup (die.GetDIE()); +        TypeList* type_list = dwarf->GetTypeList(); +        if (type_ptr == NULL) +        { +            if (type_is_new_ptr) +                *type_is_new_ptr = true; + +            const dw_tag_t tag = die.Tag(); + +            bool is_forward_declaration = false; +            DWARFAttributes attributes; +            const char *type_name_cstr = NULL; +            ConstString type_name_const_str; +            Type::ResolveState resolve_state = Type::eResolveStateUnresolved; +            uint64_t byte_size = 0; +            Declaration decl; + +            Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; +            CompilerType clang_type; +            DWARFFormValue form_value; + +            dw_attr_t attr; + +            switch (tag) +            { +                case DW_TAG_base_type: +                case DW_TAG_pointer_type: +                case DW_TAG_reference_type: +                case DW_TAG_rvalue_reference_type: +                case DW_TAG_typedef: +                case DW_TAG_const_type: +                case DW_TAG_restrict_type: +                case DW_TAG_volatile_type: +                case DW_TAG_unspecified_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    const size_t num_attributes = die.GetAttributes (attributes); +                    uint32_t encoding = 0; +                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                    case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                    case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                    case DW_AT_name: + +                                        type_name_cstr = form_value.AsCString(); +                                        // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't +                                        // include the "&"... +                                        if (tag == DW_TAG_reference_type) +                                        { +                                            if (strchr (type_name_cstr, '&') == NULL) +                                                type_name_cstr = NULL; +                                        } +                                        if (type_name_cstr) +                                            type_name_const_str.SetCString(type_name_cstr); +                                        break; +                                    case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break; +                                    case DW_AT_encoding:    encoding = form_value.Unsigned(); break; +                                    case DW_AT_type:        encoding_uid = DIERef(form_value).GetUID(); break; +                                    default: +                                    case DW_AT_sibling: +                                        break; +                                } +                            } +                        } +                    } + +                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); + +                    switch (tag) +                    { +                        default: +                            break; + +                        case DW_TAG_unspecified_type: +                            if (strcmp(type_name_cstr, "nullptr_t") == 0 || +                                strcmp(type_name_cstr, "decltype(nullptr)") == 0 ) +                            { +                                resolve_state = Type::eResolveStateFull; +                                clang_type = m_ast.GetBasicType(eBasicTypeNullPtr); +                                break; +                            } +                            // Fall through to base type below in case we can handle the type there... + +                        case DW_TAG_base_type: +                            resolve_state = Type::eResolveStateFull; +                            clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, +                                                                                         encoding, +                                                                                         byte_size * 8); +                            break; + +                        case DW_TAG_pointer_type:           encoding_data_type = Type::eEncodingIsPointerUID;           break; +                        case DW_TAG_reference_type:         encoding_data_type = Type::eEncodingIsLValueReferenceUID;   break; +                        case DW_TAG_rvalue_reference_type:  encoding_data_type = Type::eEncodingIsRValueReferenceUID;   break; +                        case DW_TAG_typedef:                encoding_data_type = Type::eEncodingIsTypedefUID;           break; +                        case DW_TAG_const_type:             encoding_data_type = Type::eEncodingIsConstUID;             break; +                        case DW_TAG_restrict_type:          encoding_data_type = Type::eEncodingIsRestrictUID;          break; +                        case DW_TAG_volatile_type:          encoding_data_type = Type::eEncodingIsVolatileUID;          break; +                    } + +                    if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) +                    { +                        bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); + +                        if (translation_unit_is_objc) +                        { +                            if (type_name_cstr != NULL) +                            { +                                static ConstString g_objc_type_name_id("id"); +                                static ConstString g_objc_type_name_Class("Class"); +                                static ConstString g_objc_type_name_selector("SEL"); + +                                if (type_name_const_str == g_objc_type_name_id) +                                { +                                    if (log) +                                        dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                         "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", +                                                                                         die.GetOffset(), +                                                                                         die.GetTagAsCString(), +                                                                                         die.GetName()); +                                    clang_type = m_ast.GetBasicType(eBasicTypeObjCID); +                                    encoding_data_type = Type::eEncodingIsUID; +                                    encoding_uid = LLDB_INVALID_UID; +                                    resolve_state = Type::eResolveStateFull; + +                                } +                                else if (type_name_const_str == g_objc_type_name_Class) +                                { +                                    if (log) +                                        dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                         "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.", +                                                                                         die.GetOffset(), +                                                                                         die.GetTagAsCString(), +                                                                                         die.GetName()); +                                    clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); +                                    encoding_data_type = Type::eEncodingIsUID; +                                    encoding_uid = LLDB_INVALID_UID; +                                    resolve_state = Type::eResolveStateFull; +                                } +                                else if (type_name_const_str == g_objc_type_name_selector) +                                { +                                    if (log) +                                        dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                         "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", +                                                                                         die.GetOffset(), +                                                                                         die.GetTagAsCString(), +                                                                                         die.GetName()); +                                    clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); +                                    encoding_data_type = Type::eEncodingIsUID; +                                    encoding_uid = LLDB_INVALID_UID; +                                    resolve_state = Type::eResolveStateFull; +                                } +                            } +                            else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID) +                            { +                                // Clang sometimes erroneously emits id as objc_object*.  In that case we fix up the type to "id". + +                                const DWARFDIE encoding_die = die.GetDIE(encoding_uid); + +                                if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) +                                { +                                    if (const char *struct_name = encoding_die.GetName()) +                                    { +                                        if (!strcmp(struct_name, "objc_object")) +                                        { +                                            if (log) +                                                dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                                 "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.", +                                                                                                 die.GetOffset(), +                                                                                                 die.GetTagAsCString(), +                                                                                                 die.GetName()); +                                            clang_type = m_ast.GetBasicType(eBasicTypeObjCID); +                                            encoding_data_type = Type::eEncodingIsUID; +                                            encoding_uid = LLDB_INVALID_UID; +                                            resolve_state = Type::eResolveStateFull; +                                        } +                                    } +                                } +                            } +                        } +                    } + +                    type_sp.reset( new Type (die.GetID(), +                                             dwarf, +                                             type_name_const_str, +                                             byte_size, +                                             NULL, +                                             encoding_uid, +                                             encoding_data_type, +                                             &decl, +                                             clang_type, +                                             resolve_state)); + +                    dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + +                    //                  Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false); +                    //                  if (encoding_type != NULL) +                    //                  { +                    //                      if (encoding_type != DIE_IS_BEING_PARSED) +                    //                          type_sp->SetEncodingType(encoding_type); +                    //                      else +                    //                          m_indirect_fixups.push_back(type_sp.get()); +                    //                  } +                } +                    break; + +                case DW_TAG_structure_type: +                case DW_TAG_union_type: +                case DW_TAG_class_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; +                    bool byte_size_valid = false; + +                    LanguageType class_language = eLanguageTypeUnknown; +                    bool is_complete_objc_class = false; +                    //bool struct_is_class = false; +                    const size_t num_attributes = die.GetAttributes (attributes); +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_decl_file: +                                        if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid()) +                                        { +                                            // llvm-gcc outputs invalid DW_AT_decl_file attributes that always +                                            // point to the compile unit file, so we clear this invalid value +                                            // so that we can still unique types efficiently. +                                            decl.SetFile(FileSpec ("<invalid>", false)); +                                        } +                                        else +                                            decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); +                                        break; + +                                    case DW_AT_decl_line: +                                        decl.SetLine(form_value.Unsigned()); +                                        break; + +                                    case DW_AT_decl_column: +                                        decl.SetColumn(form_value.Unsigned()); +                                        break; + +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_byte_size: +                                        byte_size = form_value.Unsigned(); +                                        byte_size_valid = true; +                                        break; + +                                    case DW_AT_accessibility: +                                        accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); +                                        break; + +                                    case DW_AT_declaration: +                                        is_forward_declaration = form_value.Boolean(); +                                        break; + +                                    case DW_AT_APPLE_runtime_class: +                                        class_language = (LanguageType)form_value.Signed(); +                                        break; + +                                    case DW_AT_APPLE_objc_complete_type: +                                        is_complete_objc_class = form_value.Signed(); +                                        break; + +                                    case DW_AT_allocated: +                                    case DW_AT_associated: +                                    case DW_AT_data_location: +                                    case DW_AT_description: +                                    case DW_AT_start_scope: +                                    case DW_AT_visibility: +                                    default: +                                    case DW_AT_sibling: +                                        break; +                                } +                            } +                        } +                    } + +                    // UniqueDWARFASTType is large, so don't create a local variables on the +                    // stack, put it on the heap. This function is often called recursively +                    // and clang isn't good and sharing the stack space for variables in different blocks. +                    std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); + +                    if (type_name_const_str) +                    { +                        LanguageType die_language = die.GetLanguage(); +                        bool handled = false; +                        if (Language::LanguageIsCPlusPlus(die_language)) +                        { +                            std::string qualified_name; +                            if (die.GetQualifiedName(qualified_name)) +                            { +                                handled = true; +                                ConstString const_qualified_name(qualified_name); +                                if (dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die, Declaration(), +                                                                           byte_size_valid ? byte_size : -1, +                                                                           *unique_ast_entry_ap)) +                                { +                                    type_sp = unique_ast_entry_ap->m_type_sp; +                                    if (type_sp) +                                    { +                                        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                                        return type_sp; +                                    } +                                } +                            } +                        } + +                        if (!handled) +                        { +                            if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, +                                                                       byte_size_valid ? byte_size : -1, +                                                                       *unique_ast_entry_ap)) +                            { +                                type_sp = unique_ast_entry_ap->m_type_sp; +                                if (type_sp) +                                { +                                    dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                                    return type_sp; +                                } +                            } +                        } +                    } + +                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + +                    int tag_decl_kind = -1; +                    AccessType default_accessibility = eAccessNone; +                    if (tag == DW_TAG_structure_type) +                    { +                        tag_decl_kind = clang::TTK_Struct; +                        default_accessibility = eAccessPublic; +                    } +                    else if (tag == DW_TAG_union_type) +                    { +                        tag_decl_kind = clang::TTK_Union; +                        default_accessibility = eAccessPublic; +                    } +                    else if (tag == DW_TAG_class_type) +                    { +                        tag_decl_kind = clang::TTK_Class; +                        default_accessibility = eAccessPrivate; +                    } + +                    if (byte_size_valid && byte_size == 0 && type_name_cstr && +                        die.HasChildren() == false && +                        sc.comp_unit->GetLanguage() == eLanguageTypeObjC) +                    { +                        // Work around an issue with clang at the moment where +                        // forward declarations for objective C classes are emitted +                        // as: +                        //  DW_TAG_structure_type [2] +                        //  DW_AT_name( "ForwardObjcClass" ) +                        //  DW_AT_byte_size( 0x00 ) +                        //  DW_AT_decl_file( "..." ) +                        //  DW_AT_decl_line( 1 ) +                        // +                        // Note that there is no DW_AT_declaration and there are +                        // no children, and the byte size is zero. +                        is_forward_declaration = true; +                    } + +                    if (class_language == eLanguageTypeObjC || +                        class_language == eLanguageTypeObjC_plus_plus) +                    { +                        if (!is_complete_objc_class && die.Supports_DW_AT_APPLE_objc_complete_type()) +                        { +                            // We have a valid eSymbolTypeObjCClass class symbol whose +                            // name matches the current objective C class that we +                            // are trying to find and this DIE isn't the complete +                            // definition (we checked is_complete_objc_class above and +                            // know it is false), so the real definition is in here somewhere +                            type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); + +                            if (!type_sp) +                            { +                                SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); +                                if (debug_map_symfile) +                                { +                                    // We weren't able to find a full declaration in +                                    // this DWARF, see if we have a declaration anywhere +                                    // else... +                                    type_sp = debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); +                                } +                            } + +                            if (type_sp) +                            { +                                if (log) +                                { +                                    dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                     "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64, +                                                                                     static_cast<void*>(this), +                                                                                     die.GetOffset(), +                                                                                     DW_TAG_value_to_name(tag), +                                                                                     type_name_cstr, +                                                                                     type_sp->GetID()); +                                } + +                                // We found a real definition for this type elsewhere +                                // so lets use it and cache the fact that we found +                                // a complete type for this die +                                dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                                return type_sp; +                            } +                        } +                    } + + +                    if (is_forward_declaration) +                    { +                        // We have a forward declaration to a type and we need +                        // to try and find a full declaration. We look in the +                        // current type index just in case we have a forward +                        // declaration followed by an actual declarations in the +                        // DWARF. If this fails, we need to look elsewhere... +                        if (log) +                        { +                            dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                             "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", +                                                                             static_cast<void*>(this), +                                                                             die.GetOffset(), +                                                                             DW_TAG_value_to_name(tag), +                                                                             type_name_cstr); +                        } + +                        // See if the type comes from a DWO module and if so, track down that type. +                        type_sp = ParseTypeFromDWO(die, log); +                        if (type_sp) +                            return type_sp; + +                        DWARFDeclContext die_decl_ctx; +                        die.GetDWARFDeclContext(die_decl_ctx); + +                        //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); +                        type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + +                        if (!type_sp) +                        { +                            SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); +                            if (debug_map_symfile) +                            { +                                // We weren't able to find a full declaration in +                                // this DWARF, see if we have a declaration anywhere +                                // else... +                                type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); +                            } +                        } + +                        if (type_sp) +                        { +                            if (log) +                            { +                                dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                 "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, +                                                                                 static_cast<void*>(this), +                                                                                 die.GetOffset(), +                                                                                 DW_TAG_value_to_name(tag), +                                                                                 type_name_cstr, +                                                                                 type_sp->GetID()); +                            } + +                            // We found a real definition for this type elsewhere +                            // so lets use it and cache the fact that we found +                            // a complete type for this die +                            dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                            clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( +                                dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID()))); +                            if (defn_decl_ctx) +                                LinkDeclContextToDIE(defn_decl_ctx, die); +                            return type_sp; +                        } +                    } +                    assert (tag_decl_kind != -1); +                    bool clang_type_was_created = false; +                    clang_type.SetCompilerType(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE())); +                    if (!clang_type) +                    { +                        clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); +                        if (accessibility == eAccessNone && decl_ctx) +                        { +                            // Check the decl context that contains this class/struct/union. +                            // If it is a class we must give it an accessibility. +                            const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); +                            if (DeclKindIsCXXClass (containing_decl_kind)) +                                accessibility = default_accessibility; +                        } + +                        ClangASTMetadata metadata; +                        metadata.SetUserID(die.GetID()); +                        metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual (die)); + +                        if (type_name_cstr && strchr (type_name_cstr, '<')) +                        { +                            ClangASTContext::TemplateParameterInfos template_param_infos; +                            if (ParseTemplateParameterInfos (die, template_param_infos)) +                            { +                                clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl (decl_ctx, +                                                                                                              accessibility, +                                                                                                              type_name_cstr, +                                                                                                              tag_decl_kind, +                                                                                                              template_param_infos); + +                                clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl (decl_ctx, +                                                                                                                                                 class_template_decl, +                                                                                                                                                 tag_decl_kind, +                                                                                                                                                 template_param_infos); +                                clang_type = m_ast.CreateClassTemplateSpecializationType (class_specialization_decl); +                                clang_type_was_created = true; + +                                m_ast.SetMetadata (class_template_decl, metadata); +                                m_ast.SetMetadata (class_specialization_decl, metadata); +                            } +                        } + +                        if (!clang_type_was_created) +                        { +                            clang_type_was_created = true; +                            clang_type = m_ast.CreateRecordType (decl_ctx, +                                                                 accessibility, +                                                                 type_name_cstr, +                                                                 tag_decl_kind, +                                                                 class_language, +                                                                 &metadata); +                        } +                    } + +                    // Store a forward declaration to this class type in case any +                    // parameters in any class methods need it for the clang +                    // types for function prototypes. +                    LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); +                    type_sp.reset (new Type (die.GetID(), +                                             dwarf, +                                             type_name_const_str, +                                             byte_size, +                                             NULL, +                                             LLDB_INVALID_UID, +                                             Type::eEncodingIsUID, +                                             &decl, +                                             clang_type, +                                             Type::eResolveStateForward)); + +                    type_sp->SetIsCompleteObjCClass(is_complete_objc_class); + + +                    // Add our type to the unique type map so we don't +                    // end up creating many copies of the same type over +                    // and over in the ASTContext for our module +                    unique_ast_entry_ap->m_type_sp = type_sp; +                    unique_ast_entry_ap->m_die = die; +                    unique_ast_entry_ap->m_declaration = decl; +                    unique_ast_entry_ap->m_byte_size = byte_size; +                    dwarf->GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, +                                                              *unique_ast_entry_ap); + +                    if (is_forward_declaration && die.HasChildren()) +                    { +                        // Check to see if the DIE actually has a definition, some version of GCC will +                        // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram, +                        // members, or inheritance, so we can't trust it +                        DWARFDIE child_die = die.GetFirstChild(); +                        while (child_die) +                        { +                            switch (child_die.Tag()) +                            { +                                case DW_TAG_inheritance: +                                case DW_TAG_subprogram: +                                case DW_TAG_member: +                                case DW_TAG_APPLE_property: +                                case DW_TAG_class_type: +                                case DW_TAG_structure_type: +                                case DW_TAG_enumeration_type: +                                case DW_TAG_typedef: +                                case DW_TAG_union_type: +                                    child_die.Clear(); +                                    is_forward_declaration = false; +                                    break; +                                default: +                                    child_die = child_die.GetSibling(); +                                    break; +                            } +                        } +                    } + +                    if (!is_forward_declaration) +                    { +                        // Always start the definition for a class type so that +                        // if the class has child classes or types that require +                        // the class to be created for use as their decl contexts +                        // the class will be ready to accept these child definitions. +                        if (die.HasChildren() == false) +                        { +                            // No children for this struct/union/class, lets finish it +                            ClangASTContext::StartTagDeclarationDefinition (clang_type); +                            ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + +                            if (tag == DW_TAG_structure_type) // this only applies in C +                            { +                                clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(clang_type); + +                                if (record_decl) +                                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo())); +                            } +                        } +                        else if (clang_type_was_created) +                        { +                            // Start the definition if the class is not objective C since +                            // the underlying decls respond to isCompleteDefinition(). Objective +                            // C decls don't respond to isCompleteDefinition() so we can't +                            // start the declaration definition right away. For C++ class/union/structs +                            // we want to start the definition in case the class is needed as the +                            // declaration context for a contained class or type without the need +                            // to complete that type.. + +                            if (class_language != eLanguageTypeObjC && +                                class_language != eLanguageTypeObjC_plus_plus) +                                ClangASTContext::StartTagDeclarationDefinition (clang_type); + +                            // Leave this as a forward declaration until we need +                            // to know the details of the type. lldb_private::Type +                            // will automatically call the SymbolFile virtual function +                            // "SymbolFileDWARF::CompleteType(Type *)" +                            // When the definition needs to be defined. +                            assert(!dwarf->GetForwardDeclClangTypeToDie().count(ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) && +                                   "Type already in the forward declaration map!"); +                            assert(((SymbolFileDWARF*)m_ast.GetSymbolFile())->UserIDMatches(die.GetDIERef().GetUID()) && +                                   "Adding incorrect type to forward declaration map"); +                            dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = clang_type.GetOpaqueQualType(); +                            dwarf->GetForwardDeclClangTypeToDie()[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die.GetDIERef(); +                            m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true); +                        } +                    } +                } +                    break; + +                case DW_TAG_enumeration_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    DWARFFormValue encoding_form; + +                    const size_t num_attributes = die.GetAttributes (attributes); +                    if (num_attributes > 0) +                    { +                        uint32_t i; + +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_decl_file:       decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                    case DW_AT_decl_line:       decl.SetLine(form_value.Unsigned()); break; +                                    case DW_AT_decl_column:     decl.SetColumn(form_value.Unsigned()); break; +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; +                                    case DW_AT_type:            encoding_form = form_value; break; +                                    case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break; +                                    case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; +                                    case DW_AT_declaration:     is_forward_declaration = form_value.Boolean(); break; +                                    case DW_AT_allocated: +                                    case DW_AT_associated: +                                    case DW_AT_bit_stride: +                                    case DW_AT_byte_stride: +                                    case DW_AT_data_location: +                                    case DW_AT_description: +                                    case DW_AT_start_scope: +                                    case DW_AT_visibility: +                                    case DW_AT_specification: +                                    case DW_AT_abstract_origin: +                                    case DW_AT_sibling: +                                        break; +                                } +                            } +                        } + +                        if (is_forward_declaration) +                        { +                            type_sp = ParseTypeFromDWO(die, log); +                            if (type_sp) +                                return type_sp; + +                            DWARFDeclContext die_decl_ctx; +                            die.GetDWARFDeclContext(die_decl_ctx); + +                            type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); + +                            if (!type_sp) +                            { +                                SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); +                                if (debug_map_symfile) +                                { +                                    // We weren't able to find a full declaration in +                                    // this DWARF, see if we have a declaration anywhere +                                    // else... +                                    type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); +                                } +                            } + +                            if (type_sp) +                            { +                                if (log) +                                { +                                    dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                                     "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, +                                                                                     static_cast<void*>(this), +                                                                                     die.GetOffset(), +                                                                                     DW_TAG_value_to_name(tag), +                                                                                     type_name_cstr, +                                                                                     type_sp->GetID()); +                                } + +                                // We found a real definition for this type elsewhere +                                // so lets use it and cache the fact that we found +                                // a complete type for this die +                                dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +                                clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE( +                                                                                                    dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID()))); +                                if (defn_decl_ctx) +                                    LinkDeclContextToDIE(defn_decl_ctx, die); +                                return type_sp; +                            } + +                        } +                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + +                        CompilerType enumerator_clang_type; +                        clang_type.SetCompilerType (&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE())); +                        if (!clang_type) +                        { +                            if (encoding_form.IsValid()) +                            { +                                Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form).GetUID()); +                                if (enumerator_type) +                                    enumerator_clang_type = enumerator_type->GetFullCompilerType (); +                            } + +                            if (!enumerator_clang_type) +                                enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, +                                                                                                        DW_ATE_signed, +                                                                                                        byte_size * 8); + +                            clang_type = m_ast.CreateEnumerationType (type_name_cstr, +                                                                      GetClangDeclContextContainingDIE (die, nullptr), +                                                                      decl, +                                                                      enumerator_clang_type); +                        } +                        else +                        { +                            enumerator_clang_type = m_ast.GetEnumerationIntegerType (clang_type.GetOpaqueQualType()); +                        } + +                        LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die); + +                        type_sp.reset( new Type (die.GetID(), +                                                 dwarf, +                                                 type_name_const_str, +                                                 byte_size, +                                                 NULL, +                                                 DIERef(encoding_form).GetUID(), +                                                 Type::eEncodingIsUID, +                                                 &decl, +                                                 clang_type, +                                                 Type::eResolveStateForward)); + +                        ClangASTContext::StartTagDeclarationDefinition (clang_type); +                        if (die.HasChildren()) +                        { +                            SymbolContext cu_sc(die.GetLLDBCompileUnit()); +                            bool is_signed = false; +                            enumerator_clang_type.IsIntegerType(is_signed); +                            ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die); +                        } +                        ClangASTContext::CompleteTagDeclarationDefinition (clang_type); +                    } +                } +                    break; + +                case DW_TAG_inlined_subroutine: +                case DW_TAG_subprogram: +                case DW_TAG_subroutine_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    DWARFFormValue type_die_form; +                    bool is_variadic = false; +                    bool is_inline = false; +                    bool is_static = false; +                    bool is_virtual = false; +                    bool is_explicit = false; +                    bool is_artificial = false; +                    DWARFFormValue specification_die_form; +                    DWARFFormValue abstract_origin_die_form; +                    dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; + +                    unsigned type_quals = 0; +                    clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern + + +                    const size_t num_attributes = die.GetAttributes (attributes); +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                    case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                    case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_linkage_name: +                                    case DW_AT_MIPS_linkage_name:   break; // mangled = form_value.AsCString(&dwarf->get_debug_str_data()); break; +                                    case DW_AT_type:                type_die_form = form_value; break; +                                    case DW_AT_accessibility:       accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; +                                    case DW_AT_declaration:         break; // is_forward_declaration = form_value.Boolean(); break; +                                    case DW_AT_inline:              is_inline = form_value.Boolean(); break; +                                    case DW_AT_virtuality:          is_virtual = form_value.Boolean();  break; +                                    case DW_AT_explicit:            is_explicit = form_value.Boolean();  break; +                                    case DW_AT_artificial:          is_artificial = form_value.Boolean();  break; + + +                                    case DW_AT_external: +                                        if (form_value.Unsigned()) +                                        { +                                            if (storage == clang::SC_None) +                                                storage = clang::SC_Extern; +                                            else +                                                storage = clang::SC_PrivateExtern; +                                        } +                                        break; + +                                    case DW_AT_specification: +                                        specification_die_form = form_value; +                                        break; + +                                    case DW_AT_abstract_origin: +                                        abstract_origin_die_form = form_value; +                                        break; + +                                    case DW_AT_object_pointer: +                                        object_pointer_die_offset = form_value.Reference(); +                                        break; + +                                    case DW_AT_allocated: +                                    case DW_AT_associated: +                                    case DW_AT_address_class: +                                    case DW_AT_calling_convention: +                                    case DW_AT_data_location: +                                    case DW_AT_elemental: +                                    case DW_AT_entry_pc: +                                    case DW_AT_frame_base: +                                    case DW_AT_high_pc: +                                    case DW_AT_low_pc: +                                    case DW_AT_prototyped: +                                    case DW_AT_pure: +                                    case DW_AT_ranges: +                                    case DW_AT_recursive: +                                    case DW_AT_return_addr: +                                    case DW_AT_segment: +                                    case DW_AT_start_scope: +                                    case DW_AT_static_link: +                                    case DW_AT_trampoline: +                                    case DW_AT_visibility: +                                    case DW_AT_vtable_elem_location: +                                    case DW_AT_description: +                                    case DW_AT_sibling: +                                        break; +                                } +                            } +                        } +                    } + +                    std::string object_pointer_name; +                    if (object_pointer_die_offset != DW_INVALID_OFFSET) +                    { +                        DWARFDIE object_pointer_die = die.GetDIE (object_pointer_die_offset); +                        if (object_pointer_die) +                        { +                            const char *object_pointer_name_cstr = object_pointer_die.GetName(); +                            if (object_pointer_name_cstr) +                                object_pointer_name = object_pointer_name_cstr; +                        } +                    } + +                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + +                    CompilerType return_clang_type; +                    Type *func_type = NULL; + +                    if (type_die_form.IsValid()) +                        func_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + +                    if (func_type) +                        return_clang_type = func_type->GetForwardCompilerType (); +                    else +                        return_clang_type = m_ast.GetBasicType(eBasicTypeVoid); + + +                    std::vector<CompilerType> function_param_types; +                    std::vector<clang::ParmVarDecl*> function_param_decls; + +                    // Parse the function children for the parameters + +                    DWARFDIE decl_ctx_die; +                    clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, &decl_ctx_die); +                    const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind(); + +                    const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind); +                    // Start off static. This will be set to false in ParseChildParameters(...) +                    // if we find a "this" parameters as the first parameter +                    if (is_cxx_method) +                        is_static = true; + +                    if (die.HasChildren()) +                    { +                        bool skip_artificial = true; +                        ParseChildParameters (sc, +                                              containing_decl_ctx, +                                              die, +                                              skip_artificial, +                                              is_static, +                                              is_variadic, +                                              function_param_types, +                                              function_param_decls, +                                              type_quals); +                    } + +                    // clang_type will get the function prototype clang type after this call +                    clang_type = m_ast.CreateFunctionType (return_clang_type, +                                                           function_param_types.data(), +                                                           function_param_types.size(), +                                                           is_variadic, +                                                           type_quals); + +                    bool ignore_containing_context = false; + +                    if (type_name_cstr) +                    { +                        bool type_handled = false; +                        if (tag == DW_TAG_subprogram || +                            tag == DW_TAG_inlined_subroutine) +                        { +                            ObjCLanguage::MethodName objc_method (type_name_cstr, true); +                            if (objc_method.IsValid(true)) +                            { +                                CompilerType class_opaque_type; +                                ConstString class_name(objc_method.GetClassName()); +                                if (class_name) +                                { +                                    TypeSP complete_objc_class_type_sp (dwarf->FindCompleteObjCDefinitionTypeForDIE (DWARFDIE(), class_name, false)); + +                                    if (complete_objc_class_type_sp) +                                    { +                                        CompilerType type_clang_forward_type = complete_objc_class_type_sp->GetForwardCompilerType (); +                                        if (ClangASTContext::IsObjCObjectOrInterfaceType(type_clang_forward_type)) +                                            class_opaque_type = type_clang_forward_type; +                                    } +                                } + +                                if (class_opaque_type) +                                { +                                    // If accessibility isn't set to anything valid, assume public for +                                    // now... +                                    if (accessibility == eAccessNone) +                                        accessibility = eAccessPublic; + +                                    clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType (class_opaque_type, +                                                                                                               type_name_cstr, +                                                                                                               clang_type, +                                                                                                               accessibility, +                                                                                                               is_artificial); +                                    type_handled = objc_method_decl != NULL; +                                    if (type_handled) +                                    { +                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die); +                                        m_ast.SetMetadataAsUserID (objc_method_decl, die.GetID()); +                                    } +                                    else +                                    { +                                        dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", +                                                                                          die.GetOffset(), +                                                                                          tag, +                                                                                          DW_TAG_value_to_name(tag)); +                                    } +                                } +                            } +                            else if (is_cxx_method) +                            { +                                // Look at the parent of this DIE and see if is is +                                // a class or struct and see if this is actually a +                                // C++ method +                                Type *class_type = dwarf->ResolveType (decl_ctx_die); +                                if (class_type) +                                { +                                    bool alternate_defn = false; +                                    if (class_type->GetID() != decl_ctx_die.GetID() || decl_ctx_die.GetContainingDWOModuleDIE()) +                                    { +                                        alternate_defn = true; + +                                        // We uniqued the parent class of this function to another class +                                        // so we now need to associate all dies under "decl_ctx_die" to +                                        // DIEs in the DIE for "class_type"... +                                        SymbolFileDWARF *class_symfile = NULL; +                                        DWARFDIE class_type_die; + +                                        SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile(); +                                        if (debug_map_symfile) +                                        { +                                            class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID())); +                                            class_type_die = class_symfile->DebugInfo()->GetDIE (DIERef(class_type->GetID())); +                                        } +                                        else +                                        { +                                            class_symfile = dwarf; +                                            class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID())); +                                        } +                                        if (class_type_die) +                                        { +                                            DWARFDIECollection failures; + +                                            CopyUniqueClassMethodTypes (decl_ctx_die, +                                                                        class_type_die, +                                                                        class_type, +                                                                        failures); + +                                            // FIXME do something with these failures that's smarter than +                                            // just dropping them on the ground.  Unfortunately classes don't +                                            // like having stuff added to them after their definitions are +                                            // complete... + +                                            type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; +                                            if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) +                                            { +                                                type_sp = type_ptr->shared_from_this(); +                                                break; +                                            } +                                        } +                                    } + +                                    if (specification_die_form.IsValid()) +                                    { +                                        // We have a specification which we are going to base our function +                                        // prototype off of, so we need this type to be completed so that the +                                        // m_die_to_decl_ctx for the method in the specification has a valid +                                        // clang decl context. +                                        class_type->GetForwardCompilerType (); +                                        // If we have a specification, then the function type should have been +                                        // made with the specification and not with this die. +                                        DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form)); +                                        clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (spec_die); +                                        if (spec_clang_decl_ctx) +                                        { +                                            LinkDeclContextToDIE(spec_clang_decl_ctx, die); +                                        } +                                        else +                                        { +                                            dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8" PRIx64 ") has no decl\n", +                                                                                                die.GetID(), +                                                                                                specification_die_form.Reference()); +                                        } +                                        type_handled = true; +                                    } +                                    else if (abstract_origin_die_form.IsValid()) +                                    { +                                        // We have a specification which we are going to base our function +                                        // prototype off of, so we need this type to be completed so that the +                                        // m_die_to_decl_ctx for the method in the abstract origin has a valid +                                        // clang decl context. +                                        class_type->GetForwardCompilerType (); + +                                        DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE (DIERef(abstract_origin_die_form)); +                                        clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (abs_die); +                                        if (abs_clang_decl_ctx) +                                        { +                                            LinkDeclContextToDIE (abs_clang_decl_ctx, die); +                                        } +                                        else +                                        { +                                            dwarf->GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8" PRIx64 ") has no decl\n", +                                                                                                die.GetID(), +                                                                                                abstract_origin_die_form.Reference()); +                                        } +                                        type_handled = true; +                                    } +                                    else +                                    { +                                        CompilerType class_opaque_type = class_type->GetForwardCompilerType (); +                                        if (ClangASTContext::IsCXXClassType(class_opaque_type)) +                                        { +                                            if (class_opaque_type.IsBeingDefined () || alternate_defn) +                                            { +                                                if (!is_static && !die.HasChildren()) +                                                { +                                                    // We have a C++ member function with no children (this pointer!) +                                                    // and clang will get mad if we try and make a function that isn't +                                                    // well formed in the DWARF, so we will just skip it... +                                                    type_handled = true; +                                                } +                                                else +                                                { +                                                    bool add_method = true; +                                                    if (alternate_defn) +                                                    { +                                                        // If an alternate definition for the class exists, then add the method only if an +                                                        // equivalent is not already present. +                                                        clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(class_opaque_type.GetOpaqueQualType()); +                                                        if (record_decl) +                                                        { +                                                            for (auto method_iter = record_decl->method_begin(); +                                                                 method_iter != record_decl->method_end(); +                                                                 method_iter++) +                                                            { +                                                                clang::CXXMethodDecl *method_decl = *method_iter; +                                                                if (method_decl->getNameInfo().getAsString() == std::string(type_name_cstr)) +                                                                { +                                                                    if (method_decl->getType() == ClangASTContext::GetQualType(clang_type)) +                                                                    { +                                                                        add_method = false; +                                                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die); +                                                                        type_handled = true; + +                                                                        break; +                                                                    } +                                                                } +                                                            } +                                                        } +                                                    } + +                                                    if (add_method) +                                                    { +                                                        // REMOVE THE CRASH DESCRIPTION BELOW +                                                        Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s", +                                                                                             type_name_cstr, +                                                                                             class_type->GetName().GetCString(), +                                                                                             die.GetID(), +                                                                                             dwarf->GetObjectFile()->GetFileSpec().GetPath().c_str()); + +                                                        const bool is_attr_used = false; +                                                        // Neither GCC 4.2 nor clang++ currently set a valid accessibility +                                                        // in the DWARF for C++ methods... Default to public for now... +                                                        if (accessibility == eAccessNone) +                                                            accessibility = eAccessPublic; + +                                                        clang::CXXMethodDecl *cxx_method_decl; +                                                        cxx_method_decl = m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(), +                                                                                                          type_name_cstr, +                                                                                                          clang_type, +                                                                                                          accessibility, +                                                                                                          is_virtual, +                                                                                                          is_static, +                                                                                                          is_inline, +                                                                                                          is_explicit, +                                                                                                          is_attr_used, +                                                                                                          is_artificial); + +                                                        type_handled = cxx_method_decl != NULL; + +                                                        if (type_handled) +                                                        { +                                                            LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die); + +                                                            Host::SetCrashDescription (NULL); + +                                                            ClangASTMetadata metadata; +                                                            metadata.SetUserID(die.GetID()); + +                                                            if (!object_pointer_name.empty()) +                                                            { +                                                                metadata.SetObjectPtrName(object_pointer_name.c_str()); +                                                                if (log) +                                                                    log->Printf ("Setting object pointer name: %s on method object %p.\n", +                                                                                 object_pointer_name.c_str(), +                                                                                 static_cast<void*>(cxx_method_decl)); +                                                            } +                                                            m_ast.SetMetadata (cxx_method_decl, metadata); +                                                        } +                                                        else +                                                        { +                                                            ignore_containing_context = true; +                                                        } +                                                    } +                                                } +                                            } +                                            else +                                            { +                                                // We were asked to parse the type for a method in a class, yet the +                                                // class hasn't been asked to complete itself through the +                                                // clang::ExternalASTSource protocol, so we need to just have the +                                                // class complete itself and do things the right way, then our +                                                // DIE should then have an entry in the dwarf->GetDIEToType() map. First +                                                // we need to modify the dwarf->GetDIEToType() so it doesn't think we are +                                                // trying to parse this DIE anymore... +                                                dwarf->GetDIEToType()[die.GetDIE()] = NULL; + +                                                // Now we get the full type to force our class type to complete itself +                                                // using the clang::ExternalASTSource protocol which will parse all +                                                // base classes and all methods (including the method for this DIE). +                                                class_type->GetFullCompilerType (); + +                                                // The type for this DIE should have been filled in the function call above +                                                type_ptr = dwarf->GetDIEToType()[die.GetDIE()]; +                                                if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) +                                                { +                                                    type_sp = type_ptr->shared_from_this(); +                                                    break; +                                                } + +                                                // FIXME This is fixing some even uglier behavior but we really need to +                                                // uniq the methods of each class as well as the class itself. +                                                // <rdar://problem/11240464> +                                                type_handled = true; +                                            } +                                        } +                                    } +                                } +                            } +                        } + +                        if (!type_handled) +                        { +                            // We just have a function that isn't part of a class +                            clang::FunctionDecl *function_decl = m_ast.CreateFunctionDeclaration (ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, +                                                                                                  type_name_cstr, +                                                                                                  clang_type, +                                                                                                  storage, +                                                                                                  is_inline); + +                            //                            if (template_param_infos.GetSize() > 0) +                            //                            { +                            //                                clang::FunctionTemplateDecl *func_template_decl = CreateFunctionTemplateDecl (containing_decl_ctx, +                            //                                                                                                              function_decl, +                            //                                                                                                              type_name_cstr, +                            //                                                                                                              template_param_infos); +                            // +                            //                                CreateFunctionTemplateSpecializationInfo (function_decl, +                            //                                                                          func_template_decl, +                            //                                                                          template_param_infos); +                            //                            } +                            // Add the decl to our DIE to decl context map +                            assert (function_decl); +                            LinkDeclContextToDIE(function_decl, die); +                            if (!function_param_decls.empty()) +                                m_ast.SetFunctionParameters (function_decl, +                                                             &function_param_decls.front(), +                                                             function_param_decls.size()); + +                            ClangASTMetadata metadata; +                            metadata.SetUserID(die.GetID()); + +                            if (!object_pointer_name.empty()) +                            { +                                metadata.SetObjectPtrName(object_pointer_name.c_str()); +                                if (log) +                                    log->Printf ("Setting object pointer name: %s on function object %p.", +                                                 object_pointer_name.c_str(), +                                                 static_cast<void*>(function_decl)); +                            } +                            m_ast.SetMetadata (function_decl, metadata); +                        } +                    } +                    type_sp.reset( new Type (die.GetID(), +                                             dwarf, +                                             type_name_const_str, +                                             0, +                                             NULL, +                                             LLDB_INVALID_UID, +                                             Type::eEncodingIsUID, +                                             &decl, +                                             clang_type, +                                             Type::eResolveStateFull)); +                    assert(type_sp.get()); +                } +                    break; + +                case DW_TAG_array_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    DWARFFormValue type_die_form; +                    int64_t first_index = 0; +                    uint32_t byte_stride = 0; +                    uint32_t bit_stride = 0; +                    bool is_vector = false; +                    const size_t num_attributes = die.GetAttributes (attributes); + +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                    case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                    case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_type:            type_die_form = form_value; break; +                                    case DW_AT_byte_size:       break; // byte_size = form_value.Unsigned(); break; +                                    case DW_AT_byte_stride:     byte_stride = form_value.Unsigned(); break; +                                    case DW_AT_bit_stride:      bit_stride = form_value.Unsigned(); break; +                                    case DW_AT_GNU_vector:      is_vector = form_value.Boolean(); break; +                                    case DW_AT_accessibility:   break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; +                                    case DW_AT_declaration:     break; // is_forward_declaration = form_value.Boolean(); break; +                                    case DW_AT_allocated: +                                    case DW_AT_associated: +                                    case DW_AT_data_location: +                                    case DW_AT_description: +                                    case DW_AT_ordering: +                                    case DW_AT_start_scope: +                                    case DW_AT_visibility: +                                    case DW_AT_specification: +                                    case DW_AT_abstract_origin: +                                    case DW_AT_sibling: +                                        break; +                                } +                            } +                        } + +                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); + +                        Type *element_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + +                        if (element_type) +                        { +                            std::vector<uint64_t> element_orders; +                            ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride); +                            if (byte_stride == 0 && bit_stride == 0) +                                byte_stride = element_type->GetByteSize(); +                            CompilerType array_element_type = element_type->GetForwardCompilerType (); +                            uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; +                            if (element_orders.size() > 0) +                            { +                                uint64_t num_elements = 0; +                                std::vector<uint64_t>::const_reverse_iterator pos; +                                std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend(); +                                for (pos = element_orders.rbegin(); pos != end; ++pos) +                                { +                                    num_elements = *pos; +                                    clang_type = m_ast.CreateArrayType (array_element_type, +                                                                        num_elements, +                                                                        is_vector); +                                    array_element_type = clang_type; +                                    array_element_bit_stride = num_elements ? +                                    array_element_bit_stride * num_elements : +                                    array_element_bit_stride; +                                } +                            } +                            else +                            { +                                clang_type = m_ast.CreateArrayType (array_element_type, 0, is_vector); +                            } +                            ConstString empty_name; +                            type_sp.reset( new Type (die.GetID(), +                                                     dwarf, +                                                     empty_name, +                                                     array_element_bit_stride / 8, +                                                     NULL, +                                                     DIERef(type_die_form).GetUID(), +                                                     Type::eEncodingIsUID, +                                                     &decl, +                                                     clang_type, +                                                     Type::eResolveStateFull)); +                            type_sp->SetEncodingType (element_type); +                        } +                    } +                } +                    break; + +                case DW_TAG_ptr_to_member_type: +                { +                    DWARFFormValue type_die_form; +                    DWARFFormValue containing_type_die_form; + +                    const size_t num_attributes = die.GetAttributes (attributes); + +                    if (num_attributes > 0) { +                        uint32_t i; +                        for (i=0; i<num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_type: +                                        type_die_form = form_value; break; +                                    case DW_AT_containing_type: +                                        containing_type_die_form = form_value; break; +                                } +                            } +                        } + +                        Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); +                        Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form).GetUID()); + +                        CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType (); +                        CompilerType class_clang_type = class_type->GetLayoutCompilerType (); +                         +                        clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, pointee_clang_type); + +                        byte_size = clang_type.GetByteSize(nullptr); + +                        type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL, +                                               LLDB_INVALID_UID, Type::eEncodingIsUID, NULL, clang_type, +                                               Type::eResolveStateForward)); +                    } + +                    break; +                } +                default: +                    dwarf->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", +                                                                      die.GetOffset(), +                                                                      tag, +                                                                      DW_TAG_value_to_name(tag)); +                    break; +            } + +            if (type_sp.get()) +            { +                DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); +                dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + +                SymbolContextScope * symbol_context_scope = NULL; +                if (sc_parent_tag == DW_TAG_compile_unit) +                { +                    symbol_context_scope = sc.comp_unit; +                } +                else if (sc.function != NULL && sc_parent_die) +                { +                    symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); +                    if (symbol_context_scope == NULL) +                        symbol_context_scope = sc.function; +                } + +                if (symbol_context_scope != NULL) +                { +                    type_sp->SetSymbolContextScope(symbol_context_scope); +                } + +                // We are ready to put this type into the uniqued list up at the module level +                type_list->Insert (type_sp); + +                dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); +            } +        } +        else if (type_ptr != DIE_IS_BEING_PARSED) +        { +            type_sp = type_ptr->shared_from_this(); +        } +    } +    return type_sp; +} + +// DWARF parsing functions + +class DWARFASTParserClang::DelayedAddObjCClassProperty +{ +public: +    DelayedAddObjCClassProperty(const CompilerType     &class_opaque_type, +                                const char             *property_name, +                                const CompilerType     &property_opaque_type,  // The property type is only required if you don't have an ivar decl +                                clang::ObjCIvarDecl    *ivar_decl, +                                const char             *property_setter_name, +                                const char             *property_getter_name, +                                uint32_t                property_attributes, +                                const ClangASTMetadata *metadata) : +    m_class_opaque_type     (class_opaque_type), +    m_property_name         (property_name), +    m_property_opaque_type  (property_opaque_type), +    m_ivar_decl             (ivar_decl), +    m_property_setter_name  (property_setter_name), +    m_property_getter_name  (property_getter_name), +    m_property_attributes   (property_attributes) +    { +        if (metadata != NULL) +        { +            m_metadata_ap.reset(new ClangASTMetadata()); +            *m_metadata_ap = *metadata; +        } +    } + +    DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs) +    { +        *this = rhs; +    } + +    DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs) +    { +        m_class_opaque_type    = rhs.m_class_opaque_type; +        m_property_name        = rhs.m_property_name; +        m_property_opaque_type = rhs.m_property_opaque_type; +        m_ivar_decl            = rhs.m_ivar_decl; +        m_property_setter_name = rhs.m_property_setter_name; +        m_property_getter_name = rhs.m_property_getter_name; +        m_property_attributes  = rhs.m_property_attributes; + +        if (rhs.m_metadata_ap.get()) +        { +            m_metadata_ap.reset (new ClangASTMetadata()); +            *m_metadata_ap = *rhs.m_metadata_ap; +        } +        return *this; +    } + +    bool +    Finalize() +    { +        return ClangASTContext::AddObjCClassProperty (m_class_opaque_type, +                                                      m_property_name, +                                                      m_property_opaque_type, +                                                      m_ivar_decl, +                                                      m_property_setter_name, +                                                      m_property_getter_name, +                                                      m_property_attributes, +                                                      m_metadata_ap.get()); +    } + +private: +    CompilerType            m_class_opaque_type; +    const char             *m_property_name; +    CompilerType            m_property_opaque_type; +    clang::ObjCIvarDecl    *m_ivar_decl; +    const char             *m_property_setter_name; +    const char             *m_property_getter_name; +    uint32_t                m_property_attributes; +    std::unique_ptr<ClangASTMetadata> m_metadata_ap; +}; + +bool +DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die, +                                       ClangASTContext::TemplateParameterInfos &template_param_infos) +{ +    const dw_tag_t tag = die.Tag(); + +    switch (tag) +    { +        case DW_TAG_template_type_parameter: +        case DW_TAG_template_value_parameter: +        { +            DWARFAttributes attributes; +            const size_t num_attributes = die.GetAttributes (attributes); +            const char *name = NULL; +            Type *lldb_type = NULL; +            CompilerType clang_type; +            uint64_t uval64 = 0; +            bool uval64_valid = false; +            if (num_attributes > 0) +            { +                DWARFFormValue form_value; +                for (size_t i=0; i<num_attributes; ++i) +                { +                    const dw_attr_t attr = attributes.AttributeAtIndex(i); + +                    switch (attr) +                    { +                        case DW_AT_name: +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                                name = form_value.AsCString(); +                            break; + +                        case DW_AT_type: +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                lldb_type = die.ResolveTypeUID(DIERef(form_value).GetUID()); +                                if (lldb_type) +                                    clang_type = lldb_type->GetForwardCompilerType (); +                            } +                            break; + +                        case DW_AT_const_value: +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                uval64_valid = true; +                                uval64 = form_value.Unsigned(); +                            } +                            break; +                        default: +                            break; +                    } +                } + +                clang::ASTContext *ast = m_ast.getASTContext(); +                if (!clang_type) +                    clang_type = m_ast.GetBasicType(eBasicTypeVoid); + +                if (clang_type) +                { +                    bool is_signed = false; +                    if (name && name[0]) +                        template_param_infos.names.push_back(name); +                    else +                        template_param_infos.names.push_back(NULL); + +                    if (tag == DW_TAG_template_value_parameter && +                        lldb_type != NULL && +                        clang_type.IsIntegerType (is_signed) && +                        uval64_valid) +                    { +                        llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed); +                        template_param_infos.args.push_back (clang::TemplateArgument (*ast, +                                                                                      llvm::APSInt(apint), +                                                                                      ClangASTContext::GetQualType(clang_type))); +                    } +                    else +                    { +                        template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type))); +                    } +                } +                else +                { +                    return false; +                } + +            } +        } +            return true; + +        default: +            break; +    } +    return false; +} + +bool +DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die, +                                                  ClangASTContext::TemplateParameterInfos &template_param_infos) +{ + +    if (!parent_die) +        return false; + +    Args template_parameter_names; +    for (DWARFDIE die = parent_die.GetFirstChild(); +         die.IsValid(); +         die = die.GetSibling()) +    { +        const dw_tag_t tag = die.Tag(); + +        switch (tag) +        { +            case DW_TAG_template_type_parameter: +            case DW_TAG_template_value_parameter: +                ParseTemplateDIE (die, template_param_infos); +                break; + +            default: +                break; +        } +    } +    if (template_param_infos.args.empty()) +        return false; +    return template_param_infos.args.size() == template_param_infos.names.size(); +} + +bool +DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type) +{ +    if (m_clang_ast_importer_ap) +        return ClangASTContext::CanImport(compiler_type, GetClangASTImporter()); +    else +        return false; +} + +bool +DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type) +{ +    if (CanCompleteType(compiler_type)) +    { +        if (ClangASTContext::Import(compiler_type, GetClangASTImporter())) +        { +            ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); +            return true; +        } +        else +        { +            ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false); +        } +    } +    return false; +} + +bool +DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, +                                            lldb_private::Type *type, +                                            CompilerType &clang_type) +{ +    // Disable external storage for this type so we don't get anymore +    // clang::ExternalASTSource queries for this type. +    m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false); + +    if (!die) +        return false; + +    const dw_tag_t tag = die.Tag(); + +    SymbolFileDWARF *dwarf = die.GetDWARF(); + +    Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); +    if (log) +        dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log, +                                                                         "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", +                                                                         die.GetID(), +                                                                         die.GetTagAsCString(), +                                                                         type->GetName().AsCString()); +    assert (clang_type); +    DWARFAttributes attributes; +    switch (tag) +    { +        case DW_TAG_structure_type: +        case DW_TAG_union_type: +        case DW_TAG_class_type: +        { +            LayoutInfo layout_info; + +            { +                if (die.HasChildren()) +                { +                    LanguageType class_language = eLanguageTypeUnknown; +                    if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) +                    { +                        class_language = eLanguageTypeObjC; +                        // For objective C we don't start the definition when +                        // the class is created. +                        ClangASTContext::StartTagDeclarationDefinition (clang_type); +                    } + +                    int tag_decl_kind = -1; +                    AccessType default_accessibility = eAccessNone; +                    if (tag == DW_TAG_structure_type) +                    { +                        tag_decl_kind = clang::TTK_Struct; +                        default_accessibility = eAccessPublic; +                    } +                    else if (tag == DW_TAG_union_type) +                    { +                        tag_decl_kind = clang::TTK_Union; +                        default_accessibility = eAccessPublic; +                    } +                    else if (tag == DW_TAG_class_type) +                    { +                        tag_decl_kind = clang::TTK_Class; +                        default_accessibility = eAccessPrivate; +                    } + +                    SymbolContext sc(die.GetLLDBCompileUnit()); +                    std::vector<clang::CXXBaseSpecifier *> base_classes; +                    std::vector<int> member_accessibilities; +                    bool is_a_class = false; +                    // Parse members and base classes first +                    DWARFDIECollection member_function_dies; + +                    DelayedPropertyList delayed_properties; +                    ParseChildMembers (sc, +                                       die, +                                       clang_type, +                                       class_language, +                                       base_classes, +                                       member_accessibilities, +                                       member_function_dies, +                                       delayed_properties, +                                       default_accessibility, +                                       is_a_class, +                                       layout_info); + +                    // Now parse any methods if there were any... +                    size_t num_functions = member_function_dies.Size(); +                    if (num_functions > 0) +                    { +                        for (size_t i=0; i<num_functions; ++i) +                        { +                            dwarf->ResolveType(member_function_dies.GetDIEAtIndex(i)); +                        } +                    } + +                    if (class_language == eLanguageTypeObjC) +                    { +                        ConstString class_name (clang_type.GetTypeName()); +                        if (class_name) +                        { +                            DIEArray method_die_offsets; +                            dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets); + +                            if (!method_die_offsets.empty()) +                            { +                                DWARFDebugInfo* debug_info = dwarf->DebugInfo(); + +                                const size_t num_matches = method_die_offsets.size(); +                                for (size_t i=0; i<num_matches; ++i) +                                { +                                    const DIERef& die_ref = method_die_offsets[i]; +                                    DWARFDIE method_die = debug_info->GetDIE (die_ref); + +                                    if (method_die) +                                        method_die.ResolveType (); +                                } +                            } + +                            for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end(); +                                 pi != pe; +                                 ++pi) +                                pi->Finalize(); +                        } +                    } + +                    // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we +                    // need to tell the clang type it is actually a class. +                    if (class_language != eLanguageTypeObjC) +                    { +                        if (is_a_class && tag_decl_kind != clang::TTK_Class) +                            m_ast.SetTagTypeKind (ClangASTContext::GetQualType(clang_type), clang::TTK_Class); +                    } + +                    // Since DW_TAG_structure_type gets used for both classes +                    // and structures, we may need to set any DW_TAG_member +                    // fields to have a "private" access if none was specified. +                    // When we parsed the child members we tracked that actual +                    // accessibility value for each DW_TAG_member in the +                    // "member_accessibilities" array. If the value for the +                    // member is zero, then it was set to the "default_accessibility" +                    // which for structs was "public". Below we correct this +                    // by setting any fields to "private" that weren't correctly +                    // set. +                    if (is_a_class && !member_accessibilities.empty()) +                    { +                        // This is a class and all members that didn't have +                        // their access specified are private. +                        m_ast.SetDefaultAccessForRecordFields (m_ast.GetAsRecordDecl(clang_type), +                                                               eAccessPrivate, +                                                               &member_accessibilities.front(), +                                                               member_accessibilities.size()); +                    } + +                    if (!base_classes.empty()) +                    { +                        // Make sure all base classes refer to complete types and not +                        // forward declarations. If we don't do this, clang will crash +                        // with an assertion in the call to clang_type.SetBaseClassesForClassType() +                        for (auto &base_class : base_classes) +                        { +                            clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); +                            if (type_source_info) +                            { +                                CompilerType base_class_type (&m_ast, type_source_info->getType().getAsOpaquePtr()); +                                if (base_class_type.GetCompleteType() == false) +                                { +                                    auto module = dwarf->GetObjectFile()->GetModule(); +                                    module->ReportError ( +                                        ":: Class '%s' has a base class '%s' which does not have a complete definition.", +                                        die.GetName(), +                                        base_class_type.GetTypeName().GetCString()); +                                    if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) +                                         module->ReportError (":: Try compiling the source file with -fno-limit-debug-info."); + +                                    // We have no choice other than to pretend that the base class +                                    // is complete. If we don't do this, clang will crash when we +                                    // call setBases() inside of "clang_type.SetBaseClassesForClassType()" +                                    // below. Since we provide layout assistance, all ivars in this +                                    // class and other classes will be fine, this is the best we can do +                                    // short of crashing. +                                    ClangASTContext::StartTagDeclarationDefinition (base_class_type); +                                    ClangASTContext::CompleteTagDeclarationDefinition (base_class_type); +                                } +                            } +                        } +                        m_ast.SetBaseClassesForClassType (clang_type.GetOpaqueQualType(), +                                                          &base_classes.front(), +                                                          base_classes.size()); + +                        // Clang will copy each CXXBaseSpecifier in "base_classes" +                        // so we have to free them all. +                        ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(), +                                                                    base_classes.size()); +                    } +                } +            } + +            ClangASTContext::BuildIndirectFields (clang_type); +            ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + +            if (!layout_info.field_offsets.empty() || +                !layout_info.base_offsets.empty()  || +                !layout_info.vbase_offsets.empty() ) +            { +                if (type) +                    layout_info.bit_size = type->GetByteSize() * 8; +                if (layout_info.bit_size == 0) +                    layout_info.bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + +                clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); +                if (record_decl) +                { +                    if (log) +                    { +                        ModuleSP module_sp = dwarf->GetObjectFile()->GetModule(); + +                        if (module_sp) +                        { +                            module_sp->LogMessage (log, +                                                   "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])", +                                                   static_cast<void*>(clang_type.GetOpaqueQualType()), +                                                   static_cast<void*>(record_decl), +                                                   layout_info.bit_size, +                                                   layout_info.alignment, +                                                   static_cast<uint32_t>(layout_info.field_offsets.size()), +                                                   static_cast<uint32_t>(layout_info.base_offsets.size()), +                                                   static_cast<uint32_t>(layout_info.vbase_offsets.size())); + +                            uint32_t idx; +                            { +                                llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos, +                                end = layout_info.field_offsets.end(); +                                for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx) +                                { +                                    module_sp->LogMessage(log, +                                                          "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) field[%u] = { bit_offset=%u, name='%s' }", +                                                          static_cast<void *>(clang_type.GetOpaqueQualType()), +                                                          idx, +                                                          static_cast<uint32_t>(pos->second), +                                                          pos->first->getNameAsString().c_str()); +                                } +                            } + +                            { +                                llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, +                                base_end = layout_info.base_offsets.end(); +                                for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; ++base_pos, ++idx) +                                { +                                    module_sp->LogMessage(log, +                                                          "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) base[%u] = { byte_offset=%u, name='%s' }", +                                                          clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(), +                                                          base_pos->first->getNameAsString().c_str()); +                                } +                            } +                            { +                                llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos, +                                vbase_end = layout_info.vbase_offsets.end(); +                                for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; ++vbase_pos, ++idx) +                                { +                                    module_sp->LogMessage(log, +                                                          "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) vbase[%u] = { byte_offset=%u, name='%s' }", +                                                          static_cast<void *>(clang_type.GetOpaqueQualType()), idx, +                                                          static_cast<uint32_t>(vbase_pos->second.getQuantity()), +                                                          vbase_pos->first->getNameAsString().c_str()); +                                } +                            } + +                        } +                    } +                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); +                } +            } +        } + +            return (bool)clang_type; + +        case DW_TAG_enumeration_type: +            ClangASTContext::StartTagDeclarationDefinition (clang_type); +            if (die.HasChildren()) +            { +                SymbolContext sc(die.GetLLDBCompileUnit()); +                bool is_signed = false; +                clang_type.IsIntegerType(is_signed); +                ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die); +            } +            ClangASTContext::CompleteTagDeclarationDefinition (clang_type); +            return (bool)clang_type; + +        default: +            assert(false && "not a forward clang type decl!"); +            break; +    } + +    return false; +} + +std::vector<DWARFDIE> +DWARFASTParserClang::GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) +{ +    std::vector<DWARFDIE> result; +    for (auto it = m_decl_ctx_to_die.find((clang::DeclContext *)decl_context.GetOpaqueDeclContext()); it != m_decl_ctx_to_die.end(); it++) +        result.push_back(it->second); +    return result; +} + +CompilerDecl +DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die) +{ +    clang::Decl *clang_decl = GetClangDeclForDIE(die); +    if (clang_decl != nullptr) +        return CompilerDecl(&m_ast, clang_decl); +    return CompilerDecl(); +} + +CompilerDeclContext +DWARFASTParserClang::GetDeclContextForUIDFromDWARF (const DWARFDIE &die) +{ +    clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (die); +    if (clang_decl_ctx) +        return CompilerDeclContext(&m_ast, clang_decl_ctx); +    return CompilerDeclContext(); +} + +CompilerDeclContext +DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) +{ +    clang::DeclContext *clang_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); +    if (clang_decl_ctx) +        return CompilerDeclContext(&m_ast, clang_decl_ctx); +    return CompilerDeclContext(); +} + +size_t +DWARFASTParserClang::ParseChildEnumerators (const SymbolContext& sc, +                                            lldb_private::CompilerType &clang_type, +                                            bool is_signed, +                                            uint32_t enumerator_byte_size, +                                            const DWARFDIE &parent_die) +{ +    if (!parent_die) +        return 0; + +    size_t enumerators_added = 0; + +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        const dw_tag_t tag = die.Tag(); +        if (tag == DW_TAG_enumerator) +        { +            DWARFAttributes attributes; +            const size_t num_child_attributes = die.GetAttributes(attributes); +            if (num_child_attributes > 0) +            { +                const char *name = NULL; +                bool got_value = false; +                int64_t enum_value = 0; +                Declaration decl; + +                uint32_t i; +                for (i=0; i<num_child_attributes; ++i) +                { +                    const dw_attr_t attr = attributes.AttributeAtIndex(i); +                    DWARFFormValue form_value; +                    if (attributes.ExtractFormValueAtIndex(i, form_value)) +                    { +                        switch (attr) +                        { +                            case DW_AT_const_value: +                                got_value = true; +                                if (is_signed) +                                    enum_value = form_value.Signed(); +                                else +                                    enum_value = form_value.Unsigned(); +                                break; + +                            case DW_AT_name: +                                name = form_value.AsCString(); +                                break; + +                            case DW_AT_description: +                            default: +                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                            case DW_AT_sibling: +                                break; +                        } +                    } +                } + +                if (name && name[0] && got_value) +                { +                    m_ast.AddEnumerationValueToEnumerationType (clang_type.GetOpaqueQualType(), +                                                                m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()), +                                                                decl, +                                                                name, +                                                                enum_value, +                                                                enumerator_byte_size * 8); +                    ++enumerators_added; +                } +            } +        } +    } +    return enumerators_added; +} + +#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) + +class DIEStack +{ +public: + +    void Push (const DWARFDIE &die) +    { +        m_dies.push_back (die); +    } + + +    void LogDIEs (Log *log) +    { +        StreamString log_strm; +        const size_t n = m_dies.size(); +        log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n); +        for (size_t i=0; i<n; i++) +        { +            std::string qualified_name; +            const DWARFDIE &die = m_dies[i]; +            die.GetQualifiedName(qualified_name); +            log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", +                             (uint64_t)i, +                             die.GetOffset(), +                             die.GetTagAsCString(), +                             qualified_name.c_str()); +        } +        log->PutCString(log_strm.GetData()); +    } +    void Pop () +    { +        m_dies.pop_back(); +    } + +    class ScopedPopper +    { +    public: +        ScopedPopper (DIEStack &die_stack) : +        m_die_stack (die_stack), +        m_valid (false) +        { +        } + +        void +        Push (const DWARFDIE &die) +        { +            m_valid = true; +            m_die_stack.Push (die); +        } + +        ~ScopedPopper () +        { +            if (m_valid) +                m_die_stack.Pop(); +        } + + + +    protected: +        DIEStack &m_die_stack; +        bool m_valid; +    }; + +protected: +    typedef std::vector<DWARFDIE> Stack; +    Stack m_dies; +}; +#endif + +Function * +DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, +                                             const DWARFDIE &die) +{ +    DWARFRangeList func_ranges; +    const char *name = NULL; +    const char *mangled = NULL; +    int decl_file = 0; +    int decl_line = 0; +    int decl_column = 0; +    int call_file = 0; +    int call_line = 0; +    int call_column = 0; +    DWARFExpression frame_base(die.GetCU()); + +    const dw_tag_t tag = die.Tag(); + +    if (tag != DW_TAG_subprogram) +        return NULL; + +    if (die.GetDIENamesAndRanges (name, +                                  mangled, +                                  func_ranges, +                                  decl_file, +                                  decl_line, +                                  decl_column, +                                  call_file, +                                  call_line, +                                  call_column, +                                  &frame_base)) +    { + +        // Union of all ranges in the function DIE (if the function is discontiguous) +        AddressRange func_range; +        lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0); +        lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0); +        if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) +        { +            ModuleSP module_sp (die.GetModule()); +            func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList()); +            if (func_range.GetBaseAddress().IsValid()) +                func_range.SetByteSize(highest_func_addr - lowest_func_addr); +        } + +        if (func_range.GetBaseAddress().IsValid()) +        { +            Mangled func_name; +            if (mangled) +                func_name.SetValue(ConstString(mangled), true); +            else if (die.GetParent().Tag() == DW_TAG_compile_unit && +                     Language::LanguageIsCPlusPlus(die.GetLanguage()) && +                     name && strcmp(name, "main") != 0) +            { +                // If the mangled name is not present in the DWARF, generate the demangled name +                // using the decl context. We skip if the function is "main" as its name is +                // never mangled. +                bool is_static = false; +                bool is_variadic = false; +                unsigned type_quals = 0; +                std::vector<CompilerType> param_types; +                std::vector<clang::ParmVarDecl*> param_decls; +                DWARFDeclContext decl_ctx; +                StreamString sstr; + +                die.GetDWARFDeclContext(decl_ctx); +                sstr << decl_ctx.GetQualifiedName(); + +                clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); +                ParseChildParameters(sc, +                                     containing_decl_ctx, +                                     die, +                                     true, +                                     is_static, +                                     is_variadic, +                                     param_types, +                                     param_decls, +                                     type_quals); +                sstr << "("; +                for (size_t i = 0; i < param_types.size(); i++) +                { +                    if (i > 0) +                        sstr << ", "; +                    sstr << param_types[i].GetTypeName(); +                } +                if (is_variadic) +                    sstr << ", ..."; +                sstr << ")"; +                if (type_quals & clang::Qualifiers::Const) +                    sstr << " const"; + +                func_name.SetValue(ConstString(sstr.GetData()), false); +            } +            else +                func_name.SetValue(ConstString(name), false); + +            FunctionSP func_sp; +            std::unique_ptr<Declaration> decl_ap; +            if (decl_file != 0 || decl_line != 0 || decl_column != 0) +                decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), +                                               decl_line, +                                               decl_column)); + +            SymbolFileDWARF *dwarf = die.GetDWARF(); +            // Supply the type _only_ if it has already been parsed +            Type *func_type = dwarf->GetDIEToType().lookup (die.GetDIE()); + +            assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + +            if (dwarf->FixupAddress (func_range.GetBaseAddress())) +            { +                const user_id_t func_user_id = die.GetID(); +                func_sp.reset(new Function (sc.comp_unit, +                                            func_user_id,       // UserID is the DIE offset +                                            func_user_id, +                                            func_name, +                                            func_type, +                                            func_range));           // first address range + +                if (func_sp.get() != NULL) +                { +                    if (frame_base.IsValid()) +                        func_sp->GetFrameBaseExpression() = frame_base; +                    sc.comp_unit->AddFunction(func_sp); +                    return func_sp.get(); +                } +            } +        } +    } +    return NULL; +} + + +bool +DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, +                                        const DWARFDIE &parent_die, +                                        CompilerType &class_clang_type, +                                        const LanguageType class_language, +                                        std::vector<clang::CXXBaseSpecifier *>& base_classes, +                                        std::vector<int>& member_accessibilities, +                                        DWARFDIECollection& member_function_dies, +                                        DelayedPropertyList& delayed_properties, +                                        AccessType& default_accessibility, +                                        bool &is_a_class, +                                        LayoutInfo &layout_info) +{ +    if (!parent_die) +        return 0; + +    uint32_t member_idx = 0; +    BitfieldInfo last_field_info; + +    ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); +    ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem()); +    if (ast == nullptr) +        return 0; + +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        dw_tag_t tag = die.Tag(); + +        switch (tag) +        { +            case DW_TAG_member: +            case DW_TAG_APPLE_property: +            { +                DWARFAttributes attributes; +                const size_t num_attributes = die.GetAttributes (attributes); +                if (num_attributes > 0) +                { +                    Declaration decl; +                    //DWARFExpression location; +                    const char *name = NULL; +                    const char *prop_name = NULL; +                    const char *prop_getter_name = NULL; +                    const char *prop_setter_name = NULL; +                    uint32_t prop_attributes = 0; + + +                    bool is_artificial = false; +                    DWARFFormValue encoding_form; +                    AccessType accessibility = eAccessNone; +                    uint32_t member_byte_offset = UINT32_MAX; +                    size_t byte_size = 0; +                    size_t bit_offset = 0; +                    size_t bit_size = 0; +                    bool is_external = false; // On DW_TAG_members, this means the member is static +                    uint32_t i; +                    for (i=0; i<num_attributes && !is_artificial; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                case DW_AT_name:        name = form_value.AsCString(); break; +                                case DW_AT_type:        encoding_form = form_value; break; +                                case DW_AT_bit_offset:  bit_offset = form_value.Unsigned(); break; +                                case DW_AT_bit_size:    bit_size = form_value.Unsigned(); break; +                                case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break; +                                case DW_AT_data_member_location: +                                    if (form_value.BlockData()) +                                    { +                                        Value initialValue(0); +                                        Value memberOffset(0); +                                        const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data(); +                                        uint32_t block_length = form_value.Unsigned(); +                                        uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); +                                        if (DWARFExpression::Evaluate(NULL, // ExecutionContext * +                                                                      NULL, // ClangExpressionVariableList * +                                                                      NULL, // ClangExpressionDeclMap * +                                                                      NULL, // RegisterContext * +                                                                      module_sp, +                                                                      debug_info_data, +                                                                      die.GetCU(), +                                                                      block_offset, +                                                                      block_length, +                                                                      eRegisterKindDWARF, +                                                                      &initialValue, +                                                                      memberOffset, +                                                                      NULL)) +                                        { +                                            member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); +                                        } +                                    } +                                    else +                                    { +                                        // With DWARF 3 and later, if the value is an integer constant, +                                        // this form value is the offset in bytes from the beginning +                                        // of the containing entity. +                                        member_byte_offset = form_value.Unsigned(); +                                    } +                                    break; + +                                case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break; +                                case DW_AT_artificial: is_artificial = form_value.Boolean(); break; +                                case DW_AT_APPLE_property_name:      prop_name = form_value.AsCString(); +                                    break; +                                case DW_AT_APPLE_property_getter:    prop_getter_name = form_value.AsCString(); +                                    break; +                                case DW_AT_APPLE_property_setter:    prop_setter_name = form_value.AsCString(); +                                    break; +                                case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break; +                                case DW_AT_external:                 is_external = form_value.Boolean(); break; + +                                default: +                                case DW_AT_declaration: +                                case DW_AT_description: +                                case DW_AT_mutable: +                                case DW_AT_visibility: +                                case DW_AT_sibling: +                                    break; +                            } +                        } +                    } + +                    if (prop_name) +                    { +                        ConstString fixed_getter; +                        ConstString fixed_setter; + +                        // Check if the property getter/setter were provided as full +                        // names.  We want basenames, so we extract them. + +                        if (prop_getter_name && prop_getter_name[0] == '-') +                        { +                            ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true); +                            prop_getter_name = prop_getter_method.GetSelector().GetCString(); +                        } + +                        if (prop_setter_name && prop_setter_name[0] == '-') +                        { +                            ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true); +                            prop_setter_name = prop_setter_method.GetSelector().GetCString(); +                        } + +                        // If the names haven't been provided, they need to be +                        // filled in. + +                        if (!prop_getter_name) +                        { +                            prop_getter_name = prop_name; +                        } +                        if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly)) +                        { +                            StreamString ss; + +                            ss.Printf("set%c%s:", +                                      toupper(prop_name[0]), +                                      &prop_name[1]); + +                            fixed_setter.SetCString(ss.GetData()); +                            prop_setter_name = fixed_setter.GetCString(); +                        } +                    } + +                    // Clang has a DWARF generation bug where sometimes it +                    // represents fields that are references with bad byte size +                    // and bit size/offset information such as: +                    // +                    //  DW_AT_byte_size( 0x00 ) +                    //  DW_AT_bit_size( 0x40 ) +                    //  DW_AT_bit_offset( 0xffffffffffffffc0 ) +                    // +                    // So check the bit offset to make sure it is sane, and if +                    // the values are not sane, remove them. If we don't do this +                    // then we will end up with a crash if we try to use this +                    // type in an expression when clang becomes unhappy with its +                    // recycled debug info. + +                    if (bit_offset > 128) +                    { +                        bit_size = 0; +                        bit_offset = 0; +                    } + +                    // FIXME: Make Clang ignore Objective-C accessibility for expressions +                    if (class_language == eLanguageTypeObjC || +                        class_language == eLanguageTypeObjC_plus_plus) +                        accessibility = eAccessNone; + +                    if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name)) +                    { +                        // Not all compilers will mark the vtable pointer +                        // member as artificial (llvm-gcc). We can't have +                        // the virtual members in our classes otherwise it +                        // throws off all child offsets since we end up +                        // having and extra pointer sized member in our +                        // class layouts. +                        is_artificial = true; +                    } + +                    // Handle static members +                    if (is_external && member_byte_offset == UINT32_MAX) +                    { +                        Type *var_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + +                        if (var_type) +                        { +                            if (accessibility == eAccessNone) +                                accessibility = eAccessPublic; +                            ClangASTContext::AddVariableToRecordType (class_clang_type, +                                                                      name, +                                                                      var_type->GetLayoutCompilerType (), +                                                                      accessibility); +                        } +                        break; +                    } + +                    if (is_artificial == false) +                    { +                        Type *member_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + +                        clang::FieldDecl *field_decl = NULL; +                        if (tag == DW_TAG_member) +                        { +                            if (member_type) +                            { +                                if (accessibility == eAccessNone) +                                    accessibility = default_accessibility; +                                member_accessibilities.push_back(accessibility); + +                                uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); +                                if (bit_size > 0) +                                { + +                                    BitfieldInfo this_field_info; +                                    this_field_info.bit_offset = field_bit_offset; +                                    this_field_info.bit_size = bit_size; + +                                    ///////////////////////////////////////////////////////////// +                                    // How to locate a field given the DWARF debug information +                                    // +                                    // AT_byte_size indicates the size of the word in which the +                                    // bit offset must be interpreted. +                                    // +                                    // AT_data_member_location indicates the byte offset of the +                                    // word from the base address of the structure. +                                    // +                                    // AT_bit_offset indicates how many bits into the word +                                    // (according to the host endianness) the low-order bit of +                                    // the field starts.  AT_bit_offset can be negative. +                                    // +                                    // AT_bit_size indicates the size of the field in bits. +                                    ///////////////////////////////////////////////////////////// + +                                    if (byte_size == 0) +                                        byte_size = member_type->GetByteSize(); + +                                    if (die.GetDWARF()->GetObjectFile()->GetByteOrder() == eByteOrderLittle) +                                    { +                                        this_field_info.bit_offset += byte_size * 8; +                                        this_field_info.bit_offset -= (bit_offset + bit_size); +                                    } +                                    else +                                    { +                                        this_field_info.bit_offset += bit_offset; +                                    } + +                                    // Update the field bit offset we will report for layout +                                    field_bit_offset = this_field_info.bit_offset; + +                                    // If the member to be emitted did not start on a character boundary and there is +                                    // empty space between the last field and this one, then we need to emit an +                                    // anonymous member filling up the space up to its start.  There are three cases +                                    // here: +                                    // +                                    // 1 If the previous member ended on a character boundary, then we can emit an +                                    //   anonymous member starting at the most recent character boundary. +                                    // +                                    // 2 If the previous member did not end on a character boundary and the distance +                                    //   from the end of the previous member to the current member is less than a +                                    //   word width, then we can emit an anonymous member starting right after the +                                    //   previous member and right before this member. +                                    // +                                    // 3 If the previous member did not end on a character boundary and the distance +                                    //   from the end of the previous member to the current member is greater than +                                    //   or equal a word width, then we act as in Case 1. + +                                    const uint64_t character_width = 8; +                                    const uint64_t word_width = 32; + +                                    // Objective-C has invalid DW_AT_bit_offset values in older versions +                                    // of clang, so we have to be careful and only insert unnamed bitfields +                                    // if we have a new enough clang. +                                    bool detect_unnamed_bitfields = true; + +                                    if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus) +                                        detect_unnamed_bitfields = die.GetCU()->Supports_unnamed_objc_bitfields (); + +                                    if (detect_unnamed_bitfields) +                                    { +                                        BitfieldInfo anon_field_info; + +                                        if ((this_field_info.bit_offset % character_width) != 0) // not char aligned +                                        { +                                            uint64_t last_field_end = 0; + +                                            if (last_field_info.IsValid()) +                                                last_field_end = last_field_info.bit_offset + last_field_info.bit_size; + +                                            if (this_field_info.bit_offset != last_field_end) +                                            { +                                                if (((last_field_end % character_width) == 0) ||                    // case 1 +                                                    (this_field_info.bit_offset - last_field_end >= word_width))    // case 3 +                                                { +                                                    anon_field_info.bit_size = this_field_info.bit_offset % character_width; +                                                    anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size; +                                                } +                                                else                                                                // case 2 +                                                { +                                                    anon_field_info.bit_size = this_field_info.bit_offset - last_field_end; +                                                    anon_field_info.bit_offset = last_field_end; +                                                } +                                            } +                                        } + +                                        if (anon_field_info.IsValid()) +                                        { +                                            clang::FieldDecl *unnamed_bitfield_decl = +                                            ClangASTContext::AddFieldToRecordType (class_clang_type, +                                                                                   NULL, +                                                                                   m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), +                                                                                   accessibility, +                                                                                   anon_field_info.bit_size); + +                                            layout_info.field_offsets.insert( +                                                                             std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); +                                        } +                                    } +                                    last_field_info = this_field_info; +                                } +                                else +                                { +                                    last_field_info.Clear(); +                                } + +                                CompilerType member_clang_type = member_type->GetLayoutCompilerType (); +                                if (!member_clang_type.IsCompleteType()) +                                    member_clang_type.GetCompleteType(); + +                                { +                                    // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>). +                                    // If the current field is at the end of the structure, then there is definitely no room for extra +                                    // elements and we override the type to array[0]. + +                                    CompilerType member_array_element_type; +                                    uint64_t member_array_size; +                                    bool member_array_is_incomplete; + +                                    if (member_clang_type.IsArrayType(&member_array_element_type, +                                                                      &member_array_size, +                                                                      &member_array_is_incomplete) && +                                        !member_array_is_incomplete) +                                    { +                                        uint64_t parent_byte_size = parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX); + +                                        if (member_byte_offset >= parent_byte_size) +                                        { +                                            if (member_array_size != 1) +                                            { +                                                module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64, +                                                                        die.GetID(), +                                                                        name, +                                                                        encoding_form.Reference(), +                                                                        parent_die.GetID()); +                                            } + +                                            member_clang_type = m_ast.CreateArrayType(member_array_element_type, 0, false); +                                        } +                                    } +                                } + +                                if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false) +                                { +                                    if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) +                                        module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info", +                                                                parent_die.GetOffset(), +                                                                parent_die.GetName(), +                                                                die.GetOffset(), +                                                                name); +                                    else +                                        module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", +                                                                parent_die.GetOffset(), +                                                                parent_die.GetName(), +                                                                die.GetOffset(), +                                                                name, +                                                                sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); +                                    // We have no choice other than to pretend that the member class +                                    // is complete. If we don't do this, clang will crash when trying +                                    // to layout the class. Since we provide layout assistance, all +                                    // ivars in this class and other classes will be fine, this is +                                    // the best we can do short of crashing. +                                    ClangASTContext::StartTagDeclarationDefinition(member_clang_type); +                                    ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type); +                                } + +                                field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type, +                                                                                    name, +                                                                                    member_clang_type, +                                                                                    accessibility, +                                                                                    bit_size); + +                                m_ast.SetMetadataAsUserID (field_decl, die.GetID()); + +                                layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset)); +                            } +                            else +                            { +                                if (name) +                                    module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed", +                                                            die.GetID(), +                                                            name, +                                                            encoding_form.Reference()); +                                else +                                    module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed", +                                                            die.GetID(), +                                                            encoding_form.Reference()); +                            } +                        } + +                        if (prop_name != NULL && member_type) +                        { +                            clang::ObjCIvarDecl *ivar_decl = NULL; + +                            if (field_decl) +                            { +                                ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl); +                                assert (ivar_decl != NULL); +                            } + +                            ClangASTMetadata metadata; +                            metadata.SetUserID (die.GetID()); +                            delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type, +                                                                                     prop_name, +                                                                                     member_type->GetLayoutCompilerType (), +                                                                                     ivar_decl, +                                                                                     prop_setter_name, +                                                                                     prop_getter_name, +                                                                                     prop_attributes, +                                                                                     &metadata)); + +                            if (ivar_decl) +                                m_ast.SetMetadataAsUserID (ivar_decl, die.GetID()); +                        } +                    } +                } +                ++member_idx; +            } +                break; + +            case DW_TAG_subprogram: +                // Let the type parsing code handle this one for us. +                member_function_dies.Append (die); +                break; + +            case DW_TAG_inheritance: +            { +                is_a_class = true; +                if (default_accessibility == eAccessNone) +                    default_accessibility = eAccessPrivate; +                // TODO: implement DW_TAG_inheritance type parsing +                DWARFAttributes attributes; +                const size_t num_attributes = die.GetAttributes (attributes); +                if (num_attributes > 0) +                { +                    Declaration decl; +                    DWARFExpression location(die.GetCU()); +                    DWARFFormValue encoding_form; +                    AccessType accessibility = default_accessibility; +                    bool is_virtual = false; +                    bool is_base_of_class = true; +                    off_t member_byte_offset = 0; +                    uint32_t i; +                    for (i=0; i<num_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                case DW_AT_type:        encoding_form = form_value; break; +                                case DW_AT_data_member_location: +                                    if (form_value.BlockData()) +                                    { +                                        Value initialValue(0); +                                        Value memberOffset(0); +                                        const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data(); +                                        uint32_t block_length = form_value.Unsigned(); +                                        uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); +                                        if (DWARFExpression::Evaluate (NULL, +                                                                       NULL, +                                                                       NULL, +                                                                       NULL, +                                                                       module_sp, +                                                                       debug_info_data, +                                                                       die.GetCU(), +                                                                       block_offset, +                                                                       block_length, +                                                                       eRegisterKindDWARF, +                                                                       &initialValue, +                                                                       memberOffset, +                                                                       NULL)) +                                        { +                                            member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); +                                        } +                                    } +                                    else +                                    { +                                        // With DWARF 3 and later, if the value is an integer constant, +                                        // this form value is the offset in bytes from the beginning +                                        // of the containing entity. +                                        member_byte_offset = form_value.Unsigned(); +                                    } +                                    break; + +                                case DW_AT_accessibility: +                                    accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); +                                    break; + +                                case DW_AT_virtuality: +                                    is_virtual = form_value.Boolean(); +                                    break; + +                                case DW_AT_sibling: +                                    break; + +                                default: +                                    break; +                            } +                        } +                    } + +                    Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); +                    if (base_class_type == NULL) +                    { +                        module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message", +                                               die.GetOffset(), +                                               encoding_form.Reference(), +                                               parent_die.GetOffset()); +                        break; +                    } + +                    CompilerType base_class_clang_type = base_class_type->GetFullCompilerType (); +                    assert (base_class_clang_type); +                    if (class_language == eLanguageTypeObjC) +                    { +                        ast->SetObjCSuperClass(class_clang_type, base_class_clang_type); +                    } +                    else +                    { +                        base_classes.push_back (ast->CreateBaseClassSpecifier (base_class_clang_type.GetOpaqueQualType(), +                                                                               accessibility, +                                                                               is_virtual, +                                                                               is_base_of_class)); + +                        if (is_virtual) +                        { +                            // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't +                            // give us a constant offset, but gives us a DWARF expressions that requires an actual object +                            // in memory. the DW_AT_data_member_location for a virtual base class looks like: +                            //      DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus ) +                            // Given this, there is really no valid response we can give to clang for virtual base +                            // class offsets, and this should eventually be removed from LayoutRecordType() in the external +                            // AST source in clang. +                        } +                        else +                        { +                            layout_info.base_offsets.insert( +                                                            std::make_pair(ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()), +                                                                           clang::CharUnits::fromQuantity(member_byte_offset))); +                        } +                    } +                } +            } +                break; + +            default: +                break; +        } +    } + +    return true; +} + + +size_t +DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, +                                           clang::DeclContext *containing_decl_ctx, +                                           const DWARFDIE &parent_die, +                                           bool skip_artificial, +                                           bool &is_static, +                                           bool &is_variadic, +                                           std::vector<CompilerType>& function_param_types, +                                           std::vector<clang::ParmVarDecl*>& function_param_decls, +                                           unsigned &type_quals) +{ +    if (!parent_die) +        return 0; + +    size_t arg_idx = 0; +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        const dw_tag_t tag = die.Tag(); +        switch (tag) +        { +            case DW_TAG_formal_parameter: +            { +                DWARFAttributes attributes; +                const size_t num_attributes = die.GetAttributes(attributes); +                if (num_attributes > 0) +                { +                    const char *name = NULL; +                    Declaration decl; +                    DWARFFormValue param_type_die_form; +                    bool is_artificial = false; +                    // one of None, Auto, Register, Extern, Static, PrivateExtern + +                    clang::StorageClass storage = clang::SC_None; +                    uint32_t i; +                    for (i=0; i<num_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; +                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; +                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; +                                case DW_AT_name:        name = form_value.AsCString(); +                                    break; +                                case DW_AT_type:        param_type_die_form = form_value; break; +                                case DW_AT_artificial:  is_artificial = form_value.Boolean(); break; +                                case DW_AT_location: +                                    //                          if (form_value.BlockData()) +                                    //                          { +                                    //                              const DWARFDataExtractor& debug_info_data = debug_info(); +                                    //                              uint32_t block_length = form_value.Unsigned(); +                                    //                              DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length); +                                    //                          } +                                    //                          else +                                    //                          { +                                    //                          } +                                    //                          break; +                                case DW_AT_const_value: +                                case DW_AT_default_value: +                                case DW_AT_description: +                                case DW_AT_endianity: +                                case DW_AT_is_optional: +                                case DW_AT_segment: +                                case DW_AT_variable_parameter: +                                default: +                                case DW_AT_abstract_origin: +                                case DW_AT_sibling: +                                    break; +                            } +                        } +                    } + +                    bool skip = false; +                    if (skip_artificial) +                    { +                        if (is_artificial) +                        { +                            // In order to determine if a C++ member function is +                            // "const" we have to look at the const-ness of "this"... +                            // Ugly, but that +                            if (arg_idx == 0) +                            { +                                if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) +                                { +                                    // Often times compilers omit the "this" name for the +                                    // specification DIEs, so we can't rely upon the name +                                    // being in the formal parameter DIE... +                                    if (name == NULL || ::strcmp(name, "this")==0) +                                    { +                                        Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form).GetUID()); +                                        if (this_type) +                                        { +                                            uint32_t encoding_mask = this_type->GetEncodingMask(); +                                            if (encoding_mask & Type::eEncodingIsPointerUID) +                                            { +                                                is_static = false; + +                                                if (encoding_mask & (1u << Type::eEncodingIsConstUID)) +                                                    type_quals |= clang::Qualifiers::Const; +                                                if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) +                                                    type_quals |= clang::Qualifiers::Volatile; +                                            } +                                        } +                                    } +                                } +                            } +                            skip = true; +                        } +                        else +                        { + +                            // HACK: Objective C formal parameters "self" and "_cmd" +                            // are not marked as artificial in the DWARF... +                            CompileUnit *comp_unit = die.GetLLDBCompileUnit(); +                            if (comp_unit) +                            { +                                switch (comp_unit->GetLanguage()) +                                { +                                    case eLanguageTypeObjC: +                                    case eLanguageTypeObjC_plus_plus: +                                        if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0)) +                                            skip = true; +                                        break; +                                    default: +                                        break; +                                } +                            } +                        } +                    } + +                    if (!skip) +                    { +                        Type *type = die.ResolveTypeUID(DIERef(param_type_die_form).GetUID()); +                        if (type) +                        { +                            function_param_types.push_back (type->GetForwardCompilerType ()); + +                            clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (name, +                                                                                                   type->GetForwardCompilerType (), +                                                                                                   storage); +                            assert(param_var_decl); +                            function_param_decls.push_back(param_var_decl); + +                            m_ast.SetMetadataAsUserID (param_var_decl, die.GetID()); +                        } +                    } +                } +                arg_idx++; +            } +                break; + +            case DW_TAG_unspecified_parameters: +                is_variadic = true; +                break; + +            case DW_TAG_template_type_parameter: +            case DW_TAG_template_value_parameter: +                // The one caller of this was never using the template_param_infos, +                // and the local variable was taking up a large amount of stack space +                // in SymbolFileDWARF::ParseType() so this was removed. If we ever need +                // the template params back, we can add them back. +                // ParseTemplateDIE (dwarf_cu, die, template_param_infos); +                break; + +            default: +                break; +        } +    } +    return arg_idx; +} + +void +DWARFASTParserClang::ParseChildArrayInfo (const SymbolContext& sc, +                                          const DWARFDIE &parent_die, +                                          int64_t& first_index, +                                          std::vector<uint64_t>& element_orders, +                                          uint32_t& byte_stride, +                                          uint32_t& bit_stride) +{ +    if (!parent_die) +        return; + +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        const dw_tag_t tag = die.Tag(); +        switch (tag) +        { +            case DW_TAG_subrange_type: +            { +                DWARFAttributes attributes; +                const size_t num_child_attributes = die.GetAttributes(attributes); +                if (num_child_attributes > 0) +                { +                    uint64_t num_elements = 0; +                    uint64_t lower_bound = 0; +                    uint64_t upper_bound = 0; +                    bool upper_bound_valid = false; +                    uint32_t i; +                    for (i=0; i<num_child_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_name: +                                    break; + +                                case DW_AT_count: +                                    num_elements = form_value.Unsigned(); +                                    break; + +                                case DW_AT_bit_stride: +                                    bit_stride = form_value.Unsigned(); +                                    break; + +                                case DW_AT_byte_stride: +                                    byte_stride = form_value.Unsigned(); +                                    break; + +                                case DW_AT_lower_bound: +                                    lower_bound = form_value.Unsigned(); +                                    break; + +                                case DW_AT_upper_bound: +                                    upper_bound_valid = true; +                                    upper_bound = form_value.Unsigned(); +                                    break; + +                                default: +                                case DW_AT_abstract_origin: +                                case DW_AT_accessibility: +                                case DW_AT_allocated: +                                case DW_AT_associated: +                                case DW_AT_data_location: +                                case DW_AT_declaration: +                                case DW_AT_description: +                                case DW_AT_sibling: +                                case DW_AT_threads_scaled: +                                case DW_AT_type: +                                case DW_AT_visibility: +                                    break; +                            } +                        } +                    } + +                    if (num_elements == 0) +                    { +                        if (upper_bound_valid && upper_bound >= lower_bound) +                            num_elements = upper_bound - lower_bound + 1; +                    } + +                    element_orders.push_back (num_elements); +                } +            } +                break; +        } +    } +} + +Type * +DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die) +{ +    if (die) +    { +        SymbolFileDWARF *dwarf = die.GetDWARF(); +        DWARFAttributes attributes; +        const size_t num_attributes = die.GetAttributes(attributes); +        if (num_attributes > 0) +        { +            DWARFFormValue type_die_form; +            for (size_t i = 0; i < num_attributes; ++i) +            { +                dw_attr_t attr = attributes.AttributeAtIndex(i); +                DWARFFormValue form_value; + +                if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) +                    return dwarf->ResolveTypeUID(DIERef(form_value).GetUID()); +            } +        } +    } + +    return nullptr; +} + +clang::Decl * +DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) +{ +    if (!die) +        return nullptr; + +    switch (die.Tag()) +    { +        case DW_TAG_variable: +        case DW_TAG_constant: +        case DW_TAG_formal_parameter: +        case DW_TAG_imported_declaration: +        case DW_TAG_imported_module: +            break; +        default: +            return nullptr; +    } + +    DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE()); +    if (cache_pos != m_die_to_decl.end()) +        return cache_pos->second; + +    if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) +    { +        clang::Decl *decl = GetClangDeclForDIE(spec_die); +        m_die_to_decl[die.GetDIE()] = decl; +        m_decl_to_die[decl].insert(die.GetDIE()); +        return decl; +    } + +    clang::Decl *decl = nullptr; +    switch (die.Tag()) +    { +        case DW_TAG_variable: +        case DW_TAG_constant: +        case DW_TAG_formal_parameter: +        { +            SymbolFileDWARF *dwarf = die.GetDWARF(); +            Type *type = GetTypeForDIE(die); +            const char *name = die.GetName(); +            clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); +            decl = m_ast.CreateVariableDeclaration( +                decl_context, +                name, +                ClangASTContext::GetQualType(type->GetForwardCompilerType())); +            break; +        } +        case DW_TAG_imported_declaration: +        { +            SymbolFileDWARF *dwarf = die.GetDWARF(); +            lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + +            if (dwarf->UserIDMatches(imported_uid)) +            { +                CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid); +                if (imported_decl) +                { +                    clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); +                    if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)imported_decl.GetOpaqueDecl())) +                        decl = m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl); +                } +            } +            break; +        } +        case DW_TAG_imported_module: +        { +            SymbolFileDWARF *dwarf = die.GetDWARF(); +            lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + +            if (dwarf->UserIDMatches(imported_uid)) +            { +                CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid); +                if (imported_decl) +                { +                    clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); +                    if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl)) +                        decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl); +                } +            } +            break; +        } +        default: +            break; +    } + +    m_die_to_decl[die.GetDIE()] = decl; +    m_decl_to_die[decl].insert(die.GetDIE()); + +    return decl; +} + +clang::DeclContext * +DWARFASTParserClang::GetClangDeclContextForDIE (const DWARFDIE &die) +{ +    if (die) +    { +        clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE (die); +        if (decl_ctx) +            return decl_ctx; + +        bool try_parsing_type = true; +        switch (die.Tag()) +        { +            case DW_TAG_compile_unit: +                decl_ctx = m_ast.GetTranslationUnitDecl(); +                try_parsing_type = false; +                break; + +            case DW_TAG_namespace: +                decl_ctx = ResolveNamespaceDIE (die); +                try_parsing_type = false; +                break; + +            case DW_TAG_lexical_block: +                decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die); +                try_parsing_type = false; +                break; + +            default: +                break; +        } + +        if (decl_ctx == nullptr && try_parsing_type) +        { +            Type* type = die.GetDWARF()->ResolveType (die); +            if (type) +                decl_ctx = GetCachedClangDeclContextForDIE (die); +        } + +        if (decl_ctx) +        { +            LinkDeclContextToDIE (decl_ctx, die); +            return decl_ctx; +        } +    } +    return nullptr; +} + +clang::BlockDecl * +DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die) +{ +    if (die && die.Tag() == DW_TAG_lexical_block) +    { +        clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]); + +        if (!decl) +        { +            DWARFDIE decl_context_die; +            clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die); +            decl = m_ast.CreateBlockDeclaration(decl_context); + +            if (decl) +                LinkDeclContextToDIE((clang::DeclContext *)decl, die); +        } + +        return decl; +    } +    return nullptr; +} + +clang::NamespaceDecl * +DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die) +{ +    if (die && die.Tag() == DW_TAG_namespace) +    { +        // See if we already parsed this namespace DIE and associated it with a +        // uniqued namespace declaration +        clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]); +        if (namespace_decl) +            return namespace_decl; +        else +        { +            const char *namespace_name = die.GetName(); +            clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr); +            namespace_decl = m_ast.GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx); +            Log *log = nullptr;// (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); +            if (log) +            { +                SymbolFileDWARF *dwarf = die.GetDWARF(); +                if (namespace_name) +                { +                    dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                     "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", +                                                                     static_cast<void*>(m_ast.getASTContext()), +                                                                     die.GetID(), +                                                                     namespace_name, +                                                                     static_cast<void*>(namespace_decl), +                                                                     static_cast<void*>(namespace_decl->getOriginalNamespace())); +                } +                else +                { +                    dwarf->GetObjectFile()->GetModule()->LogMessage (log, +                                                                     "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", +                                                                     static_cast<void*>(m_ast.getASTContext()), +                                                                     die.GetID(), +                                                                     static_cast<void*>(namespace_decl), +                                                                     static_cast<void*>(namespace_decl->getOriginalNamespace())); +                } +            } + +            if (namespace_decl) +                LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); +            return namespace_decl; +        } +    } +    return nullptr; +} + +clang::DeclContext * +DWARFASTParserClang::GetClangDeclContextContainingDIE (const DWARFDIE &die, +                                                       DWARFDIE *decl_ctx_die_copy) +{ +    SymbolFileDWARF *dwarf = die.GetDWARF(); + +    DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE (die); + +    if (decl_ctx_die_copy) +        *decl_ctx_die_copy = decl_ctx_die; + +    if (decl_ctx_die) +    { +        clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (decl_ctx_die); +        if (clang_decl_ctx) +            return clang_decl_ctx; +    } +    return m_ast.GetTranslationUnitDecl(); +} + +clang::DeclContext * +DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die) +{ +    if (die) +    { +        DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE()); +        if (pos != m_die_to_decl_ctx.end()) +            return pos->second; +    } +    return nullptr; +} + +void +DWARFASTParserClang::LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die) +{ +    m_die_to_decl_ctx[die.GetDIE()] = decl_ctx; +    // There can be many DIEs for a single decl context +    //m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE()); +    m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die)); +} + +bool +DWARFASTParserClang::CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die, +                                                 const DWARFDIE &dst_class_die, +                                                 lldb_private::Type *class_type, +                                                 DWARFDIECollection &failures) +{ +    if (!class_type || !src_class_die || !dst_class_die) +        return false; +    if (src_class_die.Tag() != dst_class_die.Tag()) +        return false; + +    // We need to complete the class type so we can get all of the method types +    // parsed so we can then unique those types to their equivalent counterparts +    // in "dst_cu" and "dst_class_die" +    class_type->GetFullCompilerType (); + +    DWARFDIE src_die; +    DWARFDIE dst_die; +    UniqueCStringMap<DWARFDIE> src_name_to_die; +    UniqueCStringMap<DWARFDIE> dst_name_to_die; +    UniqueCStringMap<DWARFDIE> src_name_to_die_artificial; +    UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial; +    for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); src_die = src_die.GetSibling()) +    { +        if (src_die.Tag() == DW_TAG_subprogram) +        { +            // Make sure this is a declaration and not a concrete instance by looking +            // for DW_AT_declaration set to 1. Sometimes concrete function instances +            // are placed inside the class definitions and shouldn't be included in +            // the list of things are are tracking here. +            if (src_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) +            { +                const char *src_name = src_die.GetMangledName (); +                if (src_name) +                { +                    ConstString src_const_name(src_name); +                    if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) +                        src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die); +                    else +                        src_name_to_die.Append(src_const_name.GetCString(), src_die); +                } +            } +        } +    } +    for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); dst_die = dst_die.GetSibling()) +    { +        if (dst_die.Tag() == DW_TAG_subprogram) +        { +            // Make sure this is a declaration and not a concrete instance by looking +            // for DW_AT_declaration set to 1. Sometimes concrete function instances +            // are placed inside the class definitions and shouldn't be included in +            // the list of things are are tracking here. +            if (dst_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) +            { +                const char *dst_name =  dst_die.GetMangledName (); +                if (dst_name) +                { +                    ConstString dst_const_name(dst_name); +                    if ( dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0)) +                        dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die); +                    else +                        dst_name_to_die.Append(dst_const_name.GetCString(), dst_die); +                } +            } +        } +    } +    const uint32_t src_size = src_name_to_die.GetSize (); +    const uint32_t dst_size = dst_name_to_die.GetSize (); +    Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION)); + +    // Is everything kosher so we can go through the members at top speed? +    bool fast_path = true; + +    if (src_size != dst_size) +    { +        if (src_size != 0 && dst_size != 0) +        { +            if (log) +                log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)", +                            src_class_die.GetOffset(), +                            dst_class_die.GetOffset(), +                            src_size, +                            dst_size); +        } + +        fast_path = false; +    } + +    uint32_t idx; + +    if (fast_path) +    { +        for (idx = 0; idx < src_size; ++idx) +        { +            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); +            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); + +            if (src_die.Tag() != dst_die.Tag()) +            { +                if (log) +                    log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", +                                src_class_die.GetOffset(), +                                dst_class_die.GetOffset(), +                                src_die.GetOffset(), +                                src_die.GetTagAsCString(), +                                dst_die.GetOffset(), +                                dst_die.GetTagAsCString()); +                fast_path = false; +            } + +            const char *src_name = src_die.GetMangledName (); +            const char *dst_name = dst_die.GetMangledName (); + +            // Make sure the names match +            if (src_name == dst_name || (strcmp (src_name, dst_name) == 0)) +                continue; + +            if (log) +                log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", +                            src_class_die.GetOffset(), +                            dst_class_die.GetOffset(), +                            src_die.GetOffset(), +                            src_name, +                            dst_die.GetOffset(), +                            dst_name); + +            fast_path = false; +        } +    } + +    DWARFASTParserClang *src_dwarf_ast_parser = (DWARFASTParserClang *)src_die.GetDWARFParser(); +    DWARFASTParserClang *dst_dwarf_ast_parser = (DWARFASTParserClang *)dst_die.GetDWARFParser(); + +    // Now do the work of linking the DeclContexts and Types. +    if (fast_path) +    { +        // We can do this quickly.  Just run across the tables index-for-index since +        // we know each node has matching names and tags. +        for (idx = 0; idx < src_size; ++idx) +        { +            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); +            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); + +            clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; +            if (src_decl_ctx) +            { +                if (log) +                    log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", +                                 static_cast<void*>(src_decl_ctx), +                                 src_die.GetOffset(), dst_die.GetOffset()); +                dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); +            } +            else +            { +                if (log) +                    log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", +                                 src_die.GetOffset(), dst_die.GetOffset()); +            } + +            Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; +            if (src_child_type) +            { +                if (log) +                    log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", +                                 static_cast<void*>(src_child_type), +                                 src_child_type->GetID(), +                                 src_die.GetOffset(), dst_die.GetOffset()); +                dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; +            } +            else +            { +                if (log) +                    log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); +            } +        } +    } +    else +    { +        // We must do this slowly.  For each member of the destination, look +        // up a member in the source with the same name, check its tag, and +        // unique them if everything matches up.  Report failures. + +        if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) +        { +            src_name_to_die.Sort(); + +            for (idx = 0; idx < dst_size; ++idx) +            { +                const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx); +                dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); +                src_die = src_name_to_die.Find(dst_name, DWARFDIE()); + +                if (src_die && (src_die.Tag() == dst_die.Tag())) +                { +                    clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; +                    if (src_decl_ctx) +                    { +                        if (log) +                            log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", +                                         static_cast<void*>(src_decl_ctx), +                                         src_die.GetOffset(), +                                         dst_die.GetOffset()); +                        dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); +                    } +                    else +                    { +                        if (log) +                            log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); +                    } + +                    Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; +                    if (src_child_type) +                    { +                        if (log) +                            log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", +                                         static_cast<void*>(src_child_type), +                                         src_child_type->GetID(), +                                         src_die.GetOffset(), +                                         dst_die.GetOffset()); +                        dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; +                    } +                    else +                    { +                        if (log) +                            log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); +                    } +                } +                else +                { +                    if (log) +                        log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die.GetOffset()); + +                    failures.Append(dst_die); +                } +            } +        } +    } + +    const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize (); +    const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize (); + +    if (src_size_artificial && dst_size_artificial) +    { +        dst_name_to_die_artificial.Sort(); + +        for (idx = 0; idx < src_size_artificial; ++idx) +        { +            const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx); +            src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx); +            dst_die = dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE()); + +            if (dst_die) +            { +                // Both classes have the artificial types, link them +                clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()]; +                if (src_decl_ctx) +                { +                    if (log) +                        log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", +                                     static_cast<void*>(src_decl_ctx), +                                     src_die.GetOffset(), dst_die.GetOffset()); +                    dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die); +                } +                else +                { +                    if (log) +                        log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); +                } + +                Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()]; +                if (src_child_type) +                { +                    if (log) +                        log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", +                                     static_cast<void*>(src_child_type), +                                     src_child_type->GetID(), +                                     src_die.GetOffset(), dst_die.GetOffset()); +                    dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type; +                } +                else +                { +                    if (log) +                        log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset()); +                } +            } +        } +    } + +    if (dst_size_artificial) +    { +        for (idx = 0; idx < dst_size_artificial; ++idx) +        { +            const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); +            dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx); +            if (log) +                log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die.GetOffset(), dst_name_artificial); + +            failures.Append(dst_die); +        } +    } + +    return (failures.Size() != 0); +} + + +bool +DWARFASTParserClang::LayoutRecordType(const clang::RecordDecl *record_decl, +                                      uint64_t &bit_size, +                                      uint64_t &alignment, +                                      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, +                                      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, +                                      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) +{ +    RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl); +    bool success = false; +    base_offsets.clear(); +    vbase_offsets.clear(); +    if (pos != m_record_decl_to_layout_map.end()) +    { +        bit_size = pos->second.bit_size; +        alignment = pos->second.alignment; +        field_offsets.swap(pos->second.field_offsets); +        base_offsets.swap (pos->second.base_offsets); +        vbase_offsets.swap (pos->second.vbase_offsets); +        m_record_decl_to_layout_map.erase(pos); +        success = true; +    } +    else +    { +        bit_size = 0; +        alignment = 0; +        field_offsets.clear(); +    } +    return success; +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h new file mode 100644 index 0000000000000..3814758fdd2cf --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -0,0 +1,213 @@ +//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParserClang_h_ +#define SymbolFileDWARF_DWARFASTParserClang_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/CharUnits.h" + +// Project includes +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "DWARFDefines.h" +#include "DWARFASTParser.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserClang : public DWARFASTParser +{ +public: +    DWARFASTParserClang (lldb_private::ClangASTContext &ast); + +    ~DWARFASTParserClang() override; + +    lldb::TypeSP +    ParseTypeFromDWARF (const lldb_private::SymbolContext& sc, +                        const DWARFDIE &die, +                        lldb_private::Log *log, +                        bool *type_is_new_ptr) override; + + +    lldb_private::Function * +    ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc, +                            const DWARFDIE &die) override; + +    bool +    CanCompleteType (const lldb_private::CompilerType &compiler_type) override; + +    bool +    CompleteType (const lldb_private::CompilerType &compiler_type) override; + +    bool +    CompleteTypeFromDWARF (const DWARFDIE &die, +                           lldb_private::Type *type, +                           lldb_private::CompilerType &compiler_type) override; + +    lldb_private::CompilerDecl +    GetDeclForUIDFromDWARF (const DWARFDIE &die) override; + +    std::vector<DWARFDIE> +    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override; + +    lldb_private::CompilerDeclContext +    GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override; + +    lldb_private::CompilerDeclContext +    GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) override; + +    bool +    LayoutRecordType(const clang::RecordDecl *record_decl, +                     uint64_t &bit_size, +                     uint64_t &alignment, +                     llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, +                     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, +                     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); + +protected: +    class DelayedAddObjCClassProperty; +    typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList; + +    struct LayoutInfo +    { +        LayoutInfo () : +        bit_size(0), +        alignment(0), +        field_offsets(), +        base_offsets(), +        vbase_offsets() +        { +        } +        uint64_t bit_size; +        uint64_t alignment; +        llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; +        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; +        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; +    }; + +    clang::BlockDecl * +    ResolveBlockDIE (const DWARFDIE &die); + +    clang::NamespaceDecl * +    ResolveNamespaceDIE (const DWARFDIE &die); + +    typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap; + +    bool +    ParseTemplateDIE (const DWARFDIE &die, +                      lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); +    bool +    ParseTemplateParameterInfos (const DWARFDIE &parent_die, +                                 lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); + +    bool +    ParseChildMembers (const lldb_private::SymbolContext& sc, +                       const DWARFDIE &die, +                       lldb_private::CompilerType &class_compiler_type, +                       const lldb::LanguageType class_language, +                       std::vector<clang::CXXBaseSpecifier *>& base_classes, +                       std::vector<int>& member_accessibilities, +                       DWARFDIECollection& member_function_dies, +                       DelayedPropertyList& delayed_properties, +                       lldb::AccessType &default_accessibility, +                       bool &is_a_class, +                       LayoutInfo &layout_info); + +    size_t +    ParseChildParameters (const lldb_private::SymbolContext& sc, +                          clang::DeclContext *containing_decl_ctx, +                          const DWARFDIE &parent_die, +                          bool skip_artificial, +                          bool &is_static, +                          bool &is_variadic, +                          std::vector<lldb_private::CompilerType>& function_args, +                          std::vector<clang::ParmVarDecl*>& function_param_decls, +                          unsigned &type_quals); + +    void +    ParseChildArrayInfo (const lldb_private::SymbolContext& sc, +                         const DWARFDIE &parent_die, +                         int64_t& first_index, +                         std::vector<uint64_t>& element_orders, +                         uint32_t& byte_stride, +                         uint32_t& bit_stride); + +    size_t +    ParseChildEnumerators (const lldb_private::SymbolContext& sc, +                           lldb_private::CompilerType &compiler_type, +                           bool is_signed, +                           uint32_t enumerator_byte_size, +                           const DWARFDIE &parent_die); + +    lldb_private::Type * +    GetTypeForDIE (const DWARFDIE &die); + +    clang::Decl * +    GetClangDeclForDIE (const DWARFDIE &die); + +    clang::DeclContext * +    GetClangDeclContextForDIE (const DWARFDIE &die); + +    clang::DeclContext * +    GetClangDeclContextContainingDIE (const DWARFDIE &die, +                                      DWARFDIE *decl_ctx_die); + +    bool +    CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die, +                                const DWARFDIE &dst_class_die, +                                lldb_private::Type *class_type, +                                DWARFDIECollection &failures); + +    clang::DeclContext * +    GetCachedClangDeclContextForDIE (const DWARFDIE &die); + +    void +    LinkDeclContextToDIE (clang::DeclContext *decl_ctx, +                          const DWARFDIE &die); + +    void +    LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); + +    lldb_private::ClangASTImporter & +    GetClangASTImporter(); + +    lldb::TypeSP +    ParseTypeFromDWO (const DWARFDIE &die, lldb_private::Log *log); + +    //---------------------------------------------------------------------- +    // Return true if this type is a declaration to a type in an external +    // module. +    //---------------------------------------------------------------------- +    lldb::ModuleSP +    GetModuleForType (const DWARFDIE &die); + +    typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; +    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; +    //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap; +    typedef std::multimap<const clang::DeclContext *, const DWARFDIE> DeclContextToDIEMap; +    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap; +    typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap; + +    lldb_private::ClangASTContext &m_ast; +    DIEToDeclMap m_die_to_decl; +    DeclToDIEMap m_decl_to_die; +    DIEToDeclContextMap m_die_to_decl_ctx; +    DeclContextToDIEMap m_decl_ctx_to_die; +    RecordDeclToLayoutMap m_record_decl_to_layout_map; +    std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap; +}; + +#endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp new file mode 100644 index 0000000000000..bde2694461e2e --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -0,0 +1,828 @@ +//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserGo.h" + +#include "DWARFASTParserGo.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" +#include "DWARFDeclContext.h" +#include "DWARFDefines.h" +#include "DWARFDIE.h" +#include "DWARFDIECollection.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDebugMap.h" +#include "UniqueDWARFASTType.h" + +#include "clang/Basic/Specifiers.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/Value.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/TypeList.h" + +//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN + +#ifdef ENABLE_DEBUG_PRINTF +#include <stdio.h> +#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + +#define DW_AT_go_kind 0x2900 +#define DW_AT_go_key 0x2901 +#define DW_AT_go_elem 0x2902 + +using namespace lldb; +using namespace lldb_private; +DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) +    : m_ast(ast) +{ +} + +DWARFASTParserGo::~DWARFASTParserGo() +{ +} + +TypeSP +DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, +                                     bool *type_is_new_ptr) +{ +    TypeSP type_sp; + +    if (type_is_new_ptr) +        *type_is_new_ptr = false; + +    if (die) +    { +        SymbolFileDWARF *dwarf = die.GetDWARF(); +        if (log) +        { +            dwarf->GetObjectFile()->GetModule()->LogMessage( +                log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(), +                DW_TAG_value_to_name(die.Tag()), die.GetName()); +        } + +        Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); +        TypeList *type_list = dwarf->GetTypeList(); +        if (type_ptr == NULL) +        { +            if (type_is_new_ptr) +                *type_is_new_ptr = true; + +            const dw_tag_t tag = die.Tag(); + +            bool is_forward_declaration = false; +            DWARFAttributes attributes; +            const char *type_name_cstr = NULL; +            ConstString type_name_const_str; +            Type::ResolveState resolve_state = Type::eResolveStateUnresolved; +            uint64_t byte_size = 0; +            uint64_t go_kind = 0; +            Declaration decl; + +            Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; +            CompilerType compiler_type; +            DWARFFormValue form_value; + +            dw_attr_t attr; + +            switch (tag) +            { +                case DW_TAG_base_type: +                case DW_TAG_pointer_type: +                case DW_TAG_typedef: +                case DW_TAG_unspecified_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    const size_t num_attributes = die.GetAttributes(attributes); +                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i = 0; i < num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        if (type_name_cstr) +                                            type_name_const_str.SetCString(type_name_cstr); +                                        break; +                                    case DW_AT_byte_size: +                                        byte_size = form_value.Unsigned(); +                                        break; +                                    case DW_AT_encoding: +                                        // = form_value.Unsigned(); +                                        break; +                                    case DW_AT_type: +                                        encoding_uid = form_value.Reference(); +                                        break; +                                    case DW_AT_go_kind: +                                        go_kind = form_value.Unsigned(); +                                        break; +                                    default: +                                        // Do we care about DW_AT_go_key or DW_AT_go_elem? +                                        break; +                                } +                            } +                        } +                    } + +                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()), +                                 DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); + +                    switch (tag) +                    { +                        default: +                            break; + +                        case DW_TAG_unspecified_type: +                            resolve_state = Type::eResolveStateFull; +                            compiler_type = m_ast.CreateVoidType(type_name_const_str); +                            break; + +                        case DW_TAG_base_type: +                            resolve_state = Type::eResolveStateFull; +                            compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size); +                            break; + +                        case DW_TAG_pointer_type: +                            encoding_data_type = Type::eEncodingIsPointerUID; +                            break; +                        case DW_TAG_typedef: +                            encoding_data_type = Type::eEncodingIsTypedefUID; +                            CompilerType impl; +                            Type *type = dwarf->ResolveTypeUID(encoding_uid); +                            if (type) +                            { +                                if (go_kind == 0 && type->GetName() == type_name_const_str) +                                { +                                    // Go emits extra typedefs as a forward declaration. Ignore these. +                                    dwarf->m_die_to_type[die.GetDIE()] = type; +                                    return type->shared_from_this(); +                                } +                                impl = type->GetForwardCompilerType(); +                                compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl); +                            } +                            break; +                    } + +                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size, +                                           NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state)); + +                    dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); +                } +                break; + +                case DW_TAG_structure_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; +                    bool byte_size_valid = false; + +                    const size_t num_attributes = die.GetAttributes(attributes); +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i = 0; i < num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_byte_size: +                                        byte_size = form_value.Unsigned(); +                                        byte_size_valid = true; +                                        break; + +                                    case DW_AT_go_kind: +                                        go_kind = form_value.Unsigned(); +                                        break; + +                                    // TODO: Should we use SLICETYPE's DW_AT_go_elem? +                                    default: +                                        break; +                                } +                            } +                        } +                    } + +                    // TODO(ribrdb): Do we need this? + +                    // UniqueDWARFASTType is large, so don't create a local variables on the +                    // stack, put it on the heap. This function is often called recursively +                    // and clang isn't good and sharing the stack space for variables in different blocks. +                    std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); + +                    // Only try and unique the type if it has a name. +                    if (type_name_const_str && +                        dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, +                                                               byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) +                    { +                        // We have already parsed this type or from another +                        // compile unit. GCC loves to use the "one definition +                        // rule" which can result in multiple definitions +                        // of the same class over and over in each compile +                        // unit. +                        type_sp = unique_ast_entry_ap->m_type_sp; +                        if (type_sp) +                        { +                            dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); +                            return type_sp; +                        } +                    } + +                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), +                                 DW_TAG_value_to_name(tag), type_name_cstr); + +                    bool compiler_type_was_created = false; +                    compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE())); +                    if (!compiler_type) +                    { +                        compiler_type_was_created = true; +                        compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size); +                    } + +                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size, +                                           NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, +                                           Type::eResolveStateForward)); + +                    // Add our type to the unique type map so we don't +                    // end up creating many copies of the same type over +                    // and over in the ASTContext for our module +                    unique_ast_entry_ap->m_type_sp = type_sp; +                    unique_ast_entry_ap->m_die = die; +                    unique_ast_entry_ap->m_declaration = decl; +                    unique_ast_entry_ap->m_byte_size = byte_size; +                    dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap); + +                    if (!is_forward_declaration) +                    { +                        // Always start the definition for a class type so that +                        // if the class has child classes or types that require +                        // the class to be created for use as their decl contexts +                        // the class will be ready to accept these child definitions. +                        if (die.HasChildren() == false) +                        { +                            // No children for this struct/union/class, lets finish it +                            m_ast.CompleteStructType(compiler_type); +                        } +                        else if (compiler_type_was_created) +                        { +                            // Leave this as a forward declaration until we need +                            // to know the details of the type. lldb_private::Type +                            // will automatically call the SymbolFile virtual function +                            // "SymbolFileDWARF::CompleteType(Type *)" +                            // When the definition needs to be defined. +                            dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType(); +                            dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); +                            // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true); +                        } +                    } +                } +                break; + +                case DW_TAG_subprogram: +                case DW_TAG_subroutine_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    bool is_variadic = false; +                    clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern + +                    const size_t num_attributes = die.GetAttributes(attributes); +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i = 0; i < num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_external: +                                        if (form_value.Unsigned()) +                                        { +                                            if (storage == clang::SC_None) +                                                storage = clang::SC_Extern; +                                            else +                                                storage = clang::SC_PrivateExtern; +                                        } +                                        break; + +                                    case DW_AT_high_pc: +                                    case DW_AT_low_pc: +                                        break; +                                } +                            } +                        } +                    } + +                    DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), +                                 DW_TAG_value_to_name(tag), type_name_cstr); + +                    std::vector<CompilerType> function_param_types; + +                    // Parse the function children for the parameters + +                    if (die.HasChildren()) +                    { +                        ParseChildParameters(sc, die, is_variadic, function_param_types); +                    } + +                    // compiler_type will get the function prototype clang type after this call +                    compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(), +                                                          function_param_types.size(), is_variadic); + +                    type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL, +                                           LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, +                                           Type::eResolveStateFull)); +                    assert(type_sp.get()); +                } +                break; + +                case DW_TAG_array_type: +                { +                    // Set a bit that lets us know that we are currently parsing this +                    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + +                    lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; +                    int64_t first_index = 0; +                    uint32_t byte_stride = 0; +                    uint32_t bit_stride = 0; +                    const size_t num_attributes = die.GetAttributes(attributes); + +                    if (num_attributes > 0) +                    { +                        uint32_t i; +                        for (i = 0; i < num_attributes; ++i) +                        { +                            attr = attributes.AttributeAtIndex(i); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                            { +                                switch (attr) +                                { +                                    case DW_AT_name: +                                        type_name_cstr = form_value.AsCString(); +                                        type_name_const_str.SetCString(type_name_cstr); +                                        break; + +                                    case DW_AT_type: +                                        type_die_offset = form_value.Reference(); +                                        break; +                                    case DW_AT_byte_size: +                                        break; // byte_size = form_value.Unsigned(); break; +                                    case DW_AT_go_kind: +                                        go_kind = form_value.Unsigned(); +                                        break; +                                    default: +                                        break; +                                } +                            } +                        } + +                        DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), +                                     DW_TAG_value_to_name(tag), type_name_cstr); + +                        Type *element_type = dwarf->ResolveTypeUID(type_die_offset); + +                        if (element_type) +                        { +                            std::vector<uint64_t> element_orders; +                            ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride); +                            if (byte_stride == 0) +                                byte_stride = element_type->GetByteSize(); +                            CompilerType array_element_type = element_type->GetForwardCompilerType(); +                            if (element_orders.size() > 0) +                            { +                                if (element_orders.size() > 1) +                                    printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr); +                                compiler_type = +                                    m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]); +                            } +                            else +                            { +                                compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0); +                            } +                            type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, +                                                   byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl, +                                                   compiler_type, Type::eResolveStateFull)); +                            type_sp->SetEncodingType(element_type); +                        } +                    } +                } +                break; + +                default: +                    dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), " +                                                                     "please file a bug and attach the file at the " +                                                                     "start of this error message", +                                                                     die.GetOffset(), tag, DW_TAG_value_to_name(tag)); +                    break; +            } + +            if (type_sp.get()) +            { +                DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); +                dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + +                SymbolContextScope *symbol_context_scope = NULL; +                if (sc_parent_tag == DW_TAG_compile_unit) +                { +                    symbol_context_scope = sc.comp_unit; +                } +                else if (sc.function != NULL && sc_parent_die) +                { +                    symbol_context_scope = +                        sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset())); +                    if (symbol_context_scope == NULL) +                        symbol_context_scope = sc.function; +                } + +                if (symbol_context_scope != NULL) +                { +                    type_sp->SetSymbolContextScope(symbol_context_scope); +                } + +                // We are ready to put this type into the uniqued list up at the module level +                type_list->Insert(type_sp); + +                dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); +            } +        } +        else if (type_ptr != DIE_IS_BEING_PARSED) +        { +            type_sp = type_ptr->shared_from_this(); +        } +    } +    return type_sp; +} + +size_t +DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, + +                                       const DWARFDIE &parent_die, bool &is_variadic, +                                       std::vector<CompilerType> &function_param_types) +{ +    if (!parent_die) +        return 0; + +    size_t arg_idx = 0; +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { + +        dw_tag_t tag = die.Tag(); +        switch (tag) +        { +            case DW_TAG_formal_parameter: +            { +                DWARFAttributes attributes; +                const size_t num_attributes = die.GetAttributes(attributes); +                if (num_attributes > 0) +                { +                    Declaration decl; +                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET; + +                    uint32_t i; +                    for (i = 0; i < num_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_name: +                                    // = form_value.AsCString(); +                                    break; +                                case DW_AT_type: +                                    param_type_die_offset = form_value.Reference(); +                                    break; +                                case DW_AT_location: +                                //                          if (form_value.BlockData()) +                                //                          { +                                //                              const DWARFDataExtractor& debug_info_data = +                                //                              debug_info(); +                                //                              uint32_t block_length = form_value.Unsigned(); +                                //                              DWARFDataExtractor location(debug_info_data, +                                //                              form_value.BlockData() - debug_info_data.GetDataStart(), +                                //                              block_length); +                                //                          } +                                //                          else +                                //                          { +                                //                          } +                                //                          break; +                                default: +                                    break; +                            } +                        } +                    } + +                    Type *type = parent_die.ResolveTypeUID(param_type_die_offset); +                    if (type) +                    { +                        function_param_types.push_back(type->GetForwardCompilerType()); +                    } +                } +                arg_idx++; +            } +            break; + +            case DW_TAG_unspecified_parameters: +                is_variadic = true; +                break; + +            default: +                break; +        } +    } +    return arg_idx; +} + +void +DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, +                                      std::vector<uint64_t> &element_orders, uint32_t &byte_stride, +                                      uint32_t &bit_stride) +{ +    if (!parent_die) +        return; + +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        const dw_tag_t tag = die.Tag(); +        switch (tag) +        { +            case DW_TAG_subrange_type: +            { +                DWARFAttributes attributes; +                const size_t num_child_attributes = die.GetAttributes(attributes); +                if (num_child_attributes > 0) +                { +                    uint64_t num_elements = 0; +                    uint32_t i; +                    for (i = 0; i < num_child_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_count: +                                    num_elements = form_value.Unsigned(); +                                    break; + +                                default: +                                case DW_AT_type: +                                    break; +                            } +                        } +                    } + +                    element_orders.push_back(num_elements); +                } +            } +            break; +        } +    } +} + +bool +DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &compiler_type) +{ +    if (!die) +        return false; + +    const dw_tag_t tag = die.Tag(); + +    SymbolFileDWARF *dwarf = die.GetDWARF(); +    Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); +    if (log) +        dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( +            log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()), +            DW_TAG_value_to_name(tag), type->GetName().AsCString()); +    assert(compiler_type); +    DWARFAttributes attributes; + +    switch (tag) +    { +        case DW_TAG_structure_type: +        { +            { +                if (die.HasChildren()) +                { +                    SymbolContext sc(die.GetLLDBCompileUnit()); + +                    ParseChildMembers(sc, die, compiler_type); +                } +            } +            m_ast.CompleteStructType(compiler_type); +            return (bool)compiler_type; +        } + +        default: +            assert(false && "not a forward go type decl!"); +            break; +    } + +    return false; +} + +size_t +DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type) +{ +    size_t count = 0; +    uint32_t member_idx = 0; + +    ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); +    GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem()); +    if (ast == nullptr) +        return 0; + +    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) +    { +        dw_tag_t tag = die.Tag(); + +        switch (tag) +        { +            case DW_TAG_member: +            { +                DWARFAttributes attributes; +                const size_t num_attributes = die.GetAttributes(attributes); +                if (num_attributes > 0) +                { +                    Declaration decl; +                    const char *name = NULL; + +                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; +                    uint32_t member_byte_offset = UINT32_MAX; +                    uint32_t i; +                    for (i = 0; i < num_attributes; ++i) +                    { +                        const dw_attr_t attr = attributes.AttributeAtIndex(i); +                        DWARFFormValue form_value; +                        if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        { +                            switch (attr) +                            { +                                case DW_AT_name: +                                    name = form_value.AsCString(); +                                    break; +                                case DW_AT_type: +                                    encoding_uid = form_value.Reference(); +                                    break; +                                case DW_AT_data_member_location: +                                    if (form_value.BlockData()) +                                    { +                                        Value initialValue(0); +                                        Value memberOffset(0); +                                        const DWARFDataExtractor &debug_info_data = +                                            die.GetDWARF()->get_debug_info_data(); +                                        uint32_t block_length = form_value.Unsigned(); +                                        uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); +                                        if (DWARFExpression::Evaluate(NULL, // ExecutionContext * +                                                                      NULL, // ClangExpressionVariableList * +                                                                      NULL, // ClangExpressionDeclMap * +                                                                      NULL, // RegisterContext * +                                                                      module_sp, debug_info_data, die.GetCU(), +                                                                      block_offset, block_length, eRegisterKindDWARF, +                                                                      &initialValue, memberOffset, NULL)) +                                        { +                                            member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); +                                        } +                                    } +                                    else +                                    { +                                        // With DWARF 3 and later, if the value is an integer constant, +                                        // this form value is the offset in bytes from the beginning +                                        // of the containing entity. +                                        member_byte_offset = form_value.Unsigned(); +                                    } +                                    break; + +                                default: +                                    break; +                            } +                        } +                    } + +                    Type *member_type = die.ResolveTypeUID(encoding_uid); +                    if (member_type) +                    { +                        CompilerType member_go_type = member_type->GetFullCompilerType(); +                        ConstString name_const_str(name); +                        m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset); +                    } +                } +                ++member_idx; +            } +            break; + +            default: +                break; +        } +    } + +    return count; +} + +Function * +DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die) +{ +    DWARFRangeList func_ranges; +    const char *name = NULL; +    const char *mangled = NULL; +    int decl_file = 0; +    int decl_line = 0; +    int decl_column = 0; +    int call_file = 0; +    int call_line = 0; +    int call_column = 0; +    DWARFExpression frame_base(die.GetCU()); + +    assert(die.Tag() == DW_TAG_subprogram); + +    if (die.Tag() != DW_TAG_subprogram) +        return NULL; + +    if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, +                                 call_column, &frame_base)) +    { +        // Union of all ranges in the function DIE (if the function is discontiguous) +        AddressRange func_range; +        lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0); +        lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0); +        if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) +        { +            ModuleSP module_sp(die.GetModule()); +            func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList()); +            if (func_range.GetBaseAddress().IsValid()) +                func_range.SetByteSize(highest_func_addr - lowest_func_addr); +        } + +        if (func_range.GetBaseAddress().IsValid()) +        { +            Mangled func_name; +            func_name.SetValue(ConstString(name), false); + +            FunctionSP func_sp; +            std::unique_ptr<Declaration> decl_ap; +            if (decl_file != 0 || decl_line != 0 || decl_column != 0) +                decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, +                                              decl_column)); + +            SymbolFileDWARF *dwarf = die.GetDWARF(); +            // Supply the type _only_ if it has already been parsed +            Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE()); + +            assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + +            if (dwarf->FixupAddress(func_range.GetBaseAddress())) +            { +                const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset()); +                func_sp.reset(new Function(sc.comp_unit, +                                           dwarf->MakeUserID(func_user_id), // UserID is the DIE offset +                                           dwarf->MakeUserID(func_user_id), func_name, func_type, +                                           func_range)); // first address range + +                if (func_sp.get() != NULL) +                { +                    if (frame_base.IsValid()) +                        func_sp->GetFrameBaseExpression() = frame_base; +                    sc.comp_unit->AddFunction(func_sp); +                    return func_sp.get(); +                } +            } +        } +    } +    return NULL; +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h new file mode 100644 index 0000000000000..5039fc7f76725 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h @@ -0,0 +1,84 @@ +//===-- DWARFASTParserGo.h --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFASTParserGo_h_ +#define SymbolFileDWARF_DWARFASTParserGo_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +// Project includes +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/GoASTContext.h" +#include "DWARFDefines.h" +#include "DWARFASTParser.h" +#include "DWARFDIE.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserGo : public DWARFASTParser +{ +public: +    DWARFASTParserGo(lldb_private::GoASTContext &ast); + +    ~DWARFASTParserGo() override; + +    lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, +                                    bool *type_is_new_ptr) override; + +    lldb_private::Function * +    ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, +                           const DWARFDIE &die) override; + +    bool +    CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, +                          lldb_private::CompilerType &go_type) override; + +    lldb_private::CompilerDeclContext +    GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override +    { +        return lldb_private::CompilerDeclContext(); +    } + +    lldb_private::CompilerDeclContext +    GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override +    { +        return lldb_private::CompilerDeclContext(); +    } + +    lldb_private::CompilerDecl +    GetDeclForUIDFromDWARF (const DWARFDIE &die) override +    { +        return lldb_private::CompilerDecl(); +    } + +    std::vector<DWARFDIE> +    GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override +    { +        return std::vector<DWARFDIE>(); +    } + +private: +    size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic, +                                std::vector<lldb_private::CompilerType> &function_param_types); +    void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, +                             std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride); + +    size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die, +                             lldb_private::CompilerType &class_compiler_type); + +    lldb_private::GoASTContext &m_ast; +}; + +#endif // SymbolFileDWARF_DWARFASTParserGo_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp new file mode 100644 index 0000000000000..a522bcb35288e --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -0,0 +1,90 @@ +//===-- DWARFAttribute.cpp --------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFAttribute.h" +#include "DWARFDebugInfo.h" +#include "DWARFCompileUnit.h" + +DWARFAttributes::DWARFAttributes() : +    m_infos() +{ +} + +DWARFAttributes::~DWARFAttributes() +{ +} + + +uint32_t +DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const +{ +    collection::const_iterator end = m_infos.end(); +    collection::const_iterator beg = m_infos.begin(); +    collection::const_iterator pos; +    for (pos = beg; pos != end; ++pos) +    { +        if (pos->attr.get_attr() == attr) +            return std::distance(beg, pos); +    } +    return UINT32_MAX; +} + +void +DWARFAttributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form) +{ +    AttributeValue attr_value = { cu, attr_die_offset, { attr, form } }; +    m_infos.push_back(attr_value); +} + +bool +DWARFAttributes::ContainsAttribute(dw_attr_t attr) const +{ +    return FindAttributeIndex(attr) != UINT32_MAX; +} + +bool +DWARFAttributes::RemoveAttribute(dw_attr_t attr) +{ +    uint32_t attr_index = FindAttributeIndex(attr); +    if (attr_index != UINT32_MAX) +    { +        m_infos.erase(m_infos.begin() + attr_index); +        return true; +    } +    return false; +} + +bool +DWARFAttributes::ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const +{ +    const DWARFCompileUnit *cu = CompileUnitAtIndex(i); +    form_value.SetCompileUnit(cu); +    form_value.SetForm(FormAtIndex(i)); +    lldb::offset_t offset = DIEOffsetAtIndex(i); +    return form_value.ExtractValue(cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset); +} + +uint64_t +DWARFAttributes::FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const +{ +    const uint32_t attr_idx = FindAttributeIndex (attr); +    if (attr_idx != UINT32_MAX) +        return FormValueAsUnsignedAtIndex (attr_idx, fail_value); +    return fail_value; +} + +uint64_t +DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const +{ +    DWARFFormValue form_value; +    if (ExtractFormValueAtIndex(i, form_value)) +        return form_value.Reference(); +    return fail_value; +} + diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h index 40c8af3d6e8ec..f5ca9cce525e8 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h @@ -10,36 +10,72 @@  #ifndef SymbolFileDWARF_DWARFAttribute_h_  #define SymbolFileDWARF_DWARFAttribute_h_ +#include "llvm/ADT/SmallVector.h"  #include "DWARFDefines.h"  #include <vector> +class DWARFCompileUnit; +class DWARFFormValue; +  class DWARFAttribute  {  public:      DWARFAttribute(dw_attr_t attr, dw_form_t form) : -        m_attr_form ( attr << 16 | form ) +        m_attr (attr), +        m_form (form)      {      } -    void        set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; } -    void        set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); } -    void        set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; } -    dw_attr_t   get_attr() const { return m_attr_form >> 16; } -    dw_form_t   get_form() const { return (dw_form_t)m_attr_form; } -    void        get(dw_attr_t& attr, dw_form_t& form)  const +    void        set (dw_attr_t attr, dw_form_t form) { m_attr = attr; m_form = form; } +    void        set_attr (dw_attr_t attr) { m_attr = attr; } +    void        set_form (dw_form_t form) { m_form = form; } +    dw_attr_t   get_attr () const { return m_attr; } +    dw_form_t   get_form () const { return m_form; } +    void        get (dw_attr_t& attr, dw_form_t& form)  const      { -        uint32_t attr_form = m_attr_form; -        attr = attr_form >> 16; -        form = (dw_form_t)attr_form; +        attr = m_attr; +        form = m_form;      } -    bool        operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; } +    bool operator == (const DWARFAttribute& rhs) const { return m_attr == rhs.m_attr && m_form == rhs.m_form; }      typedef std::vector<DWARFAttribute> collection;      typedef collection::iterator iterator;      typedef collection::const_iterator const_iterator;  protected: -    uint32_t    m_attr_form;    // Upper 16 bits is attribute, lower 16 bits is form +    dw_attr_t m_attr; +    dw_form_t m_form;  }; +class DWARFAttributes +{ +public: +    DWARFAttributes(); +    ~DWARFAttributes(); + +    void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form); +    const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; } +    dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; } +    dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr.get_attr(); } +    dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); } +    bool ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const; +    uint64_t FormValueAsUnsignedAtIndex (uint32_t i, uint64_t fail_value) const; +    uint64_t FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const; +    uint32_t FindAttributeIndex(dw_attr_t attr) const; +    bool ContainsAttribute(dw_attr_t attr) const; +    bool RemoveAttribute(dw_attr_t attr); +    void Clear() { m_infos.clear(); } +    size_t Size() const { return m_infos.size(); } + +protected: +    struct AttributeValue +    { +        const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values +        dw_offset_t die_offset; +        DWARFAttribute attr; +    }; +    typedef llvm::SmallVector<AttributeValue, 8> collection; +    collection m_infos; +}; +  #endif  // SymbolFileDWARF_DWARFAttribute_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 60933108c97a4..e7cb2b413ad7a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -12,12 +12,13 @@  #include "lldb/Core/Mangled.h"  #include "lldb/Core/Module.h"  #include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h"  #include "lldb/Core/Timer.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/LineTable.h"  #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/ObjCLanguageRuntime.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h"  #include "DWARFDebugAbbrev.h"  #include "DWARFDebugAranges.h" @@ -27,6 +28,7 @@  #include "LogChannelDWARF.h"  #include "NameToDIE.h"  #include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDwo.h"  #include "SymbolFileDWARFDebugMap.h"  using namespace lldb; @@ -52,10 +54,16 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :      m_producer_version_minor (0),      m_producer_version_update (0),      m_language_type (eLanguageTypeUnknown), -    m_is_dwarf64    (false) +    m_is_dwarf64    (false), +    m_is_optimized  (eLazyBoolCalculate), +    m_addr_base (0), +    m_base_obj_offset (DW_INVALID_OFFSET)  {  } +DWARFCompileUnit::~DWARFCompileUnit() +{} +  void  DWARFCompileUnit::Clear()  { @@ -71,6 +79,9 @@ DWARFCompileUnit::Clear()      m_producer      = eProducerInvalid;      m_language_type = eLanguageTypeUnknown;      m_is_dwarf64    = false; +    m_is_optimized  = eLazyBoolCalculate; +    m_addr_base     = 0; +    m_base_obj_offset = DW_INVALID_OFFSET;  }  bool @@ -128,6 +139,9 @@ DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)          if (keep_compile_unit_die)              m_die_array.push_back(tmp_array.front());      } + +    if (m_dwo_symbol_file) +        m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);  }  //---------------------------------------------------------------------- @@ -174,7 +188,8 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)      die_index_stack.reserve(32);      die_index_stack.push_back(0);      bool prev_die_had_children = false; -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); +    DWARFFormValue::FixedFormSizes fixed_form_sizes = +        DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);      while (offset < next_cu_offset &&             die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))      { @@ -188,12 +203,12 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)          const bool null_die = die.IsNULL();          if (depth == 0)          { -            uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); +            if (initial_die_array_size == 0) +                AddCompileUnitDIE(die); +            uint64_t base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);              if (base_addr == LLDB_INVALID_ADDRESS) -                base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); +                base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_entry_pc, 0);              SetBaseAddress (base_addr); -            if (initial_die_array_size == 0) -                AddDIE (die);              if (cu_die_only)                  return 1;          } @@ -283,9 +298,83 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)          verbose_log->PutCString (strm.GetString().c_str());      } -    return m_die_array.size(); +    if (!m_dwo_symbol_file) +        return m_die_array.size(); + +    DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit(); +    size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only); +    return m_die_array.size() + dwo_die_count - 1; // We have 2 CU die, but we waht to count it only as one  } +void +DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry& die) +{ +    assert (m_die_array.empty() && "Compile unit DIE already added"); +    AddDIE(die); +     +    DWARFDebugInfoEntry& cu_die = m_die_array.front(); + +    const char* dwo_name = cu_die.GetAttributeValueAsString(m_dwarf2Data, +                                                            this, +                                                            DW_AT_GNU_dwo_name, +                                                            nullptr); +    if (!dwo_name) +        return; + +    FileSpec dwo_file(dwo_name, true); +    if (dwo_file.IsRelative()) +    { +        const char* comp_dir = cu_die.GetAttributeValueAsString(m_dwarf2Data, +                                                                this, +                                                                DW_AT_comp_dir, +                                                                nullptr); +        if (!comp_dir) +            return; + +        dwo_file.SetFile(comp_dir, true); +        dwo_file.AppendPathComponent(dwo_name); +    } + +    if (!dwo_file.Exists()) +        return; + +    DataBufferSP dwo_file_data_sp; +    lldb::offset_t dwo_file_data_offset = 0; +    ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(m_dwarf2Data->GetObjectFile()->GetModule(), +                                                       &dwo_file, +                                                       0 /* file_offset */, +                                                       dwo_file.GetByteSize(), +                                                       dwo_file_data_sp, +                                                       dwo_file_data_offset); +    if (dwo_obj_file == nullptr) +        return; + +    std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file(new SymbolFileDWARFDwo(dwo_obj_file, this)); + +    DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit(); +    if (!dwo_cu) +        return; // Can't fetch the compile unit from the dwo file. + +    DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); +    if (!dwo_cu_die.IsValid()) +        return; // Can't fetch the compile unit DIE from the dwo file. + +    uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data, +                                                              this, +                                                              DW_AT_GNU_dwo_id, +                                                              0); +    uint64_t sub_dwo_id = dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); +    if (main_dwo_id != sub_dwo_id) +        return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to a differectn compilation. + +    m_dwo_symbol_file = std::move(dwo_symbol_file); +     +    dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data, +                                                             this, +                                                             DW_AT_GNU_addr_base, +                                                             0); +    dwo_cu->SetAddrBase(addr_base, m_offset); +}  dw_offset_t  DWARFCompileUnit::GetAbbrevOffset() const @@ -373,6 +462,16 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)      g_default_addr_size = addr_size;  } +lldb::user_id_t +DWARFCompileUnit::GetID () const +{ +    dw_offset_t local_id = m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; +    if (m_dwarf2Data) +        return m_dwarf2Data->MakeUserID(local_id); +    else +        return local_id; +} +  void  DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,                                            DWARFDebugAranges* debug_aranges) @@ -381,13 +480,15 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,      // in order to produce a compile unit level set of address ranges that      // is accurate. +    size_t num_debug_aranges = debug_aranges->GetNumRanges(); +          // First get the compile unit DIE only and check if it has a DW_AT_ranges -    const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly(); +    const DWARFDebugInfoEntry* die = GetCompileUnitDIEPtrOnly();      const dw_offset_t cu_offset = GetOffset();      if (die)      { -        DWARFDebugRanges::RangeList ranges; +        DWARFRangeList ranges;          const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);          if (num_ranges > 0)          { @@ -397,7 +498,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,              // this with recent GCC builds.              for (size_t i=0; i<num_ranges; ++i)              { -                const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i); +                const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);                  debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());              } @@ -411,11 +512,11 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,      // and then throwing them all away to keep memory usage down.      const bool clear_dies = ExtractDIEsIfNeeded (false) > 1; -    die = DIE(); +    die = DIEPtr();      if (die)          die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); -    if (debug_aranges->IsEmpty()) +    if (debug_aranges->GetNumRanges() == num_debug_aranges)      {          // We got nothing from the functions, maybe we have a line tables only          // situation. Check the line tables and build the arange table from this. @@ -437,7 +538,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,                      {                          const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);                          debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd()); -                        printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());                      }                  }              } @@ -446,7 +546,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,          }      } -    if (debug_aranges->IsEmpty()) +    if (debug_aranges->GetNumRanges() == num_debug_aranges)      {          // We got nothing from the functions, maybe we have a line tables only          // situation. Check the line tables and build the arange table from this. @@ -465,7 +565,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,                  {                      const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);                      debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); -                    printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());                  }              }          } @@ -493,119 +592,85 @@ DWARFCompileUnit::GetFunctionAranges ()                                                                      "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]",                                                                      GetOffset());          } -        const DWARFDebugInfoEntry* die = DIE(); +        const DWARFDebugInfoEntry* die = DIEPtr();          if (die)              die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); + +        if (m_dwo_symbol_file) +        { +            DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit(); +            const DWARFDebugInfoEntry* dwo_die = dwo_cu->DIEPtr(); +            if (dwo_die) +                dwo_die->BuildFunctionAddressRangeTable (m_dwo_symbol_file.get(), +                                                         dwo_cu, +                                                         m_func_aranges_ap.get()); +        } +                  const bool minimize = false;          m_func_aranges_ap->Sort(minimize);      }      return *m_func_aranges_ap.get();  } -bool -DWARFCompileUnit::LookupAddress -( -    const dw_addr_t address, -    DWARFDebugInfoEntry** function_die_handle, -    DWARFDebugInfoEntry** block_die_handle -) +DWARFDIE +DWARFCompileUnit::LookupAddress (const dw_addr_t address)  { -    bool success = false; - -    if (function_die_handle != NULL && DIE()) +    if (DIE())      { -          const DWARFDebugAranges &func_aranges = GetFunctionAranges ();          // Re-check the aranges auto pointer contents in case it was created above          if (!func_aranges.IsEmpty()) -        { -            *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address)); -            if (*function_die_handle != NULL) -            { -                success = true; -                if (block_die_handle != NULL) -                { -                    DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild(); -                    while (child) -                    { -                        if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle)) -                            break; -                        child = child->GetSibling(); -                    } -                } -            } -        } +            return GetDIE(func_aranges.FindAddress(address));      } -    return success; +    return DWARFDIE();  }  //----------------------------------------------------------------------  // Compare function DWARFDebugAranges::Range structures  //---------------------------------------------------------------------- -static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) +static bool CompareDIEOffset (const DWARFDebugInfoEntry& die, const dw_offset_t die_offset)  { -    return die1.GetOffset() < die2.GetOffset(); +    return die.GetOffset() < die_offset;  }  //---------------------------------------------------------------------- -// GetDIEPtr() +// GetDIE()  // -// Get the DIE (Debug Information Entry) with the specified offset. +// Get the DIE (Debug Information Entry) with the specified offset by +// first checking if the DIE is contained within this compile unit and +// grabbing the DIE from this compile unit. Otherwise we grab the DIE +// from the DWARF file.  //---------------------------------------------------------------------- -DWARFDebugInfoEntry* -DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset) +DWARFDIE +DWARFCompileUnit::GetDIE (dw_offset_t die_offset)  {      if (die_offset != DW_INVALID_OFFSET)      { -        ExtractDIEsIfNeeded (false); -        DWARFDebugInfoEntry compare_die; -        compare_die.SetOffset(die_offset); -        DWARFDebugInfoEntry::iterator end = m_die_array.end(); -        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); -        if (pos != end) -        { -            if (die_offset == (*pos).GetOffset()) -                return &(*pos); -        } -    } -    return NULL;    // Not found in any compile units -} +        if (m_dwo_symbol_file) +            return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset); -//---------------------------------------------------------------------- -// GetDIEPtrContainingOffset() -// -// Get the DIE (Debug Information Entry) that contains the specified -// .debug_info offset. -//---------------------------------------------------------------------- -const DWARFDebugInfoEntry* -DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset) -{ -    if (die_offset != DW_INVALID_OFFSET) -    { -        ExtractDIEsIfNeeded (false); -        DWARFDebugInfoEntry compare_die; -        compare_die.SetOffset(die_offset); -        DWARFDebugInfoEntry::iterator end = m_die_array.end(); -        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); -        if (pos != end) +        if (ContainsDIEOffset(die_offset))          { -            if (die_offset >= (*pos).GetOffset()) +            ExtractDIEsIfNeeded (false); +            DWARFDebugInfoEntry::iterator end = m_die_array.end(); +            DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset); +            if (pos != end)              { -                DWARFDebugInfoEntry::iterator next = pos + 1; -                if (next != end) -                { -                    if (die_offset < (*next).GetOffset()) -                        return &(*pos); -                } +                if (die_offset == (*pos).GetOffset()) +                    return DWARFDIE(this, &(*pos));              }          } +        else +        { +            // Don't specify the compile unit offset as we don't know it because the DIE belongs to +            // a different compile unit in the same symbol file. +            return m_dwarf2Data->DebugInfo()->GetDIE (DIERef(die_offset)); +        }      } -    return NULL;    // Not found in any compile units +    return DWARFDIE(); // Not found  } - -  size_t  DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const  { @@ -615,7 +680,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die      for (pos = m_die_array.begin(); pos != end; ++pos)      {          if (pos->Tag() == tag) -            dies.Append (&(*pos)); +            dies.Append (DWARFDIE(this, &(*pos)));      }      // Return the number of DIEs added to the collection @@ -646,8 +711,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die  void -DWARFCompileUnit::Index (const uint32_t cu_idx, -                         NameToDIE& func_basenames, +DWARFCompileUnit::Index (NameToDIE& func_basenames,                           NameToDIE& func_fullnames,                           NameToDIE& func_methods,                           NameToDIE& func_selectors, @@ -656,10 +720,6 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                           NameToDIE& types,                           NameToDIE& namespaces)  { -    const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); - -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); -      Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));      if (log) @@ -670,9 +730,57 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,      }      const LanguageType cu_language = GetLanguageType(); +    DWARFFormValue::FixedFormSizes fixed_form_sizes = +        DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); +     +    IndexPrivate(this, +                 cu_language, +                 fixed_form_sizes, +                 GetOffset(), +                 func_basenames, +                 func_fullnames, +                 func_methods, +                 func_selectors, +                 objc_class_selectors, +                 globals, +                 types, +                 namespaces); + +    SymbolFileDWARFDwo* dwo_symbol_file = GetDwoSymbolFile(); +    if (dwo_symbol_file) +    { +        IndexPrivate(dwo_symbol_file->GetCompileUnit(), +                     cu_language, +                     fixed_form_sizes, +                     GetOffset(), +                     func_basenames, +                     func_fullnames, +                     func_methods, +                     func_selectors, +                     objc_class_selectors, +                     globals, +                     types, +                     namespaces); +    } +} + +void +DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, +                                const LanguageType cu_language, +                                const DWARFFormValue::FixedFormSizes& fixed_form_sizes, +                                const dw_offset_t cu_offset, +                                NameToDIE& func_basenames, +                                NameToDIE& func_fullnames, +                                NameToDIE& func_methods, +                                NameToDIE& func_selectors, +                                NameToDIE& objc_class_selectors, +                                NameToDIE& globals, +                                NameToDIE& types, +                                NameToDIE& namespaces) +{      DWARFDebugInfoEntry::const_iterator pos; -    DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); -    DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); +    DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin(); +    DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();      for (pos = begin; pos != end; ++pos)      {          const DWARFDebugInfoEntry &die = *pos; @@ -701,17 +809,17 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,              continue;          } -        DWARFDebugInfoEntry::Attributes attributes; +        DWARFAttributes attributes;          const char *name = NULL;          const char *mangled_cstr = NULL;          bool is_declaration = false;          //bool is_artificial = false;          bool has_address = false; -        bool has_location = false; +        bool has_location_or_const_value = false;          bool is_global_or_static_variable = false; -        dw_offset_t specification_die_offset = DW_INVALID_OFFSET; -        const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); +        DWARFFormValue specification_die_form; +        const size_t num_attributes = die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);          if (num_attributes > 0)          {              for (uint32_t i=0; i<num_attributes; ++i) @@ -721,24 +829,24 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                  switch (attr)                  {                  case DW_AT_name: -                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) -                        name = form_value.AsCString(debug_str); +                    if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        name = form_value.AsCString();                      break;                  case DW_AT_declaration: -                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) +                    if (attributes.ExtractFormValueAtIndex(i, form_value))                          is_declaration = form_value.Unsigned() != 0;                      break;  //                case DW_AT_artificial: -//                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) +//                    if (attributes.ExtractFormValueAtIndex(i, form_value))  //                        is_artificial = form_value.Unsigned() != 0;  //                    break;                  case DW_AT_MIPS_linkage_name:                  case DW_AT_linkage_name: -                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) -                        mangled_cstr = form_value.AsCString(debug_str);                         +                    if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        mangled_cstr = form_value.AsCString();                      break;                  case DW_AT_low_pc: @@ -752,7 +860,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                      break;                  case DW_AT_location: -                    has_location = true; +                case DW_AT_const_value: +                    has_location_or_const_value = true;                      if (tag == DW_TAG_variable)                      {                          const DWARFDebugInfoEntry* parent_die = die.GetParent(); @@ -800,8 +909,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                      break;                  case DW_AT_specification: -                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) -                        specification_die_offset = form_value.Reference(); +                    if (attributes.ExtractFormValueAtIndex(i, form_value)) +                        specification_die_form = form_value;                      break;                  }              } @@ -814,24 +923,22 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,              {                  if (name)                  { -                    // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the -                    // simple inlined check outside the call. -                    ObjCLanguageRuntime::MethodName objc_method(name, true); +                    ObjCLanguage::MethodName objc_method(name, true);                      if (objc_method.IsValid(true))                      {                          ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());                          ConstString objc_selector_name (objc_method.GetSelector());                          ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));                          ConstString objc_class_name_no_category (objc_method.GetClassName()); -                        func_fullnames.Insert (ConstString(name), die.GetOffset()); +                        func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                          if (objc_class_name_with_category) -                            objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset()); +                            objc_class_selectors.Insert(objc_class_name_with_category, DIERef(cu_offset, die.GetOffset()));                          if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category) -                            objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); +                            objc_class_selectors.Insert(objc_class_name_no_category, DIERef(cu_offset, die.GetOffset()));                          if (objc_selector_name) -                            func_selectors.Insert (objc_selector_name, die.GetOffset()); +                            func_selectors.Insert (objc_selector_name, DIERef(cu_offset, die.GetOffset()));                          if (objc_fullname_no_category_name) -                            func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); +                            func_fullnames.Insert (objc_fullname_no_category_name, DIERef(cu_offset, die.GetOffset()));                      }                      // If we have a mangled name, then the DW_AT_name attribute                      // is usually the method name without the class or any parameters @@ -846,32 +953,23 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                          }                          else                          { -                            if (specification_die_offset != DW_INVALID_OFFSET) +                            if (specification_die_form.IsValid())                              { -                                const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); -                                if (specification_die) -                                { -                                    parent = specification_die->GetParent(); -                                    if (parent) -                                    { -                                        parent_tag = parent->Tag(); -                                     -                                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) -                                            is_method = true; -                                    } -                                } +                                DWARFDIE specification_die = dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE (DIERef(specification_die_form)); +                                if (specification_die.GetParent().IsStructOrClass()) +                                    is_method = true;                              }                          }                      }                      if (is_method) -                        func_methods.Insert (ConstString(name), die.GetOffset()); +                        func_methods.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                      else -                        func_basenames.Insert (ConstString(name), die.GetOffset()); +                        func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                      if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) -                        func_fullnames.Insert (ConstString(name), die.GetOffset()); +                        func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                  }                  if (mangled_cstr)                  { @@ -882,10 +980,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                      if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))                      {                          Mangled mangled (ConstString(mangled_cstr), true); -                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); +                        func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));                          ConstString demangled = mangled.GetDemangledName(cu_language);                          if (demangled) -                            func_fullnames.Insert (demangled, die.GetOffset()); +                            func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));                      }                  }              } @@ -895,7 +993,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,              if (has_address)              {                  if (name) -                    func_basenames.Insert (ConstString(name), die.GetOffset()); +                    func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                  if (mangled_cstr)                  {                      // Make sure our mangled name isn't the same string table entry @@ -905,14 +1003,14 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                      if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))                      {                          Mangled mangled (ConstString(mangled_cstr), true); -                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); +                        func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));                          ConstString demangled = mangled.GetDemangledName(cu_language);                          if (demangled) -                            func_fullnames.Insert (demangled, die.GetOffset()); +                            func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));                      }                  }                  else -                    func_fullnames.Insert (ConstString(name), die.GetOffset()); +                    func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));              }              break; @@ -928,19 +1026,19 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,          case DW_TAG_unspecified_type:              if (name && is_declaration == false)              { -                types.Insert (ConstString(name), die.GetOffset()); +                types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));              }              break;          case DW_TAG_namespace:              if (name) -                namespaces.Insert (ConstString(name), die.GetOffset()); +                namespaces.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));              break;          case DW_TAG_variable: -            if (name && has_location && is_global_or_static_variable) +            if (name && has_location_or_const_value && is_global_or_static_variable)              { -                globals.Insert (ConstString(name), die.GetOffset()); +                globals.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));                  // Be sure to include variables by their mangled and demangled                  // names if they have any since a variable can have a basename                  // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled  @@ -953,10 +1051,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,                  if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))                  {                      Mangled mangled (ConstString(mangled_cstr), true); -                    globals.Insert (mangled.GetMangledName(), die.GetOffset()); +                    globals.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));                      ConstString demangled = mangled.GetDemangledName(cu_language);                      if (demangled) -                        globals.Insert (demangled, die.GetOffset()); +                        globals.Insert (demangled, DIERef(cu_offset, die.GetOffset()));                  }              }              break; @@ -1004,7 +1102,7 @@ DWARFCompileUnit::ParseProducerInfo ()      m_producer_version_minor = UINT32_MAX;      m_producer_version_update = UINT32_MAX; -    const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); +    const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();      if (die)      { @@ -1095,10 +1193,9 @@ DWARFCompileUnit::GetLanguageType()      if (m_language_type != eLanguageTypeUnknown)          return m_language_type; -    const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); +    const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();      if (die) -        m_language_type = LanguageTypeFromDWARF( -            die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0)); +        m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0));      return m_language_type;  } @@ -1108,3 +1205,57 @@ DWARFCompileUnit::IsDWARF64() const      return m_is_dwarf64;  } +bool +DWARFCompileUnit::GetIsOptimized () +{ +    if (m_is_optimized == eLazyBoolCalculate) +    { +        const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly(); +        if (die) +        { +            m_is_optimized = eLazyBoolNo; +            if (die->GetAttributeValueAsUnsigned (m_dwarf2Data, this, DW_AT_APPLE_optimized, 0) == 1) +            { +                m_is_optimized = eLazyBoolYes; +            } +        } +    } +    if (m_is_optimized == eLazyBoolYes) +    { +        return true; +    } +    else +    { +        return false; +    } +} + +DWARFFormValue::FixedFormSizes +DWARFCompileUnit::GetFixedFormSizes () +{ +    return DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), IsDWARF64()); +} + +TypeSystem * +DWARFCompileUnit::GetTypeSystem () +{ +    if (m_dwarf2Data) +        return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType()); +    else +        return nullptr; +} + +void +DWARFCompileUnit::SetUserData(void *d) +{ +    m_user_data = d; +    if (m_dwo_symbol_file) +        m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); +} + +void +DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset) +{ +    m_addr_base = addr_base; +    m_base_obj_offset = base_obj_offset; +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 93c8df822dcc4..0fcaaca09ed8c 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -12,9 +12,11 @@  #include "lldb/lldb-enumerations.h"  #include "DWARFDebugInfoEntry.h" -#include "SymbolFileDWARF.h" +#include "DWARFDIE.h"  class NameToDIE; +class SymbolFileDWARF; +class SymbolFileDWARFDwo;  class DWARFCompileUnit  { @@ -29,19 +31,17 @@ public:      };      DWARFCompileUnit(SymbolFileDWARF* dwarf2Data); +    ~DWARFCompileUnit();      bool        Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr);      size_t      ExtractDIEsIfNeeded (bool cu_die_only); -    bool        LookupAddress( -                    const dw_addr_t address, -                    DWARFDebugInfoEntry** function_die, -                    DWARFDebugInfoEntry** block_die); - +    DWARFDIE    LookupAddress(const dw_addr_t address);      size_t      AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT32_MAX) const;      void        Clear();      bool        Verify(lldb_private::Stream *s) const;      void        Dump(lldb_private::Stream *s) const;      dw_offset_t GetOffset() const { return m_offset; } +    lldb::user_id_t GetID () const;      uint32_t    Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ }      bool        ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }      dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } @@ -53,32 +53,35 @@ public:      dw_offset_t GetAbbrevOffset() const;      uint8_t     GetAddressByteSize() const { return m_addr_size; }      dw_addr_t   GetBaseAddress() const { return m_base_addr; } +    dw_addr_t   GetAddrBase() const { return m_addr_base; } +    void        SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset);      void        ClearDIEs(bool keep_compile_unit_die);      void        BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,                                          DWARFDebugAranges* debug_aranges); + +    lldb_private::TypeSystem * +                GetTypeSystem(); + +    DWARFFormValue::FixedFormSizes +                GetFixedFormSizes (); +      void      SetBaseAddress(dw_addr_t base_addr)      {          m_base_addr = base_addr;      } -    const DWARFDebugInfoEntry* +    DWARFDIE      GetCompileUnitDIEOnly()      { -        ExtractDIEsIfNeeded (true); -        if (m_die_array.empty()) -            return NULL; -        return &m_die_array[0]; +        return DWARFDIE(this, GetCompileUnitDIEPtrOnly());      } -    const DWARFDebugInfoEntry* -    DIE() +    DWARFDIE +    DIE ()      { -        ExtractDIEsIfNeeded (false); -        if (m_die_array.empty()) -            return NULL; -        return &m_die_array[0]; +        return DWARFDIE(this, DIEPtr());      }      void @@ -97,6 +100,9 @@ public:              m_die_array.reserve(GetDebugInfoSize() / 24);          m_die_array.push_back(die);      } +     +    void +    AddCompileUnitDIE (DWARFDebugInfoEntry& die);      bool      HasDIEsParsed () const @@ -104,17 +110,8 @@ public:          return m_die_array.size() > 1;      } -    DWARFDebugInfoEntry* -    GetDIEAtIndexUnchecked (uint32_t idx) -    { -        return &m_die_array[idx]; -    } - -    DWARFDebugInfoEntry* -    GetDIEPtr (dw_offset_t die_offset); - -    const DWARFDebugInfoEntry* -    GetDIEPtrContainingOffset (dw_offset_t die_offset); +    DWARFDIE +    GetDIE (dw_offset_t die_offset);      static uint8_t      GetAddressByteSize(const DWARFCompileUnit* cu); @@ -135,10 +132,7 @@ public:      }      void -    SetUserData(void *d) -    { -        m_user_data = d; -    } +    SetUserData(void *d);      bool      Supports_DW_AT_APPLE_objc_complete_type (); @@ -149,15 +143,8 @@ public:      bool      Supports_unnamed_objc_bitfields (); -//    void -//    AddGlobalDIEByIndex (uint32_t die_idx); -// -//    void -//    AddGlobal (const DWARFDebugInfoEntry* die); -//      void -    Index (const uint32_t cu_idx, -           NameToDIE& func_basenames, +    Index (NameToDIE& func_basenames,             NameToDIE& func_fullnames,             NameToDIE& func_methods,             NameToDIE& func_selectors, @@ -196,8 +183,24 @@ public:      bool      IsDWARF64() const; +    bool +    GetIsOptimized (); + +    SymbolFileDWARFDwo* +    GetDwoSymbolFile() const +    { +        return m_dwo_symbol_file.get(); +    } + +    dw_offset_t +    GetBaseObjOffset() const +    { +        return m_base_obj_offset; +    } +  protected:      SymbolFileDWARF*    m_dwarf2Data; +    std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;      const DWARFAbbreviationDeclarationSet *m_abbrevs;      void *              m_user_data;      DWARFDebugInfoEntry::collection m_die_array;    // The compile unit debug information entry item @@ -213,10 +216,49 @@ protected:      uint32_t            m_producer_version_update;      lldb::LanguageType  m_language_type;      bool                m_is_dwarf64; -     +    lldb_private::LazyBool m_is_optimized; +    dw_addr_t           m_addr_base;       // Value of DW_AT_addr_base +    dw_offset_t         m_base_obj_offset; // If this is a dwo compile unit this is the offset of +                                           // the base compile unit in the main object file +      void      ParseProducerInfo (); + +    static void +    IndexPrivate (DWARFCompileUnit* dwarf_cu, +                  const lldb::LanguageType cu_language, +                  const DWARFFormValue::FixedFormSizes& fixed_form_sizes, +                  const dw_offset_t cu_offset, +                  NameToDIE& func_basenames, +                  NameToDIE& func_fullnames, +                  NameToDIE& func_methods, +                  NameToDIE& func_selectors, +                  NameToDIE& objc_class_selectors, +                  NameToDIE& globals, +                  NameToDIE& types, +                  NameToDIE& namespaces); +  private: + +    const DWARFDebugInfoEntry* +    GetCompileUnitDIEPtrOnly() +    { +        ExtractDIEsIfNeeded (true); +        if (m_die_array.empty()) +            return NULL; +        return &m_die_array[0]; +    } + +    const DWARFDebugInfoEntry* +    DIEPtr() +    { +        ExtractDIEsIfNeeded (false); +        if (m_die_array.empty()) +            return NULL; +        return &m_die_array[0]; +    } + +      DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit);  }; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp new file mode 100644 index 0000000000000..0564de9e5dd1f --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -0,0 +1,543 @@ +//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDIE.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugAbbrev.h" +#include "DWARFDebugAranges.h" +#include "DWARFDebugInfo.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDebugRanges.h" +#include "DWARFDeclContext.h" +#include "DWARFDIECollection.h" +#include "DWARFFormValue.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeSystem.h" + +using namespace lldb_private; + +DIERef +DWARFDIE::GetDIERef() const +{ +    if (!IsValid()) +        return DIERef(); + +    dw_offset_t cu_offset = m_cu->GetOffset(); +    if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) +        cu_offset = m_cu->GetBaseObjOffset(); +    return DIERef(cu_offset, m_die->GetOffset()); +} + +dw_tag_t +DWARFDIE::Tag() const +{ +    if (m_die) +        return m_die->Tag(); +    else +        return 0; +} + +const char * +DWARFDIE::GetTagAsCString () const +{ +    return lldb_private::DW_TAG_value_to_name (Tag()); +} + +DWARFDIE +DWARFDIE::GetParent () const +{ +    if (IsValid()) +        return DWARFDIE(m_cu, m_die->GetParent()); +    else +        return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetFirstChild () const +{ +    if (IsValid()) +        return DWARFDIE(m_cu, m_die->GetFirstChild()); +    else +        return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetSibling () const +{ +    if (IsValid()) +        return DWARFDIE(m_cu, m_die->GetSibling()); +    else +        return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetReferencedDIE (const dw_attr_t attr) const +{ +    const dw_offset_t die_offset = GetAttributeValueAsReference (attr, DW_INVALID_OFFSET); +    if (die_offset != DW_INVALID_OFFSET) +        return GetDIE(die_offset); +    else +        return DWARFDIE(); +} + +DWARFDIE +DWARFDIE::GetDIE (dw_offset_t die_offset) const +{ +    if (IsValid()) +        return m_cu->GetDIE(die_offset); +    else +        return DWARFDIE(); +} + +const char * +DWARFDIE::GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const +{ +    if (IsValid()) +        return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, fail_value); +    else +        return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const +{ +    if (IsValid()) +        return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, fail_value); +    else +        return fail_value; +} + +int64_t +DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const +{ +    if (IsValid()) +        return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, fail_value); +    else +        return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const +{ +    if (IsValid()) +        return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, fail_value); +    else +        return fail_value; +} + +uint64_t +DWARFDIE::GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const +{ +    if (IsValid()) +        return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, fail_value); +    else +        return fail_value; +} + + +DWARFDIE +DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const +{ +    if (IsValid()) +    { +        SymbolFileDWARF *dwarf= GetDWARF(); +        DWARFCompileUnit *cu = GetCU(); +        DWARFDebugInfoEntry* function_die = nullptr; +        DWARFDebugInfoEntry* block_die = nullptr; +        if (m_die->LookupAddress (file_addr, +                                  dwarf, +                                  cu, +                                  &function_die, +                                  &block_die)) +        { +            if (block_die && block_die != function_die) +            { +                if (cu->ContainsDIEOffset(block_die->GetOffset())) +                    return DWARFDIE(cu, block_die); +                else +                    return DWARFDIE(dwarf->DebugInfo()->GetCompileUnitContainingDIE(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die); +            } +        } +    } +    return DWARFDIE(); +} + +lldb::user_id_t +DWARFDIE::GetID () const +{ +    const dw_offset_t die_offset = GetOffset(); +    if (die_offset != DW_INVALID_OFFSET) +    { +        lldb::user_id_t id = 0; +        SymbolFileDWARF *dwarf = GetDWARF(); +        if (dwarf) +            id = dwarf->MakeUserID(die_offset); +        else +            id = die_offset; + +        if (m_cu) +        { +            lldb::user_id_t cu_id = m_cu->GetID()&0xffffffff00000000ull; +            assert ((id&0xffffffff00000000ull) == 0 || +                    (cu_id&0xffffffff00000000ll) == 0 || +                    (id&0xffffffff00000000ull) == (cu_id&0xffffffff00000000ll)); +            id |= cu_id; +        } +        return id; +    } +    return LLDB_INVALID_UID; +} + +const char * +DWARFDIE::GetName () const +{ +    if (IsValid()) +        return m_die->GetName (GetDWARF(), m_cu); +    else +        return nullptr; +} + +const char * +DWARFDIE::GetMangledName () const +{ +    if (IsValid()) +        return m_die->GetMangledName (GetDWARF(), m_cu); +    else +        return nullptr; +} + +const char * +DWARFDIE::GetPubname () const +{ +    if (IsValid()) +        return m_die->GetPubname (GetDWARF(), m_cu); +    else +        return nullptr; +} + +const char * +DWARFDIE::GetQualifiedName (std::string &storage) const +{ +    if (IsValid()) +        return m_die->GetQualifiedName (GetDWARF(), m_cu, storage); +    else +        return nullptr; +} + +lldb::LanguageType +DWARFDIE::GetLanguage () const +{ +    if (IsValid()) +        return m_cu->GetLanguageType(); +    else +        return lldb::eLanguageTypeUnknown; +} + + +lldb::ModuleSP +DWARFDIE::GetModule () const +{ +    SymbolFileDWARF *dwarf = GetDWARF(); +    if (dwarf) +        return dwarf->GetObjectFile()->GetModule(); +    else +        return lldb::ModuleSP(); +} + +lldb_private::CompileUnit * +DWARFDIE::GetLLDBCompileUnit () const +{ +    if (IsValid()) +        return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU()); +    else +        return nullptr; +} + +lldb_private::Type * +DWARFDIE::ResolveType () const +{ +    if (IsValid()) +        return GetDWARF()->ResolveType(*this, true); +    else +        return nullptr; +} + +lldb_private::Type * +DWARFDIE::ResolveTypeUID (lldb::user_id_t uid) const +{ +    SymbolFileDWARF *dwarf = GetDWARF(); +    if (dwarf) +        return dwarf->ResolveTypeUID(uid); +    else +        return nullptr; +} + +void +DWARFDIE::GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const +{ +    if (IsValid()) +    { +        DWARFDIE parent_decl_ctx_die = m_die->GetParentDeclContextDIE (GetDWARF(), GetCU()); +        if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) +        { +            decl_context_dies.Append(parent_decl_ctx_die); +            parent_decl_ctx_die.GetDeclContextDIEs (decl_context_dies); +        } +    } +} + +void +DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const +{ +    if (IsValid()) +    { +        m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx); +    } +    else +    { +        dwarf_decl_ctx.Clear(); +    } +} + +void +DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const +{ +    const dw_tag_t tag = Tag(); +    if (tag == DW_TAG_compile_unit) +        return; +    DWARFDIE parent = GetParent(); +    if (parent) +        parent.GetDWOContext(context); +    switch (tag) +    { +        case DW_TAG_module: +            context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); +            break; +        case DW_TAG_namespace: +            context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName()))); +            break; +        case DW_TAG_structure_type: +            context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName()))); +            break; +        case DW_TAG_union_type: +            context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); +            break; +        case DW_TAG_class_type: +            context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); +            break; +        case DW_TAG_enumeration_type: +            context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName()))); +            break; +        case DW_TAG_subprogram: +            context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname()))); +            break; +        case DW_TAG_variable: +            context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname()))); +            break; +        case DW_TAG_typedef: +            context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); +            break; +        default: +            break; +    } +} + + + +DWARFDIE +DWARFDIE::GetParentDeclContextDIE () const +{ +    if (IsValid()) +        return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu); +    else +        return DWARFDIE(); +} + + +dw_offset_t +DWARFDIE::GetOffset () const +{ +    if (IsValid()) +        return m_die->GetOffset(); +    else +        return DW_INVALID_OFFSET; +} + +dw_offset_t +DWARFDIE::GetCompileUnitRelativeOffset () const +{ +    if (IsValid()) +        return m_die->GetOffset() - m_cu->GetOffset(); +    else +        return DW_INVALID_OFFSET; +} + +SymbolFileDWARF * +DWARFDIE::GetDWARF () const +{ +    if (m_cu) +        return m_cu->GetSymbolFileDWARF(); +    else +        return nullptr; +} + +lldb_private::TypeSystem * +DWARFDIE::GetTypeSystem () const +{ +    if (m_cu) +        return m_cu->GetTypeSystem(); +    else +        return nullptr; +} + +DWARFASTParser * +DWARFDIE::GetDWARFParser () const +{ +    lldb_private::TypeSystem *type_system = GetTypeSystem (); +    if (type_system) +        return type_system->GetDWARFParser(); +    else +        return nullptr; +} + +bool +DWARFDIE::IsStructOrClass () const +{ +    const dw_tag_t tag = Tag(); +    return tag == DW_TAG_class_type || tag == DW_TAG_structure_type; +} + + +DWARFDIE +DWARFDIE::GetContainingDWOModuleDIE () const +{ +    if (IsValid()) +    { +        DWARFDIE top_module_die; +        // Now make sure this DIE is scoped in a DW_TAG_module tag and return true if so +        for (DWARFDIE parent = GetParent(); parent.IsValid(); parent = parent.GetParent()) +        { +            const dw_tag_t tag = parent.Tag(); +            if (tag == DW_TAG_module) +                top_module_die = parent; +            else if (tag == DW_TAG_compile_unit) +                break; +        } + +        return top_module_die; +    } +    return DWARFDIE(); +} + +lldb::ModuleSP +DWARFDIE::GetContainingDWOModule () const +{ +    if (IsValid()) +    { +        DWARFDIE dwo_module_die = GetContainingDWOModuleDIE(); + +        if (dwo_module_die) +        { +            const char *module_name = dwo_module_die.GetName(); +            if (module_name) +                return GetDWARF()->GetDWOModule (lldb_private::ConstString(module_name)); +        } +    } +    return lldb::ModuleSP(); +} + +bool +DWARFDIE::HasChildren () const +{ +    if (m_die) +        return m_die->HasChildren(); +    else +        return false; +} + +bool +DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type () const +{ +    if (IsValid()) +        return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu); +    else +        return false; +} + +size_t +DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const +{ +    if (IsValid()) +    { +        return m_die->GetAttributes (m_cu, +                                     m_cu->GetFixedFormSizes(), +                                     attributes, +                                     depth); +    } +    if (depth == 0) +        attributes.Clear(); +    return 0; +} + + +bool +DWARFDIE::GetDIENamesAndRanges (const char * &name, +                                const char * &mangled, +                                DWARFRangeList& ranges, +                                int& decl_file, +                                int& decl_line, +                                int& decl_column, +                                int& call_file, +                                int& call_line, +                                int& call_column, +                                lldb_private::DWARFExpression *frame_base) const +{ +    if (IsValid()) +    { +        return m_die->GetDIENamesAndRanges (GetDWARF(), +                                            GetCU(), +                                            name, +                                            mangled, +                                            ranges, +                                            decl_file, +                                            decl_line, +                                            decl_column, +                                            call_file, +                                            call_line, +                                            call_column, +                                            frame_base); +    } +    else +        return false; +} + +void +DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const +{ +    if (s && IsValid()) +        m_die->Dump (GetDWARF(), GetCU(), *s, recurse_depth); +} + + +bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs) +{ +    return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU(); +} + +bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs) +{ +    return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); +} + + diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h new file mode 100644 index 0000000000000..db37a45ad01a8 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -0,0 +1,281 @@ +//===-- DWARFDIE.h ----------------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFDIE_h_ +#define SymbolFileDWARF_DWARFDIE_h_ + +#include "lldb/lldb-types.h" +#include "lldb/Core/dwarf.h" + +struct DIERef; +class DWARFASTParser; +class DWARFAttributes; +class DWARFCompileUnit; +class DWARFDebugInfoEntry; +class DWARFDeclContext; +class DWARFDIECollection; +class SymbolFileDWARF; + +class DWARFDIE +{ +public: +    DWARFDIE () : +        m_cu (nullptr), +        m_die (nullptr) +    { +    } + +    DWARFDIE (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) : +        m_cu (cu), +        m_die (die) +    { +    } + +    DWARFDIE (const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) : +        m_cu (const_cast<DWARFCompileUnit *>(cu)), +        m_die (die) +    { +    } + +    DWARFDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) : +        m_cu (cu), +        m_die (const_cast<DWARFDebugInfoEntry *>(die)) +    { +    } + +    DWARFDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) : +        m_cu (const_cast<DWARFCompileUnit *>(cu)), +        m_die (const_cast<DWARFDebugInfoEntry *>(die)) +    { +    } + +    //---------------------------------------------------------------------- +    // Tests +    //---------------------------------------------------------------------- +    operator bool () const +    { +        return IsValid(); +    } + +    bool +    IsValid() const +    { +        return m_cu && m_die; +    } + +    bool +    IsStructOrClass () const; + +    bool +    HasChildren () const; + +    bool +    Supports_DW_AT_APPLE_objc_complete_type () const; + +    //---------------------------------------------------------------------- +    // Accessors +    //---------------------------------------------------------------------- +    SymbolFileDWARF * +    GetDWARF () const; + +    DWARFCompileUnit * +    GetCU() const +    { +        return m_cu; +    } + +    DWARFDebugInfoEntry * +    GetDIE() const +    { +        return m_die; +    } + +    DIERef +    GetDIERef() const; + +    lldb_private::TypeSystem * +    GetTypeSystem () const; + +    DWARFASTParser * +    GetDWARFParser () const; + +    void +    Set (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) +    { +        if (cu && die) +        { +            m_cu = cu; +            m_die = die; +        } +        else +        { +            Clear(); +        } +    } + +    void +    Clear () +    { +        m_cu = nullptr; +        m_die = nullptr; +    } + +    lldb::ModuleSP +    GetContainingDWOModule () const; + +    DWARFDIE +    GetContainingDWOModuleDIE () const; + +    //---------------------------------------------------------------------- +    // Accessing information about a DIE +    //---------------------------------------------------------------------- +    dw_tag_t +    Tag() const; + +    const char * +    GetTagAsCString () const; + +    dw_offset_t +    GetOffset () const; + +    dw_offset_t +    GetCompileUnitRelativeOffset () const; + +    //---------------------------------------------------------------------- +    // Get the LLDB user ID for this DIE. This is often just the DIE offset, +    // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if +    // we are doing Darwin DWARF in .o file, or DWARF stand alone debug +    // info. +    //---------------------------------------------------------------------- +    lldb::user_id_t +    GetID() const; + +    const char * +    GetName () const; + +    const char * +    GetMangledName () const; + +    const char * +    GetPubname () const; + +    const char * +    GetQualifiedName (std::string &storage) const; + +    lldb::LanguageType +    GetLanguage () const; + +    lldb::ModuleSP +    GetModule () const; + +    lldb_private::CompileUnit * +    GetLLDBCompileUnit () const; + +    lldb_private::Type * +    ResolveType () const; + +    // Resolve a type by UID using this DIE's DWARF file +    lldb_private::Type * +    ResolveTypeUID (lldb::user_id_t uid) const; + +    //---------------------------------------------------------------------- +    // Functions for obtaining DIE relations and references +    //---------------------------------------------------------------------- + +    DWARFDIE +    GetParent () const; + +    DWARFDIE +    GetFirstChild () const; + +    DWARFDIE +    GetSibling () const; + +    DWARFDIE +    GetReferencedDIE (const dw_attr_t attr) const; + +    //---------------------------------------------------------------------- +    // Get a another DIE from the same DWARF file as this DIE. This will +    // check the current DIE's compile unit first to see if "die_offset" is +    // in the same compile unit, and fall back to checking the DWARF file. +    //---------------------------------------------------------------------- +    DWARFDIE +    GetDIE (dw_offset_t die_offset) const; + +    DWARFDIE +    LookupDeepestBlock (lldb::addr_t file_addr) const; + +    DWARFDIE +    GetParentDeclContextDIE () const; + +    //---------------------------------------------------------------------- +    // DeclContext related functions +    //---------------------------------------------------------------------- +    void +    GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const; + +    void +    GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const; + +    void +    GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const; + +    //---------------------------------------------------------------------- +    // Getting attribute values from the DIE. +    // +    // GetAttributeValueAsXXX() functions should only be used if you are +    // looking for one or two attributes on a DIE. If you are trying to +    // parse all attributes, use GetAttributes (...) instead +    //---------------------------------------------------------------------- +    const char * +    GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const; + +    uint64_t +    GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const; + +    int64_t +    GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const; + +    uint64_t +    GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const; + +    uint64_t +    GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const; + +    size_t +    GetAttributes (DWARFAttributes &attributes, uint32_t depth = 0) const; + +    bool +    GetDIENamesAndRanges (const char * &name, +                          const char * &mangled, +                          DWARFRangeList& ranges, +                          int& decl_file, +                          int& decl_line, +                          int& decl_column, +                          int& call_file, +                          int& call_line, +                          int& call_column, +                          lldb_private::DWARFExpression *frame_base) const; + +    //---------------------------------------------------------------------- +    // Pretty printing +    //---------------------------------------------------------------------- + +    void +    Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const; + +protected: +    DWARFCompileUnit *m_cu; +    DWARFDebugInfoEntry *m_die; +}; + +bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs); +bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs); + +#endif  // SymbolFileDWARF_DWARFDIE_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp index 1beb75d336421..9e021c7185bd6 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp @@ -13,13 +13,11 @@  #include "lldb/Core/Stream.h" -#include "DWARFDebugInfoEntry.h" -  using namespace lldb_private;  using namespace std;  bool -DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die) +DWARFDIECollection::Insert(const DWARFDIE &die)  {      iterator end_pos = m_dies.end();      iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die); @@ -30,17 +28,17 @@ DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)  }  void -DWARFDIECollection::Append (const DWARFDebugInfoEntry *die) +DWARFDIECollection::Append (const DWARFDIE &die)  {      m_dies.push_back (die);  } -const DWARFDebugInfoEntry * -DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const +DWARFDIE +DWARFDIECollection::GetDIEAtIndex(uint32_t idx) const  {      if (idx < m_dies.size())          return m_dies[idx]; -    return NULL; +    return DWARFDIE();  } @@ -55,8 +53,6 @@ DWARFDIECollection::Dump(Stream *s, const char* title) const  {      if (title && title[0] != '\0')          s->Printf( "%s\n", title); -    const_iterator end_pos = m_dies.end(); -    const_iterator pos; -    for (pos = m_dies.begin(); pos != end_pos; ++pos) -        s->Printf( "0x%8.8x\n", (*pos)->GetOffset()); +    for (const auto &die : m_dies) +        s->Printf( "0x%8.8x\n", die.GetOffset());  } diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h index 173d0a5604d09..e39e1aa4ccda3 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h @@ -10,7 +10,7 @@  #ifndef SymbolFileDWARF_DWARFDIECollection_h_  #define SymbolFileDWARF_DWARFDIECollection_h_ -#include "SymbolFileDWARF.h" +#include "DWARFDIE.h"  #include <vector>  class DWARFDIECollection @@ -25,22 +25,22 @@ public:      }      void -    Append (const DWARFDebugInfoEntry *die); +    Append (const DWARFDIE &die);      void      Dump(lldb_private::Stream *s, const char* title) const; -    const DWARFDebugInfoEntry* -    GetDIEPtrAtIndex(uint32_t idx) const; +    DWARFDIE +    GetDIEAtIndex (uint32_t idx) const;      bool -    Insert(const DWARFDebugInfoEntry *die); +    Insert(const DWARFDIE &die);      size_t      Size() const;  protected: -    typedef std::vector<const DWARFDebugInfoEntry *>    collection; +    typedef std::vector<DWARFDIE>               collection;      typedef collection::iterator                iterator;      typedef collection::const_iterator          const_iterator; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h index ba2e8ad08accb..0281b5ad5c892 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -19,10 +19,10 @@ namespace lldb_private {  class DWARFDataExtractor : public lldb_private::DataExtractor  {  public: -    DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { }; +    DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { }      DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) : -      DataExtractor(data, offset, length), m_is_dwarf64(false) { }; +      DataExtractor(data, offset, length), m_is_dwarf64(false) { }      uint64_t      GetDWARFInitialLength(lldb::offset_t *offset_ptr) const; @@ -43,4 +43,3 @@ protected:  }  #endif  // liblldb_DWARFDataExtractor_h_                                  - diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 393434800c017..a1b00d1892e91 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -103,57 +103,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()      return *m_cu_aranges_ap.get();  } - -//---------------------------------------------------------------------- -// LookupAddress -//---------------------------------------------------------------------- -bool -DWARFDebugInfo::LookupAddress -( -    const dw_addr_t address, -    const dw_offset_t hint_die_offset, -    DWARFCompileUnitSP& cu_sp, -    DWARFDebugInfoEntry** function_die, -    DWARFDebugInfoEntry** block_die -) -{ - -    if (hint_die_offset != DW_INVALID_OFFSET) -        cu_sp = GetCompileUnit(hint_die_offset); -    else -    { -        DWARFDebugAranges &cu_aranges = GetCompileUnitAranges (); -        const dw_offset_t cu_offset = cu_aranges.FindAddress (address); -        cu_sp = GetCompileUnit(cu_offset); -    } - -    if (cu_sp.get()) -    { -        if (cu_sp->LookupAddress(address, function_die, block_die)) -            return true; -        cu_sp.reset(); -    } -    else -    { -        // The hint_die_offset may have been a pointer to the actual item that -        // we are looking for -        DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp); -        if (die_ptr) -        { -            if (cu_sp.get()) -            { -                if (function_die || block_die) -                    return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die); - -                // We only wanted the compile unit that contained this address -                return true; -            } -        } -    } -    return false; -} - -  void  DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()  { @@ -213,19 +162,13 @@ DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const      return false;  } -static int -CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem) +bool +DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp)  { -    const dw_offset_t key_cu_offset = *(dw_offset_t*) key; -    const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset(); -    if (key_cu_offset < cu_offset) -        return -1; -    if (key_cu_offset > cu_offset) -        return 1; -    return 0; +    return offset < cu_sp->GetOffset();  } -DWARFCompileUnitSP +DWARFCompileUnit *  DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)  {      DWARFCompileUnitSP cu_sp; @@ -234,41 +177,80 @@ DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)      {          ParseCompileUnitHeadersIfNeeded(); -        DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset); -        if (match) +        // Watch out for single compile unit executable as they are pretty common +        const size_t num_cus = m_compile_units.size(); +        if (num_cus == 1)          { -            cu_sp = *match; -            cu_idx = match - &m_compile_units[0]; +            if (m_compile_units[0]->GetOffset() == cu_offset) +            { +                cu_sp = m_compile_units[0]; +                cu_idx = 0; +            } +        } +        else if (num_cus) +        { +            CompileUnitColl::const_iterator end_pos = m_compile_units.end(); +            CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); +            CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset); +            if (pos != begin_pos) +            { +                --pos; +                if ((*pos)->GetOffset() == cu_offset) +                { +                    cu_sp = *pos; +                    cu_idx = std::distance(begin_pos, pos); +                } +            }          }      }      if (idx_ptr)          *idx_ptr = cu_idx; -    return cu_sp; +    return cu_sp.get();  } -DWARFCompileUnitSP -DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset) +DWARFCompileUnit * +DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref)  { +    dw_offset_t search_offset = die_ref.die_offset; +    bool is_cu_offset = false; +    if (m_dwarf2Data->GetID() == 0 && die_ref.cu_offset != DW_INVALID_OFFSET) +    { +        is_cu_offset = true; +        search_offset = die_ref.cu_offset; +    } +      DWARFCompileUnitSP cu_sp; -    if (die_offset != DW_INVALID_OFFSET) +    if (search_offset != DW_INVALID_OFFSET)      {          ParseCompileUnitHeadersIfNeeded(); -        CompileUnitColl::const_iterator end_pos = m_compile_units.end(); -        CompileUnitColl::const_iterator pos; - -        for (pos = m_compile_units.begin(); pos != end_pos; ++pos) +        // Watch out for single compile unit executable as they are pretty common +        const size_t num_cus = m_compile_units.size(); +        if (num_cus == 1)          { -            dw_offset_t cu_start_offset = (*pos)->GetOffset(); -            dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset(); -            if (cu_start_offset <= die_offset && die_offset < cu_end_offset) +            if ((is_cu_offset && m_compile_units[0]->GetOffset() == search_offset) || +                (!is_cu_offset && m_compile_units[0]->ContainsDIEOffset(search_offset)))              { -                cu_sp = *pos; -                break; +                cu_sp = m_compile_units[0]; +            } +        } +        else if (num_cus) +        { +            CompileUnitColl::const_iterator end_pos = m_compile_units.end(); +            CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); +            CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, search_offset, OffsetLessThanCompileUnitOffset); +            if (pos != begin_pos) +            { +                --pos; +                if ((is_cu_offset && (*pos)->GetOffset() == search_offset) || +                    (!is_cu_offset && (*pos)->ContainsDIEOffset(search_offset))) +                { +                    cu_sp = *pos; +                }              }          }      } -    return cu_sp; +    return cu_sp.get();  }  //---------------------------------------------------------------------- @@ -276,73 +258,15 @@ DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)  //  // Get the DIE (Debug Information Entry) with the specified offset.  //---------------------------------------------------------------------- -DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) -{ -    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); -    if (cu_sp_ptr) -        *cu_sp_ptr = cu_sp; -    if (cu_sp.get()) -        return cu_sp->GetDIEPtr(die_offset); -    return NULL;    // Not found in any compile units -} - -DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle) -{ -    assert (cu_handle); -    DWARFDebugInfoEntry* die = NULL; -    if (*cu_handle) -        die = (*cu_handle)->GetDIEPtr(die_offset); - -    if (die == NULL) -    { -        DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset)); -        if (cu_sp.get()) -        { -            *cu_handle = cu_sp.get(); -            die = cu_sp->GetDIEPtr(die_offset); -        } -    } -    if (die == NULL) -        *cu_handle = NULL; -    return die; -} - - -const DWARFDebugInfoEntry* -DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr) -{ -    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset)); -    if (cu_sp_ptr) -        *cu_sp_ptr = cu_sp; -    if (cu_sp.get()) -        return cu_sp->GetDIEPtrContainingOffset(die_offset); - -    return NULL;    // Not found in any compile units - -} - -//---------------------------------------------------------------------- -// AddCompileUnit -//---------------------------------------------------------------------- -void -DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu) +DWARFDIE +DWARFDebugInfo::GetDIE(const DIERef& die_ref)  { -    m_compile_units.push_back(cu); +    DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_ref); +    if (cu) +        return cu->GetDIE (die_ref.die_offset); +    return DWARFDIE();    // Not found  } -/* -void -DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die) -{ -    m_die_array.push_back(die); -} -*/ - - - -  //----------------------------------------------------------------------  // Parse  // @@ -372,7 +296,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user              depth = 0;              // Call the callback function with no DIE pointer for the compile unit              // and get the offset that we are to continue to parse from -            offset = callback(dwarf2Data, cu, NULL, offset, depth, userData); +            offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);              // Make sure we are within our compile unit              if (offset < next_cu_offset) @@ -383,7 +307,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user                  while (!done && die.Extract(dwarf2Data, cu.get(), &offset))                  {                      // Call the callback function with DIE pointer that falls within the compile unit -                    offset = callback(dwarf2Data, cu, &die, offset, depth, userData); +                    offset = callback(dwarf2Data, cu.get(), &die, offset, depth, userData);                      if (die.IsNULL())                      { @@ -450,7 +374,7 @@ typedef struct DumpInfo  static dw_offset_t DumpCallback  (      SymbolFileDWARF* dwarf2Data, -    DWARFCompileUnitSP& cu_sp, +    DWARFCompileUnit* cu,      DWARFDebugInfoEntry* die,      const dw_offset_t next_offset,      const uint32_t curr_depth, @@ -458,9 +382,6 @@ static dw_offset_t DumpCallback  )  {      DumpInfo* dumpInfo = (DumpInfo*)userData; - -    const DWARFCompileUnit* cu = cu_sp.get(); -      Stream *s = dumpInfo->strm;      bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); @@ -676,12 +597,12 @@ DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recur      ParseCompileUnitHeadersIfNeeded();      for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)      { -        const DWARFCompileUnitSP& cu_sp = *pos; -        DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo); +        DWARFCompileUnit *cu = pos->get(); +        DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo); -        const DWARFDebugInfoEntry* die = cu_sp->DIE(); +        const DWARFDIE die = cu->DIE();          if (die) -            die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth); +            die.Dump(s, recurse_depth);      }  } @@ -707,7 +628,7 @@ typedef struct FindCallbackStringInfoTag  static dw_offset_t FindCallbackString  (      SymbolFileDWARF* dwarf2Data, -    DWARFCompileUnitSP& cu_sp, +    DWARFCompileUnit* cu,      DWARFDebugInfoEntry* die,      const dw_offset_t next_offset,      const uint32_t curr_depth, @@ -715,7 +636,6 @@ static dw_offset_t FindCallbackString  )  {      FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData; -    const DWARFCompileUnit* cu = cu_sp.get();      if (die)      { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index 50a7ae76921f8..ea2e204db7029 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -16,19 +16,18 @@  #include "lldb/lldb-private.h"  #include "lldb/lldb-private.h"  #include "SymbolFileDWARF.h" +#include "DWARFDIE.h"  typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap;  typedef CStringToDIEMap::iterator CStringToDIEMapIter;  typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter; -typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; -  class DWARFDebugInfo  {  public:      typedef dw_offset_t (*Callback)(          SymbolFileDWARF* dwarf2Data, -        DWARFCompileUnitSP& cu_shared_ptr, +        DWARFCompileUnit* cu,          DWARFDebugInfoEntry* die,          const dw_offset_t next_offset,          const uint32_t depth, @@ -37,24 +36,13 @@ public:      DWARFDebugInfo();      void SetDwarfData(SymbolFileDWARF* dwarf2Data); -    bool LookupAddress( -            const dw_addr_t address, -            const dw_offset_t cu_offset,    // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually -            DWARFCompileUnitSP& cu_shared_ptr, -            DWARFDebugInfoEntry** function_die, -            DWARFDebugInfoEntry** block_die); - -    void AddCompileUnit(DWARFCompileUnitSP& cu);      size_t GetNumCompileUnits();      bool ContainsCompileUnit (const DWARFCompileUnit *cu) const; -    DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx); -    DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); -    DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset); +    DWARFCompileUnit* GetCompileUnitAtIndex (uint32_t idx); +    DWARFCompileUnit* GetCompileUnit (dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); +    DWARFCompileUnit* GetCompileUnitContainingDIE (const DIERef& die_ref); -    DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr); -    DWARFDebugInfoEntry* GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle); - -    const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr); +    DWARFDIE GetDIE (const DIERef& die_ref);      void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth);      static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData); @@ -74,8 +62,17 @@ public:      GetCompileUnitAranges ();  protected: -    SymbolFileDWARF* m_dwarf2Data; +    typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP; + +    static bool +    OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp); +      typedef std::vector<DWARFCompileUnitSP>     CompileUnitColl; + +    //---------------------------------------------------------------------- +    // Member variables +    //---------------------------------------------------------------------- +    SymbolFileDWARF* m_dwarf2Data;      CompileUnitColl m_compile_units;      std::unique_ptr<DWARFDebugAranges> m_cu_aranges_ap; // A quick address to compile unit table diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 0ad1f1a3a95ab..b9d825489aef9 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -19,107 +19,26 @@  #include "lldb/Symbol/ObjectFile.h"  #include "DWARFCompileUnit.h" -#include "SymbolFileDWARF.h"  #include "DWARFDebugAbbrev.h"  #include "DWARFDebugAranges.h"  #include "DWARFDebugInfo.h"  #include "DWARFDeclContext.h"  #include "DWARFDIECollection.h"  #include "DWARFFormValue.h" -#include "DWARFLocationDescription.h" -#include "DWARFLocationList.h"  #include "DWARFDebugRanges.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDwo.h"  using namespace lldb_private;  using namespace std;  extern int g_verbose; - - -DWARFDebugInfoEntry::Attributes::Attributes() : -    m_infos() -{ -} - -DWARFDebugInfoEntry::Attributes::~Attributes() -{ -} - - -uint32_t -DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const -{ -    collection::const_iterator end = m_infos.end(); -    collection::const_iterator beg = m_infos.begin(); -    collection::const_iterator pos; -    for (pos = beg; pos != end; ++pos) -    { -        if (pos->attr == attr) -            return std::distance(beg, pos); -    } -    return UINT32_MAX; -} - -void -DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form) -{ -    Info info = { cu, attr_die_offset, attr, form }; -    m_infos.push_back(info); -} - -bool -DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const -{ -    return FindAttributeIndex(attr) != UINT32_MAX; -} - -bool -DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr) -{ -    uint32_t attr_index = FindAttributeIndex(attr); -    if (attr_index != UINT32_MAX) -    { -        m_infos.erase(m_infos.begin() + attr_index); -        return true; -    } -    return false; -} - -bool -DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const -{ -    form_value.SetCompileUnit(CompileUnitAtIndex(i)); -    form_value.SetForm(FormAtIndex(i)); -    lldb::offset_t offset = DIEOffsetAtIndex(i); -    return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset); -} - -uint64_t -DWARFDebugInfoEntry::Attributes::FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const -{ -    const uint32_t attr_idx = FindAttributeIndex (attr); -    if (attr_idx != UINT32_MAX) -        return FormValueAsUnsignedAtIndex (dwarf2Data, attr_idx, fail_value); -    return fail_value; -} - -uint64_t -DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const -{ -    DWARFFormValue form_value; -    if (ExtractFormValueAtIndex(dwarf2Data, i, form_value)) -        return form_value.Reference(); -    return fail_value; -} - - -  bool  DWARFDebugInfoEntry::FastExtract  (      const DWARFDataExtractor& debug_info_data,      const DWARFCompileUnit* cu, -    const uint8_t *fixed_form_sizes, +    const DWARFFormValue::FixedFormSizes& fixed_form_sizes,      lldb::offset_t *offset_ptr  )  { @@ -158,7 +77,7 @@ DWARFDebugInfoEntry::FastExtract          {              form = abbrevDecl->GetFormByIndexUnchecked(i); -            const uint8_t fixed_skip_size = fixed_form_sizes [form]; +            const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);              if (fixed_skip_size)                  offset += fixed_skip_size;              else @@ -226,9 +145,11 @@ DWARFDebugInfoEntry::FastExtract                          break;                      // signed or unsigned LEB 128 values -                    case DW_FORM_sdata       : -                    case DW_FORM_udata       : -                    case DW_FORM_ref_udata   : +                    case DW_FORM_sdata         : +                    case DW_FORM_udata         : +                    case DW_FORM_ref_udata     : +                    case DW_FORM_GNU_addr_index: +                    case DW_FORM_GNU_str_index :                          debug_info_data.Skip_LEB128 (&offset);                          break; @@ -306,7 +227,7 @@ DWARFDebugInfoEntry::Extract                  bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;                  if (cu && isCompileUnitTag) -                    ((DWARFCompileUnit*)cu)->SetBaseAddress(0); +                    const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0);                  // Skip all data in the .debug_info for the attributes                  const uint32_t numAttributes = abbrevDecl->NumAttributes(); @@ -323,7 +244,7 @@ DWARFDebugInfoEntry::Extract                          if (form_value.ExtractValue(debug_info_data, &offset))                          {                              if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) -                                ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned()); +                                const_cast<DWARFCompileUnit*>(cu)->SetBaseAddress(form_value.Address());                          }                      }                      else @@ -389,9 +310,11 @@ DWARFDebugInfoEntry::Extract                                  break;                              // signed or unsigned LEB 128 values -                            case DW_FORM_sdata       : -                            case DW_FORM_udata       : -                            case DW_FORM_ref_udata   : +                            case DW_FORM_sdata         : +                            case DW_FORM_udata         : +                            case DW_FORM_ref_udata     : +                            case DW_FORM_GNU_addr_index: +                            case DW_FORM_GNU_str_index :                                  debug_info_data.Skip_LEB128(&offset);                                  break; @@ -456,276 +379,6 @@ DWARFDebugInfoEntry::DumpAncestry  }  //---------------------------------------------------------------------- -// Compare two DIE by comparing all their attributes values, and -// following all DW_FORM_ref attributes and comparing their contents as -// well (except for DW_AT_sibling attributes. -// -//  DWARFDebugInfoEntry::CompareState compare_state; -//  int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true); -//---------------------------------------------------------------------- -//int -//DWARFDebugInfoEntry::Compare -//( -//    SymbolFileDWARF* dwarf2Data, -//    dw_offset_t a_die_offset, -//    dw_offset_t b_die_offset, -//    CompareState &compare_state, -//    bool compare_siblings, -//    bool compare_children -//) -//{ -//    if (a_die_offset == b_die_offset) -//        return 0; -// -//    DWARFCompileUnitSP a_cu_sp; -//    DWARFCompileUnitSP b_cu_sp; -//    const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp); -//    const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp); -// -//    return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children); -//} -// -//int -//DWARFDebugInfoEntry::Compare -//( -//    SymbolFileDWARF* dwarf2Data, -//    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, -//    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, -//    CompareState &compare_state, -//    bool compare_siblings, -//    bool compare_children -//) -//{ -//    if (a_die == b_die) -//        return 0; -// -//    if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset())) -//    { -//        // We are already comparing both of these types, so let -//        // compares complete for the real result -//        return 0; -//    } -// -//    //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset()); -// -//    // Do we have two valid DIEs? -//    if (a_die && b_die) -//    { -//        // Both DIE are valid -//        int result = 0; -// -//        const dw_tag_t a_tag = a_die->Tag(); -//        const dw_tag_t b_tag = b_die->Tag(); -//        if (a_tag == 0 && b_tag == 0) -//            return 0; -// -//        //printf("    comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag)); -// -//        if (a_tag < b_tag) -//            return -1; -//        else if (a_tag > b_tag) -//            return 1; -// -//        DWARFDebugInfoEntry::Attributes a_attrs; -//        DWARFDebugInfoEntry::Attributes b_attrs; -//        size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs); -//        size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs); -//        if (a_attr_count != b_attr_count) -//        { -//            a_attrs.RemoveAttribute(DW_AT_sibling); -//            b_attrs.RemoveAttribute(DW_AT_sibling); -//        } -// -//        a_attr_count = a_attrs.Size(); -//        b_attr_count = b_attrs.Size(); -// -//        DWARFFormValue a_form_value; -//        DWARFFormValue b_form_value; -// -//        if (a_attr_count != b_attr_count) -//        { -//            uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration); -//            uint32_t a_name_index = UINT32_MAX; -//            uint32_t b_name_index = UINT32_MAX; -//            if (is_decl_index != UINT32_MAX) -//            { -//                if (a_attr_count == 2) -//                { -//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); -//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); -//                } -//            } -//            else -//            { -//                is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration); -//                if (is_decl_index != UINT32_MAX && a_attr_count == 2) -//                { -//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); -//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); -//                } -//            } -//            if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX) -//            { -//                if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) && -//                    b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value)) -//                { -//                    result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data()); -//                    if (result == 0) -//                    { -//                        a_attr_count = b_attr_count = 0; -//                        compare_children = false; -//                    } -//                } -//            } -//        } -// -//        if (a_attr_count < b_attr_count) -//            return -1; -//        if (a_attr_count > b_attr_count) -//            return 1; -// -// -//        // The number of attributes are the same... -//        if (a_attr_count > 0) -//        { -//            const DWARFDataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data(); -// -//            uint32_t i; -//            for (i=0; i<a_attr_count; ++i) -//            { -//                const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i); -//                const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i); -//                //printf("    comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n", -//                //                a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr), -//                //                b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr)); -// -//                if (a_attr < b_attr) -//                    return -1; -//                else if (a_attr > b_attr) -//                    return 1; -// -//                switch (a_attr) -//                { -//                // Since we call a form of GetAttributes which inlines the -//                // attributes from DW_AT_abstract_origin and DW_AT_specification -//                // we don't care if their values mismatch... -//                case DW_AT_abstract_origin: -//                case DW_AT_specification: -//                case DW_AT_sibling: -//                case DW_AT_containing_type: -//                    //printf("        action = IGNORE\n"); -//                    result = 0; -//                    break;  // ignore -// -//                default: -//                    if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) && -//                        b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value)) -//                        result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr); -//                    break; -//                } -// -//                //printf("\t  result = %i\n", result); -// -//                if (result != 0) -//                { -//                    // Attributes weren't equal, lets see if we care? -//                    switch (a_attr) -//                    { -//                    case DW_AT_decl_file: -//                        // TODO: add the ability to compare files in two different compile units -//                        if (a_cu == b_cu) -//                        { -//                            //printf("        action = RETURN RESULT\n"); -//                            return result;  // Only return the compare results when the compile units are the same and the decl_file attributes can be compared -//                        } -//                        else -//                        { -//                            result = 0; -//                            //printf("        action = IGNORE\n"); -//                        } -//                        break; -// -//                    default: -//                        switch (a_attrs.FormAtIndex(i)) -//                        { -//                        case DW_FORM_ref1: -//                        case DW_FORM_ref2: -//                        case DW_FORM_ref4: -//                        case DW_FORM_ref8: -//                        case DW_FORM_ref_udata: -//                        case DW_FORM_ref_addr: -//                            //printf("    action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu)); -//                            // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets... -//                            result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true); -//                            if (result != 0) -//                                return result; -//                            break; -// -//                        default: -//                            // We do care that they were different, return this result... -//                            //printf("        action = RETURN RESULT\n"); -//                            return result; -//                        } -//                    } -//                } -//            } -//        } -//        //printf("    SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag)); -// -//        if (compare_children) -//        { -//            bool a_has_children = a_die->HasChildren(); -//            bool b_has_children = b_die->HasChildren(); -//            if (a_has_children == b_has_children) -//            { -//                // Both either have kids or don't -//                if (a_has_children) -//                    result = Compare(   dwarf2Data, -//                                        a_cu, a_die->GetFirstChild(), -//                                        b_cu, b_die->GetFirstChild(), -//                                        compare_state, true, compare_children); -//                else -//                    result = 0; -//            } -//            else if (!a_has_children) -//                result = -1;    // A doesn't have kids, but B does -//            else -//                result = 1; // A has kids, but B doesn't -//        } -// -//        if (compare_siblings) -//        { -//            result = Compare(   dwarf2Data, -//                                a_cu, a_die->GetSibling(), -//                                b_cu, b_die->GetSibling(), -//                                compare_state, true, compare_children); -//        } -// -//        return result; -//    } -// -//    if (a_die == NULL) -//        return -1;  // a_die is NULL, yet b_die is non-NULL -//    else -//        return 1;   // a_die is non-NULL, yet b_die is NULL -// -//} -// -// -//int -//DWARFDebugInfoEntry::Compare -//( -//  SymbolFileDWARF* dwarf2Data, -//  const DWARFCompileUnit* cu_a, -//  const DWARFDebugInfoEntry* die_a, -//  const DWARFCompileUnit* cu_a, -//  const DWARFDebugInfoEntry* die_b, -//  CompareState &compare_state -//) -//{ -//} - -//----------------------------------------------------------------------  // GetDIENamesAndRanges  //  // Gets the valid address ranges for a given DIE by looking for a @@ -739,7 +392,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges      const DWARFCompileUnit* cu,      const char * &name,      const char * &mangled, -    DWARFDebugRanges::RangeList& ranges, +    DWARFRangeList& ranges,      int& decl_file,      int& decl_line,      int& decl_column, @@ -749,12 +402,27 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges      DWARFExpression *frame_base  ) const  { -    if (dwarf2Data == NULL) +    if (dwarf2Data == nullptr)          return false; +    SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); +    if (dwo_symbol_file) +        return GetDIENamesAndRanges(dwo_symbol_file, +                                    dwo_symbol_file->GetCompileUnit(), +                                    name, +                                    mangled, +                                    ranges, +                                    decl_file, +                                    decl_line, +                                    decl_column, +                                    call_file, +                                    call_line, +                                    call_column, +                                    frame_base); +      dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;      dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; -    std::vector<dw_offset_t> die_offsets; +    std::vector<DIERef> die_refs;      bool set_frame_base_loclist_addr = false;      lldb::offset_t offset; @@ -784,7 +452,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges                  switch (attr)                  {                  case DW_AT_low_pc: -                    lo_pc = form_value.Unsigned(); +                    lo_pc = form_value.Address();                      if (do_offset)                          hi_pc += lo_pc; @@ -792,13 +460,18 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges                      break;                  case DW_AT_entry_pc: -                    lo_pc = form_value.Unsigned(); +                    lo_pc = form_value.Address();                      break;                  case DW_AT_high_pc: -                    hi_pc = form_value.Unsigned(); -                    if (form_value.Form() != DW_FORM_addr) +                    if (form_value.Form() == DW_FORM_addr || +                        form_value.Form() == DW_FORM_GNU_addr_index)                      { +                        hi_pc = form_value.Address(); +                    } +                    else +                    { +                        hi_pc = form_value.Unsigned();                          if (lo_pc == LLDB_INVALID_ADDRESS)                              do_offset = hi_pc != LLDB_INVALID_ADDRESS;                          else @@ -819,21 +492,21 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges                  case DW_AT_name:                      if (name == NULL) -                        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); +                        name = form_value.AsCString();                      break;                  case DW_AT_MIPS_linkage_name:                  case DW_AT_linkage_name:                      if (mangled == NULL) -                        mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data()); +                        mangled = form_value.AsCString();                      break;                  case DW_AT_abstract_origin: -                    die_offsets.push_back(form_value.Reference()); +                    die_refs.emplace_back(form_value);                      break;                  case DW_AT_specification: -                    die_offsets.push_back(form_value.Reference()); +                    die_refs.emplace_back(form_value);                      break;                  case DW_AT_decl_file: @@ -880,7 +553,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges                              const DWARFDataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();                              const dw_offset_t debug_loc_offset = form_value.Unsigned(); -                            size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset); +                            size_t loc_list_length = DWARFExpression::LocationListSize(cu, debug_loc_data, debug_loc_offset);                              if (loc_list_length > 0)                              {                                  frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); @@ -910,9 +583,9 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges          if (lo_pc != LLDB_INVALID_ADDRESS)          {              if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc) -                ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc)); +                ranges.Append(DWARFRangeList::Entry (lo_pc, hi_pc - lo_pc));              else -                ranges.Append(DWARFDebugRanges::Range (lo_pc, 0)); +                ranges.Append(DWARFRangeList::Entry (lo_pc, 0));          }      } @@ -925,18 +598,13 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges      if (ranges.IsEmpty() || name == NULL || mangled == NULL)      { -        std::vector<dw_offset_t>::const_iterator pos; -        std::vector<dw_offset_t>::const_iterator end = die_offsets.end(); -        for (pos = die_offsets.begin(); pos != end; ++pos) +        for (const DIERef& die_ref : die_refs)          { -            DWARFCompileUnitSP cu_sp_ptr; -            const DWARFDebugInfoEntry* die = NULL; -            dw_offset_t die_offset = *pos; -            if (die_offset != DW_INVALID_OFFSET) +            if (die_ref.die_offset != DW_INVALID_OFFSET)              { -                die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr); +                DWARFDIE die = dwarf2Data->DebugInfo()->GetDIE(die_ref);                  if (die) -                    die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column); +                    die.GetDIE()->GetDIENamesAndRanges(die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);              }          }      } @@ -1023,10 +691,10 @@ DWARFDebugInfoEntry::DumpLocation      Stream &s  ) const  { -    const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly(); +    const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly();      const char *cu_name = NULL; -    if (cu_die != NULL) -        cu_name = cu_die->GetName (dwarf2Data, cu); +    if (cu_die) +        cu_name = cu_die.GetName ();      const char *obj_file_name = NULL;      ObjectFile *obj_file = dwarf2Data->GetObjectFile();      if (obj_file) @@ -1062,7 +730,6 @@ DWARFDebugInfoEntry::DumpAttribute      bool verbose    = s.GetVerbose();      bool show_form  = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm); -    const DWARFDataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;      if (verbose)          s.Offset (*offset_ptr);      else @@ -1094,7 +761,7 @@ DWARFDebugInfoEntry::DumpAttribute      // Always dump form value if verbose is enabled      if (verbose)      { -        form_value.Dump(s, debug_str_data); +        form_value.Dump(s);      } @@ -1127,12 +794,16 @@ DWARFDebugInfoEntry::DumpAttribute              if (blockData)              {                  if (!verbose) -                    form_value.Dump(s, debug_str_data); +                    form_value.Dump(s);                  // Location description is inlined in data in the form value                  DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());                  if ( verbose ) s.PutCString(" ( "); -                print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false); +                DWARFExpression::PrintDWARFExpression(s, +                                                      locationData, +                                                      DWARFCompileUnit::GetAddressByteSize(cu), +                                                      4, +                                                      false);                  if ( verbose ) s.PutCString(" )");              }              else @@ -1144,13 +815,16 @@ DWARFDebugInfoEntry::DumpAttribute                  if (dwarf2Data)                  {                      if ( !verbose ) -                        form_value.Dump(s, debug_str_data); -                    DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset); +                        form_value.Dump(s); +                    DWARFExpression::PrintDWARFLocationList(s, +                                                            cu, +                                                            dwarf2Data->get_debug_loc_data(), +                                                            debug_loc_offset);                  }                  else                  {                      if ( !verbose ) -                        form_value.Dump(s, NULL); +                        form_value.Dump(s);                  }              }          } @@ -1160,7 +834,7 @@ DWARFDebugInfoEntry::DumpAttribute      case DW_AT_specification:          {              uint64_t abstract_die_offset = form_value.Reference(); -            form_value.Dump(s, debug_str_data); +            form_value.Dump(s);          //  *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";              if ( verbose ) s.PutCString(" ( ");              GetName(dwarf2Data, cu, abstract_die_offset, s); @@ -1172,7 +846,7 @@ DWARFDebugInfoEntry::DumpAttribute          {              uint64_t type_die_offset = form_value.Reference();              if (!verbose) -                form_value.Dump(s, debug_str_data); +                form_value.Dump(s);              s.PutCString(" ( ");              AppendTypeName(dwarf2Data, cu, type_die_offset, s);              s.PutCString(" )"); @@ -1182,7 +856,7 @@ DWARFDebugInfoEntry::DumpAttribute      case DW_AT_ranges:          {              if ( !verbose ) -                form_value.Dump(s, debug_str_data); +                form_value.Dump(s);              lldb::offset_t ranges_offset = form_value.Unsigned();              dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;              if (dwarf2Data) @@ -1192,7 +866,7 @@ DWARFDebugInfoEntry::DumpAttribute      default:          if ( !verbose ) -            form_value.Dump(s, debug_str_data); +            form_value.Dump(s);          break;      } @@ -1206,24 +880,37 @@ DWARFDebugInfoEntry::DumpAttribute  // take precedence (this can happen for declaration attributes).  //----------------------------------------------------------------------  size_t -DWARFDebugInfoEntry::GetAttributes -( -    SymbolFileDWARF* dwarf2Data, -    const DWARFCompileUnit* cu, -    const uint8_t *fixed_form_sizes, -    DWARFDebugInfoEntry::Attributes& attributes, -    uint32_t curr_depth -) const +DWARFDebugInfoEntry::GetAttributes (const DWARFCompileUnit* cu, +                                    DWARFFormValue::FixedFormSizes fixed_form_sizes, +                                    DWARFAttributes& attributes, +                                    uint32_t curr_depth) const  { -    lldb::offset_t offset; -    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); +    SymbolFileDWARF* dwarf2Data = nullptr; +    const DWARFAbbreviationDeclaration* abbrevDecl = nullptr; +    lldb::offset_t offset = 0; +    if (cu) +    { +        if (m_tag != DW_TAG_compile_unit) +        { +            SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); +            if (dwo_symbol_file) +                return GetAttributes(dwo_symbol_file->GetCompileUnit(), +                                     fixed_form_sizes, +                                     attributes, +                                     curr_depth); +        } + +        dwarf2Data = cu->GetSymbolFileDWARF(); +        abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); +    }      if (abbrevDecl)      {          const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); -        if (fixed_form_sizes == NULL) -            fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64()); +        if (fixed_form_sizes.Empty()) +            fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize( +                    cu->GetAddressByteSize(), cu->IsDWARF64());          const uint32_t num_attributes = abbrevDecl->NumAttributes();          uint32_t i; @@ -1258,26 +945,15 @@ DWARFDebugInfoEntry::GetAttributes                  DWARFFormValue form_value (cu, form);                  if (form_value.ExtractValue(debug_info_data, &offset))                  { -                    const DWARFDebugInfoEntry* die = NULL;                      dw_offset_t die_offset = form_value.Reference(); -                    if (cu->ContainsDIEOffset(die_offset)) -                    { -                        die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset); -                        if (die) -                            die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1); -                    } -                    else -                    { -                        DWARFCompileUnitSP cu_sp_ptr; -                        die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr); -                        if (die) -                            die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1); -                    } +                    DWARFDIE spec_die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(die_offset); +                    if (spec_die) +                        spec_die.GetAttributes(attributes, curr_depth + 1);                  }              }              else              { -                const uint8_t fixed_skip_size = fixed_form_sizes [form]; +                const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);                  if (fixed_skip_size)                      offset += fixed_skip_size;                  else @@ -1308,9 +984,19 @@ DWARFDebugInfoEntry::GetAttributeValue      const DWARFCompileUnit* cu,      const dw_attr_t attr,      DWARFFormValue& form_value, -    dw_offset_t* end_attr_offset_ptr +    dw_offset_t* end_attr_offset_ptr, +    bool check_specification_or_abstract_origin  ) const  { +    SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile(); +    if (dwo_symbol_file && m_tag != DW_TAG_compile_unit) +        return GetAttributeValue(dwo_symbol_file, +                                 dwo_symbol_file->GetCompileUnit(), +                                 attr, +                                 form_value, +                                 end_attr_offset_ptr, +                                 check_specification_or_abstract_origin); +      lldb::offset_t offset;      const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); @@ -1338,7 +1024,58 @@ DWARFDebugInfoEntry::GetAttributeValue          }      } -    return 0; +    if (check_specification_or_abstract_origin) +    { +        if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) +        { +            DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference()); +            if (die) +            { +                dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(), +                                                                         die.GetCU(), +                                                                         attr, +                                                                         form_value, +                                                                         end_attr_offset_ptr, +                                                                         false); +                if (die_offset) +                    return die_offset; +            } +        } + +        if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) +        { +            DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference()); +            if (die) +            { +                dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(), +                                                                         die.GetCU(), +                                                                         attr, +                                                                         form_value, +                                                                         end_attr_offset_ptr, +                                                                         false); +                if (die_offset) +                    return die_offset; +            } +        } +    } + +    if (!dwo_symbol_file) +        return 0; + +    DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit(); +    if (!dwo_cu) +        return 0; + +    DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly(); +    if (!dwo_cu_die.IsValid()) +        return 0; + +    return dwo_cu_die.GetDIE()->GetAttributeValue(dwo_symbol_file, +                                                  dwo_cu, +                                                  attr, +                                                  form_value, +                                                  end_attr_offset_ptr, +                                                  check_specification_or_abstract_origin);  }  //---------------------------------------------------------------------- @@ -1355,11 +1092,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsString      SymbolFileDWARF* dwarf2Data,      const DWARFCompileUnit* cu,      const dw_attr_t attr, -    const char* fail_value) const +    const char* fail_value, +    bool check_specification_or_abstract_origin) const  {      DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) -        return form_value.AsCString(&dwarf2Data->get_debug_str_data()); +    if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) +        return form_value.AsCString();      return fail_value;  } @@ -1374,11 +1112,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsUnsigned      SymbolFileDWARF* dwarf2Data,      const DWARFCompileUnit* cu,      const dw_attr_t attr, -    uint64_t fail_value +    uint64_t fail_value, +    bool check_specification_or_abstract_origin  ) const  {      DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) +    if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))          return form_value.Unsigned();      return fail_value;  } @@ -1394,11 +1133,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsSigned      SymbolFileDWARF* dwarf2Data,      const DWARFCompileUnit* cu,      const dw_attr_t attr, -    int64_t fail_value +    int64_t fail_value, +    bool check_specification_or_abstract_origin  ) const  {      DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) +    if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))          return form_value.Signed();      return fail_value;  } @@ -1415,15 +1155,32 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference      SymbolFileDWARF* dwarf2Data,      const DWARFCompileUnit* cu,      const dw_attr_t attr, -    uint64_t fail_value +    uint64_t fail_value, +    bool check_specification_or_abstract_origin  ) const  {      DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, attr, form_value)) +    if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))          return form_value.Reference();      return fail_value;  } +uint64_t +DWARFDebugInfoEntry::GetAttributeValueAsAddress +( +    SymbolFileDWARF* dwarf2Data, +    const DWARFCompileUnit* cu, +    const dw_attr_t attr, +    uint64_t fail_value, +    bool check_specification_or_abstract_origin +) const +{ +    DWARFFormValue form_value; +    if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) +        return form_value.Address(); +    return fail_value; +} +  //----------------------------------------------------------------------  // GetAttributeHighPC  // @@ -1438,17 +1195,19 @@ DWARFDebugInfoEntry::GetAttributeHighPC      SymbolFileDWARF* dwarf2Data,      const DWARFCompileUnit* cu,      dw_addr_t lo_pc, -    uint64_t fail_value +    uint64_t fail_value, +    bool check_specification_or_abstract_origin  ) const  {      DWARFFormValue form_value; - -    if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value)) +    if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin))      { -        dw_addr_t hi_pc = form_value.Unsigned(); -        if (form_value.Form() != DW_FORM_addr) -            hi_pc += lo_pc; // DWARF4 can specify the hi_pc as an <offset-from-lowpc> -        return hi_pc;  +        dw_form_t form = form_value.Form(); +        if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index) +            return form_value.Address(); +         +        // DWARF4 can specify the hi_pc as an <offset-from-lowpc> +        return lo_pc + form_value.Unsigned();      }      return fail_value;  } @@ -1468,13 +1227,14 @@ DWARFDebugInfoEntry::GetAttributeAddressRange      const DWARFCompileUnit* cu,      dw_addr_t& lo_pc,      dw_addr_t& hi_pc, -    uint64_t fail_value +    uint64_t fail_value, +    bool check_specification_or_abstract_origin  ) const  { -    lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, fail_value); +    lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin);      if (lo_pc != fail_value)      { -        hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value); +        hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, check_specification_or_abstract_origin);          if (hi_pc != fail_value)            return true;      } @@ -1484,89 +1244,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange  }  size_t -DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data, -                                               const DWARFCompileUnit* cu, -                                               DWARFDebugRanges::RangeList &ranges, -                                               bool check_hi_lo_pc) const +DWARFDebugInfoEntry::GetAttributeAddressRanges (SymbolFileDWARF* dwarf2Data, +                                                const DWARFCompileUnit* cu, +                                                DWARFRangeList &ranges, +                                                bool check_hi_lo_pc, +                                                bool check_specification_or_abstract_origin) const  {      ranges.Clear(); -    dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); -    if (ranges_offset != DW_INVALID_OFFSET) +    dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, +                                                                  cu, +                                                                  DW_AT_ranges, +                                                                  DW_INVALID_OFFSET, +                                                                  check_specification_or_abstract_origin); +    if (debug_ranges_offset != DW_INVALID_OFFSET)      { -        dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET); -        if (debug_ranges_offset != DW_INVALID_OFFSET) -        { -            DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); -             -            debug_ranges->FindRanges(debug_ranges_offset, ranges); -            ranges.Slide (cu->GetBaseAddress()); -        } +        DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); +         +        debug_ranges->FindRanges(debug_ranges_offset, ranges); +        ranges.Slide (cu->GetBaseAddress());      }      else if (check_hi_lo_pc)      {          dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;          dw_addr_t hi_pc = LLDB_INVALID_ADDRESS; -        if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS)) +        if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, check_specification_or_abstract_origin))          {              if (lo_pc < hi_pc) -                ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc)); +                ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));          }      }      return ranges.GetSize();  }  //---------------------------------------------------------------------- -// GetAttributeValueAsLocation -// -// Get the value of an attribute as reference and fix up and compile -// unit relative offsets as needed. -//---------------------------------------------------------------------- -dw_offset_t -DWARFDebugInfoEntry::GetAttributeValueAsLocation -( -    SymbolFileDWARF* dwarf2Data, -    const DWARFCompileUnit* cu, -    const dw_attr_t attr, -    DWARFDataExtractor& location_data, -    uint32_t &block_size -) const -{ -    block_size = 0; -    DWARFFormValue form_value; - -    // Empty out data in case we don't find anything -    location_data.Clear(); -    dw_offset_t end_addr_offset = DW_INVALID_OFFSET; -    const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset); -    if (attr_offset) -    { -        const uint8_t* blockData = form_value.BlockData(); -        if (blockData) -        { -            // We have an inlined location list in the .debug_info section -            const DWARFDataExtractor& debug_info = dwarf2Data->get_debug_info_data(); -            dw_offset_t block_offset = blockData - debug_info.GetDataStart(); -            block_size = (end_addr_offset - attr_offset) - form_value.Unsigned(); -            location_data.SetData(debug_info, block_offset, block_size); -        } -        else -        { -            // We have a location list offset as the value that is -            // the offset into the .debug_loc section that describes -            // the value over it's lifetime -            lldb::offset_t debug_loc_offset = form_value.Unsigned(); -            if (dwarf2Data) -            { -                assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize()); -                return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data); -            } -        } -    } -    return attr_offset; -} - -//----------------------------------------------------------------------  // GetName  //  // Get value of the DW_AT_name attribute and return it if one exists, @@ -1579,27 +1290,9 @@ DWARFDebugInfoEntry::GetName      const DWARFCompileUnit* cu  ) const  { -    DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) -        return form_value.AsCString(&dwarf2Data->get_debug_str_data()); -    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) -    { -        DWARFCompileUnitSP cu_sp_ptr; -        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); -        if (die) -            return die->GetName(dwarf2Data, cu_sp_ptr.get()); -    } -    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) -    { -        DWARFCompileUnitSP cu_sp_ptr; -        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); -        if (die) -            return die->GetName(dwarf2Data, cu_sp_ptr.get()); -    } -    return nullptr; +    return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);  } -  //----------------------------------------------------------------------  // GetMangledName  // @@ -1614,20 +1307,20 @@ DWARFDebugInfoEntry::GetMangledName      bool substitute_name_allowed  ) const  { -    const char* name = NULL; -    DWARFFormValue form_value; +    const char* name = nullptr; -    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value)) -        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true); +    if (name) +        return name; -    if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value)) -        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true); +    if (name) +        return name; -    if (substitute_name_allowed && name == NULL) -    { -        if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) -            name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); -    } +    if (!substitute_name_allowed) +        return nullptr; + +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);      return name;  } @@ -1645,27 +1338,19 @@ DWARFDebugInfoEntry::GetPubname      const DWARFCompileUnit* cu  ) const  { -    const char* name = NULL; +    const char* name = nullptr;      if (!dwarf2Data)          return name; -     -    DWARFFormValue form_value; -    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value)) -        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); -    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value)) -        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); -    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) -        name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); -    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) -    { -        // The specification DIE may be in another compile unit so we need -        // to get a die and its compile unit. -        DWARFCompileUnitSP cu_sp_ptr; -        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr); -        if (die) -            return die->GetPubname(dwarf2Data, cu_sp_ptr.get()); -    } +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true); +    if (name) +        return name; + +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true); +    if (name) +        return name; + +    name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);      return name;  } @@ -1705,15 +1390,11 @@ DWARFDebugInfoEntry::GetName          }          else          { -            DWARFFormValue form_value; -            if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) +            const char* name = die.GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true); +            if (name)              { -                const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data()); -                if (name) -                { -                    s.PutCString(name); -                    return true; -                } +                s.PutCString(name); +                return true;              }          }      } @@ -1755,8 +1436,6 @@ DWARFDebugInfoEntry::AppendTypeName          else          {              const char* name = die.GetPubname(dwarf2Data, cu); -        //  if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value)) -        //      name = form_value.AsCString(&dwarf2Data->get_debug_str_data());              if (name)                  s.PutCString(name);              else @@ -1909,16 +1588,12 @@ DWARFDebugInfoEntry::BuildFunctionAddressRangeTable  }  void -DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,  -                                         DWARFCompileUnit* cu, +DWARFDebugInfoEntry::GetDeclContextDIEs (DWARFCompileUnit* cu,                                           DWARFDIECollection &decl_context_dies) const  { -    const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); -    if (parent_decl_ctx_die && parent_decl_ctx_die != this) -    { -        decl_context_dies.Append(parent_decl_ctx_die); -        parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies); -    } + +    DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this)); +    die.GetDeclContextDIEs(decl_context_dies);  }  void @@ -1930,11 +1605,11 @@ DWARFDebugInfoEntry::GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,      if (tag != DW_TAG_compile_unit)      {          dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu)); -        const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); -        if (parent_decl_ctx_die && parent_decl_ctx_die != this) +        DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); +        if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this)          { -            if (parent_decl_ctx_die->Tag() != DW_TAG_compile_unit) -                parent_decl_ctx_die->GetDWARFDeclContext (dwarf2Data, cu, dwarf_decl_ctx); +            if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit) +                parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext (parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), dwarf_decl_ctx);          }      }  } @@ -1951,30 +1626,30 @@ DWARFDebugInfoEntry::MatchesDWARFDeclContext (SymbolFileDWARF* dwarf2Data,      return this_dwarf_decl_ctx == dwarf_decl_ctx;  } -const DWARFDebugInfoEntry * +DWARFDIE  DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,   											  DWARFCompileUnit* cu) const  { -	DWARFDebugInfoEntry::Attributes attributes; -	GetAttributes(dwarf2Data, cu, NULL, attributes); +	DWARFAttributes attributes; +	GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);  	return GetParentDeclContextDIE (dwarf2Data, cu, attributes);  } -const DWARFDebugInfoEntry * +DWARFDIE  DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,   											  DWARFCompileUnit* cu, -											  const DWARFDebugInfoEntry::Attributes& attributes) const +											  const DWARFAttributes& attributes) const  { -	const DWARFDebugInfoEntry * die = this; -	 -	while (die != NULL) +    DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this)); + +	while (die)  	{  		// If this is the original DIE that we are searching for a declaration   		// for, then don't look in the cache as we don't want our own decl   		// context to be our decl context... -		if (die != this) +		if (die.GetDIE() != this)  		{             -			switch (die->Tag()) +			switch (die.Tag())  			{  				case DW_TAG_compile_unit:  				case DW_TAG_namespace: @@ -1990,33 +1665,33 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,  		dw_offset_t die_offset; -		die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_specification, DW_INVALID_OFFSET); +		die_offset = attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET);  		if (die_offset != DW_INVALID_OFFSET)  		{ -			const DWARFDebugInfoEntry *spec_die = cu->GetDIEPtr (die_offset); +			DWARFDIE spec_die = cu->GetDIE (die_offset);  			if (spec_die) -			{ -				const DWARFDebugInfoEntry *spec_die_decl_ctx_die = spec_die->GetParentDeclContextDIE (dwarf2Data, cu); -				if (spec_die_decl_ctx_die) -					return spec_die_decl_ctx_die; -			} +            { +                DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE(); +                if (decl_ctx_die) +                    return decl_ctx_die; +            }  		} -        die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_abstract_origin, DW_INVALID_OFFSET); +        die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, DW_INVALID_OFFSET);  		if (die_offset != DW_INVALID_OFFSET)  		{ -			const DWARFDebugInfoEntry *abs_die = cu->GetDIEPtr (die_offset); +            DWARFDIE abs_die = cu->GetDIE (die_offset);  			if (abs_die)  			{ -				const DWARFDebugInfoEntry *abs_die_decl_ctx_die = abs_die->GetParentDeclContextDIE (dwarf2Data, cu); -				if (abs_die_decl_ctx_die) -					return abs_die_decl_ctx_die; +                DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE(); +                if (decl_ctx_die) +                    return decl_ctx_die;  			}  		} -		die = die->GetParent(); +		die = die.GetParent();  	} -    return NULL; +    return DWARFDIE();  } @@ -2025,15 +1700,15 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,  									   DWARFCompileUnit* cu,  									   std::string &storage) const  { -	DWARFDebugInfoEntry::Attributes attributes; -	GetAttributes(dwarf2Data, cu, NULL, attributes); +	DWARFAttributes attributes; +	GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);  	return GetQualifiedName (dwarf2Data, cu, attributes, storage);  }  const char*  DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,   									   DWARFCompileUnit* cu, -									   const DWARFDebugInfoEntry::Attributes& attributes, +									   const DWARFAttributes& attributes,  									   std::string &storage) const  { @@ -2041,47 +1716,47 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,  	if (name)  	{ -		const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu); +		DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);  		storage.clear();  		// TODO: change this to get the correct decl context parent....  		while (parent_decl_ctx_die)  		{ -			const dw_tag_t parent_tag = parent_decl_ctx_die->Tag(); +			const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();  			switch (parent_tag)  			{                  case DW_TAG_namespace: -				{ -					const char *namespace_name = parent_decl_ctx_die->GetName (dwarf2Data, cu); -					if (namespace_name) -					{ -						storage.insert (0, "::"); -						storage.insert (0, namespace_name); -					} -					else -					{ -						storage.insert (0, "(anonymous namespace)::"); -					} -					parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu); -				} +                    { +                        const char *namespace_name = parent_decl_ctx_die.GetName (); +                        if (namespace_name) +                        { +                            storage.insert (0, "::"); +                            storage.insert (0, namespace_name); +                        } +                        else +                        { +                            storage.insert (0, "(anonymous namespace)::"); +                        } +                        parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); +                    }                      break;                  case DW_TAG_class_type:                  case DW_TAG_structure_type:                  case DW_TAG_union_type: -				{ -					const char *class_union_struct_name = parent_decl_ctx_die->GetName (dwarf2Data, cu); -                     -					if (class_union_struct_name) -					{ -						storage.insert (0, "::"); -						storage.insert (0, class_union_struct_name); -					} -					parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu); -				} +                    { +                        const char *class_union_struct_name = parent_decl_ctx_die.GetName (); +                         +                        if (class_union_struct_name) +                        { +                            storage.insert (0, "::"); +                            storage.insert (0, class_union_struct_name); +                        } +                        parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE(); +                    }                      break;                  default: -                    parent_decl_ctx_die = NULL; +                    parent_decl_ctx_die.Clear();                      break;  			}  		} @@ -2179,7 +1854,7 @@ DWARFDebugInfoEntry::LookupAddress          if (match_addr_range)          { -            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); +            dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);              if (lo_pc != LLDB_INVALID_ADDRESS)              {                  dw_addr_t hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS); @@ -2229,7 +1904,7 @@ DWARFDebugInfoEntry::LookupAddress                  dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);                  if (debug_ranges_offset != DW_INVALID_OFFSET)                  { -                    DWARFDebugRanges::RangeList ranges; +                    DWARFRangeList ranges;                      DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();                      debug_ranges->FindRanges(debug_ranges_offset, ranges);                      // All DW_AT_ranges are relative to the base address of the diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 3949ad339dd85..02bbff8defc0a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -57,56 +57,6 @@ public:      typedef offset_collection::iterator         offset_collection_iterator;      typedef offset_collection::const_iterator   offset_collection_const_iterator; -    class Attributes -    { -    public: -        Attributes(); -        ~Attributes(); - -        void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form); -        const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; } -        dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; } -        dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; } -        dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; } -        bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const; -        uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const; -        uint64_t FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const; -        uint32_t FindAttributeIndex(dw_attr_t attr) const; -        bool ContainsAttribute(dw_attr_t attr) const; -        bool RemoveAttribute(dw_attr_t attr); -        void Clear() { m_infos.clear(); } -        size_t Size() const { return m_infos.size(); } - -    protected: -        struct Info -        { -            const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values -            dw_offset_t die_offset; -            dw_attr_t attr; -            dw_form_t form; -        }; - -        typedef llvm::SmallVector<Info, 8> collection; -        collection m_infos; -    }; - -    struct CompareState -    { -        CompareState() : -            die_offset_pairs() -        { -            assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t)); -        } - -        bool AddTypePair(dw_offset_t a, dw_offset_t b) -        { -            uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b; -            // Return true if this type was inserted, false otherwise -            return die_offset_pairs.insert(a_b_offsets).second; -        } -        std::set< uint64_t > die_offset_pairs; -    }; -                  DWARFDebugInfoEntry():                      m_offset        (DW_INVALID_OFFSET),                      m_parent_idx    (0), @@ -144,7 +94,7 @@ public:      bool        FastExtract(                      const lldb_private::DWARFDataExtractor& debug_info_data,                      const DWARFCompileUnit* cu, -                    const uint8_t *fixed_form_sizes, +                    const DWARFFormValue::FixedFormSizes& fixed_form_sizes,                      lldb::offset_t* offset_ptr);      bool        Extract( @@ -160,68 +110,67 @@ public:                      DWARFDebugInfoEntry** block_die);      size_t      GetAttributes( -                    SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu, -                    const uint8_t *fixed_form_sizes, -                    DWARFDebugInfoEntry::Attributes& attrs, +                    DWARFFormValue::FixedFormSizes fixed_form_sizes, +                    DWARFAttributes& attrs,                      uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!! -    dw_offset_t GetAttributeValue( -                    SymbolFileDWARF* dwarf2Data, -                    const DWARFCompileUnit* cu, -                    const dw_attr_t attr, -                    DWARFFormValue& formValue, -                    dw_offset_t* end_attr_offset_ptr = NULL) const; -      const char* GetAttributeValueAsString(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      const dw_attr_t attr, -                    const char* fail_value) const; +                    const char* fail_value, +                    bool check_specification_or_abstract_origin = false) const;      uint64_t    GetAttributeValueAsUnsigned(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      const dw_attr_t attr, -                    uint64_t fail_value) const; +                    uint64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const;      uint64_t    GetAttributeValueAsReference(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      const dw_attr_t attr, -                    uint64_t fail_value) const; +                    uint64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const;      int64_t     GetAttributeValueAsSigned(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      const dw_attr_t attr, -                    int64_t fail_value) const; +                    int64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const; + +    uint64_t    GetAttributeValueAsAddress( +                    SymbolFileDWARF* dwarf2Data, +                    const DWARFCompileUnit* cu, +                    const dw_attr_t attr, +                    uint64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const;      dw_addr_t   GetAttributeHighPC(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      dw_addr_t lo_pc, -                    uint64_t fail_value) const; +                    uint64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const;      bool        GetAttributeAddressRange(                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu,                      dw_addr_t& lo_pc,                      dw_addr_t& hi_pc, -                    uint64_t fail_value) const; +                    uint64_t fail_value, +                    bool check_specification_or_abstract_origin = false) const;      size_t      GetAttributeAddressRanges (                      SymbolFileDWARF* dwarf2Data,                      const DWARFCompileUnit* cu, -                    DWARFDebugRanges::RangeList &ranges, -                    bool check_hi_lo_pc) const; -     -    dw_offset_t GetAttributeValueAsLocation( -                    SymbolFileDWARF* dwarf2Data, -                    const DWARFCompileUnit* cu, -                    const dw_attr_t attr, -                    lldb_private::DWARFDataExtractor& data, -                    uint32_t &block_size) const; +                    DWARFRangeList &ranges, +                    bool check_hi_lo_pc, +                    bool check_specification_or_abstract_origin = false) const;      const char* GetName(                      SymbolFileDWARF* dwarf2Data, @@ -256,25 +205,9 @@ public:      const char * GetQualifiedName (                      SymbolFileDWARF* dwarf2Data,                       DWARFCompileUnit* cu, -                    const DWARFDebugInfoEntry::Attributes& attributes, +                    const DWARFAttributes& attributes,                      std::string &storage) const; -//    static int  Compare( -//                    SymbolFileDWARF* dwarf2Data, -//                    dw_offset_t a_die_offset, -//                    dw_offset_t b_die_offset, -//                    CompareState &compare_state, -//                    bool compare_siblings, -//                    bool compare_children); -// -//    static int Compare( -//                    SymbolFileDWARF* dwarf2Data, -//                    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, -//                    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, -//                    CompareState &compare_state, -//                    bool compare_siblings, -//                    bool compare_children); -      static bool OffsetLessThan (                      const DWARFDebugInfoEntry& a,                      const DWARFDebugInfoEntry& b); @@ -311,7 +244,7 @@ public:                      const DWARFCompileUnit* cu,                      const char * &name,                      const char * &mangled, -                    DWARFDebugRanges::RangeList& rangeList, +                    DWARFRangeList& rangeList,                      int& decl_file,                      int& decl_line,                      int& decl_column, @@ -376,8 +309,7 @@ public:      const   DWARFDebugInfoEntry*    GetFirstChild() const   { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; } -    void                            GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,  -                                                        DWARFCompileUnit* cu, +    void                            GetDeclContextDIEs (DWARFCompileUnit* cu,                                                          DWARFDIECollection &decl_context_dies) const;      void                            GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data, @@ -389,11 +321,11 @@ public:                                                              DWARFCompileUnit* cu,                                                              const DWARFDeclContext &dwarf_decl_ctx) const; -    const   DWARFDebugInfoEntry*    GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,  +            DWARFDIE                GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,                                                               DWARFCompileUnit* cu) const; -    const   DWARFDebugInfoEntry*    GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,  +            DWARFDIE                GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,                                                               DWARFCompileUnit* cu,  -                                                             const DWARFDebugInfoEntry::Attributes& attributes) const; +                                                             const DWARFAttributes& attributes) const;      void              SetParent (DWARFDebugInfoEntry* parent)      @@ -450,6 +382,13 @@ public:                         DWARFDebugInfoEntry::collection &die_collection);  protected: +    dw_offset_t GetAttributeValue(SymbolFileDWARF* dwarf2Data, +                                  const DWARFCompileUnit* cu, +                                  const dw_attr_t attr, +                                  DWARFFormValue& formValue, +                                  dw_offset_t* end_attr_offset_ptr = nullptr, +                                  bool check_specification_or_abstract_origin = false) const; +      dw_offset_t m_offset;           // Offset within the .debug_info of the start of this entry      uint32_t    m_parent_idx;       // How many to subtract from "this" to get the parent. If zero this die has no parent      uint32_t    m_sibling_idx:31,   // How many to add to "this" to get the sibling. @@ -457,7 +396,6 @@ protected:      uint32_t    m_abbr_idx:DIE_ABBR_IDX_BITSIZE,                  m_has_children:1,   // Set to 1 if this DIE has children                  m_tag:16;           // A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table -                  };  #endif  // SymbolFileDWARF_DWARFDebugInfoEntry_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp index 48e11bd800892..84c2142e84193 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp @@ -249,7 +249,7 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_l                              fileEntry.length    = debug_line_data.GetULEB128(&offset);                              log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",                                      op_offset, -                                    fileEntry.name.c_str(), +                                    fileEntry.name,                                      fileEntry.dir_idx,                                      fileEntry.mod_time,                                      fileEntry.length); @@ -486,65 +486,25 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,                                     FileSpecList &support_files)  {      lldb::offset_t offset = stmt_list; -    // Skip the total length -    (void)debug_line_data.GetDWARFInitialLength(&offset); -    uint32_t version = debug_line_data.GetU16(&offset); -    if (version < 2 || version > 4) -      return false; -    const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset; -    // Skip instruction length, default is stmt, line base, line range -    offset += 4; -    // For DWARF4, skip maximum operations per instruction -    if (version >= 4) -        offset += 1; -    // Skip opcode base, and all opcode lengths -    const uint8_t opcode_base = debug_line_data.GetU8(&offset); -    offset += opcode_base - 1; -    std::vector<FileSpec> include_directories{{}}; // Directory at index zero doesn't exist -    while (offset < end_prologue_offset) +    Prologue prologue; +    if (!ParsePrologue(debug_line_data, &offset, &prologue))      { -        FileSpec dir{debug_line_data.GetCStr(&offset), false}; -        if (dir) -            include_directories.emplace_back(std::move(dir)); -        else -            break; +        Host::SystemLog (Host::eSystemLogError, "error: parsing line table prologue at 0x%8.8x (parsing ended around 0x%8.8" PRIx64 "\n", stmt_list, offset); +        return false;      } -    while (offset < end_prologue_offset) -    { -        FileSpec file_spec{debug_line_data.GetCStr(&offset), false}; -        if (file_spec) -        { -            uint32_t dir_idx = debug_line_data.GetULEB128(&offset); -            debug_line_data.Skip_LEB128(&offset); // Skip mod_time -            debug_line_data.Skip_LEB128(&offset); // Skip length -            if (file_spec.IsRelative()) -            { -                if (0 < dir_idx && dir_idx < include_directories.size()) -                { -                    const FileSpec &dir = include_directories[dir_idx]; -                    file_spec.PrependPathComponent(dir); -                } -                if (file_spec.IsRelative()) -                    file_spec.PrependPathComponent(cu_comp_dir); -            } -            std::string remapped_file; -            if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file)) -                file_spec.SetFile(remapped_file, false); -            support_files.Append(file_spec); -        } -    } +    FileSpec file_spec; +    std::string remapped_file; -    if (offset != end_prologue_offset) +    for (uint32_t file_idx = 1; prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx)      { -        Host::SystemLog (Host::eSystemLogError,  -                         "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended at 0x%8.8" PRIx64 "\n", -                         stmt_list,  -                         end_prologue_offset,  -                         offset); +        if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file)) +            file_spec.SetFile(remapped_file, false); +        support_files.Append(file_spec); +      } -    return end_prologue_offset; +    return true;  }  //---------------------------------------------------------------------- @@ -900,7 +860,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)      {          for (i=0; i<include_directories.size(); ++i)          { -            log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str()); +            log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i]);          }      } @@ -916,7 +876,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)                  fileEntry.dir_idx,                  fileEntry.mod_time,                  fileEntry.length, -                fileEntry.name.c_str()); +                fileEntry.name);          }      }  } @@ -959,17 +919,28 @@ DWARFDebugLine::Prologue::Dump(Log *log)  //} -bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const +bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir, FileSpec &file) const  {      uint32_t idx = file_idx - 1;    // File indexes are 1 based...      if (idx < file_names.size())      { -        path = file_names[idx].name; -        uint32_t dir_idx = file_names[idx].dir_idx - 1; -        if (dir_idx < include_directories.size()) -            directory = include_directories[dir_idx]; -        else -            directory.clear(); +        file.SetFile(file_names[idx].name, false); +        if (file.IsRelative()) +        { +            if (file_names[idx].dir_idx > 0) +            { +                const uint32_t dir_idx = file_names[idx].dir_idx - 1; +                if (dir_idx < include_directories.size()) +                { +                    file.PrependPathComponent(include_directories[dir_idx]); +                    if (!file.IsRelative()) +                        return true; +                } +            } + +            if (comp_dir && comp_dir[0]) +                file.PrependPathComponent(comp_dir); +        }          return true;      }      return false; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h index 7da0e76a22be3..9f2219b018127 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h @@ -20,7 +20,6 @@  #include "DWARFDefines.h"  class SymbolFileDWARF; -class DWARFDebugInfoEntry;  //----------------------------------------------------------------------  // DWARFDebugLine @@ -34,14 +33,14 @@ public:      struct FileNameEntry      {          FileNameEntry() : -            name(), +            name(nullptr),              dir_idx(0),              mod_time(0),              length(0)          {          } -        std::string     name; +        const char*     name;          dw_sleb128_t    dir_idx;          dw_sleb128_t    mod_time;          dw_sleb128_t    length; @@ -81,7 +80,7 @@ public:          uint8_t     line_range;     // This parameter affects the meaning of the special opcodes. See below.          uint8_t     opcode_base;    // The number assigned to the first special opcode.          std::vector<uint8_t>            standard_opcode_lengths; -        std::vector<std::string>        include_directories; +        std::vector<const char *>       include_directories;          std::vector<FileNameEntry>      file_names;          int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; } @@ -96,7 +95,7 @@ public:              include_directories.clear();              file_names.clear();          } -        bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const; +        bool GetFile(uint32_t file_idx, const char *comp_dir, lldb_private::FileSpec &file) const;      }; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp new file mode 100644 index 0000000000000..75c812e6e79df --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp @@ -0,0 +1,128 @@ +//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFDebugMacro.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Symbol/DebugMacros.h" + +#include "DWARFDataExtractor.h" + +using namespace lldb_private; + +DWARFDebugMacroHeader +DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) +{ +    DWARFDebugMacroHeader header; + +    // Skip over the version field in header. +    header.m_version = debug_macro_data.GetU16(offset); + +    uint8_t flags = debug_macro_data.GetU8(offset); +    header.m_offset_is_64_bit = flags & OFFSET_SIZE_MASK ? true : false; + +    if (flags & DEBUG_LINE_OFFSET_MASK) +    { +        if (header.m_offset_is_64_bit) +            header.m_debug_line_offset = debug_macro_data.GetU64(offset); +        else +            header.m_debug_line_offset = debug_macro_data.GetU32(offset); +    } + +    // Skip over the operands table if it is present. +    if (flags & OPCODE_OPERANDS_TABLE_MASK) +        SkipOperandTable(debug_macro_data, offset); + +    return header; +} + +void +DWARFDebugMacroHeader::SkipOperandTable(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset) +{ +    uint8_t entry_count = debug_macro_data.GetU8(offset); +    for (uint8_t i = 0; i < entry_count; i++) +    { +        // Skip over the opcode number. +        debug_macro_data.GetU8(offset); + +        uint64_t operand_count = debug_macro_data.GetULEB128(offset); + +        for (uint64_t j = 0; j < operand_count; j++) +        { +            // Skip over the operand form +            debug_macro_data.GetU8(offset); +        } +    } +} + +void +DWARFDebugMacroEntry::ReadMacroEntries(const DWARFDataExtractor &debug_macro_data, +                                       const DWARFDataExtractor &debug_str_data, +                                       const bool offset_is_64_bit, +                                       lldb::offset_t *offset, +                                       SymbolFileDWARF *sym_file_dwarf, +                                       DebugMacrosSP &debug_macros_sp) +{ +    llvm::dwarf::MacroEntryType type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset)); +    while (type != 0) +    { +        lldb::offset_t new_offset = 0, str_offset = 0; +        uint32_t line = 0; +        const char *macro_str = nullptr; +        uint32_t debug_line_file_idx = 0; + +        switch (type) +        { +            case DW_MACRO_define: +            case DW_MACRO_undef: +                line = debug_macro_data.GetULEB128(offset); +                macro_str = debug_macro_data.GetCStr(offset); +                if (type == DW_MACRO_define) +                    debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str)); +                else +                    debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str)); +                break; +            case DW_MACRO_define_indirect: +            case DW_MACRO_undef_indirect: +                line = debug_macro_data.GetULEB128(offset); +                if (offset_is_64_bit) +                    str_offset = debug_macro_data.GetU64(offset); +                else +                    str_offset = debug_macro_data.GetU32(offset); +                macro_str = debug_str_data.GetCStr(&str_offset); +                if (type == DW_MACRO_define_indirect) +                    debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str)); +                else +                    debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str)); +                break; +            case DW_MACRO_start_file: +                line = debug_macro_data.GetULEB128(offset); +                debug_line_file_idx = debug_macro_data.GetULEB128(offset); +                debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx)); +                break; +            case DW_MACRO_end_file: +                // This operation has no operands. +                debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry()); +                break; +            case DW_MACRO_transparent_include: +                if (offset_is_64_bit) +                    new_offset = debug_macro_data.GetU64(offset); +                else +                    new_offset = debug_macro_data.GetU32(offset); +                debug_macros_sp->AddMacroEntry( +                    DebugMacroEntry::CreateIndirectEntry(sym_file_dwarf->ParseDebugMacros(&new_offset))); +                break; +            default: +                // TODO: Add support for other standard operations. +                // TODO: Provide mechanism to hook handling of non-standard/extension operands. +                return; +        } +        type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset)); +    } +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h new file mode 100644 index 0000000000000..c60b9749b005e --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h @@ -0,0 +1,68 @@ +//===-- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARF_DWARFDebugMacro_h_ +#define SymbolFileDWARF_DWARFDebugMacro_h_ + +#include <map> + +#include "lldb/lldb-types.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Symbol/DebugMacros.h" + +namespace lldb_private +{ + +class DWARFDataExtractor; + +} // namespace lldb_private + +class SymbolFileDWARF; + +class DWARFDebugMacroHeader +{ +public: +    enum HeaderFlagMask +    { +        OFFSET_SIZE_MASK = 0x1, +        DEBUG_LINE_OFFSET_MASK = 0x2, +        OPCODE_OPERANDS_TABLE_MASK = 0x4 +    }; + +    static DWARFDebugMacroHeader +    ParseHeader(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); + +    bool +    OffsetIs64Bit() const +    { +        return m_offset_is_64_bit; +    } + +private: +    static void +    SkipOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset); + +    uint16_t m_version; +    bool m_offset_is_64_bit; +    uint64_t m_debug_line_offset; +}; + +class DWARFDebugMacroEntry +{ +public: +    static void +    ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data, +                     const lldb_private::DWARFDataExtractor &debug_str_data, +                     const bool offset_is_64_bit, +                     lldb::offset_t *sect_offset, +                     SymbolFileDWARF *sym_file_dwarf, +                     lldb_private::DebugMacrosSP &debug_macros_sp); +}; + +#endif // SymbolFileDWARF_DWARFDebugMacro_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp index 8469b78d0dd56..547bd0cd1a5a2 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp @@ -77,9 +77,6 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)      DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();      if (debug_info)      { - -        const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data(); -          uint32_t cu_idx = 0;          const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();          for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) @@ -87,7 +84,9 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)              DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); -            const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64()); +            DWARFFormValue::FixedFormSizes fixed_form_sizes = +                DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), +                                                                 cu->IsDWARF64());              bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; @@ -101,17 +100,17 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)              size_t die_idx;              for (die_idx = 0; die_idx < die_count; ++die_idx)              { -                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); -                DWARFDebugInfoEntry::Attributes attributes; +                DWARFDIE die = dies.GetDIEAtIndex(die_idx); +                DWARFAttributes attributes;                  const char *name = NULL;                  const char *mangled = NULL;                  bool add_die = false; -                const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); +                const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes);                  if (num_attributes > 0)                  {                      uint32_t i; -                    dw_tag_t tag = die->Tag(); +                    dw_tag_t tag = die.Tag();                      for (i=0; i<num_attributes; ++i)                      { @@ -120,14 +119,14 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)                          switch (attr)                          {                          case DW_AT_name: -                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) -                                name = form_value.AsCString(debug_str); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                                name = form_value.AsCString();                              break;                          case DW_AT_MIPS_linkage_name:                          case DW_AT_linkage_name: -                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) -                                mangled = form_value.AsCString(debug_str); +                            if (attributes.ExtractFormValueAtIndex(i, form_value)) +                                mangled = form_value.AsCString();                              break;                          case DW_AT_low_pc: @@ -140,10 +139,10 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)                          case DW_AT_location:                              if (tag == DW_TAG_variable)                              { -                                const DWARFDebugInfoEntry* parent_die = die->GetParent(); -                                while ( parent_die != NULL ) +                                DWARFDIE parent_die = die.GetParent(); +                                while ( parent_die )                                  { -                                    switch (parent_die->Tag()) +                                    switch (parent_die.Tag())                                      {                                      case DW_TAG_subprogram:                                      case DW_TAG_lexical_block: @@ -153,31 +152,16 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)                                          // if the location describes a hard coded address, but we don't want the performance                                          // penalty of that right now.                                          add_die = false; -//                                      if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) -//                                      { -//                                          // If we have valid block data, then we have location expression bytes -//                                          // that are fixed (not a location list). -//                                          const uint8_t *block_data = form_value.BlockData(); -//                                          if (block_data) -//                                          { -//                                              uint32_t block_length = form_value.Unsigned(); -//                                              if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) -//                                              { -//                                                  if (block_data[0] == DW_OP_addr) -//                                                      add_die = true; -//                                              } -//                                          } -//                                      } -                                        parent_die = NULL;  // Terminate the while loop. +                                        parent_die.Clear();  // Terminate the while loop.                                          break;                                      case DW_TAG_compile_unit:                                          add_die = true; -                                        parent_die = NULL;  // Terminate the while loop. +                                        parent_die.Clear();  // Terminate the while loop.                                          break;                                      default: -                                        parent_die = parent_die->GetParent();   // Keep going in the while loop. +                                        parent_die = parent_die.GetParent();   // Keep going in the while loop.                                          break;                                      }                                  } @@ -189,7 +173,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)                  if (add_die && (name || mangled))                  { -                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name); +                    pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name);                  }              } @@ -231,13 +215,11 @@ DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)              size_t die_idx;              for (die_idx = 0; die_idx < die_count; ++die_idx)              { -                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); -                const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL); +                DWARFDIE die = dies.GetDIEAtIndex (die_idx); +                const char *name = die.GetName();                  if (name) -                { -                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name); -                } +                    pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);              }              if (pubnames_set.NumDescriptors() > 0) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp index 0953554ffd7d0..fc2831f224380 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp @@ -27,7 +27,7 @@ DWARFDebugRanges::~DWARFDebugRanges()  void  DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)  { -    RangeList range_list; +    DWARFRangeList range_list;      lldb::offset_t offset = 0;      dw_offset_t debug_ranges_offset = offset;      while (Extract(dwarf2Data, &offset, range_list)) @@ -38,52 +38,8 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)      }  } -//void -//DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset) -//{ -//    if (!ranges.empty()) -//    { -//        Range::iterator pos = ranges.begin(); -//        Range::iterator end_pos = ranges.end(); -//        for (pos = ranges.begin(); pos != end_pos; ++pos) -//        { -//            // assert for unsigned overflows -//            assert (~pos->begin_offset >= offset); -//            assert (~pos->end_offset >= offset); -//            pos->begin_offset += offset; -//            pos->end_offset += offset; -//        } -//    } -//} -// -//void -//DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset) -//{ -//    if (!ranges.empty()) -//    { -//        Range::iterator pos = ranges.begin(); -//        Range::iterator end_pos = ranges.end(); -//        for (pos = ranges.begin(); pos != end_pos; ++pos) -//        { -//            assert (pos->begin_offset >= offset); -//            assert (pos->end_offset >= offset); -//            pos->begin_offset -= offset; -//            pos->end_offset -= offset; -//        } -//    } -//} -// -// -//const DWARFDebugRanges::Range* -//DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const -//{ -//    if (i < ranges.size()) -//        return &ranges[i]; -//    return NULL; -//} -  bool -DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list) +DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, DWARFRangeList &range_list)  {      range_list.Clear(); @@ -118,13 +74,13 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt              break;          default: -            assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size."); +            assert(!"DWARFRangeList::Extract() unsupported address size.");              break;          }          // Filter out empty ranges          if (begin < end) -            range_list.Append(Range(begin, end - begin)); +            range_list.Append(DWARFRangeList::Entry(begin, end - begin));      }      // Make sure we consumed at least something @@ -178,7 +134,7 @@ DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, l  }  bool -DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const +DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const  {      range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);      if (pos != m_range_map.end()) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h index 50af91d410094..3ff4ea3502c99 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h @@ -11,34 +11,30 @@  #define SymbolFileDWARF_DWARFDebugRanges_h_  #include "SymbolFileDWARF.h" +#include "DWARFDIE.h"  #include <map> -#include <vector> - -#include "lldb/Core/RangeMap.h"  class DWARFDebugRanges  {  public: -    typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> RangeList; -    typedef RangeList::Entry Range;      DWARFDebugRanges();      ~DWARFDebugRanges();      void Extract(SymbolFileDWARF* dwarf2Data);      static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr); -    bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const; +    bool FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const;  protected:      bool      Extract (SymbolFileDWARF* dwarf2Data,                lldb::offset_t *offset_ptr,  -             RangeList &range_list); +             DWARFRangeList &range_list); -    typedef std::map<dw_offset_t, RangeList>    range_map; -    typedef range_map::iterator                 range_map_iterator; -    typedef range_map::const_iterator           range_map_const_iterator; +    typedef std::map<dw_offset_t, DWARFRangeList>   range_map; +    typedef range_map::iterator                     range_map_iterator; +    typedef range_map::const_iterator               range_map_const_iterator;      range_map m_range_map;  }; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 3a99d2b338786..4c29447b47bb8 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -108,6 +108,13 @@ public:          return lldb_private::ConstString (GetQualifiedName ());      } +    void +    Clear() +    { +        m_entries.clear(); +        m_qualified_name.clear(); +    } +  protected:      typedef std::vector<Entry> collection;      collection m_entries; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index c733832e4f4df..a0ed9731a565d 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -136,21 +136,21 @@ g_form_sizes_addr8_dwarf64[] =      8, // 0x20 DW_FORM_ref_sig8  }; -const uint8_t *  +DWARFFormValue::FixedFormSizes  DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)  {      if (!is_dwarf64) {          switch (addr_size)          { -        case 4: return g_form_sizes_addr4; -        case 8: return g_form_sizes_addr8; +        case 4: return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4)); +        case 8: return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8));          }      } else {          if (addr_size == 8) -            return g_form_sizes_addr8_dwarf64; +            return FixedFormSizes(g_form_sizes_addr8_dwarf64, sizeof(g_form_sizes_addr8_dwarf64));          // is_dwarf64 && addr_size == 4 : no provider does this.      } -    return NULL; +    return FixedFormSizes();  }  DWARFFormValue::DWARFFormValue() : @@ -187,11 +187,7 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off          case DW_FORM_data2:     m_value.value.uval = data.GetU16(offset_ptr);                           break;          case DW_FORM_data4:     m_value.value.uval = data.GetU32(offset_ptr);                           break;          case DW_FORM_data8:     m_value.value.uval = data.GetU64(offset_ptr);                           break; -        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr); -                                // Set the string value to also be the data for inlined cstr form values only -                                // so we can tell the difference between DW_FORM_string and DW_FORM_strp form -                                // values; -                                m_value.data = (const uint8_t*)m_value.value.cstr;                      break; +        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr);                          break;          case DW_FORM_exprloc:          case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;          case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break; @@ -219,10 +215,12 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off              indirect = true;              break; -        case DW_FORM_sec_offset:    assert(m_cu); -                                    m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);  break; -        case DW_FORM_flag_present:  m_value.value.uval = 1;                                             break; -        case DW_FORM_ref_sig8:      m_value.value.uval = data.GetU64(offset_ptr);                       break; +        case DW_FORM_sec_offset:     assert(m_cu); +                                     m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break; +        case DW_FORM_flag_present:   m_value.value.uval = 1;                                            break; +        case DW_FORM_ref_sig8:       m_value.value.uval = data.GetU64(offset_ptr);                      break; +        case DW_FORM_GNU_str_index:  m_value.value.uval = data.GetULEB128(offset_ptr);                  break; +        case DW_FORM_GNU_addr_index: m_value.value.uval = data.GetULEB128(offset_ptr);                  break;          default:              return false;              break; @@ -322,6 +320,8 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d      case DW_FORM_sdata:      case DW_FORM_udata:      case DW_FORM_ref_udata: +    case DW_FORM_GNU_addr_index: +    case DW_FORM_GNU_str_index:          debug_info_data.Skip_LEB128(offset_ptr);          return true; @@ -342,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d  void -DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const +DWARFFormValue::Dump(Stream &s) const  {      uint64_t uvalue = Unsigned();      bool cu_relative_offset = false; @@ -353,13 +353,13 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const      {      case DW_FORM_addr:      s.Address(uvalue, sizeof (uint64_t)); break;      case DW_FORM_flag: -    case DW_FORM_data1:     s.PutHex8(uvalue);     break; +    case DW_FORM_data1:     s.PutHex8(uvalue);         break;      case DW_FORM_data2:     s.PutHex16(uvalue);        break;      case DW_FORM_sec_offset:      case DW_FORM_data4:     s.PutHex32(uvalue);        break;      case DW_FORM_ref_sig8:      case DW_FORM_data8:     s.PutHex64(uvalue);        break; -    case DW_FORM_string:    s.QuotedCString(AsCString(NULL));          break; +    case DW_FORM_string:    s.QuotedCString(AsCString()); break;      case DW_FORM_exprloc:      case DW_FORM_block:      case DW_FORM_block1: @@ -395,18 +395,18 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const      case DW_FORM_sdata:     s.PutSLEB128(uvalue); break;      case DW_FORM_udata:     s.PutULEB128(uvalue); break;      case DW_FORM_strp: -        if (debug_str_data)          { -            if (verbose) -                s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); - -            const char* dbg_str = AsCString(debug_str_data); +            const char* dbg_str = AsCString();              if (dbg_str) +            { +                if (verbose) +                    s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);                  s.QuotedCString(dbg_str); -        } -        else -        { -            s.PutHex32(uvalue); +            } +            else +            { +                s.PutHex32(uvalue); +            }          }          break; @@ -444,13 +444,52 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const  }  const char* -DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const +DWARFFormValue::AsCString() const  { -    if (IsInlinedCStr()) +    SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF(); + +    if (m_form == DW_FORM_string) +    {          return m_value.value.cstr; -    else if (debug_str_data_ptr) -        return debug_str_data_ptr->PeekCStr(m_value.value.uval); -    return NULL; +    } +    else if (m_form == DW_FORM_strp) +    { +        if (!symbol_file) +            return nullptr; + +        return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval); +    } +    else if (m_form == DW_FORM_GNU_str_index) +    { +        if (!symbol_file) +            return nullptr; + +        uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4; +        lldb::offset_t offset = m_value.value.uval * index_size; +        dw_offset_t str_offset = symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, index_size); +        return symbol_file->get_debug_str_data().PeekCStr(str_offset); +    } +    return nullptr; +} + +dw_addr_t +DWARFFormValue::Address() const +{ +    SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF(); + +    if (m_form == DW_FORM_addr) +        return Unsigned(); + +    assert(m_cu); +    assert(m_form == DW_FORM_GNU_addr_index); + +    if (!symbol_file) +        return 0; + +    uint32_t index_size = m_cu->GetAddressByteSize(); +    dw_offset_t addr_base = m_cu->GetAddrBase(); +    lldb::offset_t offset = addr_base + m_value.value.uval * index_size; +    return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);  }  uint64_t @@ -500,9 +539,7 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const  const uint8_t*  DWARFFormValue::BlockData() const  { -    if (!IsInlinedCStr()) -        return m_value.data; -    return NULL; +    return m_value.data;  } @@ -537,7 +574,8 @@ DWARFFormValue::IsDataForm(const dw_form_t form)  }  int -DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr) +DWARFFormValue::Compare (const DWARFFormValue& a_value, +                         const DWARFFormValue& b_value)  {      dw_form_t a_form = a_value.Form();      dw_form_t b_form = b_value.Form(); @@ -558,6 +596,7 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_      case DW_FORM_sec_offset:      case DW_FORM_flag_present:      case DW_FORM_ref_sig8: +    case DW_FORM_GNU_addr_index:          {              uint64_t a = a_value.Unsigned();              uint64_t b = b_value.Unsigned(); @@ -581,9 +620,10 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_      case DW_FORM_string:      case DW_FORM_strp: +    case DW_FORM_GNU_str_index:          { -            const char *a_string = a_value.AsCString(debug_str_data_ptr); -            const char *b_string = b_value.AsCString(debug_str_data_ptr); +            const char *a_string = a_value.AsCString(); +            const char *b_string = b_value.AsCString();              if (a_string == b_string)                  return 0;              else if (a_string && b_string) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 392df26a088e1..b10f4d3a0ac97 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -35,6 +35,34 @@ public:          } value;          const uint8_t* data;      } ValueType; +     +    class FixedFormSizes +    { +    public: +        FixedFormSizes() : +            m_fix_sizes(nullptr), m_size(0) +        {} + +        FixedFormSizes(const uint8_t* fix_sizes, size_t size) : +            m_fix_sizes(fix_sizes), m_size(size) +        {} + +        uint8_t +        GetSize(uint32_t index) const +        { +            return index < m_size ? m_fix_sizes[index] : 0; +        } + +        bool +        Empty() const +        { +            return m_size == 0; +        } + +    private: +        const uint8_t* m_fix_sizes; +        size_t         m_size; +    };      enum      { @@ -52,10 +80,9 @@ public:      dw_form_t           Form()  const { return m_form; }      void                SetForm(dw_form_t form) { m_form = form; }      const ValueType&    Value() const { return m_value; } -    void                Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const; +    void                Dump(lldb_private::Stream &s) const;      bool                ExtractValue(const lldb_private::DWARFDataExtractor& data,                                       lldb::offset_t* offset_ptr); -    bool                IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; }      const uint8_t*      BlockData() const;      uint64_t            Reference() const;      uint64_t            Reference (dw_offset_t offset) const; @@ -64,13 +91,16 @@ public:      void                SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }      int64_t             Signed() const { return m_value.value.sval; }      void                SetSigned(int64_t sval) { m_value.value.sval = sval; } -    const char*         AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const; +    const char*         AsCString() const; +    dw_addr_t           Address() const; +    bool                IsValid() const { return m_form != 0; }      bool                SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const;      static bool         SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);      static bool         IsBlockForm(const dw_form_t form);      static bool         IsDataForm(const dw_form_t form); -    static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); -    static int          Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr); +    static FixedFormSizes GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); +    static int          Compare (const DWARFFormValue& a,  +                                 const DWARFFormValue& b);  protected:      const DWARFCompileUnit* m_cu; // Compile unit for this form      dw_form_t   m_form;     // Form for this value diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp deleted file mode 100644 index d79ae79822b08..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp +++ /dev/null @@ -1,172 +0,0 @@ -//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFLocationDescription.h" -#include "DWARFDefines.h" -#include "lldb/lldb-private.h" -#include "lldb/Core/Stream.h" - - -using namespace lldb_private; - -static int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size); - -int -print_dwarf_expression (Stream &s, -                        const DWARFDataExtractor& data, -                        int address_size, -                        int dwarf_ref_size, -                        bool location_expression) -{ -    int op_count = 0; -    lldb::offset_t offset = 0; -    while (data.ValidOffset(offset)) -    { -        if (location_expression && op_count > 0) -        { -            //  err (baton, "Dwarf location expressions may only have one operand!"); -            return 1; -        } -        if (op_count > 0) -        { -            s.PutCString(", "); -        } -        if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1) -            return 1; -        op_count++; -    } - -    return 0; -} - -static int -print_dwarf_exp_op (Stream &s, -                    const DWARFDataExtractor& data, -                    lldb::offset_t *offset_ptr, -                    int address_size, -                    int dwarf_ref_size) -{ -    uint8_t opcode = data.GetU8(offset_ptr); -    DRC_class opcode_class; -    uint64_t  uint; -    int64_t   sint; - -    int size; - -    opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); - -    s.Printf("%s ", DW_OP_value_to_name (opcode)); - -    /* Does this take zero parameters?  If so we can shortcut this function.  */ -    if (opcode_class == DRC_ZEROOPERANDS) -        return 0; - -    if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) -    { -        uint = data.GetULEB128(offset_ptr); -        sint = data.GetSLEB128(offset_ptr); -        s.Printf("%" PRIu64 " %" PRIi64, uint, sint); -        return 0; -    } -    if (opcode_class != DRC_ONEOPERAND) -    { -        s.Printf("UNKNOWN OP %u", opcode); -        return 1; -    } - -    switch (opcode) -    { -        case DW_OP_addr:    size = address_size;    break; -        case DW_OP_const1u: size = 1;               break; -        case DW_OP_const1s: size = -1;              break; -        case DW_OP_const2u: size = 2;               break; -        case DW_OP_const2s: size = -2;              break; -        case DW_OP_const4u: size = 4;               break; -        case DW_OP_const4s: size = -4;              break; -        case DW_OP_const8u: size = 8;               break; -        case DW_OP_const8s: size = -8;              break; -        case DW_OP_constu:  size = 128;             break; -        case DW_OP_consts:  size = -128;            break; -        case DW_OP_fbreg:   size = -128;            break; -        case DW_OP_breg0: -        case DW_OP_breg1: -        case DW_OP_breg2: -        case DW_OP_breg3: -        case DW_OP_breg4: -        case DW_OP_breg5: -        case DW_OP_breg6: -        case DW_OP_breg7: -        case DW_OP_breg8: -        case DW_OP_breg9: -        case DW_OP_breg10: -        case DW_OP_breg11: -        case DW_OP_breg12: -        case DW_OP_breg13: -        case DW_OP_breg14: -        case DW_OP_breg15: -        case DW_OP_breg16: -        case DW_OP_breg17: -        case DW_OP_breg18: -        case DW_OP_breg19: -        case DW_OP_breg20: -        case DW_OP_breg21: -        case DW_OP_breg22: -        case DW_OP_breg23: -        case DW_OP_breg24: -        case DW_OP_breg25: -        case DW_OP_breg26: -        case DW_OP_breg27: -        case DW_OP_breg28: -        case DW_OP_breg29: -        case DW_OP_breg30: -        case DW_OP_breg31: -            size = -128; break; -        case DW_OP_pick: -            size = 1;       break; -        case DW_OP_deref_size: -            size = 1;       break; -        case DW_OP_xderef_size: -            size = 1;       break; -        case DW_OP_plus_uconst: -            size = 128;     break; -        case DW_OP_skip: -            size = -2;      break; -        case DW_OP_bra: -            size = -2;      break; -        case DW_OP_call2: -            size = 2;       break; -        case DW_OP_call4: -            size = 4;       break; -        case DW_OP_call_ref: -            size = dwarf_ref_size;  break; -        case DW_OP_piece: -            size = 128; break; -        case DW_OP_regx: -            size = 128; break; -        default: -            s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); -            return 1; -    } - -    switch (size) -    { -    case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s.Printf("%+" PRIi64, sint); break; -    case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s.Printf("%+" PRIi64, sint); break; -    case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s.Printf("%+" PRIi64, sint); break; -    case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s.Printf("%+" PRIi64, sint); break; -    case -128:  sint = data.GetSLEB128(offset_ptr);             s.Printf("%+" PRIi64, sint); break; -    case 1:     uint = data.GetU8(offset_ptr);                  s.Printf("0x%2.2" PRIx64, uint); break; -    case 2:     uint = data.GetU16(offset_ptr);                 s.Printf("0x%4.4" PRIx64, uint); break; -    case 4:     uint = data.GetU32(offset_ptr);                 s.Printf("0x%8.8" PRIx64, uint); break; -    case 8:     uint = data.GetU64(offset_ptr);                 s.Printf("0x%16.16" PRIx64, uint); break; -    case 128:   uint = data.GetULEB128(offset_ptr);             s.Printf("0x%" PRIx64, uint); break; -    } - -    return 0; -} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h deleted file mode 100644 index 69cc0c15969c4..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- DWARFLocationDescription.h ------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFLocationDescription_h_ -#define SymbolFileDWARF_DWARFLocationDescription_h_ - -#include "SymbolFileDWARF.h" - -int -print_dwarf_expression (lldb_private::Stream &s, -                        const lldb_private::DWARFDataExtractor& data, -                        int address_size, -                        int dwarf_ref_size, -                        bool location_expression); - - - -#endif  // SymbolFileDWARF_DWARFLocationDescription_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp deleted file mode 100644 index 26768f060ef12..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFLocationList.h" - -#include "lldb/Core/Stream.h" - -#include "DWARFCompileUnit.h" -#include "DWARFDebugInfo.h" -#include "DWARFLocationDescription.h" - -using namespace lldb_private; - -dw_offset_t -DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset) -{ -    uint64_t start_addr, end_addr; -    uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu); -    s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu)); -    dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0; -    while (debug_loc_data.ValidOffset(offset)) -    { -        start_addr = debug_loc_data.GetMaxU64(&offset,addr_size); -        end_addr = debug_loc_data.GetMaxU64(&offset,addr_size); - -        if (start_addr == 0 && end_addr == 0) -            break; - -        s.PutCString("\n            "); -        s.Indent(); -        if (cu) -            s.AddressRange (start_addr + base_addr,  -                            end_addr + base_addr,  -                            cu->GetAddressByteSize(),  -                            NULL, -                            ": "); -        uint32_t loc_length = debug_loc_data.GetU16(&offset); - -        DWARFDataExtractor locationData(debug_loc_data, offset, loc_length); -    //  if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( "; -        print_dwarf_expression (s, locationData, addr_size, 4, false); -        offset += loc_length; -    } - -    return offset; -} - -bool -DWARFLocationList::Extract(const DWARFDataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DWARFDataExtractor& location_list_data) -{ -    // Initialize with no data just in case we don't find anything -    location_list_data.Clear(); - -    size_t loc_list_length = Size(debug_loc_data, *offset_ptr); -    if (loc_list_length > 0) -    { -        location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length); -        *offset_ptr += loc_list_length; -        return true; -    } - -    return false; -} - -size_t -DWARFLocationList::Size(const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset) -{ -    const dw_offset_t debug_loc_offset = offset; - -    while (debug_loc_data.ValidOffset(offset)) -    { -        dw_addr_t start_addr = debug_loc_data.GetAddress(&offset); -        dw_addr_t end_addr = debug_loc_data.GetAddress(&offset); - -        if (start_addr == 0 && end_addr == 0) -            break; - -        uint16_t loc_length = debug_loc_data.GetU16(&offset); -        offset += loc_length; -    } - -    if (offset > debug_loc_offset) -        return offset - debug_loc_offset; -    return 0; -} - - - diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h deleted file mode 100644 index 6dcc0d74e441f..0000000000000 --- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h +++ /dev/null @@ -1,34 +0,0 @@ -//===-- DWARFLocationList.h -------------------------------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef SymbolFileDWARF_DWARFLocationList_h_ -#define SymbolFileDWARF_DWARFLocationList_h_ - -#include "SymbolFileDWARF.h" - -class DWARFLocationList -{ -public: -    static dw_offset_t -    Dump (lldb_private::Stream &s, -          const DWARFCompileUnit* cu, -          const lldb_private::DWARFDataExtractor& debug_loc_data, -          lldb::offset_t offset); - -    static bool -    Extract (const lldb_private::DWARFDataExtractor& debug_loc_data, -             lldb::offset_t* offset_ptr, -             lldb_private::DWARFDataExtractor& location_list_data); - -    static size_t -    Size (const lldb_private::DWARFDataExtractor& debug_loc_data, -          lldb::offset_t offset); - -}; -#endif  // SymbolFileDWARF_DWARFLocationList_h_ diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp new file mode 100644 index 0000000000000..0db416054ae8e --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -0,0 +1,747 @@ +//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "HashedNameToDIE.h" + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets) +{ +    const size_t count = die_info_array.size(); +    for (size_t i=0; i<count; ++i) +        die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +} + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, +                                  const dw_tag_t tag, +                                  DIEArray &die_offsets) +{ +    if (tag == 0) +    { +        ExtractDIEArray (die_info_array, die_offsets); +    } +    else +    { +        const size_t count = die_info_array.size(); +        for (size_t i=0; i<count; ++i) +        { +            const dw_tag_t die_tag = die_info_array[i].tag; +            bool tag_matches = die_tag == 0 || tag == die_tag; +            if (!tag_matches) +            { +                if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) +                    tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; +            } +            if (tag_matches) +                die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +        } +    } +} + +void +DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, +                                  const dw_tag_t tag, +                                  const uint32_t qualified_name_hash, +                                  DIEArray &die_offsets) +{ +    if (tag == 0) +    { +        ExtractDIEArray (die_info_array, die_offsets); +    } +    else +    { +        const size_t count = die_info_array.size(); +        for (size_t i=0; i<count; ++i) +        { +            if (qualified_name_hash != die_info_array[i].qualified_name_hash) +                continue; +            const dw_tag_t die_tag = die_info_array[i].tag; +            bool tag_matches = die_tag == 0 || tag == die_tag; +            if (!tag_matches) +            { +                if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) +                    tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; +            } +            if (tag_matches) +                die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +        } +    } +} + +void +DWARFMappedHash::ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, +                                               bool return_implementation_only_if_available, +                                               DIEArray &die_offsets) +{ +    const size_t count = die_info_array.size(); +    for (size_t i=0; i<count; ++i) +    { +        const dw_tag_t die_tag = die_info_array[i].tag; +        if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) +        { +            if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) +            { +                if (return_implementation_only_if_available) +                { +                    // We found the one true definition for this class, so +                    // only return that +                    die_offsets.clear();                         +                    die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +                    return; +                } +                else +                { +                    // Put the one true definition as the first entry so it +                    // matches first +                    die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset, die_info_array[i].offset); +                } +            } +            else +            { +                die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +            } +        } +    } +} + +void +DWARFMappedHash::ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, +                                           uint32_t type_flag_mask, +                                           uint32_t type_flag_value, +                                           DIEArray &die_offsets) +{ +    const size_t count = die_info_array.size(); +    for (size_t i=0; i<count; ++i) +    { +        if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) +            die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset); +    } +} + +const char * +DWARFMappedHash::GetAtomTypeName (uint16_t atom) +{ +    switch (atom) +    { +        case eAtomTypeNULL:         return "NULL"; +        case eAtomTypeDIEOffset:    return "die-offset"; +        case eAtomTypeCUOffset:     return "cu-offset"; +        case eAtomTypeTag:          return "die-tag"; +        case eAtomTypeNameFlags:    return "name-flags"; +        case eAtomTypeTypeFlags:    return "type-flags"; +        case eAtomTypeQualNameHash: return "qualified-name-hash"; +    } +    return "<invalid>"; +} + +DWARFMappedHash::DIEInfo::DIEInfo () : +    cu_offset (DW_INVALID_OFFSET), +    offset (DW_INVALID_OFFSET), +    tag (0), +    type_flags (0), +    qualified_name_hash (0) +{ +} + +DWARFMappedHash::DIEInfo::DIEInfo (dw_offset_t c, +                                   dw_offset_t o, +                                   dw_tag_t t, +                                   uint32_t f, +                                   uint32_t h) : +    cu_offset (c), +    offset (o), +    tag (t), +    type_flags (f), +    qualified_name_hash (h) +{ +} + +DWARFMappedHash::Prologue::Prologue (dw_offset_t _die_base_offset) : +    die_base_offset (_die_base_offset), +    atoms(), +    atom_mask (0), +    min_hash_data_byte_size(0), +    hash_data_has_fixed_byte_size(true) +{ +    // Define an array of DIE offsets by first defining an array,  +    // and then define the atom type for the array, in this case +    // we have an array of DIE offsets +    AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); +} + +void +DWARFMappedHash::Prologue::ClearAtoms () +{ +    hash_data_has_fixed_byte_size = true; +    min_hash_data_byte_size = 0; +    atom_mask = 0; +    atoms.clear(); +} + +bool +DWARFMappedHash::Prologue::ContainsAtom (AtomType atom_type) const +{ +    return (atom_mask & (1u << atom_type)) != 0; +} + +void +DWARFMappedHash::Prologue::Clear () +{ +    die_base_offset = 0; +    ClearAtoms (); +} + +void +DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form) +{ +    atoms.push_back ({type, form}); +    atom_mask |= 1u << type; +    switch (form) +    { +        case DW_FORM_indirect: +        case DW_FORM_exprloc: +        case DW_FORM_flag_present: +        case DW_FORM_ref_sig8: +            assert (!"Unhandled atom form"); +            break; + +        case DW_FORM_string: +        case DW_FORM_block: +        case DW_FORM_block1: +        case DW_FORM_sdata: +        case DW_FORM_udata: +        case DW_FORM_ref_udata: +        case DW_FORM_GNU_addr_index: +        case DW_FORM_GNU_str_index: +            hash_data_has_fixed_byte_size = false; +            // Fall through to the cases below... +        case DW_FORM_flag: +        case DW_FORM_data1: +        case DW_FORM_ref1: +        case DW_FORM_sec_offset: +            min_hash_data_byte_size += 1;  +            break; + +        case DW_FORM_block2: +            hash_data_has_fixed_byte_size = false; +            // Fall through to the cases below... +        case DW_FORM_data2:  +        case DW_FORM_ref2: +            min_hash_data_byte_size += 2;  +            break; + +        case DW_FORM_block4:  +            hash_data_has_fixed_byte_size = false; +            // Fall through to the cases below... +        case DW_FORM_data4: +        case DW_FORM_ref4: +        case DW_FORM_addr: +        case DW_FORM_ref_addr: +        case DW_FORM_strp: +            min_hash_data_byte_size += 4;  +            break; + +        case DW_FORM_data8: +        case DW_FORM_ref8: +            min_hash_data_byte_size += 8;  +            break; +             +    } +} + +lldb::offset_t +DWARFMappedHash::Prologue::Read (const lldb_private::DataExtractor &data, +      lldb::offset_t offset) +{ +    ClearAtoms (); +     +    die_base_offset = data.GetU32 (&offset); +     +    const uint32_t atom_count = data.GetU32 (&offset); +    if (atom_count == 0x00060003u) +    { +        // Old format, deal with contents of old pre-release format +        while (data.GetU32(&offset)) +            /* do nothing */; + +        // Hardcode to the only known value for now. +        AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); +    } +    else +    { +        for (uint32_t i=0; i<atom_count; ++i) +        { +            AtomType type = (AtomType)data.GetU16 (&offset); +            dw_form_t form = (dw_form_t)data.GetU16 (&offset);                     +            AppendAtom (type, form); +        } +    } +    return offset; +} + +size_t +DWARFMappedHash::Prologue::GetByteSize () const +{ +    // Add an extra count to the atoms size for the zero termination Atom that gets +    // written to disk +    return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); +} + +size_t +DWARFMappedHash::Prologue::GetMinimumHashDataByteSize () const +{ +    return min_hash_data_byte_size; +} + +bool +DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const +{ +    return hash_data_has_fixed_byte_size; +} + +size_t +DWARFMappedHash::Header::GetByteSize (const HeaderData &header_data) +{ +    return header_data.GetByteSize(); +} + +lldb::offset_t +DWARFMappedHash::Header::Read (lldb_private::DataExtractor &data, lldb::offset_t offset) +{ +    offset = MappedHash::Header<Prologue>::Read (data, offset); +    if (offset != UINT32_MAX) +    { +        offset = header_data.Read (data, offset); +    } +    return offset; +} + +bool +DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data,  +                               lldb::offset_t *offset_ptr,  +                               DIEInfo &hash_data) const +{ +    const size_t num_atoms = header_data.atoms.size(); +    if (num_atoms == 0) +        return false; +     +    for (size_t i=0; i<num_atoms; ++i) +    { +        DWARFFormValue form_value (NULL, header_data.atoms[i].form); +         +        if (!form_value.ExtractValue(data, offset_ptr)) +            return false; +         +        switch (header_data.atoms[i].type) +        { +            case eAtomTypeDIEOffset:    // DIE offset, check form for encoding +                hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); +                break; + +            case eAtomTypeTag:          // DW_TAG value for the DIE +                hash_data.tag = (dw_tag_t)form_value.Unsigned (); +                 +            case eAtomTypeTypeFlags:    // Flags from enum TypeFlags +                hash_data.type_flags = (uint32_t)form_value.Unsigned (); +                break; + +            case eAtomTypeQualNameHash:    // Flags from enum TypeFlags +                hash_data.qualified_name_hash = form_value.Unsigned (); +                break; + +            default: +                // We can always skip atoms we don't know about +                break; +        } +    } +    return true; +} + +void +DWARFMappedHash::Header::Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const +{ +    const size_t num_atoms = header_data.atoms.size(); +    for (size_t i=0; i<num_atoms; ++i) +    { +        if (i > 0) +            strm.PutCString (", "); +         +        DWARFFormValue form_value (NULL, header_data.atoms[i].form); +        switch (header_data.atoms[i].type) +        { +            case eAtomTypeDIEOffset:    // DIE offset, check form for encoding +                strm.Printf ("{0x%8.8x}", hash_data.offset); +                break; + +            case eAtomTypeTag:          // DW_TAG value for the DIE +                { +                    const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); +                    if (tag_cstr) +                        strm.PutCString (tag_cstr); +                    else +                        strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); +                } +                break; + +            case eAtomTypeTypeFlags:    // Flags from enum TypeFlags +                strm.Printf ("0x%2.2x", hash_data.type_flags); +                if (hash_data.type_flags) +                { +                    strm.PutCString (" ("); +                    if (hash_data.type_flags & eTypeFlagClassIsImplementation) +                        strm.PutCString (" implementation"); +                    strm.PutCString (" )"); +                } +                break; + +            case eAtomTypeQualNameHash:    // Flags from enum TypeFlags +                strm.Printf ("0x%8.8x", hash_data.qualified_name_hash); +                break; + +            default: +                strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); +                break; +        } +    } +} + +DWARFMappedHash::MemoryTable::MemoryTable (lldb_private::DWARFDataExtractor &table_data,  +                                           const lldb_private::DWARFDataExtractor &string_table, +                                           const char *name) : +    MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), +    m_data (table_data), +    m_string_table (string_table), +    m_name (name) +{ +} + +const char * +DWARFMappedHash::MemoryTable::GetStringForKeyType (KeyType key) const +{ +    // The key in the DWARF table is the .debug_str offset for the string +    return m_string_table.PeekCStr (key); +} + +bool +DWARFMappedHash::MemoryTable::ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const +{ +    lldb::offset_t offset = hash_data_offset; +    offset += 4; // Skip string table offset that contains offset of hash name in .debug_str +    const uint32_t count = m_data.GetU32 (&offset); +    if (count > 0) +    { +        hash_data.resize(count); +        for (uint32_t i=0; i<count; ++i) +        { +            if (!m_header.Read(m_data, &offset, hash_data[i])) +                return false; +        } +    } +    else +        hash_data.clear(); +    return true; +} + +DWARFMappedHash::MemoryTable::Result +DWARFMappedHash::MemoryTable::GetHashDataForName (const char *name, +                                                  lldb::offset_t* hash_data_offset_ptr, +                                                  Pair &pair) const +{ +    pair.key = m_data.GetU32 (hash_data_offset_ptr); +    pair.value.clear(); + +    // If the key is zero, this terminates our chain of HashData objects +    // for this hash value. +    if (pair.key == 0) +        return eResultEndOfHashData; + +    // There definitely should be a string for this string offset, if +    // there isn't, there is something wrong, return and error +    const char *strp_cstr = m_string_table.PeekCStr (pair.key); +    if (strp_cstr == NULL) +    { +        *hash_data_offset_ptr = UINT32_MAX; +        return eResultError; +    } + +    const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); +    const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); +    if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) +    { +        // We have at least one HashData entry, and we have enough +        // data to parse at least "count" HashData entries. +         +        // First make sure the entire C string matches... +        const bool match = strcmp (name, strp_cstr) == 0; +         +        if (!match && m_header.header_data.HashDataHasFixedByteSize()) +        { +            // If the string doesn't match and we have fixed size data, +            // we can just add the total byte size of all HashData objects +            // to the hash data offset and be done... +            *hash_data_offset_ptr += min_total_hash_data_size; +        } +        else +        { +            // If the string does match, or we don't have fixed size data +            // then we need to read the hash data as a stream. If the +            // string matches we also append all HashData objects to the +            // value array. +            for (uint32_t i=0; i<count; ++i) +            { +                DIEInfo die_info; +                if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) +                { +                    // Only happened if the HashData of the string matched... +                    if (match) +                        pair.value.push_back (die_info); +                } +                else +                { +                    // Something went wrong while reading the data +                    *hash_data_offset_ptr = UINT32_MAX; +                    return eResultError; +                } +            } +        } +        // Return the correct response depending on if the string matched +        // or not... +        if (match) +            return eResultKeyMatch;     // The key (cstring) matches and we have lookup results! +        else +            return eResultKeyMismatch;  // The key doesn't match, this function will get called  +                                        // again for the next key/value or the key terminator +                                        // which in our case is a zero .debug_str offset. +    } +    else +    { +        *hash_data_offset_ptr = UINT32_MAX; +        return eResultError; +    } +} + +DWARFMappedHash::MemoryTable::Result +DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression ( +        const lldb_private::RegularExpression& regex, +        lldb::offset_t* hash_data_offset_ptr,  +        Pair &pair) const +{ +    pair.key = m_data.GetU32 (hash_data_offset_ptr); +    // If the key is zero, this terminates our chain of HashData objects +    // for this hash value. +    if (pair.key == 0) +        return eResultEndOfHashData; +     +    // There definitely should be a string for this string offset, if +    // there isn't, there is something wrong, return and error +    const char *strp_cstr = m_string_table.PeekCStr (pair.key); +    if (strp_cstr == NULL) +        return eResultError; +     +    const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); +    const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); +    if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) +    { +        const bool match = regex.Execute(strp_cstr); +         +        if (!match && m_header.header_data.HashDataHasFixedByteSize()) +        { +            // If the regex doesn't match and we have fixed size data, +            // we can just add the total byte size of all HashData objects +            // to the hash data offset and be done... +            *hash_data_offset_ptr += min_total_hash_data_size; +        } +        else +        { +            // If the string does match, or we don't have fixed size data +            // then we need to read the hash data as a stream. If the +            // string matches we also append all HashData objects to the +            // value array. +            for (uint32_t i=0; i<count; ++i) +            { +                DIEInfo die_info; +                if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) +                { +                    // Only happened if the HashData of the string matched... +                    if (match) +                        pair.value.push_back (die_info); +                } +                else +                { +                    // Something went wrong while reading the data +                    *hash_data_offset_ptr = UINT32_MAX; +                    return eResultError; +                } +            } +        } +        // Return the correct response depending on if the string matched +        // or not... +        if (match) +            return eResultKeyMatch;     // The key (cstring) matches and we have lookup results! +        else +            return eResultKeyMismatch;  // The key doesn't match, this function will get called  +                                        // again for the next key/value or the key terminator +                                        // which in our case is a zero .debug_str offset. +    } +    else +    { +        *hash_data_offset_ptr = UINT32_MAX; +        return eResultError; +    } +} + +size_t +DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex ( +        const lldb_private::RegularExpression& regex,  +        DIEInfoArray &die_info_array) const +{ +    const uint32_t hash_count = m_header.hashes_count; +    Pair pair; +    for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) +    { +        lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); +        while (hash_data_offset != UINT32_MAX) +        { +            const lldb::offset_t prev_hash_data_offset = hash_data_offset; +            Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); +            if (prev_hash_data_offset == hash_data_offset) +                break; + +            // Check the result of getting our hash data +            switch (hash_result) +            { +                case eResultKeyMatch: +                case eResultKeyMismatch: +                    // Whether we matches or not, it doesn't matter, we +                    // keep looking. +                    break; +                     +                case eResultEndOfHashData: +                case eResultError: +                    hash_data_offset = UINT32_MAX; +                    break; +            } +        } +    } +    die_info_array.swap (pair.value); +    return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_start,  +                                                    const uint32_t die_offset_end,  +                                                    DIEInfoArray &die_info_array) const +{ +    const uint32_t hash_count = m_header.hashes_count; +    for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) +    { +        bool done = false; +        lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); +        while (!done && hash_data_offset != UINT32_MAX) +        { +            KeyType key = m_data.GetU32 (&hash_data_offset); +            // If the key is zero, this terminates our chain of HashData objects +            // for this hash value. +            if (key == 0) +                break; +             +            const uint32_t count = m_data.GetU32 (&hash_data_offset); +            for (uint32_t i=0; i<count; ++i) +            { +                DIEInfo die_info; +                if (m_header.Read(m_data, &hash_data_offset, die_info)) +                { +                    if (die_info.offset == 0) +                        done = true; +                    if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) +                        die_info_array.push_back(die_info); +                } +            } +        } +    } +    return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets) +{ +    DIEInfoArray die_info_array; +    if (FindByName(name, die_info_array)) +        DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); +    return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByNameAndTag (const char *name, +                                                const dw_tag_t tag, +                                                DIEArray &die_offsets) +{ +    DIEInfoArray die_info_array; +    if (FindByName(name, die_info_array)) +        DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); +    return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash (const char *name, +                                                                    const dw_tag_t tag, +                                                                    const uint32_t qualified_name_hash, +                                                                    DIEArray &die_offsets) +{ +    DIEInfoArray die_info_array; +    if (FindByName(name, die_info_array)) +        DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets); +    return die_info_array.size(); +} + +size_t +DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name, +                                                           DIEArray &die_offsets, +                                                           bool must_be_implementation) +{ +    DIEInfoArray die_info_array; +    if (FindByName(name, die_info_array)) +    { +        if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) +        { +            // If we have two atoms, then we have the DIE offset and +            // the type flags so we can find the objective C class +            // efficiently. +            DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,  +                                                       UINT32_MAX, +                                                       eTypeFlagClassIsImplementation, +                                                       die_offsets); +        } +        else +        { +            // We don't only want the one true definition, so try and see +            // what we can find, and only return class or struct DIEs. +            // If we do have the full implementation, then return it alone, +            // else return all possible matches. +            const bool return_implementation_only_if_available = true; +            DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,  +                                                           return_implementation_only_if_available, +                                                           die_offsets); +        } +    } +    return die_offsets.size(); +} + +size_t  +DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array) +{ +    Pair kv_pair; +    size_t old_size = die_info_array.size(); +    if (Find (name, kv_pair)) +    { +        die_info_array.swap(kv_pair.value); +        return die_info_array.size() - old_size; +    } +    return 0; +} diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h index f8a8cc60467dd..bcde558ae4496 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h @@ -12,139 +12,36 @@  #include <vector> -#include "DWARFDefines.h" -#include "DWARFFormValue.h" -  #include "lldb/lldb-defines.h"  #include "lldb/Core/dwarf.h"  #include "lldb/Core/RegularExpression.h"  #include "lldb/Core/MappedHash.h" +#include "DWARFDefines.h" +#include "DWARFFormValue.h" +#include "NameToDIE.h"  class SymbolFileDWARF;  class DWARFCompileUnit;  class DWARFDebugInfoEntry; -struct DWARFMappedHash +class DWARFMappedHash  { -    struct DIEInfo -    { -        dw_offset_t offset;  // The DIE offset -        dw_tag_t tag; -        uint32_t type_flags; // Any flags for this DIEInfo -        uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name - -        DIEInfo () : -            offset (DW_INVALID_OFFSET), -            tag (0), -            type_flags (0), -            qualified_name_hash (0) -        { -        } - -        DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) : -            offset(o), -            tag (t), -            type_flags (f), -            qualified_name_hash (h) -        { -        } -         -        void -        Clear() -        { -            offset = DW_INVALID_OFFSET; -            tag = 0; -            type_flags = 0; -            qualified_name_hash = 0; -        }             -    }; -     -    typedef std::vector<DIEInfo> DIEInfoArray; -    typedef std::vector<uint32_t> DIEArray; -     -    static void -    ExtractDIEArray (const DIEInfoArray &die_info_array, -                     DIEArray &die_offsets) -    { -        const size_t count = die_info_array.size(); -        for (size_t i=0; i<count; ++i) -        { -            die_offsets.push_back (die_info_array[i].offset); -        } -    } - -    static void -    ExtractDIEArray (const DIEInfoArray &die_info_array, -                     const dw_tag_t tag, -                     DIEArray &die_offsets) -    { -        if (tag == 0) -        { -            ExtractDIEArray (die_info_array, die_offsets); -        } -        else -        { -            const size_t count = die_info_array.size(); -            for (size_t i=0; i<count; ++i) -            { -                const dw_tag_t die_tag = die_info_array[i].tag; -                bool tag_matches = die_tag == 0 || tag == die_tag; -                if (!tag_matches) -                { -                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) -                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; -                } -                if (tag_matches) -                    die_offsets.push_back (die_info_array[i].offset); -            } -        } -    } - -    static void -    ExtractDIEArray (const DIEInfoArray &die_info_array, -                     const dw_tag_t tag, -                     const uint32_t qualified_name_hash, -                     DIEArray &die_offsets) -    { -        if (tag == 0) -        { -            ExtractDIEArray (die_info_array, die_offsets); -        } -        else -        { -            const size_t count = die_info_array.size(); -            for (size_t i=0; i<count; ++i) -            { -                if (qualified_name_hash != die_info_array[i].qualified_name_hash) -                    continue; -                const dw_tag_t die_tag = die_info_array[i].tag; -                bool tag_matches = die_tag == 0 || tag == die_tag; -                if (!tag_matches) -                { -                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) -                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; -                } -                if (tag_matches) -                    die_offsets.push_back (die_info_array[i].offset); -            } -        } -    } - -    enum AtomType +public: +    enum AtomType : uint16_t      { -        eAtomTypeNULL       = 0u, -        eAtomTypeDIEOffset  = 1u,   // DIE offset, check form for encoding -        eAtomTypeCUOffset   = 2u,   // DIE offset of the compiler unit header that contains the item in question -        eAtomTypeTag        = 3u,   // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 -        eAtomTypeNameFlags  = 4u,   // Flags from enum NameFlags -        eAtomTypeTypeFlags  = 5u,   // Flags from enum TypeFlags, +        eAtomTypeNULL         = 0u, +        eAtomTypeDIEOffset    = 1u, // DIE offset, check form for encoding +        eAtomTypeCUOffset     = 2u, // DIE offset of the compiler unit header that contains the item in question +        eAtomTypeTag          = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 +        eAtomTypeNameFlags    = 4u, // Flags from enum NameFlags +        eAtomTypeTypeFlags    = 5u, // Flags from enum TypeFlags,          eAtomTypeQualNameHash = 6u  // A 32 bit hash of the full qualified name (since all hash entries are basename only)                                      // For example a type like "std::vector<int>::iterator" would have a name of "iterator"                                      // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull                                      // in debug info for a type when we know the fully qualified name.      }; -     +      // Bit definitions for the eAtomTypeTypeFlags flags      enum TypeFlags      { @@ -152,782 +49,171 @@ struct DWARFMappedHash          // @implementation for class          eTypeFlagClassIsImplementation  = ( 1u << 1 )      }; -     -    static void -    ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, -                                  bool return_implementation_only_if_available, -                                  DIEArray &die_offsets) +    struct DIEInfo      { -        const size_t count = die_info_array.size(); -        for (size_t i=0; i<count; ++i) -        { -            const dw_tag_t die_tag = die_info_array[i].tag; -            if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) -            { -                if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) -                { -                    if (return_implementation_only_if_available) -                    { -                        // We found the one true definition for this class, so -                        // only return that -                        die_offsets.clear();                         -                        die_offsets.push_back (die_info_array[i].offset); -                        return; -                    } -                    else -                    { -                        // Put the one true definition as the first entry so it -                        // matches first -                        die_offsets.insert (die_offsets.begin(), die_info_array[i].offset); -                    } -                } -                else -                { -                    die_offsets.push_back (die_info_array[i].offset); -                } -            } -        } -    } +        dw_offset_t cu_offset; +        dw_offset_t offset;  // The DIE offset +        dw_tag_t tag; +        uint32_t type_flags; // Any flags for this DIEInfo +        uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name -    static void -    ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, -                              uint32_t type_flag_mask, -                              uint32_t type_flag_value, -                              DIEArray &die_offsets) -    { -        const size_t count = die_info_array.size(); -        for (size_t i=0; i<count; ++i) -        { -            if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) -                die_offsets.push_back (die_info_array[i].offset); -        } -    } +        DIEInfo (); +        DIEInfo (dw_offset_t c, dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h); +    };      struct Atom      { -        uint16_t type; +        AtomType type;          dw_form_t form; -         -        Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) : -            type (t), -            form (f) -        { -        }      }; -     + +    typedef std::vector<DIEInfo> DIEInfoArray;      typedef std::vector<Atom> AtomArray; -     -    static uint32_t  -    GetTypeFlags (SymbolFileDWARF *dwarf2Data, -                  const DWARFCompileUnit* cu, -                  const DWARFDebugInfoEntry* die); -     -    static const char * -    GetAtomTypeName (uint16_t atom) -    { -        switch (atom) -        { -            case eAtomTypeNULL:         return "NULL"; -            case eAtomTypeDIEOffset:    return "die-offset"; -            case eAtomTypeCUOffset:     return "cu-offset"; -            case eAtomTypeTag:          return "die-tag"; -            case eAtomTypeNameFlags:    return "name-flags"; -            case eAtomTypeTypeFlags:    return "type-flags"; -            case eAtomTypeQualNameHash: return "qualified-name-hash"; -        } -        return "<invalid>"; -    } -    struct Prologue +    class Prologue      { -        // DIE offset base so die offsets in hash_data can be CU relative -        dw_offset_t die_base_offset; -        AtomArray atoms; -        uint32_t atom_mask; -        size_t min_hash_data_byte_size; -        bool hash_data_has_fixed_byte_size; -         -        Prologue (dw_offset_t _die_base_offset = 0) : -            die_base_offset (_die_base_offset), -            atoms(), -            atom_mask (0), -            min_hash_data_byte_size(0), -            hash_data_has_fixed_byte_size(true) -        { -            // Define an array of DIE offsets by first defining an array,  -            // and then define the atom type for the array, in this case -            // we have an array of DIE offsets -            AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); -        } -         -        virtual ~Prologue() -        { -        } +    public: +        Prologue (dw_offset_t _die_base_offset = 0);          void -        ClearAtoms () -        { -            hash_data_has_fixed_byte_size = true; -            min_hash_data_byte_size = 0; -            atom_mask = 0; -            atoms.clear(); -        } +        ClearAtoms ();          bool -        ContainsAtom (AtomType atom_type) const -        { -            return (atom_mask & (1u << atom_type)) != 0; -        } - -        virtual void -        Clear () -        { -            die_base_offset = 0; -            ClearAtoms (); -        } -         +        ContainsAtom (AtomType atom_type) const; +          void -        AppendAtom (AtomType type, dw_form_t form) -        { -            atoms.push_back (Atom(type, form)); -            atom_mask |= 1u << type; -            switch (form) -            { -                case DW_FORM_indirect: -                case DW_FORM_exprloc: -                case DW_FORM_flag_present: -                case DW_FORM_ref_sig8: -                    assert (!"Unhandled atom form"); -                    break; - -                case DW_FORM_string: -                case DW_FORM_block: -                case DW_FORM_block1: -                case DW_FORM_sdata: -                case DW_FORM_udata: -                case DW_FORM_ref_udata: -                    hash_data_has_fixed_byte_size = false; -                    // Fall through to the cases below... -                case DW_FORM_flag: -                case DW_FORM_data1: -                case DW_FORM_ref1: -                case DW_FORM_sec_offset: -                    min_hash_data_byte_size += 1;  -                    break; - -                case DW_FORM_block2: -                    hash_data_has_fixed_byte_size = false; -                    // Fall through to the cases below... -                case DW_FORM_data2:  -                case DW_FORM_ref2: -                    min_hash_data_byte_size += 2;  -                    break; - -                case DW_FORM_block4:  -                    hash_data_has_fixed_byte_size = false; -                    // Fall through to the cases below... -                case DW_FORM_data4: -                case DW_FORM_ref4: -                case DW_FORM_addr: -                case DW_FORM_ref_addr: -                case DW_FORM_strp: -                    min_hash_data_byte_size += 4;  -                    break; - -                case DW_FORM_data8: -                case DW_FORM_ref8: -                    min_hash_data_byte_size += 8;  -                    break; -                     -            } -        } -         -//        void -//        Dump (std::ostream* ostrm_ptr);         -         +        Clear (); + +        void +        AppendAtom (AtomType type, dw_form_t form); +          lldb::offset_t -        Read (const lldb_private::DataExtractor &data, -              lldb::offset_t offset) -        { -            ClearAtoms (); -             -            die_base_offset = data.GetU32 (&offset); -             -            const uint32_t atom_count = data.GetU32 (&offset); -            if (atom_count == 0x00060003u) -            { -                // Old format, deal with contents of old pre-release format -                while (data.GetU32(&offset)) -                    /* do nothing */; - -                // Hardcode to the only known value for now. -                AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); -            } -            else -            { -                for (uint32_t i=0; i<atom_count; ++i) -                { -                    AtomType type = (AtomType)data.GetU16 (&offset); -                    dw_form_t form = (dw_form_t)data.GetU16 (&offset);                     -                    AppendAtom (type, form); -                } -            } -            return offset; -        } -         -//        virtual void -//        Write (BinaryStreamBuf &s); -         +        Read (const lldb_private::DataExtractor &data, lldb::offset_t offset); +          size_t -        GetByteSize () const -        { -            // Add an extra count to the atoms size for the zero termination Atom that gets -            // written to disk -            return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); -        } -         +        GetByteSize () const; +          size_t -        GetMinimumHashDataByteSize () const -        { -            return min_hash_data_byte_size; -        } +        GetMinimumHashDataByteSize () const;          bool -        HashDataHasFixedByteSize() const -        { -            return hash_data_has_fixed_byte_size; -        } +        HashDataHasFixedByteSize() const; + +        // DIE offset base so die offsets in hash_data can be CU relative +        dw_offset_t die_base_offset; +        AtomArray atoms; +        uint32_t atom_mask; +        size_t min_hash_data_byte_size; +        bool hash_data_has_fixed_byte_size;      }; -    struct Header : public MappedHash::Header<Prologue> +    class Header : public MappedHash::Header<Prologue>      { -        Header (dw_offset_t _die_base_offset = 0) -        { -        } -         -        virtual  -        ~Header() -        { -        } - -        virtual size_t -        GetByteSize (const HeaderData &header_data) -        { -            return header_data.GetByteSize(); -        } - -        //        virtual void -        //        Dump (std::ostream* ostrm_ptr);         -        //         -        virtual lldb::offset_t -        Read (lldb_private::DataExtractor &data, lldb::offset_t offset) -        { -            offset = MappedHash::Header<Prologue>::Read (data, offset); -            if (offset != UINT32_MAX) -            { -                offset = header_data.Read (data, offset); -            } -            return offset; -        } -         +    public: +        size_t +        GetByteSize (const HeaderData &header_data) override; + +        lldb::offset_t +        Read (lldb_private::DataExtractor &data, lldb::offset_t offset) override; +          bool          Read (const lldb_private::DWARFDataExtractor &data,                 lldb::offset_t *offset_ptr,  -              DIEInfo &hash_data) const -        { -            const size_t num_atoms = header_data.atoms.size(); -            if (num_atoms == 0) -                return false; -             -            for (size_t i=0; i<num_atoms; ++i) -            { -                DWARFFormValue form_value (NULL, header_data.atoms[i].form); -                 -                if (!form_value.ExtractValue(data, offset_ptr)) -                    return false; -                 -                switch (header_data.atoms[i].type) -                { -                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding -                        hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); -                        break; - -                    case eAtomTypeTag:          // DW_TAG value for the DIE -                        hash_data.tag = (dw_tag_t)form_value.Unsigned (); -                         -                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags -                        hash_data.type_flags = (uint32_t)form_value.Unsigned (); -                        break; - -                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags -                        hash_data.qualified_name_hash = form_value.Unsigned (); -                        break; - -                    default: -                        // We can always skip atoms we don't know about -                        break; -                } -            } -            return true; -        } -         +              DIEInfo &hash_data) const; +          void -        Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const -        { -            const size_t num_atoms = header_data.atoms.size(); -            for (size_t i=0; i<num_atoms; ++i) -            { -                if (i > 0) -                    strm.PutCString (", "); -                 -                DWARFFormValue form_value (NULL, header_data.atoms[i].form); -                switch (header_data.atoms[i].type) -                { -                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding -                        strm.Printf ("{0x%8.8x}", hash_data.offset); -                        break; - -                    case eAtomTypeTag:          // DW_TAG value for the DIE -                        { -                            const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); -                            if (tag_cstr) -                                strm.PutCString (tag_cstr); -                            else -                                strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); -                        } -                        break; - -                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags -                        strm.Printf ("0x%2.2x", hash_data.type_flags); -                        if (hash_data.type_flags) -                        { -                            strm.PutCString (" ("); -                            if (hash_data.type_flags & eTypeFlagClassIsImplementation) -                                strm.PutCString (" implementation"); -                            strm.PutCString (" )"); -                        } -                        break; - -                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags -                        strm.Printf ("0x%8.8x", hash_data.qualified_name_hash); -                        break; - -                    default: -                        strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); -                        break; -                } -            } -        } +        Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const;      }; -     -//    class ExportTable -//    { -//    public: -//        ExportTable (); -//         -//        void -//        AppendNames (DWARFDebugPubnamesSet &pubnames_set, -//                     StringTable &string_table); -//         -//        void -//        AppendNamesEntry (SymbolFileDWARF *dwarf2Data, -//                          const DWARFCompileUnit* cu, -//                          const DWARFDebugInfoEntry* die, -//                          StringTable &string_table); -//         -//        void -//        AppendTypesEntry (DWARFData *dwarf2Data, -//                          const DWARFCompileUnit* cu, -//                          const DWARFDebugInfoEntry* die, -//                          StringTable &string_table); -//         -//        size_t -//        Save (BinaryStreamBuf &names_data, const StringTable &string_table); -//         -//        void -//        AppendName (const char *name,  -//                    uint32_t die_offset,  -//                    StringTable &string_table, -//                    dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied -//        void -//        AppendType (const char *name,  -//                    uint32_t die_offset,  -//                    StringTable &string_table); -//         -//         -//    protected: -//        struct Entry -//        { -//            uint32_t hash; -//            uint32_t str_offset; -//            uint32_t die_offset; -//        }; -//         -//        // Map uniqued .debug_str offset to the corresponding DIE offsets -//        typedef std::map<uint32_t, DIEInfoArray> NameInfo; -//        // Map a name hash to one or more name infos -//        typedef std::map<uint32_t, NameInfo> BucketEntry; -//         -//        static uint32_t -//        GetByteSize (const NameInfo &name_info); -//         -//        typedef std::vector<BucketEntry> BucketEntryColl; -//        typedef std::vector<Entry> EntryColl; -//        EntryColl m_entries; -//         -//    }; -     -     +      // A class for reading and using a saved hash table from a block of data      // in memory      class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>      {      public: -                  MemoryTable (lldb_private::DWARFDataExtractor &table_data,                        const lldb_private::DWARFDataExtractor &string_table, -                     const char *name) : -            MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), -            m_data (table_data), -            m_string_table (string_table), -            m_name (name) -        { -        } -     -        virtual  -        ~MemoryTable () -        { -        } - -        virtual const char * -        GetStringForKeyType (KeyType key) const -        { -            // The key in the DWARF table is the .debug_str offset for the string -            return m_string_table.PeekCStr (key); -        } +                     const char *name); + +        const char * +        GetStringForKeyType (KeyType key) const override; -        virtual bool -        ReadHashData (uint32_t hash_data_offset, -                      HashData &hash_data) const -        { -            lldb::offset_t offset = hash_data_offset; -            offset += 4; // Skip string table offset that contains offset of hash name in .debug_str -            const uint32_t count = m_data.GetU32 (&offset); -            if (count > 0) -            { -                hash_data.resize(count); -                for (uint32_t i=0; i<count; ++i) -                { -                    if (!m_header.Read(m_data, &offset, hash_data[i])) -                        return false; -                } -            } -            else -                hash_data.clear(); -            return true; -        } - -        virtual Result -        GetHashDataForName (const char *name, -                            lldb::offset_t* hash_data_offset_ptr, -                            Pair &pair) const -        { -            pair.key = m_data.GetU32 (hash_data_offset_ptr); -            pair.value.clear(); - -            // If the key is zero, this terminates our chain of HashData objects -            // for this hash value. -            if (pair.key == 0) -                return eResultEndOfHashData; - -            // There definitely should be a string for this string offset, if -            // there isn't, there is something wrong, return and error -            const char *strp_cstr = m_string_table.PeekCStr (pair.key); -            if (strp_cstr == NULL) -            { -                *hash_data_offset_ptr = UINT32_MAX; -                return eResultError; -            } - -            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); -            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); -            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) -            { -                // We have at least one HashData entry, and we have enough -                // data to parse at least "count" HashData entries. -                 -                // First make sure the entire C string matches... -                const bool match = strcmp (name, strp_cstr) == 0; -                 -                if (!match && m_header.header_data.HashDataHasFixedByteSize()) -                { -                    // If the string doesn't match and we have fixed size data, -                    // we can just add the total byte size of all HashData objects -                    // to the hash data offset and be done... -                    *hash_data_offset_ptr += min_total_hash_data_size; -                } -                else -                { -                    // If the string does match, or we don't have fixed size data -                    // then we need to read the hash data as a stream. If the -                    // string matches we also append all HashData objects to the -                    // value array. -                    for (uint32_t i=0; i<count; ++i) -                    { -                        DIEInfo die_info; -                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) -                        { -                            // Only happened if the HashData of the string matched... -                            if (match) -                                pair.value.push_back (die_info); -                        } -                        else -                        { -                            // Something went wrong while reading the data -                            *hash_data_offset_ptr = UINT32_MAX; -                            return eResultError; -                        } -                    } -                } -                // Return the correct response depending on if the string matched -                // or not... -                if (match) -                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results! -                else -                    return eResultKeyMismatch;  // The key doesn't match, this function will get called  -                                                // again for the next key/value or the key terminator -                                                // which in our case is a zero .debug_str offset. -            } -            else -            { -                *hash_data_offset_ptr = UINT32_MAX; -                return eResultError; -            } -        } - -        virtual Result -        AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, -                                            lldb::offset_t* hash_data_offset_ptr,  -                                            Pair &pair) const -        { -            pair.key = m_data.GetU32 (hash_data_offset_ptr); -            // If the key is zero, this terminates our chain of HashData objects -            // for this hash value. -            if (pair.key == 0) -                return eResultEndOfHashData; -             -            // There definitely should be a string for this string offset, if -            // there isn't, there is something wrong, return and error -            const char *strp_cstr = m_string_table.PeekCStr (pair.key); -            if (strp_cstr == NULL) -                return eResultError; -             -            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); -            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize(); -            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) -            { -                const bool match = regex.Execute(strp_cstr); -                 -                if (!match && m_header.header_data.HashDataHasFixedByteSize()) -                { -                    // If the regex doesn't match and we have fixed size data, -                    // we can just add the total byte size of all HashData objects -                    // to the hash data offset and be done... -                    *hash_data_offset_ptr += min_total_hash_data_size; -                } -                else -                { -                    // If the string does match, or we don't have fixed size data -                    // then we need to read the hash data as a stream. If the -                    // string matches we also append all HashData objects to the -                    // value array. -                    for (uint32_t i=0; i<count; ++i) -                    { -                        DIEInfo die_info; -                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) -                        { -                            // Only happened if the HashData of the string matched... -                            if (match) -                                pair.value.push_back (die_info); -                        } -                        else -                        { -                            // Something went wrong while reading the data -                            *hash_data_offset_ptr = UINT32_MAX; -                            return eResultError; -                        } -                    } -                } -                // Return the correct response depending on if the string matched -                // or not... -                if (match) -                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results! -                else -                    return eResultKeyMismatch;  // The key doesn't match, this function will get called  -                                                // again for the next key/value or the key terminator -                                                // which in our case is a zero .debug_str offset. -            } -            else -            { -                *hash_data_offset_ptr = UINT32_MAX; -                return eResultError; -            } -        } +        bool +        ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const override;          size_t          AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,  -                                        DIEInfoArray &die_info_array) const -        { -            const uint32_t hash_count = m_header.hashes_count; -            Pair pair; -            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) -            { -                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); -                while (hash_data_offset != UINT32_MAX) -                { -                    const lldb::offset_t prev_hash_data_offset = hash_data_offset; -                    Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); -                    if (prev_hash_data_offset == hash_data_offset) -                        break; - -                    // Check the result of getting our hash data -                    switch (hash_result) -                    { -                        case eResultKeyMatch: -                        case eResultKeyMismatch: -                            // Whether we matches or not, it doesn't matter, we -                            // keep looking. -                            break; -                             -                        case eResultEndOfHashData: -                        case eResultError: -                            hash_data_offset = UINT32_MAX; -                            break; -                    } -                } -            } -            die_info_array.swap (pair.value); -            return die_info_array.size(); -        } -         +                                        DIEInfoArray &die_info_array) const; +          size_t          AppendAllDIEsInRange (const uint32_t die_offset_start,                                 const uint32_t die_offset_end,  -                              DIEInfoArray &die_info_array) const -        { -            const uint32_t hash_count = m_header.hashes_count; -            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) -            { -                bool done = false; -                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); -                while (!done && hash_data_offset != UINT32_MAX) -                { -                    KeyType key = m_data.GetU32 (&hash_data_offset); -                    // If the key is zero, this terminates our chain of HashData objects -                    // for this hash value. -                    if (key == 0) -                        break; -                     -                    const uint32_t count = m_data.GetU32 (&hash_data_offset); -                    for (uint32_t i=0; i<count; ++i) -                    { -                        DIEInfo die_info; -                        if (m_header.Read(m_data, &hash_data_offset, die_info)) -                        { -                            if (die_info.offset == 0) -                                done = true; -                            if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) -                                die_info_array.push_back(die_info); -                        } -                    } -                } -            } -            return die_info_array.size(); -        } +                              DIEInfoArray &die_info_array) const;          size_t -        FindByName (const char *name, DIEArray &die_offsets) -        { -            DIEInfoArray die_info_array; -            if (FindByName(name, die_info_array)) -                DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); -            return die_info_array.size(); -        } +        FindByName (const char *name, DIEArray &die_offsets);          size_t -        FindByNameAndTag (const char *name,  -                          const dw_tag_t tag,  -                          DIEArray &die_offsets) -        { -            DIEInfoArray die_info_array; -            if (FindByName(name, die_info_array)) -                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); -            return die_info_array.size(); -        } +        FindByNameAndTag (const char *name, const dw_tag_t tag, DIEArray &die_offsets);          size_t          FindByNameAndTagAndQualifiedNameHash (const char *name,                                                const dw_tag_t tag,                                                const uint32_t qualified_name_hash, -                                              DIEArray &die_offsets) -        { -            DIEInfoArray die_info_array; -            if (FindByName(name, die_info_array)) -                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets); -            return die_info_array.size(); -        } +                                              DIEArray &die_offsets);          size_t -        FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation) -        { -            DIEInfoArray die_info_array; -            if (FindByName(name, die_info_array)) -            { -                if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) -                { -                    // If we have two atoms, then we have the DIE offset and -                    // the type flags so we can find the objective C class -                    // efficiently. -                    DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,  -                                                               UINT32_MAX, -                                                               eTypeFlagClassIsImplementation, -                                                               die_offsets); -                } -                else -                { -                    // We don't only want the one true definition, so try and see -                    // what we can find, and only return class or struct DIEs. -                    // If we do have the full implementation, then return it alone, -                    // else return all possible matches. -                    const bool return_implementation_only_if_available = true; -                    DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,  -                                                                   return_implementation_only_if_available, -                                                                   die_offsets); -                } -            } -            return die_offsets.size(); -        } +        FindCompleteObjCClassByName (const char *name, +                                     DIEArray &die_offsets, +                                     bool must_be_implementation); -        size_t  -        FindByName (const char *name, DIEInfoArray &die_info_array) -        { -            Pair kv_pair; -            size_t old_size = die_info_array.size(); -            if (Find (name, kv_pair)) -            { -                die_info_array.swap(kv_pair.value); -                return die_info_array.size() - old_size; -            } -            return 0; -        } -              protected: +        Result +        AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, +                                            lldb::offset_t* hash_data_offset_ptr,  +                                            Pair &pair) const; + +        size_t  +        FindByName (const char *name, DIEInfoArray &die_info_array); + +        Result +        GetHashDataForName (const char *name, +                            lldb::offset_t* hash_data_offset_ptr, +                            Pair &pair) const override; +          const lldb_private::DWARFDataExtractor &m_data;          const lldb_private::DWARFDataExtractor &m_string_table;          std::string m_name;      }; -}; +    static void +    ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets); + +protected: +    static void +    ExtractDIEArray (const DIEInfoArray &die_info_array, +                     const dw_tag_t tag, +                     DIEArray &die_offsets); + +    static void +    ExtractDIEArray (const DIEInfoArray &die_info_array, +                     const dw_tag_t tag, +                     const uint32_t qualified_name_hash, +                     DIEArray &die_offsets); + +    static void +    ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, +                                  bool return_implementation_only_if_available, +                                  DIEArray &die_offsets); + +    static void +    ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, +                              uint32_t type_flag_mask, +                              uint32_t type_flag_value, +                              DIEArray &die_offsets); + +    static const char * +    GetAtomTypeName (uint16_t atom); +};  #endif  // SymbolFileDWARF_HashedNameToDIE_h_ diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h index 2091a8414f586..24fa7d148cd35 100644 --- a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h @@ -1,4 +1,4 @@ -//===-- LogChannelDWARF.h --------------------------------------*- C++ -*-===// +//===-- LogChannelDWARF.h ---------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -13,7 +13,6 @@  // C Includes  // C++ Includes  // Other libraries and framework includes -  // Project includes  #include "lldb/Core/Log.h" @@ -34,8 +33,7 @@ class LogChannelDWARF : public lldb_private::LogChannel  public:      LogChannelDWARF (); -    virtual -    ~LogChannelDWARF (); +    ~LogChannelDWARF() override;      static void      Initialize(); @@ -52,26 +50,26 @@ public:      static lldb_private::LogChannel *      CreateInstance (); -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override; -    virtual void -    Disable (const char** categories, lldb_private::Stream *feedback_strm); +    void +    Disable(const char** categories, lldb_private::Stream *feedback_strm) override;      void      Delete (); -    virtual bool -    Enable (lldb::StreamSP &log_stream_sp, -            uint32_t log_options, -            lldb_private::Stream *feedback_strm,      // Feedback stream for argument errors etc -            const char **categories);    // The categories to enable within this logging stream, if empty, enable default set +    bool +    Enable(lldb::StreamSP &log_stream_sp, +           uint32_t log_options, +           lldb_private::Stream *feedback_strm,  // Feedback stream for argument errors etc +           const char **categories) override;    // The categories to enable within this logging stream, if empty, enable default set -    virtual void -    ListCategories (lldb_private::Stream *strm); +    void +    ListCategories(lldb_private::Stream *strm) override;      static lldb_private::Log *      GetLog (); @@ -86,4 +84,4 @@ public:      LogIf (uint32_t mask, const char *format, ...);  }; -#endif  // SymbolFileDWARF_LogChannelDWARF_h_ +#endif // SymbolFileDWARF_LogChannelDWARF_h_ diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index c49237b8fbbcf..775bb6718b8a2 100644 --- a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -18,6 +18,7 @@  #include "DWARFDebugInfo.h"  #include "DWARFDebugInfoEntry.h"  #include "SymbolFileDWARF.h" +  using namespace lldb;  using namespace lldb_private; @@ -29,9 +30,9 @@ NameToDIE::Finalize()  }  void -NameToDIE::Insert (const ConstString& name, uint32_t die_offset) +NameToDIE::Insert (const ConstString& name, const DIERef& die_ref)  { -    m_map.Append(name.GetCString(), die_offset); +    m_map.Append(name.GetCString(), die_ref);  }  size_t @@ -47,17 +48,15 @@ NameToDIE::Find (const RegularExpression& regex, DIEArray &info_array) const  }  size_t -NameToDIE::FindAllEntriesForCompileUnit (uint32_t cu_offset,  -                                         uint32_t cu_end_offset,  -                                         DIEArray &info_array) const +NameToDIE::FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const  {      const size_t initial_size = info_array.size();      const uint32_t size = m_map.GetSize();      for (uint32_t i=0; i<size; ++i)      { -        const uint32_t die_offset = m_map.GetValueAtIndexUnchecked(i); -        if (cu_offset < die_offset && die_offset < cu_end_offset) -            info_array.push_back (die_offset); +        const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i); +        if (cu_offset == die_ref.cu_offset) +            info_array.push_back (die_ref);      }      return info_array.size() - initial_size;  } @@ -69,18 +68,29 @@ NameToDIE::Dump (Stream *s)      for (uint32_t i=0; i<size; ++i)      {          const char *cstr = m_map.GetCStringAtIndex(i); -        s->Printf("%p: {0x%8.8x} \"%s\"\n", (const void *)cstr, m_map.GetValueAtIndexUnchecked(i), cstr); +        const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i); +        s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", cstr, die_ref.cu_offset, die_ref.die_offset, cstr);      }  }  void -NameToDIE::ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const +NameToDIE::ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const  {      const uint32_t size = m_map.GetSize();      for (uint32_t i=0; i<size; ++i)      { -        if (!callback(m_map.GetCStringAtIndexUnchecked(i), -                      m_map.GetValueAtIndexUnchecked (i))) +        if (!callback(m_map.GetCStringAtIndexUnchecked(i), m_map.GetValueAtIndexUnchecked (i)))              break;      }  } + +void +NameToDIE::Append (const NameToDIE& other) +{ +    const uint32_t size = other.m_map.GetSize(); +    for (uint32_t i = 0; i < size; ++i) +    { +        m_map.Append(other.m_map.GetCStringAtIndexUnchecked (i), +                     other.m_map.GetValueAtIndexUnchecked (i)); +    } +} diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/source/Plugins/SymbolFile/DWARF/NameToDIE.h index f9a12736bf9e6..7fc66138f51e7 100644 --- a/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -10,56 +10,53 @@  #ifndef SymbolFileDWARF_NameToDIE_h_  #define SymbolFileDWARF_NameToDIE_h_ -#include "lldb/Core/UniqueCStringMap.h" -  #include <functional> +#include "lldb/Core/dwarf.h" +#include "lldb/Core/UniqueCStringMap.h"  #include "lldb/lldb-defines.h" +#include "DIERef.h"  class SymbolFileDWARF; -typedef std::vector<uint32_t> DIEArray; -  class NameToDIE  {  public: -    NameToDIE () :    +    NameToDIE () :          m_map()      {      } -     +      ~NameToDIE ()      {      } -     +      void      Dump (lldb_private::Stream *s);      void -    Insert (const lldb_private::ConstString& name, uint32_t die_offset); +    Insert (const lldb_private::ConstString& name, const DIERef& die_ref); + +    void +    Append (const NameToDIE& other);      void      Finalize();      size_t -    Find (const lldb_private::ConstString &name,  -          DIEArray &info_array) const; +    Find (const lldb_private::ConstString &name, DIEArray &info_array) const;      size_t -    Find (const lldb_private::RegularExpression& regex,  -          DIEArray &info_array) const; +    Find (const lldb_private::RegularExpression& regex, DIEArray &info_array) const;      size_t -    FindAllEntriesForCompileUnit (uint32_t cu_offset,  -                                  uint32_t cu_end_offset,  -                                  DIEArray &info_array) const; +    FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const;      void -    ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const; +    ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const;  protected: -    lldb_private::UniqueCStringMap<uint32_t> m_map; - +    lldb_private::UniqueCStringMap<DIERef> m_map;  };  #endif  // SymbolFileDWARF_NameToDIE_h_ diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ea8aedcc2be05..0ed4d05be5c23 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -10,20 +10,6 @@  #include "SymbolFileDWARF.h"  // Other libraries and framework includes -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclGroup.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/Basic/Builtins.h" -#include "clang/Basic/IdentifierTable.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Specifiers.h" -#include "clang/Sema/DeclSpec.h" -  #include "llvm/Support/Casting.h"  #include "lldb/Core/ArchSpec.h" @@ -39,34 +25,48 @@  #include "lldb/Core/Timer.h"  #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "lldb/Host/FileSystem.h"  #include "lldb/Host/Host.h" +#include "lldb/Interpreter/OptionValueFileSpecList.h" +#include "lldb/Interpreter/OptionValueProperties.h" +  #include "lldb/Symbol/Block.h" -#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/DebugMacros.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeSystem.h"  #include "lldb/Symbol/VariableList.h" +#include "lldb/Symbol/TypeMap.h" + +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" + +#include "lldb/Target/Language.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Utility/TaskPool.h" +#include "DWARFASTParser.h"  #include "DWARFCompileUnit.h"  #include "DWARFDebugAbbrev.h"  #include "DWARFDebugAranges.h"  #include "DWARFDebugInfo.h" -#include "DWARFDebugInfoEntry.h"  #include "DWARFDebugLine.h" +#include "DWARFDebugMacro.h"  #include "DWARFDebugPubnames.h"  #include "DWARFDebugRanges.h"  #include "DWARFDeclContext.h"  #include "DWARFDIECollection.h"  #include "DWARFFormValue.h" -#include "DWARFLocationList.h"  #include "LogChannelDWARF.h" +#include "SymbolFileDWARFDwo.h"  #include "SymbolFileDWARFDebugMap.h"  #include <map> @@ -83,8 +83,6 @@  #define DEBUG_PRINTF(fmt, ...)  #endif -#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1) -  using namespace lldb;  using namespace lldb_private; @@ -105,18 +103,58 @@ using namespace lldb_private;  //    return false;  //}  // -static AccessType -DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility) -{ -    switch (dwarf_accessibility) + +namespace { + +    PropertyDefinition +    g_properties[] = +    { +        { "comp-dir-symlink-paths" , OptionValue::eTypeFileSpecList, true,  0 ,   nullptr, nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time." }, +        {  nullptr                 , OptionValue::eTypeInvalid     , false, 0,    nullptr, nullptr, nullptr } +    }; + +    enum +    { +        ePropertySymLinkPaths +    }; + + +    class PluginProperties : public Properties      { -        case DW_ACCESS_public:      return eAccessPublic; -        case DW_ACCESS_private:     return eAccessPrivate; -        case DW_ACCESS_protected:   return eAccessProtected; -        default:                    break; +    public: +        static ConstString +        GetSettingName() +        { +            return SymbolFileDWARF::GetPluginNameStatic(); +        } + +        PluginProperties() +        { +            m_collection_sp.reset (new OptionValueProperties(GetSettingName())); +            m_collection_sp->Initialize(g_properties); +        } + +        FileSpecList& +        GetSymLinkPaths() +        { +            OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths); +            assert(option_value); +            return option_value->GetCurrentValue(); +        } + +    }; + +    typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP; + +    static const SymbolFileDWARFPropertiesSP& +    GetGlobalPluginProperties() +    { +        static const auto g_settings_sp(std::make_shared<PluginProperties>()); +        return g_settings_sp;      } -    return eAccessNone; -} + +}  // anonymous namespace end +  static const char*  removeHostnameFromPathname(const char* path_from_dwarf) @@ -125,9 +163,15 @@ removeHostnameFromPathname(const char* path_from_dwarf)      {          return path_from_dwarf;      } - +          const char *colon_pos = strchr(path_from_dwarf, ':'); -    if (!colon_pos) +    if (nullptr == colon_pos) +    { +        return path_from_dwarf; +    } +     +    const char *slash_pos = strchr(path_from_dwarf, '/'); +    if (slash_pos && (slash_pos < colon_pos))      {          return path_from_dwarf;      } @@ -142,89 +186,42 @@ removeHostnameFromPathname(const char* path_from_dwarf)      {          return path_from_dwarf;      } - +          return colon_pos + 1;  } -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) - -class DIEStack +static const char* +resolveCompDir(const char* path_from_dwarf)  { -public: -     -    void Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) -    { -        m_dies.push_back (DIEInfo(cu, die)); -    } +    if (!path_from_dwarf) +        return nullptr; -     -    void LogDIEs (Log *log, SymbolFileDWARF *dwarf) -    { -        StreamString log_strm; -        const size_t n = m_dies.size(); -        log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n); -        for (size_t i=0; i<n; i++) -        { -            DWARFCompileUnit *cu = m_dies[i].cu; -            const DWARFDebugInfoEntry *die = m_dies[i].die; -            std::string qualified_name; -            die->GetQualifiedName(dwarf, cu, qualified_name); -            log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", -                             (uint64_t)i, -                             die->GetOffset(),  -                             DW_TAG_value_to_name(die->Tag()),  -                             qualified_name.c_str()); -        } -        log->PutCString(log_strm.GetData()); -    } -    void Pop () -    { -        m_dies.pop_back(); -    } -     -    class ScopedPopper -    { -    public: -        ScopedPopper (DIEStack &die_stack) : -            m_die_stack (die_stack), -            m_valid (false) -        { -        } -         -        void -        Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) -        { -            m_valid = true; -            m_die_stack.Push (cu, die); -        } -         -        ~ScopedPopper () -        { -            if (m_valid) -                m_die_stack.Pop(); -        } -         -         -         -    protected: -        DIEStack &m_die_stack; -        bool m_valid; -    }; +    // DWARF2/3 suggests the form hostname:pathname for compilation directory. +    // Remove the host part if present. +    const char* local_path = removeHostnameFromPathname(path_from_dwarf); +    if (!local_path) +        return nullptr; + +    bool is_symlink = false; +    FileSpec local_path_spec(local_path, false); +    const auto& file_specs = GetGlobalPluginProperties()->GetSymLinkPaths(); +    for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i) +        is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), local_path_spec, true); + +    if (!is_symlink) +        return local_path; + +    if (!local_path_spec.IsSymbolicLink()) +        return local_path; + +    FileSpec resolved_local_path_spec; +    const auto error = FileSystem::Readlink(local_path_spec, resolved_local_path_spec); +    if (error.Success()) +        return resolved_local_path_spec.GetCString(); + +    return nullptr; +} -protected: -    struct DIEInfo { -        DIEInfo (DWARFCompileUnit *c, const DWARFDebugInfoEntry *d) : -            cu(c), -            die(d) -        { -        } -        DWARFCompileUnit *cu; -        const DWARFDebugInfoEntry *die; -    }; -    typedef std::vector<DIEInfo> Stack; -    Stack m_dies; -}; -#endif  void  SymbolFileDWARF::Initialize() @@ -232,7 +229,21 @@ SymbolFileDWARF::Initialize()      LogChannelDWARF::Initialize();      PluginManager::RegisterPlugin (GetPluginNameStatic(),                                     GetPluginDescriptionStatic(), -                                   CreateInstance); +                                   CreateInstance, +                                   DebuggerInitialize); +} + +void +SymbolFileDWARF::DebuggerInitialize(Debugger &debugger) +{ +    if (!PluginManager::GetSettingForSymbolFilePlugin(debugger, PluginProperties::GetSettingName())) +    { +        const bool is_global_setting = true; +        PluginManager::CreateSettingForSymbolFilePlugin(debugger, +                                                        GetGlobalPluginProperties()->GetValueProperties(), +                                                        ConstString ("Properties for the dwarf symbol-file plug-in."), +                                                        is_global_setting); +    }  }  void @@ -272,65 +283,61 @@ SymbolFileDWARF::GetTypeList ()  }  void -SymbolFileDWARF::GetTypes (DWARFCompileUnit* cu, -                           const DWARFDebugInfoEntry *die, +SymbolFileDWARF::GetTypes (const DWARFDIE &die,                             dw_offset_t min_die_offset,                             dw_offset_t max_die_offset,                             uint32_t type_mask,                             TypeSet &type_set)  { -    if (cu) +    if (die)      { -        if (die) +        const dw_offset_t die_offset = die.GetOffset(); +         +        if (die_offset >= max_die_offset) +            return; +         +        if (die_offset >= min_die_offset)          { -            const dw_offset_t die_offset = die->GetOffset(); -             -            if (die_offset >= max_die_offset) -                return; +            const dw_tag_t tag = die.Tag(); -            if (die_offset >= min_die_offset) -            { -                const dw_tag_t tag = die->Tag(); -                 -                bool add_type = false; +            bool add_type = false; -                switch (tag) -                { -                    case DW_TAG_array_type:         add_type = (type_mask & eTypeClassArray         ) != 0; break; -                    case DW_TAG_unspecified_type: -                    case DW_TAG_base_type:          add_type = (type_mask & eTypeClassBuiltin       ) != 0; break; -                    case DW_TAG_class_type:         add_type = (type_mask & eTypeClassClass         ) != 0; break; -                    case DW_TAG_structure_type:     add_type = (type_mask & eTypeClassStruct        ) != 0; break; -                    case DW_TAG_union_type:         add_type = (type_mask & eTypeClassUnion         ) != 0; break; -                    case DW_TAG_enumeration_type:   add_type = (type_mask & eTypeClassEnumeration   ) != 0; break; -                    case DW_TAG_subroutine_type: -                    case DW_TAG_subprogram: -                    case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction      ) != 0; break; -                    case DW_TAG_pointer_type:       add_type = (type_mask & eTypeClassPointer       ) != 0; break; -                    case DW_TAG_rvalue_reference_type: -                    case DW_TAG_reference_type:     add_type = (type_mask & eTypeClassReference     ) != 0; break; -                    case DW_TAG_typedef:            add_type = (type_mask & eTypeClassTypedef       ) != 0; break; -                    case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break; -                } +            switch (tag) +            { +                case DW_TAG_array_type:         add_type = (type_mask & eTypeClassArray         ) != 0; break; +                case DW_TAG_unspecified_type: +                case DW_TAG_base_type:          add_type = (type_mask & eTypeClassBuiltin       ) != 0; break; +                case DW_TAG_class_type:         add_type = (type_mask & eTypeClassClass         ) != 0; break; +                case DW_TAG_structure_type:     add_type = (type_mask & eTypeClassStruct        ) != 0; break; +                case DW_TAG_union_type:         add_type = (type_mask & eTypeClassUnion         ) != 0; break; +                case DW_TAG_enumeration_type:   add_type = (type_mask & eTypeClassEnumeration   ) != 0; break; +                case DW_TAG_subroutine_type: +                case DW_TAG_subprogram: +                case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction      ) != 0; break; +                case DW_TAG_pointer_type:       add_type = (type_mask & eTypeClassPointer       ) != 0; break; +                case DW_TAG_rvalue_reference_type: +                case DW_TAG_reference_type:     add_type = (type_mask & eTypeClassReference     ) != 0; break; +                case DW_TAG_typedef:            add_type = (type_mask & eTypeClassTypedef       ) != 0; break; +                case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break; +            } -                if (add_type) +            if (add_type) +            { +                const bool assert_not_being_parsed = true; +                Type *type = ResolveTypeUID (die, assert_not_being_parsed); +                if (type)                  { -                    const bool assert_not_being_parsed = true; -                    Type *type = ResolveTypeUID (cu, die, assert_not_being_parsed); -                    if (type) -                    { -                        if (type_set.find(type) == type_set.end()) -                            type_set.insert(type); -                    } +                    if (type_set.find(type) == type_set.end()) +                        type_set.insert(type);                  }              } -             -            for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); -                 child_die != NULL; -                 child_die = child_die->GetSibling()) -            { -                GetTypes (cu, child_die, min_die_offset, max_die_offset, type_mask, type_set); -            } +        } +         +        for (DWARFDIE child_die = die.GetFirstChild(); +             child_die.IsValid(); +             child_die = child_die.GetSibling()) +        { +            GetTypes (child_die, min_die_offset, max_die_offset, type_mask, type_set);          }      }  } @@ -353,8 +360,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,          dwarf_cu = GetDWARFCompileUnit(comp_unit);          if (dwarf_cu == 0)              return 0; -        GetTypes (dwarf_cu, -                  dwarf_cu->DIE(), +        GetTypes (dwarf_cu->DIE(),                    dwarf_cu->GetOffset(),                    dwarf_cu->GetNextCompileUnitOffset(),                    type_mask, @@ -371,8 +377,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,                  dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);                  if (dwarf_cu)                  { -                    GetTypes (dwarf_cu, -                              dwarf_cu->DIE(), +                    GetTypes (dwarf_cu->DIE(),                                0,                                UINT32_MAX,                                type_mask, @@ -381,76 +386,15 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,              }          }      } -//    if (m_using_apple_tables) -//    { -//        DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get(); -//        if (apple_types) -//        { -//            apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool { -// -//                for (auto die_info: die_info_array) -//                { -//                    bool add_type = TagMatchesTypeMask (type_mask, 0); -//                    if (!add_type) -//                    { -//                        dw_tag_t tag = die_info.tag; -//                        if (tag == 0) -//                        { -//                            const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL); -//                            tag = die->Tag(); -//                        } -//                        add_type = TagMatchesTypeMask (type_mask, tag); -//                    } -//                    if (add_type) -//                    { -//                        Type *type = ResolveTypeUID(die_info.offset); -//                         -//                        if (type_set.find(type) == type_set.end()) -//                            type_set.insert(type); -//                    } -//                } -//                return true; // Keep iterating -//            }); -//        } -//    } -//    else -//    { -//        if (!m_indexed) -//            Index (); -//         -//        m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool { -//             -//            bool add_type = TagMatchesTypeMask (type_mask, 0); -// -//            if (!add_type) -//            { -//                const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL); -//                if (die) -//                { -//                    const dw_tag_t tag = die->Tag(); -//                    add_type = TagMatchesTypeMask (type_mask, tag); -//                } -//            } -//             -//            if (add_type) -//            { -//                Type *type = ResolveTypeUID(die_offset); -//                 -//                if (type_set.find(type) == type_set.end()) -//                    type_set.insert(type); -//            } -//            return true; // Keep iterating -//        }); -//    } -     -    std::set<ClangASTType> clang_type_set; + +    std::set<CompilerType> compiler_type_set;      size_t num_types_added = 0;      for (Type *type : type_set)      { -        ClangASTType clang_type = type->GetClangForwardType(); -        if (clang_type_set.find(clang_type) == clang_type_set.end()) +        CompilerType compiler_type = type->GetForwardCompilerType (); +        if (compiler_type_set.find(compiler_type) == compiler_type_set.end())          { -            clang_type_set.insert(clang_type); +            compiler_type_set.insert(compiler_type);              type_list.Insert (type->shared_from_this());              ++num_types_added;          } @@ -463,13 +407,13 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,  // Gets the first parent that is a lexical block, function or inlined  // subroutine, or compile unit.  //---------------------------------------------------------------------- -static const DWARFDebugInfoEntry * -GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die) +DWARFDIE +SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die)  { -    const DWARFDebugInfoEntry *die; -    for (die = child_die->GetParent(); die != NULL; die = die->GetParent()) +    DWARFDIE die; +    for (die = child_die.GetParent(); die; die = die.GetParent())      { -        dw_tag_t tag = die->Tag(); +        dw_tag_t tag = die.Tag();          switch (tag)          { @@ -480,7 +424,7 @@ GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)              return die;          }      } -    return NULL; +    return DWARFDIE();  } @@ -489,13 +433,12 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :      UserID (0),  // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID      m_debug_map_module_wp (),      m_debug_map_symfile (NULL), -    m_clang_tu_decl (NULL), -    m_flags(),      m_data_debug_abbrev (),      m_data_debug_aranges (),      m_data_debug_frame (),      m_data_debug_info (),      m_data_debug_line (), +    m_data_debug_macro (),      m_data_debug_loc (),      m_data_debug_ranges (),      m_data_debug_str (), @@ -518,7 +461,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :      m_type_index(),      m_namespace_index(),      m_indexed (false), -    m_is_external_ast_source (false),      m_using_apple_tables (false),      m_fetched_external_modules (false),      m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate), @@ -529,12 +471,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :  SymbolFileDWARF::~SymbolFileDWARF()  { -    if (m_is_external_ast_source) -    { -        ModuleSP module_sp (m_obj_file->GetModule()); -        if (module_sp) -            module_sp->GetClangASTContext().RemoveExternalSource (); -    }  }  static const ConstString & @@ -552,36 +488,31 @@ SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()      return m_unique_ast_type_map;  } -ClangASTContext &        -SymbolFileDWARF::GetClangASTContext () +TypeSystem * +SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language)  { -    if (GetDebugMapSymfile ()) -        return m_debug_map_symfile->GetClangASTContext (); - -    ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); -    if (!m_is_external_ast_source) +    SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); +    TypeSystem *type_system; +    if (debug_map_symfile)      { -        m_is_external_ast_source = true; -        llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap ( -            new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl, -                                                 SymbolFileDWARF::CompleteObjCInterfaceDecl, -                                                 SymbolFileDWARF::FindExternalVisibleDeclsByName, -                                                 SymbolFileDWARF::LayoutRecordType, -                                                 this)); -        ast.SetExternalSource (ast_source_ap); +        type_system = debug_map_symfile->GetTypeSystemForLanguage(language);      } -    return ast; +    else +    { +        type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); +        if (type_system) +            type_system->SetSymbolFile(this); +    } +    return type_system;  }  void  SymbolFileDWARF::InitializeObject()  { -    // Install our external AST source callbacks so we can complete Clang types.      ModuleSP module_sp (m_obj_file->GetModule());      if (module_sp)      {          const SectionList *section_list = module_sp->GetSectionList(); -          const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();          // Memory map the DWARF mach-o segment so we have everything mmap'ed @@ -589,19 +520,24 @@ SymbolFileDWARF::InitializeObject()          if (section)              m_obj_file->MemoryMapSectionData(section, m_dwarf_data);      } +      get_apple_names_data(); -    if (m_data_apple_names.GetByteSize() > 0) +    if (m_data_apple_names.m_data.GetByteSize() > 0)      { -        m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names")); +        m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data, +                                                                  get_debug_str_data(), +                                                                  ".apple_names"));          if (m_apple_names_ap->IsValid())              m_using_apple_tables = true;          else              m_apple_names_ap.reset();      }      get_apple_types_data(); -    if (m_data_apple_types.GetByteSize() > 0) +    if (m_data_apple_types.m_data.GetByteSize() > 0)      { -        m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types")); +        m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data, +                                                                  get_debug_str_data(), +                                                                  ".apple_types"));          if (m_apple_types_ap->IsValid())              m_using_apple_tables = true;          else @@ -609,9 +545,11 @@ SymbolFileDWARF::InitializeObject()      }      get_apple_namespaces_data(); -    if (m_data_apple_namespaces.GetByteSize() > 0) +    if (m_data_apple_namespaces.m_data.GetByteSize() > 0)      { -        m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces")); +        m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data, +                                                                       get_debug_str_data(), +                                                                       ".apple_namespaces"));          if (m_apple_namespaces_ap->IsValid())              m_using_apple_tables = true;          else @@ -619,9 +557,11 @@ SymbolFileDWARF::InitializeObject()      }      get_apple_objc_data(); -    if (m_data_apple_objc.GetByteSize() > 0) +    if (m_data_apple_objc.m_data.GetByteSize() > 0)      { -        m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc")); +        m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data, +                                                                 get_debug_str_data(), +                                                                 ".apple_objc"));          if (m_apple_objc_ap->IsValid())              m_using_apple_tables = true;          else @@ -663,46 +603,10 @@ SymbolFileDWARF::CalculateAbilities ()              section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get();              if (section)                  debug_abbrev_file_size = section->GetFileSize(); -            else -                m_flags.Set (flagsGotDebugAbbrevData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugArangesData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugFrameData);              section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();              if (section)                  debug_line_file_size = section->GetFileSize(); -            else -                m_flags.Set (flagsGotDebugLineData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugLocData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugMacInfoData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugPubNamesData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugPubTypesData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugRangesData); - -            section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get(); -            if (!section) -                m_flags.Set (flagsGotDebugStrData);          }          else          { @@ -737,104 +641,128 @@ SymbolFileDWARF::CalculateAbilities ()  }  const DWARFDataExtractor& -SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data) +SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment)  { -    if (m_flags.IsClear (got_flag)) +    std::call_once(data_segment.m_flag, +                   &SymbolFileDWARF::LoadSectionData, +                   this, +                   sect_type, +                   std::ref(data_segment.m_data)); +    return data_segment.m_data; +} + +void +SymbolFileDWARF::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data) +{ +    ModuleSP module_sp (m_obj_file->GetModule()); +    const SectionList *section_list = module_sp->GetSectionList(); +    if (section_list)      { -        ModuleSP module_sp (m_obj_file->GetModule()); -        m_flags.Set (got_flag); -        const SectionList *section_list = module_sp->GetSectionList(); -        if (section_list) +        SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); +        if (section_sp)          { -            SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); -            if (section_sp) +            // See if we memory mapped the DWARF segment? +            if (m_dwarf_data.GetByteSize())              { -                // See if we memory mapped the DWARF segment? -                if (m_dwarf_data.GetByteSize()) -                { -                    data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize()); -                } -                else -                { -                    if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0) -                        data.Clear(); -                } +                data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize()); +            } +            else +            { +                if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0) +                    data.Clear();              }          }      } -    return data;  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_abbrev_data()  { -    return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev); +    return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_addr_data() +{ +    return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_aranges_data()  { -    return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges); +    return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_frame_data()  { -    return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame); +    return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_info_data()  { -    return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info); +    return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_line_data()  { -    return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line); +    return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_macro_data() +{ +    return GetCachedSectionData (eSectionTypeDWARFDebugMacro, m_data_debug_macro);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_loc_data()  { -    return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc); +    return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_ranges_data()  { -    return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges); +    return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_debug_str_data()  { -    return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str); +    return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str); +} + +const DWARFDataExtractor& +SymbolFileDWARF::get_debug_str_offsets_data() +{ +    return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_apple_names_data()  { -    return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names); +    return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_apple_types_data()  { -    return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types); +    return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_apple_namespaces_data()  { -    return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces); +    return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);  }  const DWARFDataExtractor&  SymbolFileDWARF::get_apple_objc_data()  { -    return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc); +    return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc);  } @@ -889,6 +817,9 @@ SymbolFileDWARF::DebugInfo() const  DWARFCompileUnit*  SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)  { +    if (!comp_unit) +        return nullptr; +      DWARFDebugInfo* info = DebugInfo();      if (info)      { @@ -900,7 +831,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)              // TODO: modify to support LTO .o files where each .o file might              // have multiple DW_TAG_compile_unit tags. -            DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get(); +            DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0);              if (dwarf_cu && dwarf_cu->GetUserData() == NULL)                  dwarf_cu->SetUserData(comp_unit);              return dwarf_cu; @@ -910,7 +841,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)              // Just a normal DWARF file whose user ID for the compile unit is              // the DWARF offset itself -            DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get(); +            DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID());              if (dwarf_cu && dwarf_cu->GetUserData() == NULL)                  dwarf_cu->SetUserData(comp_unit);              return dwarf_cu; @@ -958,7 +889,11 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)          }          else          { -            if (GetDebugMapSymfile ()) +            if (dwarf_cu->GetSymbolFileDWARF() != this) +            { +                return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx); +            } +            else if (GetDebugMapSymfile ())              {                  // Let the debug map create the compile unit                  cu_sp = m_debug_map_symfile->GetCompileUnit(this); @@ -969,20 +904,18 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)                  ModuleSP module_sp (m_obj_file->GetModule());                  if (module_sp)                  { -                    const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly (); +                    const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly ();                      if (cu_die)                      { -                        FileSpec cu_file_spec{cu_die->GetName(this, dwarf_cu), false}; +                        FileSpec cu_file_spec{cu_die.GetName(), false};                          if (cu_file_spec)                          {                              // If we have a full path to the compile unit, we don't need to resolve                              // the file.  This can be expensive e.g. when the source files are NFS mounted.                              if (cu_file_spec.IsRelative())                              { -                                // DWARF2/3 suggests the form hostname:pathname for compilation directory. -                                // Remove the host part if present. -                                const char *cu_comp_dir{cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, nullptr)}; -                                cu_file_spec.PrependPathComponent(removeHostnameFromPathname(cu_comp_dir)); +                                const char *cu_comp_dir{cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)}; +                                cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir));                              }                              std::string remapped_file; @@ -990,13 +923,15 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)                                  cu_file_spec.SetFile(remapped_file, false);                          } -                        LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0)); +                        LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0)); +                        bool is_optimized = dwarf_cu->GetIsOptimized ();                          cu_sp.reset(new CompileUnit (module_sp,                                                       dwarf_cu,                                                       cu_file_spec,  -                                                     MakeUserID(dwarf_cu->GetOffset()), -                                                     cu_language)); +                                                     dwarf_cu->GetID(), +                                                     cu_language, +                                                     is_optimized));                          if (cu_sp)                          {                              // If we just created a compile unit with an invalid file spec, try and get the @@ -1053,137 +988,20 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)  }  Function * -SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die) +SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFDIE &die)  { -    DWARFDebugRanges::RangeList func_ranges; -    const char *name = NULL; -    const char *mangled = NULL; -    int decl_file = 0; -    int decl_line = 0; -    int decl_column = 0; -    int call_file = 0; -    int call_line = 0; -    int call_column = 0; -    DWARFExpression frame_base; - -    assert (die->Tag() == DW_TAG_subprogram); -     -    if (die->Tag() != DW_TAG_subprogram) -        return NULL; - -    if (die->GetDIENamesAndRanges (this,  -                                   dwarf_cu,  -                                   name,  -                                   mangled,  -                                   func_ranges,  -                                   decl_file,  -                                   decl_line,  -                                   decl_column,  -                                   call_file,  -                                   call_line,  -                                   call_column,  -                                   &frame_base)) +    if (die.IsValid())      { -        // Union of all ranges in the function DIE (if the function is discontiguous) -        AddressRange func_range; -        lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0); -        lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0); -        if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) -        { -            ModuleSP module_sp (m_obj_file->GetModule()); -            func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList()); -            if (func_range.GetBaseAddress().IsValid()) -                func_range.SetByteSize(highest_func_addr - lowest_func_addr); -        } +        TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); -        if (func_range.GetBaseAddress().IsValid()) +        if (type_system)          { -            Mangled func_name; -            if (mangled) -                func_name.SetValue(ConstString(mangled), true); -            else if (die->GetParent()->Tag() == DW_TAG_compile_unit && -                     LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()) && -                     name && strcmp(name, "main") != 0) -            { -                // If the mangled name is not present in the DWARF, generate the demangled name -                // using the decl context. We skip if the function is "main" as its name is -                // never mangled. -                bool is_static = false; -                bool is_variadic = false; -                unsigned type_quals = 0; -                std::vector<ClangASTType> param_types; -                std::vector<clang::ParmVarDecl*> param_decls; -                const DWARFDebugInfoEntry *decl_ctx_die = NULL; -                DWARFDeclContext decl_ctx; -                StreamString sstr; - -                die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx); -                sstr << decl_ctx.GetQualifiedName(); - -                clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(dwarf_cu, -                                                                                           die, -                                                                                           &decl_ctx_die); -                ParseChildParameters(sc, -                                     containing_decl_ctx, -                                     dwarf_cu, -                                     die, -                                     true, -                                     is_static, -                                     is_variadic, -                                     param_types, -                                     param_decls, -                                     type_quals); -                sstr << "("; -                for (size_t i = 0; i < param_types.size(); i++) -                { -                    if (i > 0) -                        sstr << ", "; -                    sstr << param_types[i].GetTypeName(); -                } -                if (is_variadic) -                    sstr << ", ..."; -                sstr << ")"; -                if (type_quals & clang::Qualifiers::Const) -                    sstr << " const"; - -                func_name.SetValue(ConstString(sstr.GetData()), false); -            } -            else -                func_name.SetValue(ConstString(name), false); - -            FunctionSP func_sp; -            std::unique_ptr<Declaration> decl_ap; -            if (decl_file != 0 || decl_line != 0 || decl_column != 0) -                decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),  -                                               decl_line,  -                                               decl_column)); - -            // Supply the type _only_ if it has already been parsed -            Type *func_type = m_die_to_type.lookup (die); - -            assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); - -            if (FixupAddress (func_range.GetBaseAddress())) -            { -                const user_id_t func_user_id = MakeUserID(die->GetOffset()); -                func_sp.reset(new Function (sc.comp_unit, -                                            MakeUserID(func_user_id),       // UserID is the DIE offset -                                            MakeUserID(func_user_id), -                                            func_name, -                                            func_type, -                                            func_range));           // first address range - -                if (func_sp.get() != NULL) -                { -                    if (frame_base.IsValid()) -                        func_sp->GetFrameBaseExpression() = frame_base; -                    sc.comp_unit->AddFunction(func_sp); -                    return func_sp.get(); -                } -            } +            DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); +            if (dwarf_ast) +                return dwarf_ast->ParseFunctionFromDWARF(sc, die);          }      } -    return NULL; +    return nullptr;  }  bool @@ -1203,12 +1021,9 @@ SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)      assert (sc.comp_unit);      DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);      if (dwarf_cu) -    { -        const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly(); -        if (die) -            return DWARFCompileUnit::LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0)); -    } -    return eLanguageTypeUnknown; +        return dwarf_cu->GetLanguageType(); +    else +        return eLanguageTypeUnknown;  }  size_t @@ -1224,10 +1039,10 @@ SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)          size_t func_idx;          for (func_idx = 0; func_idx < num_functions; ++func_idx)          { -            const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx); -            if (sc.comp_unit->FindFunctionByUID (MakeUserID(die->GetOffset())).get() == NULL) +            DWARFDIE die = function_dies.GetDIEAtIndex(func_idx); +            if (sc.comp_unit->FindFunctionByUID (die.GetID()).get() == NULL)              { -                if (ParseCompileUnitFunction(sc, dwarf_cu, die)) +                if (ParseCompileUnitFunction(sc, die))                      ++functions_added;              }          } @@ -1243,17 +1058,13 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec      DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);      if (dwarf_cu)      { -        const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly(); +        const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();          if (cu_die)          { -            const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL); - -            // DWARF2/3 suggests the form hostname:pathname for compilation directory. -            // Remove the host part if present. -            cu_comp_dir = removeHostnameFromPathname(cu_comp_dir); +            const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)); -            dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET); +            const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);              // All file indexes in DWARF are one based and a file of index zero is              // supposed to be the compile unit itself. @@ -1275,9 +1086,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st          if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))          {              UpdateExternalModuleListIfNeeded(); -            for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules) +            for (const auto &pair : m_external_type_modules)              { -                imported_modules.push_back(external_type_module.second.m_name); +                imported_modules.push_back(pair.first);              }          }      } @@ -1288,6 +1099,7 @@ struct ParseDWARFLineTableCallbackInfo  {      LineTable* line_table;      std::unique_ptr<LineSequence> sequence_ap; +    lldb::addr_t addr_mask;  };  //---------------------------------------------------------------------- @@ -1317,7 +1129,7 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta              assert(info->sequence_ap.get());          }          line_table->AppendLineEntryToSequence (info->sequence_ap.get(), -                                               state.address, +                                               state.address & info->addr_mask,                                                 state.line,                                                 state.column,                                                 state.file, @@ -1346,10 +1158,10 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)      DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);      if (dwarf_cu)      { -        const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); +        const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();          if (dwarf_cu_die)          { -            const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET); +            const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);              if (cu_line_offset != DW_INVALID_OFFSET)              {                  std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit)); @@ -1357,6 +1169,28 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)                  {                      ParseDWARFLineTableCallbackInfo info;                      info.line_table = line_table_ap.get(); + +                    /* +                     * MIPS: +                     * The SymbolContext may not have a valid target, thus we may not be able +                     * to call Address::GetOpcodeLoadAddress() which would clear the bit #0 +                     * for MIPS. Use ArchSpec to clear the bit #0. +                    */ +                    ArchSpec arch; +                    GetObjectFile()->GetArchitecture(arch); +                    switch (arch.GetMachine()) +                    { +                    case llvm::Triple::mips: +                    case llvm::Triple::mipsel: +                    case llvm::Triple::mips64: +                    case llvm::Triple::mips64el: +                        info.addr_mask = ~((lldb::addr_t)1); +                        break; +                    default: +                        info.addr_mask = ~((lldb::addr_t)0); +                        break; +                    } +                      lldb::offset_t offset = cu_line_offset;                      DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);                      if (m_debug_map_symfile) @@ -1379,21 +1213,63 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)      return false;  } +lldb_private::DebugMacrosSP +SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) +{ +    auto iter = m_debug_macros_map.find(*offset); +    if (iter != m_debug_macros_map.end()) +        return iter->second; + +    const DWARFDataExtractor &debug_macro_data = get_debug_macro_data(); +    if (debug_macro_data.GetByteSize() == 0) +        return DebugMacrosSP(); + +    lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros()); +    m_debug_macros_map[*offset] = debug_macros_sp; + +    const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset); +    DWARFDebugMacroEntry::ReadMacroEntries( +        debug_macro_data, get_debug_str_data(), header.OffsetIs64Bit(), offset, this, debug_macros_sp); + +    return debug_macros_sp; +} + +bool +SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc) +{ +    assert (sc.comp_unit); + +    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); +    if (dwarf_cu == nullptr) +        return false; + +    const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly(); +    if (!dwarf_cu_die) +        return false; + +    lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET); +    if (sect_offset == DW_INVALID_OFFSET) +        sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET); +    if (sect_offset == DW_INVALID_OFFSET) +        return false; + +    sc.comp_unit->SetDebugMacros(ParseDebugMacros(§_offset)); + +    return true; +} +  size_t -SymbolFileDWARF::ParseFunctionBlocks -( -    const SymbolContext& sc, -    Block *parent_block, -    DWARFCompileUnit* dwarf_cu, -    const DWARFDebugInfoEntry *die, -    addr_t subprogram_low_pc, -    uint32_t depth -) +SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc, +                                      Block *parent_block, +                                      const DWARFDIE &orig_die, +                                      addr_t subprogram_low_pc, +                                      uint32_t depth)  {      size_t blocks_added = 0; -    while (die != NULL) +    DWARFDIE die = orig_die; +    while (die)      { -        dw_tag_t tag = die->Tag(); +        dw_tag_t tag = die.Tag();          switch (tag)          { @@ -1415,11 +1291,11 @@ SymbolFileDWARF::ParseFunctionBlocks                  }                  else                  { -                    BlockSP block_sp(new Block (MakeUserID(die->GetOffset()))); +                    BlockSP block_sp(new Block (die.GetID()));                      parent_block->AddChild(block_sp);                      block = block_sp.get();                  } -                DWARFDebugRanges::RangeList ranges; +                DWARFRangeList ranges;                  const char *name = NULL;                  const char *mangled_name = NULL; @@ -1429,13 +1305,11 @@ SymbolFileDWARF::ParseFunctionBlocks                  int call_file = 0;                  int call_line = 0;                  int call_column = 0; -                if (die->GetDIENamesAndRanges (this,  -                                               dwarf_cu,  -                                               name,  -                                               mangled_name,  -                                               ranges,  -                                               decl_file, decl_line, decl_column, -                                               call_file, call_line, call_column)) +                if (die.GetDIENamesAndRanges (name, +                                              mangled_name, +                                              ranges, +                                              decl_file, decl_line, decl_column, +                                              call_file, call_line, call_column, nullptr))                  {                      if (tag == DW_TAG_subprogram)                      { @@ -1461,7 +1335,7 @@ SymbolFileDWARF::ParseFunctionBlocks                      const size_t num_ranges = ranges.GetSize();                      for (size_t i = 0; i<num_ranges; ++i)                      { -                        const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i); +                        const DWARFRangeList::Entry &range = ranges.GetEntryRef (i);                          const addr_t range_base = range.GetRangeBase();                          if (range_base >= subprogram_low_pc)                              block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize())); @@ -1493,12 +1367,11 @@ SymbolFileDWARF::ParseFunctionBlocks                      ++blocks_added; -                    if (die->HasChildren()) +                    if (die.HasChildren())                      {                          blocks_added += ParseFunctionBlocks (sc,                                                                block,  -                                                             dwarf_cu,  -                                                             die->GetFirstChild(),  +                                                             die.GetFirstChild(),                                                               subprogram_low_pc,                                                                depth + 1);                      } @@ -1514,278 +1387,21 @@ SymbolFileDWARF::ParseFunctionBlocks          // DW_TAG_subprogram DIE          if (depth == 0) -            die = NULL; +            die.Clear();          else -            die = die->GetSibling(); +            die = die.GetSibling();      }      return blocks_added;  }  bool -SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, -                                   const DWARFDebugInfoEntry *die, -                                   ClangASTContext::TemplateParameterInfos &template_param_infos) -{ -    const dw_tag_t tag = die->Tag(); -     -    switch (tag) -    { -    case DW_TAG_template_type_parameter: -    case DW_TAG_template_value_parameter: -        { -            const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - -            DWARFDebugInfoEntry::Attributes attributes; -            const size_t num_attributes = die->GetAttributes (this,  -                                                              dwarf_cu,  -                                                              fixed_form_sizes,  -                                                              attributes); -            const char *name = NULL; -            Type *lldb_type = NULL; -            ClangASTType clang_type; -            uint64_t uval64 = 0; -            bool uval64_valid = false; -            if (num_attributes > 0) -            { -                DWARFFormValue form_value; -                for (size_t i=0; i<num_attributes; ++i) -                { -                    const dw_attr_t attr = attributes.AttributeAtIndex(i); -                     -                    switch (attr) -                    { -                        case DW_AT_name: -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                                name = form_value.AsCString(&get_debug_str_data()); -                            break; -                             -                        case DW_AT_type: -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                const dw_offset_t type_die_offset = form_value.Reference(); -                                lldb_type = ResolveTypeUID(type_die_offset); -                                if (lldb_type) -                                    clang_type = lldb_type->GetClangForwardType(); -                            } -                            break; -                             -                        case DW_AT_const_value: -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                uval64_valid = true; -                                uval64 = form_value.Unsigned(); -                            } -                            break; -                        default: -                            break; -                    } -                } -                 -                clang::ASTContext *ast = GetClangASTContext().getASTContext(); -                if (!clang_type) -                    clang_type = GetClangASTContext().GetBasicType(eBasicTypeVoid); - -                if (clang_type) -                { -                    bool is_signed = false; -                    if (name && name[0]) -                        template_param_infos.names.push_back(name); -                    else -                        template_param_infos.names.push_back(NULL); -     -                    if (tag == DW_TAG_template_value_parameter && -                        lldb_type != NULL && -                        clang_type.IsIntegerType (is_signed) && -                        uval64_valid) -                    { -                        llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed); -                        template_param_infos.args.push_back (clang::TemplateArgument (*ast, -                                                                                      llvm::APSInt(apint), -                                                                                      clang_type.GetQualType())); -                    } -                    else -                    { -                        template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType())); -                    } -                } -                else -                { -                    return false; -                } -                 -            } -        } -        return true; - -    default: -        break; -    } -    return false; -} - -bool -SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu, -                                              const DWARFDebugInfoEntry *parent_die, -                                              ClangASTContext::TemplateParameterInfos &template_param_infos) -{ - -    if (parent_die == NULL) -        return false; -     -    Args template_parameter_names; -    for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild();  -         die != NULL;  -         die = die->GetSibling()) -    { -        const dw_tag_t tag = die->Tag(); -         -        switch (tag) -        { -            case DW_TAG_template_type_parameter: -            case DW_TAG_template_value_parameter: -                ParseTemplateDIE (dwarf_cu, die, template_param_infos); -            break; -                 -        default: -            break; -        } -    } -    if (template_param_infos.args.empty()) -        return false; -    return template_param_infos.args.size() == template_param_infos.names.size(); -} - -clang::ClassTemplateDecl * -SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx, -                                         lldb::AccessType access_type, -                                         const char *parent_name, -                                         int tag_decl_kind, -                                         const ClangASTContext::TemplateParameterInfos &template_param_infos) -{ -    if (template_param_infos.IsValid()) -    { -        std::string template_basename(parent_name); -        template_basename.erase (template_basename.find('<')); -        ClangASTContext &ast = GetClangASTContext(); - -        return ast.CreateClassTemplateDecl (decl_ctx, -                                            access_type, -                                            template_basename.c_str(),  -                                            tag_decl_kind,  -                                            template_param_infos); -    } -    return NULL; -} - -class SymbolFileDWARF::DelayedAddObjCClassProperty -{ -public: -    DelayedAddObjCClassProperty -    ( -        const ClangASTType     &class_opaque_type, -        const char             *property_name, -        const ClangASTType     &property_opaque_type,  // The property type is only required if you don't have an ivar decl -        clang::ObjCIvarDecl    *ivar_decl,    -        const char             *property_setter_name, -        const char             *property_getter_name, -        uint32_t                property_attributes, -        const ClangASTMetadata *metadata -    ) : -        m_class_opaque_type     (class_opaque_type), -        m_property_name         (property_name), -        m_property_opaque_type  (property_opaque_type), -        m_ivar_decl             (ivar_decl), -        m_property_setter_name  (property_setter_name), -        m_property_getter_name  (property_getter_name), -        m_property_attributes   (property_attributes) -    { -        if (metadata != NULL) -        { -            m_metadata_ap.reset(new ClangASTMetadata()); -            *m_metadata_ap = *metadata; -        } -    } -     -    DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs) -    { -        *this = rhs; -    } - -    DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs) -    { -        m_class_opaque_type    = rhs.m_class_opaque_type; -        m_property_name        = rhs.m_property_name; -        m_property_opaque_type = rhs.m_property_opaque_type; -        m_ivar_decl            = rhs.m_ivar_decl; -        m_property_setter_name = rhs.m_property_setter_name; -        m_property_getter_name = rhs.m_property_getter_name; -        m_property_attributes  = rhs.m_property_attributes; -         -        if (rhs.m_metadata_ap.get()) -        { -            m_metadata_ap.reset (new ClangASTMetadata()); -            *m_metadata_ap = *rhs.m_metadata_ap; -        } -        return *this; -    } -     -    bool -    Finalize() -    { -        return m_class_opaque_type.AddObjCClassProperty (m_property_name, -                                                         m_property_opaque_type, -                                                         m_ivar_decl, -                                                         m_property_setter_name, -                                                         m_property_getter_name, -                                                         m_property_attributes, -                                                         m_metadata_ap.get()); -    } -private: -    ClangASTType            m_class_opaque_type; -    const char             *m_property_name; -    ClangASTType            m_property_opaque_type; -    clang::ObjCIvarDecl    *m_ivar_decl; -    const char             *m_property_setter_name; -    const char             *m_property_getter_name; -    uint32_t                m_property_attributes; -    std::unique_ptr<ClangASTMetadata> m_metadata_ap; -}; - -struct BitfieldInfo -{ -    uint64_t bit_size; -    uint64_t bit_offset; -     -    BitfieldInfo () : -        bit_size (LLDB_INVALID_ADDRESS), -        bit_offset (LLDB_INVALID_ADDRESS) -    { -    } -     -    void -    Clear() -    { -        bit_size = LLDB_INVALID_ADDRESS; -        bit_offset = LLDB_INVALID_ADDRESS; -    } - -    bool IsValid () -    { -        return (bit_size != LLDB_INVALID_ADDRESS) && -               (bit_offset != LLDB_INVALID_ADDRESS); -    } -}; - - -bool -SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu, -                                         const DWARFDebugInfoEntry *parent_die) +SymbolFileDWARF::ClassOrStructIsVirtual (const DWARFDIE &parent_die)  {      if (parent_die)      { -        for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) +        for (DWARFDIE die = parent_die.GetFirstChild(); die; die = die.GetSibling())          { -            dw_tag_t tag = die->Tag(); +            dw_tag_t tag = die.Tag();              bool check_virtuality = false;              switch (tag)              { @@ -1798,7 +1414,7 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,              }              if (check_virtuality)              { -                if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0) +                if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0)                      return true;              }          } @@ -1806,602 +1422,79 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,      return false;  } -size_t -SymbolFileDWARF::ParseChildMembers -( -    const SymbolContext& sc, -    DWARFCompileUnit* dwarf_cu, -    const DWARFDebugInfoEntry *parent_die, -    ClangASTType &class_clang_type, -    const LanguageType class_language, -    std::vector<clang::CXXBaseSpecifier *>& base_classes, -    std::vector<int>& member_accessibilities, -    DWARFDIECollection& member_function_dies, -    DelayedPropertyList& delayed_properties, -    AccessType& default_accessibility, -    bool &is_a_class, -    LayoutInfo &layout_info -) +void +SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx)  { -    if (parent_die == NULL) -        return 0; +    TypeSystem *type_system = decl_ctx.GetTypeSystem(); +    DWARFASTParser *ast_parser = type_system->GetDWARFParser(); +    std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx); -    size_t count = 0; -    const DWARFDebugInfoEntry *die; -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); -    uint32_t member_idx = 0; -    BitfieldInfo last_field_info; -    ModuleSP module = GetObjectFile()->GetModule(); +    for (DWARFDIE decl_ctx_die : decl_ctx_die_list) +        for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling()) +            ast_parser->GetDeclForUIDFromDWARF(decl); +} -    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) +CompilerDecl +SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid) +{ +    if (UserIDMatches(type_uid))      { -        dw_tag_t tag = die->Tag(); - -        switch (tag) +        DWARFDebugInfo* debug_info = DebugInfo(); +        if (debug_info)          { -        case DW_TAG_member: -        case DW_TAG_APPLE_property: -            { -                DWARFDebugInfoEntry::Attributes attributes; -                const size_t num_attributes = die->GetAttributes (this,  -                                                                  dwarf_cu,  -                                                                  fixed_form_sizes,  -                                                                  attributes); -                if (num_attributes > 0) -                { -                    Declaration decl; -                    //DWARFExpression location; -                    const char *name = NULL; -                    const char *prop_name = NULL; -                    const char *prop_getter_name = NULL; -                    const char *prop_setter_name = NULL; -                    uint32_t prop_attributes = 0; -                     -                     -                    bool is_artificial = false; -                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; -                    AccessType accessibility = eAccessNone; -                    uint32_t member_byte_offset = UINT32_MAX; -                    size_t byte_size = 0; -                    size_t bit_offset = 0; -                    size_t bit_size = 0; -                    bool is_external = false; // On DW_TAG_members, this means the member is static -                    uint32_t i; -                    for (i=0; i<num_attributes && !is_artificial; ++i) -                    { -                        const dw_attr_t attr = attributes.AttributeAtIndex(i); -                        DWARFFormValue form_value; -                        if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                        { -                            switch (attr) -                            { -                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break; -                            case DW_AT_type:        encoding_uid = form_value.Reference(); break; -                            case DW_AT_bit_offset:  bit_offset = form_value.Unsigned(); break; -                            case DW_AT_bit_size:    bit_size = form_value.Unsigned(); break; -                            case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break; -                            case DW_AT_data_member_location: -                                if (form_value.BlockData()) -                                { -                                    Value initialValue(0); -                                    Value memberOffset(0); -                                    const DWARFDataExtractor& debug_info_data = get_debug_info_data(); -                                    uint32_t block_length = form_value.Unsigned(); -                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); -                                    if (DWARFExpression::Evaluate(NULL, // ExecutionContext * -                                                                  NULL, // ClangExpressionVariableList * -                                                                  NULL, // ClangExpressionDeclMap * -                                                                  NULL, // RegisterContext * -                                                                  module, -                                                                  debug_info_data,  -                                                                  block_offset,  -                                                                  block_length,  -                                                                  eRegisterKindDWARF,  -                                                                  &initialValue,  -                                                                  memberOffset,  -                                                                  NULL)) -                                    { -                                        member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); -                                    } -                                } -                                else -                                { -                                    // With DWARF 3 and later, if the value is an integer constant, -                                    // this form value is the offset in bytes from the beginning -                                    // of the containing entity.  -                                    member_byte_offset = form_value.Unsigned();  -                                } -                                break; - -                            case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break; -                            case DW_AT_artificial: is_artificial = form_value.Boolean(); break; -                            case DW_AT_APPLE_property_name:      prop_name = form_value.AsCString(&get_debug_str_data()); break; -                            case DW_AT_APPLE_property_getter:    prop_getter_name = form_value.AsCString(&get_debug_str_data()); break; -                            case DW_AT_APPLE_property_setter:    prop_setter_name = form_value.AsCString(&get_debug_str_data()); break; -                            case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break; -                            case DW_AT_external:                 is_external = form_value.Boolean(); break; - -                            default: -                            case DW_AT_declaration: -                            case DW_AT_description: -                            case DW_AT_mutable: -                            case DW_AT_visibility: -                            case DW_AT_sibling: -                                break; -                            } -                        } -                    } -                                         -                    if (prop_name) -                    { -                        ConstString fixed_getter; -                        ConstString fixed_setter; - -                        // Check if the property getter/setter were provided as full -                        // names.  We want basenames, so we extract them. -                         -                        if (prop_getter_name && prop_getter_name[0] == '-') -                        { -                            ObjCLanguageRuntime::MethodName prop_getter_method(prop_getter_name, true); -                            prop_getter_name = prop_getter_method.GetSelector().GetCString(); -                        } -                         -                        if (prop_setter_name && prop_setter_name[0] == '-') -                        { -                            ObjCLanguageRuntime::MethodName prop_setter_method(prop_setter_name, true); -                            prop_setter_name = prop_setter_method.GetSelector().GetCString(); -                        } -                         -                        // If the names haven't been provided, they need to be -                        // filled in. -                         -                        if (!prop_getter_name) -                        { -                            prop_getter_name = prop_name; -                        } -                        if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly)) -                        { -                            StreamString ss; -                             -                            ss.Printf("set%c%s:", -                                      toupper(prop_name[0]), -                                      &prop_name[1]); -                             -                            fixed_setter.SetCString(ss.GetData()); -                            prop_setter_name = fixed_setter.GetCString(); -                        } -                    } -                     -                    // Clang has a DWARF generation bug where sometimes it -                    // represents fields that are references with bad byte size -                    // and bit size/offset information such as: -                    // -                    //  DW_AT_byte_size( 0x00 ) -                    //  DW_AT_bit_size( 0x40 ) -                    //  DW_AT_bit_offset( 0xffffffffffffffc0 ) -                    // -                    // So check the bit offset to make sure it is sane, and if  -                    // the values are not sane, remove them. If we don't do this -                    // then we will end up with a crash if we try to use this  -                    // type in an expression when clang becomes unhappy with its -                    // recycled debug info. -                     -                    if (bit_offset > 128) -                    { -                        bit_size = 0; -                        bit_offset = 0; -                    } - -                    // FIXME: Make Clang ignore Objective-C accessibility for expressions -                    if (class_language == eLanguageTypeObjC || -                        class_language == eLanguageTypeObjC_plus_plus) -                        accessibility = eAccessNone;  -                     -                    if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name)) -                    { -                        // Not all compilers will mark the vtable pointer -                        // member as artificial (llvm-gcc). We can't have -                        // the virtual members in our classes otherwise it -                        // throws off all child offsets since we end up -                        // having and extra pointer sized member in our  -                        // class layouts. -                        is_artificial = true; -                    } - -                    // Handle static members -                    if (is_external && member_byte_offset == UINT32_MAX) -                    { -                        Type *var_type = ResolveTypeUID(encoding_uid); - -                        if (var_type) -                        { -                            if (accessibility == eAccessNone) -                                accessibility = eAccessPublic; -                            class_clang_type.AddVariableToRecordType (name, -                                                                      var_type->GetClangLayoutType(), -                                                                      accessibility); -                        } -                        break; -                    } - -                    if (is_artificial == false) -                    { -                        Type *member_type = ResolveTypeUID(encoding_uid); -                         -                        clang::FieldDecl *field_decl = NULL; -                        if (tag == DW_TAG_member) -                        { -                            if (member_type) -                            { -                                if (accessibility == eAccessNone) -                                    accessibility = default_accessibility; -                                member_accessibilities.push_back(accessibility); -                                 -                                uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); -                                if (bit_size > 0) -                                { -                                     -                                    BitfieldInfo this_field_info; -                                    this_field_info.bit_offset = field_bit_offset; -                                    this_field_info.bit_size = bit_size; -                                     -                                    ///////////////////////////////////////////////////////////// -                                    // How to locate a field given the DWARF debug information -                                    // -                                    // AT_byte_size indicates the size of the word in which the -                                    // bit offset must be interpreted. -                                    // -                                    // AT_data_member_location indicates the byte offset of the -                                    // word from the base address of the structure. -                                    // -                                    // AT_bit_offset indicates how many bits into the word -                                    // (according to the host endianness) the low-order bit of -                                    // the field starts.  AT_bit_offset can be negative. -                                    // -                                    // AT_bit_size indicates the size of the field in bits. -                                    ///////////////////////////////////////////////////////////// -                                     -                                    if (byte_size == 0) -                                        byte_size = member_type->GetByteSize(); -                                         -                                    if (GetObjectFile()->GetByteOrder() == eByteOrderLittle) -                                    { -                                        this_field_info.bit_offset += byte_size * 8; -                                        this_field_info.bit_offset -= (bit_offset + bit_size); -                                    } -                                    else -                                    { -                                        this_field_info.bit_offset += bit_offset; -                                    } -                                     -                                    // Update the field bit offset we will report for layout -                                    field_bit_offset = this_field_info.bit_offset; - -                                    // If the member to be emitted did not start on a character boundary and there is -                                    // empty space between the last field and this one, then we need to emit an -                                    // anonymous member filling up the space up to its start.  There are three cases -                                    // here: -                                    // -                                    // 1 If the previous member ended on a character boundary, then we can emit an -                                    //   anonymous member starting at the most recent character boundary. -                                    // -                                    // 2 If the previous member did not end on a character boundary and the distance -                                    //   from the end of the previous member to the current member is less than a -                                    //   word width, then we can emit an anonymous member starting right after the -                                    //   previous member and right before this member. -                                    // -                                    // 3 If the previous member did not end on a character boundary and the distance -                                    //   from the end of the previous member to the current member is greater than -                                    //   or equal a word width, then we act as in Case 1. -                                     -                                    const uint64_t character_width = 8; -                                    const uint64_t word_width = 32; -                                     -                                    // Objective-C has invalid DW_AT_bit_offset values in older versions -                                    // of clang, so we have to be careful and only insert unnamed bitfields -                                    // if we have a new enough clang. -                                    bool detect_unnamed_bitfields = true; -                                     -                                    if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus) -                                        detect_unnamed_bitfields = dwarf_cu->Supports_unnamed_objc_bitfields (); -                                     -                                    if (detect_unnamed_bitfields) -                                    { -                                        BitfieldInfo anon_field_info; -                                         -                                        if ((this_field_info.bit_offset % character_width) != 0) // not char aligned -                                        { -                                            uint64_t last_field_end = 0; -                                             -                                            if (last_field_info.IsValid()) -                                                last_field_end = last_field_info.bit_offset + last_field_info.bit_size; -                                             -                                            if (this_field_info.bit_offset != last_field_end) -                                            {                                                 -                                                if (((last_field_end % character_width) == 0) ||                    // case 1 -                                                    (this_field_info.bit_offset - last_field_end >= word_width))    // case 3 -                                                { -                                                    anon_field_info.bit_size = this_field_info.bit_offset % character_width; -                                                    anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size; -                                                } -                                                else                                                                // case 2 -                                                { -                                                    anon_field_info.bit_size = this_field_info.bit_offset - last_field_end; -                                                    anon_field_info.bit_offset = last_field_end; -                                                } -                                            } -                                        } -                                         -                                        if (anon_field_info.IsValid()) -                                        { -                                            clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL, -                                                                                                                             GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width), -                                                                                                                             accessibility, -                                                                                                                             anon_field_info.bit_size); - -                                            layout_info.field_offsets.insert( -                                                std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); -                                        } -                                    } -                                    last_field_info = this_field_info; -                                } -                                else -                                { -                                    last_field_info.Clear(); -                                } -                                 -                                ClangASTType member_clang_type = member_type->GetClangLayoutType(); -                                 -                                { -                                    // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>). -                                    // If the current field is at the end of the structure, then there is definitely no room for extra -                                    // elements and we override the type to array[0]. -                                     -                                    ClangASTType member_array_element_type; -                                    uint64_t member_array_size; -                                    bool member_array_is_incomplete; -                                     -                                    if (member_clang_type.IsArrayType(&member_array_element_type, -                                                                      &member_array_size, -                                                                      &member_array_is_incomplete) && -                                        !member_array_is_incomplete) -                                    { -                                        uint64_t parent_byte_size = parent_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, UINT64_MAX); -                                     -                                        if (member_byte_offset >= parent_byte_size) -                                        { -                                            if (member_array_size != 1) -                                            { -                                                GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64, -                                                                                           MakeUserID(die->GetOffset()), -                                                                                           name, -                                                                                           encoding_uid, -                                                                                           MakeUserID(parent_die->GetOffset())); -                                            } -                                             -                                            member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false); -                                        } -                                    } -                                } -                                 -                                field_decl = class_clang_type.AddFieldToRecordType (name, -                                                                                    member_clang_type, -                                                                                    accessibility, -                                                                                    bit_size); -                                 -                                GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset())); - -                                layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset)); -                            } -                            else -                            { -                                if (name) -                                    GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed", -                                                                               MakeUserID(die->GetOffset()), -                                                                               name, -                                                                               encoding_uid); -                                else -                                    GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed", -                                                                               MakeUserID(die->GetOffset()), -                                                                               encoding_uid); -                            } -                        } -                         -                        if (prop_name != NULL && member_type) -                        { -                            clang::ObjCIvarDecl *ivar_decl = NULL; -                             -                            if (field_decl) -                            { -                                ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl); -                                assert (ivar_decl != NULL); -                            } -                             -                            ClangASTMetadata metadata; -                            metadata.SetUserID (MakeUserID(die->GetOffset())); -                            delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type, -                                                                                     prop_name, -                                                                                     member_type->GetClangLayoutType(), -                                                                                     ivar_decl, -                                                                                     prop_setter_name, -                                                                                     prop_getter_name, -                                                                                     prop_attributes, -                                                                                     &metadata)); -                             -                            if (ivar_decl) -                                GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset())); -                        } -                    } -                } -                ++member_idx; -            } -            break; - -        case DW_TAG_subprogram: -            // Let the type parsing code handle this one for us.  -            member_function_dies.Append (die); -            break; - -        case DW_TAG_inheritance: +            DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); +            if (die)              { -                is_a_class = true; -                if (default_accessibility == eAccessNone) -                    default_accessibility = eAccessPrivate; -                // TODO: implement DW_TAG_inheritance type parsing -                DWARFDebugInfoEntry::Attributes attributes; -                const size_t num_attributes = die->GetAttributes (this,  -                                                                  dwarf_cu,  -                                                                  fixed_form_sizes,  -                                                                  attributes); -                if (num_attributes > 0) -                { -                    Declaration decl; -                    DWARFExpression location; -                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; -                    AccessType accessibility = default_accessibility; -                    bool is_virtual = false; -                    bool is_base_of_class = true; -                    off_t member_byte_offset = 0; -                    uint32_t i; -                    for (i=0; i<num_attributes; ++i) -                    { -                        const dw_attr_t attr = attributes.AttributeAtIndex(i); -                        DWARFFormValue form_value; -                        if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                        { -                            switch (attr) -                            { -                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                            case DW_AT_type:        encoding_uid = form_value.Reference(); break; -                            case DW_AT_data_member_location: -                                if (form_value.BlockData()) -                                { -                                    Value initialValue(0); -                                    Value memberOffset(0); -                                    const DWARFDataExtractor& debug_info_data = get_debug_info_data(); -                                    uint32_t block_length = form_value.Unsigned(); -                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); -                                    if (DWARFExpression::Evaluate (NULL,  -                                                                   NULL,  -                                                                   NULL,  -                                                                   NULL, -                                                                   module, -                                                                   debug_info_data,  -                                                                   block_offset,  -                                                                   block_length,  -                                                                   eRegisterKindDWARF,  -                                                                   &initialValue,  -                                                                   memberOffset,  -                                                                   NULL)) -                                    { -                                        member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); -                                    } -                                } -                                else -                                { -                                    // With DWARF 3 and later, if the value is an integer constant, -                                    // this form value is the offset in bytes from the beginning -                                    // of the containing entity.  -                                    member_byte_offset = form_value.Unsigned();  -                                } -                                break; - -                            case DW_AT_accessibility: -                                accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); -                                break; - -                            case DW_AT_virtuality: -                                is_virtual = form_value.Boolean(); -                                break; -                                                    -                            case DW_AT_sibling: -                                break; - -                            default: -                                break; -                            } -                        } -                    } - -                    Type *base_class_type = ResolveTypeUID(encoding_uid); -                    if (base_class_type == NULL) -                    { -                        GetObjectFile()->GetModule()->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message", -                                                                  die->GetOffset(), -                                                                  encoding_uid, -                                                                  parent_die->GetOffset()); -                        break; -                    } - -                    ClangASTType base_class_clang_type = base_class_type->GetClangFullType(); -                    assert (base_class_clang_type); -                    if (class_language == eLanguageTypeObjC) -                    { -                        class_clang_type.SetObjCSuperClass(base_class_clang_type); -                    } -                    else -                    { -                        base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility, -                                                                                               is_virtual,  -                                                                                               is_base_of_class)); -                         -                        if (is_virtual) -                        { -                            // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't -                            // give us a constant offset, but gives us a DWARF expressions that requires an actual object -                            // in memory. the DW_AT_data_member_location for a virtual base class looks like: -                            //      DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus ) -                            // Given this, there is really no valid response we can give to clang for virtual base -                            // class offsets, and this should eventually be removed from LayoutRecordType() in the external -                            // AST source in clang. -                        } -                        else -                        { -                            layout_info.base_offsets.insert( -                                std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(), -                                               clang::CharUnits::fromQuantity(member_byte_offset))); -                        } -                    } -                } +                DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +                if (dwarf_ast) +                    return dwarf_ast->GetDeclForUIDFromDWARF(die);              } -            break; - -        default: -            break;          }      } -     -    return count; +    return CompilerDecl();  } - -clang::DeclContext* -SymbolFileDWARF::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid)  { -    DWARFDebugInfo* debug_info = DebugInfo(); -    if (debug_info && UserIDMatches(type_uid)) +    if (UserIDMatches(type_uid))      { -        DWARFCompileUnitSP cu_sp; -        const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp); -        if (die) -            return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL); +        DWARFDebugInfo* debug_info = DebugInfo(); +        if (debug_info) +        { +            DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); +            if (die) +            { +                DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +                if (dwarf_ast) +                    return dwarf_ast->GetDeclContextForUIDFromDWARF(die); +            } +        }      } -    return NULL; +    return CompilerDeclContext();  } -clang::DeclContext* -SymbolFileDWARF::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid)  {      if (UserIDMatches(type_uid)) -        return GetClangDeclContextForDIEOffset (sc, type_uid); -    return NULL; +    { +        DWARFDebugInfo* debug_info = DebugInfo(); +        if (debug_info) +        { +            DWARFDIE die = debug_info->GetDIE(DIERef(type_uid)); +            if (die) +            { +                DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +                if (dwarf_ast) +                    return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die); +            } +        } +    } +    return CompilerDeclContext();  } +  Type*  SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)  { @@ -2410,418 +1503,143 @@ SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)          DWARFDebugInfo* debug_info = DebugInfo();          if (debug_info)          { -            DWARFCompileUnitSP cu_sp; -            const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp); -            const bool assert_not_being_parsed = true; -            return ResolveTypeUID (cu_sp.get(), type_die, assert_not_being_parsed); +            DWARFDIE type_die = debug_info->GetDIE (DIERef(type_uid)); +            if (type_die) +            { +                const bool assert_not_being_parsed = true; +                return ResolveTypeUID (type_die, assert_not_being_parsed); +            }          }      }      return NULL;  }  Type* -SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed) +SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_parsed)  {     -    if (die != NULL) +    if (die)      {          Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));          if (log)              GetObjectFile()->GetModule()->LogMessage (log,                                                        "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",  -                                                      die->GetOffset(),  -                                                      DW_TAG_value_to_name(die->Tag()),  -                                                      die->GetName(this, cu)); +                                                      die.GetOffset(), +                                                      die.GetTagAsCString(), +                                                      die.GetName());          // We might be coming in in the middle of a type tree (a class          // withing a class, an enum within a class), so parse any needed          // parent DIEs before we get to this one... -        const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die); -        switch (decl_ctx_die->Tag()) +        DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE (die); +        if (decl_ctx_die)          { -            case DW_TAG_structure_type: -            case DW_TAG_union_type: -            case DW_TAG_class_type: +            if (log)              { -                // Get the type, which could be a forward declaration -                if (log) -                    GetObjectFile()->GetModule()->LogMessage (log, -                                                              "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",  -                                                              die->GetOffset(),  -                                                              DW_TAG_value_to_name(die->Tag()),  -                                                              die->GetName(this, cu),  -                                                              decl_ctx_die->GetOffset()); -// -//                Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed); -//                if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag())) -//                { -//                    if (log) -//                        GetObjectFile()->GetModule()->LogMessage (log, -//                                                                  "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function",  -//                                                                  die->GetOffset(),  -//                                                                  DW_TAG_value_to_name(die->Tag()),  -//                                                                  die->GetName(this, cu),  -//                                                                  decl_ctx_die->GetOffset()); -//                    // Ask the type to complete itself if it already hasn't since if we -//                    // want a function (method or static) from a class, the class must  -//                    // create itself and add it's own methods and class functions. -//                    if (parent_type) -//                        parent_type->GetClangFullType(); -//                } -            } -            break; +                switch (decl_ctx_die.Tag()) +                { +                    case DW_TAG_structure_type: +                    case DW_TAG_union_type: +                    case DW_TAG_class_type: +                    { +                        // Get the type, which could be a forward declaration +                        if (log) +                            GetObjectFile()->GetModule()->LogMessage (log, +                                                                      "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",  +                                                                      die.GetOffset(), +                                                                      die.GetTagAsCString(), +                                                                      die.GetName(), +                                                                      decl_ctx_die.GetOffset()); +                    } +                    break; -            default: -                break; +                    default: +                        break; +                } +            }          } -        return ResolveType (cu, die); +        return ResolveType (die);      }      return NULL;  }  // This function is used when SymbolFileDWARFDebugMap owns a bunch of  // SymbolFileDWARF objects to detect if this DWARF file is the one that -// can resolve a clang_type. +// can resolve a compiler_type.  bool -SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type) +SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)  { -    ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); -    const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); -    return die != NULL; +    CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); +    if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType())) +    { +        return true; +    } +    TypeSystem *type_system = compiler_type.GetTypeSystem(); +    if (type_system) +    { +        DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); +        if (dwarf_ast) +            return dwarf_ast->CanCompleteType(compiler_type); +    } +    return false;  }  bool -SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) +SymbolFileDWARF::CompleteType (CompilerType &compiler_type)  { +    TypeSystem *type_system = compiler_type.GetTypeSystem(); +    if (type_system) +    { +        DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); +        if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type)) +            return dwarf_ast->CompleteType(compiler_type); +    } +      // We have a struct/union/class/enum that needs to be fully resolved. -    ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers(); -    const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType()); -    if (die == NULL) +    CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); +    auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType()); +    if (die_it == GetForwardDeclClangTypeToDie().end())      {          // We have already resolved this type...          return true;      } + +    DWARFDebugInfo* debug_info = DebugInfo(); +    DWARFDIE dwarf_die = debug_info->GetDIE(die_it->getSecond()); + +    assert(UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile"); +      // Once we start resolving this type, remove it from the forward declaration      // map in case anyone child members or other types require this type to get resolved.      // The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition      // are done. -    m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType()); - -    // Disable external storage for this type so we don't get anymore  -    // clang::ExternalASTSource queries for this type. -    clang_type.SetHasExternalStorage (false); - -    DWARFDebugInfo* debug_info = DebugInfo(); +    GetForwardDeclClangTypeToDie().erase (die_it); -    DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIE (die->GetOffset()).get(); -    Type *type = m_die_to_type.lookup (die); - -    const dw_tag_t tag = die->Tag(); +    Type *type = GetDIEToType().lookup (dwarf_die.GetDIE());      Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));      if (log)          GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,                                                                    "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", -                                                                  MakeUserID(die->GetOffset()), -                                                                  DW_TAG_value_to_name(tag), +                                                                  dwarf_die.GetID(), +                                                                  dwarf_die.GetTagAsCString(),                                                                    type->GetName().AsCString()); -    assert (clang_type); -    DWARFDebugInfoEntry::Attributes attributes; - -    switch (tag) -    { -    case DW_TAG_structure_type: -    case DW_TAG_union_type: -    case DW_TAG_class_type: -        { -            LayoutInfo layout_info; - -            { -                if (die->HasChildren()) -                { -                    LanguageType class_language = eLanguageTypeUnknown; -                    if (clang_type.IsObjCObjectOrInterfaceType()) -                    { -                        class_language = eLanguageTypeObjC; -                        // For objective C we don't start the definition when -                        // the class is created. -                        clang_type.StartTagDeclarationDefinition (); -                    } - -                    int tag_decl_kind = -1; -                    AccessType default_accessibility = eAccessNone; -                    if (tag == DW_TAG_structure_type) -                    { -                        tag_decl_kind = clang::TTK_Struct; -                        default_accessibility = eAccessPublic; -                    } -                    else if (tag == DW_TAG_union_type) -                    { -                        tag_decl_kind = clang::TTK_Union; -                        default_accessibility = eAccessPublic; -                    } -                    else if (tag == DW_TAG_class_type) -                    { -                        tag_decl_kind = clang::TTK_Class; -                        default_accessibility = eAccessPrivate; -                    } - -                    SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); -                    std::vector<clang::CXXBaseSpecifier *> base_classes; -                    std::vector<int> member_accessibilities; -                    bool is_a_class = false; -                    // Parse members and base classes first -                    DWARFDIECollection member_function_dies; - -                    DelayedPropertyList delayed_properties; -                    ParseChildMembers (sc, -                                       dwarf_cu, -                                       die,  -                                       clang_type, -                                       class_language, -                                       base_classes,  -                                       member_accessibilities, -                                       member_function_dies, -                                       delayed_properties, -                                       default_accessibility,  -                                       is_a_class, -                                       layout_info); - -                    // Now parse any methods if there were any... -                    size_t num_functions = member_function_dies.Size();                 -                    if (num_functions > 0) -                    { -                        for (size_t i=0; i<num_functions; ++i) -                        { -                            ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i)); -                        } -                    } - -                    if (class_language == eLanguageTypeObjC) -                    { -                        ConstString class_name (clang_type.GetTypeName()); -                        if (class_name) -                        { -                            DIEArray method_die_offsets; -                            if (m_using_apple_tables) -                            { -                                if (m_apple_objc_ap.get()) -                                    m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets); -                            } -                            else -                            { -                                if (!m_indexed) -                                    Index (); - -                                m_objc_class_selectors_index.Find (class_name, method_die_offsets); -                            } - -                            if (!method_die_offsets.empty()) -                            { -                                DWARFDebugInfo* debug_info = DebugInfo(); - -                                DWARFCompileUnit* method_cu = NULL; -                                const size_t num_matches = method_die_offsets.size(); -                                for (size_t i=0; i<num_matches; ++i) -                                { -                                    const dw_offset_t die_offset = method_die_offsets[i]; -                                    DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu); - -                                    if (method_die) -                                        ResolveType (method_cu, method_die); -                                    else -                                    { -                                        if (m_using_apple_tables) -                                        { -                                            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n", -                                                                                                       die_offset, class_name.GetCString()); -                                        } -                                    }             -                                } -                            } - -                            for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end(); -                                 pi != pe; -                                 ++pi) -                                pi->Finalize(); -                        } -                    } - -                    // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we -                    // need to tell the clang type it is actually a class. -                    if (class_language != eLanguageTypeObjC) -                    { -                        if (is_a_class && tag_decl_kind != clang::TTK_Class) -                            clang_type.SetTagTypeKind (clang::TTK_Class); -                    } - -                    // Since DW_TAG_structure_type gets used for both classes -                    // and structures, we may need to set any DW_TAG_member -                    // fields to have a "private" access if none was specified. -                    // When we parsed the child members we tracked that actual -                    // accessibility value for each DW_TAG_member in the -                    // "member_accessibilities" array. If the value for the -                    // member is zero, then it was set to the "default_accessibility" -                    // which for structs was "public". Below we correct this -                    // by setting any fields to "private" that weren't correctly -                    // set. -                    if (is_a_class && !member_accessibilities.empty()) -                    { -                        // This is a class and all members that didn't have -                        // their access specified are private. -                        clang_type.SetDefaultAccessForRecordFields (eAccessPrivate, -                                                                    &member_accessibilities.front(), -                                                                    member_accessibilities.size()); -                    } - -                    if (!base_classes.empty()) -                    { -                        // Make sure all base classes refer to complete types and not -                        // forward declarations. If we don't do this, clang will crash -                        // with an assertion in the call to clang_type.SetBaseClassesForClassType() -                        bool base_class_error = false; -                        for (auto &base_class : base_classes) -                        { -                            clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); -                            if (type_source_info) -                            { -                                ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType()); -                                if (base_class_type.GetCompleteType() == false) -                                { -                                    if (!base_class_error) -                                    { -                                        GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", -                                                                                   die->GetOffset(), -                                                                                   die->GetName(this, dwarf_cu), -                                                                                   base_class_type.GetTypeName().GetCString(), -                                                                                   sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); -                                    } -                                    // We have no choice other than to pretend that the base class -                                    // is complete. If we don't do this, clang will crash when we -                                    // call setBases() inside of "clang_type.SetBaseClassesForClassType()" -                                    // below. Since we provide layout assistance, all ivars in this -                                    // class and other classes will be fine, this is the best we can do -                                    // short of crashing. -                                    base_class_type.StartTagDeclarationDefinition (); -                                    base_class_type.CompleteTagDeclarationDefinition (); -                                } -                            } -                        } -                        clang_type.SetBaseClassesForClassType (&base_classes.front(), -                                                               base_classes.size()); - -                        // Clang will copy each CXXBaseSpecifier in "base_classes" -                        // so we have to free them all. -                        ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(), -                                                                 base_classes.size()); -                    } -                } -            } - -            clang_type.BuildIndirectFields (); -            clang_type.CompleteTagDeclarationDefinition (); - -            if (!layout_info.field_offsets.empty() || -                !layout_info.base_offsets.empty()  || -                !layout_info.vbase_offsets.empty() ) -            { -                if (type) -                    layout_info.bit_size = type->GetByteSize() * 8; -                if (layout_info.bit_size == 0) -                    layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8; - -                clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl(); -                if (record_decl) -                { -                    if (log) -                    { -                        GetObjectFile()->GetModule()->LogMessage (log, -                                                                  "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])", -                                                                  static_cast<void*>(clang_type.GetOpaqueQualType()), -                                                                  static_cast<void*>(record_decl), -                                                                  layout_info.bit_size, -                                                                  layout_info.alignment, -                                                                  static_cast<uint32_t>(layout_info.field_offsets.size()), -                                                                  static_cast<uint32_t>(layout_info.base_offsets.size()), -                                                                  static_cast<uint32_t>(layout_info.vbase_offsets.size())); - -                        uint32_t idx; -                        { -                            llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator pos, -                                end = layout_info.field_offsets.end(); -                            for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx) -                        { -                            GetObjectFile()->GetModule()->LogMessage( -                                log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = " -                                     "{ bit_offset=%u, name='%s' }", -                                static_cast<void *>(clang_type.GetOpaqueQualType()), idx, -                                static_cast<uint32_t>(pos->second), pos->first->getNameAsString().c_str()); -                        } -                        } - -                        { -                            llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, -                                base_end = layout_info.base_offsets.end(); -                            for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; -                                 ++base_pos, ++idx) -                            { -                                GetObjectFile()->GetModule()->LogMessage( -                                    log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) base[%u] " -                                         "= { byte_offset=%u, name='%s' }", -                                    clang_type.GetOpaqueQualType(), idx, (uint32_t)base_pos->second.getQuantity(), -                                    base_pos->first->getNameAsString().c_str()); -                            } -                        } -                        { -                            llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos, -                                vbase_end = layout_info.vbase_offsets.end(); -                            for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; -                                 ++vbase_pos, ++idx) -                            { -                                GetObjectFile()->GetModule()->LogMessage( -                                    log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) " -                                         "vbase[%u] = { byte_offset=%u, name='%s' }", -                                    static_cast<void *>(clang_type.GetOpaqueQualType()), idx, -                                    static_cast<uint32_t>(vbase_pos->second.getQuantity()), -                                    vbase_pos->first->getNameAsString().c_str()); -                            } -                        } -                    } -                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); -                } -            } -        } - -        return (bool)clang_type; - -    case DW_TAG_enumeration_type: -        clang_type.StartTagDeclarationDefinition (); -        if (die->HasChildren()) -        { -            SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); -            bool is_signed = false; -            clang_type.IsIntegerType(is_signed); -            ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die); -        } -        clang_type.CompleteTagDeclarationDefinition (); -        return (bool)clang_type; - -    default: -        assert(false && "not a forward clang type decl!"); -        break; -    } +    assert (compiler_type); +    DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); +    if (dwarf_ast) +        return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type);      return false;  }  Type* -SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed) +SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context)  { -    if (type_die != NULL) +    if (die)      { -        Type *type = m_die_to_type.lookup (type_die); +        Type *type = GetDIEToType().lookup (die.GetDIE());          if (type == NULL) -            type = GetTypeForDIE (dwarf_cu, type_die).get(); +            type = GetTypeForDIE (die, resolve_function_context).get();          if (assert_not_being_parsed)          {  @@ -2829,15 +1647,15 @@ SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn                  return type;              GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s", -                                                       type_die->GetOffset(),  -                                                       DW_TAG_value_to_name(type_die->Tag()),  -                                                       type_die->GetName(this, dwarf_cu)); +                                                       die.GetOffset(), +                                                       die.GetTagAsCString(), +                                                       die.GetName());          }          else              return type;      } -    return NULL; +    return nullptr;  }  CompileUnit* @@ -2853,26 +1671,60 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32      return (CompileUnit*)dwarf_cu->GetUserData();  } +size_t +SymbolFileDWARF::GetObjCMethodDIEOffsets (ConstString class_name, DIEArray &method_die_offsets) +{ +    method_die_offsets.clear(); +    if (m_using_apple_tables) +    { +        if (m_apple_objc_ap.get()) +            m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets); +    } +    else +    { +        if (!m_indexed) +            Index (); + +        m_objc_class_selectors_index.Find (class_name, method_die_offsets); +    } +    return method_die_offsets.size(); +} +  bool -SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc) +SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc)  {      sc.Clear(false); -    // Check if the symbol vendor already knows about this compile unit? -    sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); -    sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(func_die->GetOffset())).get(); -    if (sc.function == NULL) -        sc.function = ParseCompileUnitFunction(sc, dwarf_cu, func_die); -         -    if (sc.function) -    {         -        sc.module_sp = sc.function->CalculateSymbolContextModule(); -        return true; +    if (die) +    { +        // Check if the symbol vendor already knows about this compile unit? +        sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); + +        sc.function = sc.comp_unit->FindFunctionByUID (die.GetID()).get(); +        if (sc.function == NULL) +            sc.function = ParseCompileUnitFunction(sc, die); +             +        if (sc.function) +        {         +            sc.module_sp = sc.function->CalculateSymbolContextModule(); +            return true; +        }      }      return false;  } +lldb::ModuleSP +SymbolFileDWARF::GetDWOModule (ConstString name) +{ +    UpdateExternalModuleListIfNeeded(); +    const auto &pos = m_external_type_modules.find(name); +    if (pos != m_external_type_modules.end()) +        return pos->second; +    else +        return lldb::ModuleSP(); +} +  void  SymbolFileDWARF::UpdateExternalModuleListIfNeeded()  { @@ -2881,47 +1733,33 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded()      m_fetched_external_modules = true;      DWARFDebugInfo * debug_info = DebugInfo(); -    debug_info->GetNumCompileUnits(); -     +      const uint32_t num_compile_units = GetNumCompileUnits();      for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)      {          DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); -        const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly(); -        if (die && die->HasChildren() == false) +        const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly(); +        if (die && die.HasChildren() == false)          { -            const uint64_t name_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_name, UINT64_MAX); -            const uint64_t dwo_path_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_GNU_dwo_name, UINT64_MAX); -             -            if (name_strp != UINT64_MAX) +            const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr); + +            if (name)              { -                if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end()) +                ConstString const_name(name); +                if (m_external_type_modules.find(const_name) == m_external_type_modules.end())                  { -                    const char *name = get_debug_str_data().PeekCStr(name_strp); -                    const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp); -                    if (name || dwo_path) +                    ModuleSP module_sp; +                    const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); +                    if (dwo_path)                      { -                        ModuleSP module_sp; -                        if (dwo_path) -                        { -                            ModuleSpec dwo_module_spec; -                            dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); -                            dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); -                            //printf ("Loading dwo = '%s'\n", dwo_path); -                            Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL); -                        } -                         -                        if (dwo_path_strp != LLDB_INVALID_UID) -                        { -                            m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp }; -                        } -                        else -                        { -                            // This hack should be removed promptly once clang emits both. -                            m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp }; -                        } +                        ModuleSpec dwo_module_spec; +                        dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); +                        dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture(); +                        //printf ("Loading dwo = '%s'\n", dwo_path); +                        Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);                      } +                    m_external_type_modules[const_name] = module_sp;                  }              }          } @@ -3025,7 +1863,7 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_              else              {                  uint32_t cu_idx = DW_INVALID_INDEX; -                DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get(); +                DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx);                  if (dwarf_cu)                  {                      sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx); @@ -3036,22 +1874,16 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_                          bool force_check_line_table = false;                          if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))                          { -                            DWARFDebugInfoEntry *function_die = NULL; -                            DWARFDebugInfoEntry *block_die = NULL; -                            if (resolve_scope & eSymbolContextBlock) -                            { -                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, &block_die); -                            } -                            else -                            { -                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, NULL); -                            } - -                            if (function_die != NULL) +                            DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); +                            DWARFDIE block_die; +                            if (function_die)                              { -                                sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get(); +                                sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();                                  if (sc.function == NULL) -                                    sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die); +                                    sc.function = ParseCompileUnitFunction(sc, function_die); + +                                if (sc.function && (resolve_scope & eSymbolContextBlock)) +                                    block_die = function_die.LookupDeepestBlock(file_vm_addr);                              }                              else                              { @@ -3072,10 +1904,10 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_                                  {                                      Block& block = sc.function->GetBlock (true); -                                    if (block_die != NULL) -                                        sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset())); +                                    if (block_die) +                                        sc.block = block.FindBlockByID (block_die.GetID());                                      else -                                        sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset())); +                                        sc.block = block.FindBlockByID (function_die.GetID());                                      if (sc.block)                                          resolved |= eSymbolContextBlock;                                  } @@ -3190,25 +2022,26 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,                                              const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();                                              if (file_vm_addr != LLDB_INVALID_ADDRESS)                                              { -                                                DWARFDebugInfoEntry *function_die = NULL; -                                                DWARFDebugInfoEntry *block_die = NULL; -                                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL); - -                                                if (function_die != NULL) +                                                DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr); +                                                DWARFDIE block_die; +                                                if (function_die)                                                  { -                                                    sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get(); +                                                    sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();                                                      if (sc.function == NULL) -                                                        sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die); +                                                        sc.function = ParseCompileUnitFunction(sc, function_die); + +                                                    if (sc.function && (resolve_scope & eSymbolContextBlock)) +                                                        block_die = function_die.LookupDeepestBlock(file_vm_addr);                                                  }                                                  if (sc.function != NULL)                                                  {                                                      Block& block = sc.function->GetBlock (true); -                                                    if (block_die != NULL) -                                                        sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset())); -                                                    else if (function_die != NULL) -                                                        sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset())); +                                                    if (block_die) +                                                        sc.block = block.FindBlockByID (block_die.GetID()); +                                                    else if (function_die) +                                                        sc.block = block.FindBlockByID (function_die.GetID());                                                  }                                              }                                          } @@ -3255,38 +2088,77 @@ SymbolFileDWARF::Index ()      DWARFDebugInfo* debug_info = DebugInfo();      if (debug_info)      { -        uint32_t cu_idx = 0;          const uint32_t num_compile_units = GetNumCompileUnits(); -        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) +        std::vector<NameToDIE> function_basename_index(num_compile_units); +        std::vector<NameToDIE> function_fullname_index(num_compile_units); +        std::vector<NameToDIE> function_method_index(num_compile_units); +        std::vector<NameToDIE> function_selector_index(num_compile_units); +        std::vector<NameToDIE> objc_class_selectors_index(num_compile_units); +        std::vector<NameToDIE> global_index(num_compile_units); +        std::vector<NameToDIE> type_index(num_compile_units); +        std::vector<NameToDIE> namespace_index(num_compile_units); +         +        auto parser_fn = [this, +                          debug_info, +                          &function_basename_index, +                          &function_fullname_index, +                          &function_method_index, +                          &function_selector_index, +                          &objc_class_selectors_index, +                          &global_index, +                          &type_index, +                          &namespace_index](uint32_t cu_idx)          {              DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); +            bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1; + +            dwarf_cu->Index(function_basename_index[cu_idx], +                            function_fullname_index[cu_idx], +                            function_method_index[cu_idx], +                            function_selector_index[cu_idx], +                            objc_class_selectors_index[cu_idx], +                            global_index[cu_idx], +                            type_index[cu_idx], +                            namespace_index[cu_idx]); -            bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1; - -            dwarf_cu->Index (cu_idx, -                             m_function_basename_index, -                             m_function_fullname_index, -                             m_function_method_index, -                             m_function_selector_index, -                             m_objc_class_selectors_index, -                             m_global_index,  -                             m_type_index, -                             m_namespace_index); -                          // Keep memory down by clearing DIEs if this generate function              // caused them to be parsed              if (clear_dies) -                dwarf_cu->ClearDIEs (true); +                dwarf_cu->ClearDIEs(true); + +            return cu_idx; +        }; + +        TaskRunner<uint32_t> task_runner; +        for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) +            task_runner.AddTask(parser_fn, cu_idx); + +        while (true) +        { +            std::future<uint32_t> f = task_runner.WaitForNextCompletedTask(); +            if (!f.valid()) +                break; +            uint32_t cu_idx = f.get(); + +            m_function_basename_index.Append(function_basename_index[cu_idx]); +            m_function_fullname_index.Append(function_fullname_index[cu_idx]); +            m_function_method_index.Append(function_method_index[cu_idx]); +            m_function_selector_index.Append(function_selector_index[cu_idx]); +            m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]); +            m_global_index.Append(global_index[cu_idx]); +            m_type_index.Append(type_index[cu_idx]); +            m_namespace_index.Append(namespace_index[cu_idx]);          } -         -        m_function_basename_index.Finalize(); -        m_function_fullname_index.Finalize(); -        m_function_method_index.Finalize(); -        m_function_selector_index.Finalize(); -        m_objc_class_selectors_index.Finalize(); -        m_global_index.Finalize();  -        m_type_index.Finalize(); -        m_namespace_index.Finalize(); + +        TaskPool::RunTasks( +            [&]() { m_function_basename_index.Finalize(); }, +            [&]() { m_function_fullname_index.Finalize(); }, +            [&]() { m_function_method_index.Finalize(); }, +            [&]() { m_function_selector_index.Finalize(); }, +            [&]() { m_objc_class_selectors_index.Finalize(); }, +            [&]() { m_global_index.Finalize(); }, +            [&]() { m_type_index.Finalize(); }, +            [&]() { m_namespace_index.Finalize(); });  #if defined (ENABLE_DEBUG_PRINTF)          StreamFile s(stdout, false); @@ -3299,30 +2171,26 @@ SymbolFileDWARF::Index ()          s.Printf("\nObjective C class selectors:\n");    m_objc_class_selectors_index.Dump (&s);          s.Printf("\nGlobals and statics:\n");   m_global_index.Dump (&s);           s.Printf("\nTypes:\n");                 m_type_index.Dump (&s); -        s.Printf("\nNamepaces:\n");             m_namespace_index.Dump (&s); +        s.Printf("\nNamespaces:\n")             m_namespace_index.Dump (&s);  #endif      }  }  bool -SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *namespace_decl) +SymbolFileDWARF::DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx)  { -    if (namespace_decl == NULL) +    if (decl_ctx == nullptr || !decl_ctx->IsValid())      {          // Invalid namespace decl which means we aren't matching only things          // in this symbol file, so return true to indicate it matches this          // symbol file.          return true;      } -     -    clang::ASTContext *namespace_ast = namespace_decl->GetASTContext(); - -    if (namespace_ast == NULL) -        return true;    // No AST in the "namespace_decl", return true since it  -                        // could then match any symbol file, including this one -    if (namespace_ast == GetClangASTContext().getASTContext()) -        return true;    // The ASTs match, return true +    TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); +    TypeSystem *type_system = GetTypeSystemForLanguage(decl_ctx_type_system->GetMinimumLanguage(nullptr)); +    if (decl_ctx_type_system == type_system) +        return true;    // The type systems match, return true      // The namespace AST was valid, and it does not match...      Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -3333,66 +2201,19 @@ SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *n      return false;  } -bool -SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl,  -                                   DWARFCompileUnit* cu,  -                                   const DWARFDebugInfoEntry* die) -{ -    // No namespace specified, so the answer is -    if (namespace_decl == NULL) -        return true; -     -    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); - -    const DWARFDebugInfoEntry *decl_ctx_die = NULL; -    clang::DeclContext *die_clang_decl_ctx = GetClangDeclContextContainingDIE (cu, die, &decl_ctx_die); -    if (decl_ctx_die) -    {  -        clang::NamespaceDecl *clang_namespace_decl = namespace_decl->GetNamespaceDecl(); - -        if (clang_namespace_decl) -        { -            if (decl_ctx_die->Tag() != DW_TAG_namespace) -            { -                if (log) -                    GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent is not a namespace"); -                return false; -            } -                 -            if (clang_namespace_decl == die_clang_decl_ctx) -                return true; -            else -                return false; -        } -        else -        { -            // We have a namespace_decl that was not NULL but it contained -            // a NULL "clang::NamespaceDecl", so this means the global namespace -            // So as long the contained decl context DIE isn't a namespace -            // we should be ok. -            if (decl_ctx_die->Tag() != DW_TAG_namespace) -                return true; -        } -    } -     -    if (log) -        GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent doesn't exist"); -     -    return false; -}  uint32_t -SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) +SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables)  {      Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));      if (log)          GetObjectFile()->GetModule()->LogMessage (log, -                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)",  +                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",                                                    name.GetCString(),  -                                                  static_cast<const void*>(namespace_decl), +                                                  static_cast<const void*>(parent_decl_ctx),                                                    append, max_matches); -    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) +    if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))          return 0;      DWARFDebugInfo* info = DebugInfo(); @@ -3417,7 +2238,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat              llvm::StringRef basename;              llvm::StringRef context; -            if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename)) +            if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, basename))                  basename = name_cstr;              m_apple_names_ap->FindByName (basename.data(), die_offsets); @@ -3440,17 +2261,15 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat          assert (sc.module_sp);          DWARFDebugInfo* debug_info = DebugInfo(); -        DWARFCompileUnit* dwarf_cu = NULL; -        const DWARFDebugInfoEntry* die = NULL;          bool done = false;          for (size_t i=0; i<num_die_matches && !done; ++i)          { -            const dw_offset_t die_offset = die_offsets[i]; -            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +            const DIERef& die_ref = die_offsets[i]; +            DWARFDIE die = debug_info->GetDIE (die_ref);              if (die)              { -                switch (die->Tag()) +                switch (die.Tag())                  {                      default:                      case DW_TAG_subprogram: @@ -3461,12 +2280,20 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat                      case DW_TAG_variable:                          { -                            sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); +                            sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); -                            if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) -                                continue; +                            if (parent_decl_ctx) +                            { +                                DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +                                if (dwarf_ast) +                                { +                                    CompilerDeclContext actual_parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); +                                    if (!actual_parent_decl_ctx || actual_parent_decl_ctx != *parent_decl_ctx) +                                        continue; +                                } +                            } -                            ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables); +                            ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);                              if (variables.GetSize() - original_size >= max_matches)                                  done = true; @@ -3479,7 +2306,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat                  if (m_using_apple_tables)                  {                      GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n", -                                                                               die_offset, name.GetCString()); +                                                                               die_ref.die_offset, name.GetCString());                  }              }          } @@ -3490,9 +2317,9 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat      if (log && num_matches > 0)      {          GetObjectFile()->GetModule()->LogMessage (log, -                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u", +                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u",                                                    name.GetCString(), -                                                  static_cast<const void*>(namespace_decl), +                                                  static_cast<const void*>(parent_decl_ctx),                                                    append, max_matches,                                                    num_matches);      } @@ -3525,7 +2352,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append      const uint32_t original_size = variables.GetSize();      DIEArray die_offsets; -     +      if (m_using_apple_tables)      {          if (m_apple_names_ap.get()) @@ -3548,22 +2375,20 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append      sc.module_sp = m_obj_file->GetModule();      assert (sc.module_sp); -    DWARFCompileUnit* dwarf_cu = NULL; -    const DWARFDebugInfoEntry* die = NULL;      const size_t num_matches = die_offsets.size();      if (num_matches)      {          DWARFDebugInfo* debug_info = DebugInfo();          for (size_t i=0; i<num_matches; ++i)          { -            const dw_offset_t die_offset = die_offsets[i]; -            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +            const DIERef& die_ref = die_offsets[i]; +            DWARFDIE die = debug_info->GetDIE (die_ref);              if (die)              { -                sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); +                sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX); -                ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables); +                ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);                  if (variables.GetSize() - original_size >= max_matches)                      break; @@ -3573,7 +2398,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append                  if (m_using_apple_tables)                  {                      GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n", -                                                                               die_offset, regex.GetText()); +                                                                               die_ref.die_offset, regex.GetText());                  }              }                      } @@ -3585,53 +2410,59 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append  bool -SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset, -                                  DWARFCompileUnit *&dwarf_cu, +SymbolFileDWARF::ResolveFunction (const DIERef& die_ref,                                    bool include_inlines,                                    SymbolContextList& sc_list)  { -    const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); -    return ResolveFunction (dwarf_cu, die, include_inlines, sc_list); +    DWARFDIE die = DebugInfo()->GetDIE (die_ref); +    return ResolveFunction (die, include_inlines, sc_list);  }  bool -SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu, -                                  const DWARFDebugInfoEntry *die, +SymbolFileDWARF::ResolveFunction (const DWARFDIE &orig_die,                                    bool include_inlines,                                    SymbolContextList& sc_list)  {      SymbolContext sc; -    if (die == NULL) +    if (!orig_die)          return false;      // If we were passed a die that is not a function, just return false... -    if (! (die->Tag() == DW_TAG_subprogram || (include_inlines && die->Tag() == DW_TAG_inlined_subroutine))) +    if (!(orig_die.Tag() == DW_TAG_subprogram || (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine)))          return false; -     -    const DWARFDebugInfoEntry* inlined_die = NULL; -    if (die->Tag() == DW_TAG_inlined_subroutine) + +    DWARFDIE die = orig_die; +    DWARFDIE inlined_die; +    if (die.Tag() == DW_TAG_inlined_subroutine)      {          inlined_die = die; -        while ((die = die->GetParent()) != NULL) +        while (1)          { -            if (die->Tag() == DW_TAG_subprogram) +            die = die.GetParent(); + +            if (die) +            { +                if (die.Tag() == DW_TAG_subprogram) +                    break; +            } +            else                  break;          }      } -    assert (die && die->Tag() == DW_TAG_subprogram); -    if (GetFunction (cu, die, sc)) +    assert (die && die.Tag() == DW_TAG_subprogram); +    if (GetFunction (die, sc))      {          Address addr;          // Parse all blocks if needed          if (inlined_die)          {              Block &function_block = sc.function->GetBlock (true); -            sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset())); +            sc.block = function_block.FindBlockByID (inlined_die.GetID());              if (sc.block == NULL) -                sc.block = function_block.FindBlockByID (inlined_die->GetOffset()); +                sc.block = function_block.FindBlockByID (inlined_die.GetOffset());              if (sc.block == NULL || sc.block->GetStartAddress (addr) == false)                  addr.Clear();          } @@ -3702,131 +2533,37 @@ SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,      const size_t num_matches = die_offsets.size();      if (num_matches)      { -        DWARFCompileUnit* dwarf_cu = NULL;          for (size_t i=0; i<num_matches; ++i) -        { -            const dw_offset_t die_offset = die_offsets[i]; -            ResolveFunction (die_offset, dwarf_cu, include_inlines, sc_list); -        } +            ResolveFunction (die_offsets[i], include_inlines, sc_list);      }  }  bool -SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die, -                                                const DWARFCompileUnit *dwarf_cu, -                                                uint32_t name_type_mask,  -                                                const char *partial_name, -                                                const char *base_name_start, -                                                const char *base_name_end) +SymbolFileDWARF::DIEInDeclContext (const CompilerDeclContext *decl_ctx, +                                   const DWARFDIE &die)  { -    // If we are looking only for methods, throw away all the ones that are or aren't in C++ classes: -    if (name_type_mask == eFunctionNameTypeMethod || name_type_mask == eFunctionNameTypeBase) -    { -        clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset()); -        if (!containing_decl_ctx) -            return false; -         -        bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()); -         -        if (name_type_mask == eFunctionNameTypeMethod) -        { -            if (is_cxx_method == false) -                return false; -        } -         -        if (name_type_mask == eFunctionNameTypeBase) -        { -            if (is_cxx_method == true) -                return false; -        } -    } +    // If we have no parent decl context to match this DIE matches, and if the parent +    // decl context isn't valid, we aren't trying to look for any particular decl +    // context so any die matches. +    if (decl_ctx == nullptr || !decl_ctx->IsValid()) +        return true; -    // Now we need to check whether the name we got back for this type matches the extra specifications -    // that were in the name we're looking up: -    if (base_name_start != partial_name || *base_name_end != '\0') +    if (die)      { -        // First see if the stuff to the left matches the full name.  To do that let's see if -        // we can pull out the mips linkage name attribute: -         -        Mangled best_name; -        DWARFDebugInfoEntry::Attributes attributes; -        DWARFFormValue form_value; -        die->GetAttributes(this, dwarf_cu, NULL, attributes); -        uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name); -        if (idx == UINT32_MAX) -            idx = attributes.FindAttributeIndex(DW_AT_linkage_name); -        if (idx != UINT32_MAX) +        DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +        if (dwarf_ast)          { -            if (attributes.ExtractFormValueAtIndex(this, idx, form_value)) -            { -                const char *mangled_name = form_value.AsCString(&get_debug_str_data()); -                if (mangled_name) -                    best_name.SetValue (ConstString(mangled_name), true); -            } -        } - -        if (!best_name) -        { -            idx = attributes.FindAttributeIndex(DW_AT_name); -            if (idx != UINT32_MAX && attributes.ExtractFormValueAtIndex(this, idx, form_value)) -            { -                const char *name = form_value.AsCString(&get_debug_str_data()); -                best_name.SetValue (ConstString(name), false); -            } -        } - -        const LanguageType cu_language = const_cast<DWARFCompileUnit *>(dwarf_cu)->GetLanguageType(); -        if (best_name.GetDemangledName(cu_language)) -        { -            const char *demangled = best_name.GetDemangledName(cu_language).GetCString(); -            if (demangled) -            { -                std::string name_no_parens(partial_name, base_name_end - partial_name); -                const char *partial_in_demangled = strstr (demangled, name_no_parens.c_str()); -                if (partial_in_demangled == NULL) -                    return false; -                else -                { -                    // Sort out the case where our name is something like "Process::Destroy" and the match is -                    // "SBProcess::Destroy" - that shouldn't be a match.  We should really always match on -                    // namespace boundaries... -                     -                    if (partial_name[0] == ':'  && partial_name[1] == ':') -                    { -                        // The partial name was already on a namespace boundary so all matches are good. -                        return true; -                    } -                    else if (partial_in_demangled == demangled) -                    { -                        // They both start the same, so this is an good match. -                        return true; -                    } -                    else -                    { -                        if (partial_in_demangled - demangled == 1) -                        { -                            // Only one character difference, can't be a namespace boundary... -                            return false; -                        } -                        else if (*(partial_in_demangled - 1) == ':' && *(partial_in_demangled - 2) == ':') -                        { -                            // We are on a namespace boundary, so this is also good. -                            return true; -                        } -                        else -                            return false; -                    } -                } -            } +            CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die); +            if (actual_decl_ctx) +                return actual_decl_ctx == *decl_ctx;          }      } -     -    return true; +    return false;  }  uint32_t -SymbolFileDWARF::FindFunctions (const ConstString &name,  -                                const lldb_private::ClangNamespaceDecl *namespace_decl,  +SymbolFileDWARF::FindFunctions (const ConstString &name, +                                const CompilerDeclContext *parent_decl_ctx,                                  uint32_t name_type_mask,                                  bool include_inlines,                                  bool append,  @@ -3854,7 +2591,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,      if (!append)          sc_list.Clear(); -    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) +    if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))          return 0;      // If name is empty then we won't find anything. @@ -3872,7 +2609,6 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,      if (info == NULL)          return 0; -    DWARFCompileUnit *dwarf_cu = NULL;      std::set<const DWARFDebugInfoEntry *> resolved_dies;      if (m_using_apple_tables)      { @@ -3891,30 +2627,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,                  num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);                  for (uint32_t i = 0; i < num_matches; i++)                  { -                    const dw_offset_t die_offset = die_offsets[i]; -                    const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +                    const DIERef& die_ref = die_offsets[i]; +                    DWARFDIE die = info->GetDIE (die_ref);                      if (die)                      { -                        if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) -                            continue; -                         -                        if (resolved_dies.find(die) == resolved_dies.end()) +                        if (!DIEInDeclContext(parent_decl_ctx, die)) +                            continue; // The containing decl contexts don't match + +                        if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())                          { -                            if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) -                                resolved_dies.insert(die); +                            if (ResolveFunction (die, include_inlines, sc_list)) +                                resolved_dies.insert(die.GetDIE());                          }                      }                      else                      {                          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",  -                                                                                   die_offset, name_cstr); +                                                                                   die_ref.die_offset, name_cstr);                      }                                                      }              }              if (name_type_mask & eFunctionNameTypeSelector)              { -                if (namespace_decl && *namespace_decl) +                if (parent_decl_ctx && parent_decl_ctx->IsValid())                      return 0; // no selectors in namespaces                  num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets); @@ -3923,30 +2659,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,                  for (uint32_t i = 0; i < num_matches; i++)                  { -                    const dw_offset_t die_offset = die_offsets[i]; -                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +                    const DIERef& die_ref = die_offsets[i]; +                    DWARFDIE die = info->GetDIE (die_ref);                      if (die)                      { -                        const char *die_name = die->GetName(this, dwarf_cu); -                        if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name)) +                        const char *die_name = die.GetName(); +                        if (ObjCLanguage::IsPossibleObjCMethodName(die_name))                          { -                            if (resolved_dies.find(die) == resolved_dies.end()) +                            if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())                              { -                                if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) -                                    resolved_dies.insert(die); +                                if (ResolveFunction (die, include_inlines, sc_list)) +                                    resolved_dies.insert(die.GetDIE());                              }                          }                      }                      else                      {                          GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", -                                                                   die_offset, name_cstr); +                                                                   die_ref.die_offset, name_cstr);                      }                                                      }                  die_offsets.clear();              } -            if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase) +            if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || name_type_mask & eFunctionNameTypeBase)              {                  // The apple_names table stores just the "base name" of C++ methods in the table.  So we have to                  // extract the base name, look that up, and if there is any other information in the name we were @@ -3957,16 +2693,16 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,                  for (uint32_t i = 0; i < num_matches; i++)                  { -                    const dw_offset_t die_offset = die_offsets[i]; -                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +                    const DIERef& die_ref = die_offsets[i]; +                    DWARFDIE die = info->GetDIE (die_ref);                      if (die)                      { -                        if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) -                            continue; +                        if (!DIEInDeclContext(parent_decl_ctx, die)) +                            continue; // The containing decl contexts don't match +                          // If we get to here, the die is good, and we should add it: -                        if (resolved_dies.find(die) == resolved_dies.end()) -                        if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) +                        if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && ResolveFunction (die, include_inlines, sc_list))                          {                              bool keep_die = true;                              if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod)) @@ -3986,8 +2722,8 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,                                          if (type)                                          { -                                            clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID()); -                                            if (decl_ctx->isRecord()) +                                            CompilerDeclContext decl_ctx = GetDeclContextContainingUID (type->GetID()); +                                            if (decl_ctx.IsStructUnionOrClass())                                              {                                                  if (name_type_mask & eFunctionNameTypeBase)                                                  { @@ -4007,19 +2743,19 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,                                          else                                          {                                              GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type", -                                                                                         die_offset); +                                                                                         die_ref.die_offset);                                          }                                      }                                  }                              }                              if (keep_die) -                                resolved_dies.insert(die); +                                resolved_dies.insert(die.GetDIE());                          }                      }                      else                      {                          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", -                                                                                   die_offset, name_cstr); +                                                                                   die_ref.die_offset, name_cstr);                      }                                                      }                  die_offsets.clear(); @@ -4046,10 +2782,10 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,              // TODO: The arch in the object file isn't correct for MSVC              // binaries on windows, we should find a way to make it              // correct and handle those symbols as well. -            if (sc_list.GetSize() == 0) +            if (sc_list.GetSize() == original_size)              {                  ArchSpec arch; -                if (!namespace_decl && +                if (!parent_decl_ctx &&                      GetObjectFile()->GetArchitecture(arch) &&                      (arch.GetTriple().isOSFreeBSD() || arch.GetTriple().isOSLinux() ||                       arch.GetMachine() == llvm::Triple::hexagon)) @@ -4076,24 +2812,22 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,              }          }          DIEArray die_offsets; -        DWARFCompileUnit *dwarf_cu = NULL; -                  if (name_type_mask & eFunctionNameTypeBase)          {              uint32_t num_base = m_function_basename_index.Find(name, die_offsets);              for (uint32_t i = 0; i < num_base; i++)              { -                const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu); +                DWARFDIE die = info->GetDIE (die_offsets[i]);                  if (die)                  { -                    if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) -                        continue; -                     +                    if (!DIEInDeclContext(parent_decl_ctx, die)) +                        continue; // The containing decl contexts don't match +                      // If we get to here, the die is good, and we should add it: -                    if (resolved_dies.find(die) == resolved_dies.end()) +                    if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())                      { -                        if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) -                            resolved_dies.insert(die); +                        if (ResolveFunction (die, include_inlines, sc_list)) +                            resolved_dies.insert(die.GetDIE());                      }                  }              } @@ -4102,21 +2836,21 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,          if (name_type_mask & eFunctionNameTypeMethod)          { -            if (namespace_decl && *namespace_decl) +            if (parent_decl_ctx && parent_decl_ctx->IsValid())                  return 0; // no methods in namespaces              uint32_t num_base = m_function_method_index.Find(name, die_offsets);              {                  for (uint32_t i = 0; i < num_base; i++)                  { -                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu); +                    DWARFDIE die = info->GetDIE (die_offsets[i]);                      if (die)                      {                          // If we get to here, the die is good, and we should add it: -                        if (resolved_dies.find(die) == resolved_dies.end()) +                        if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())                          { -                            if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list)) -                                resolved_dies.insert(die); +                            if (ResolveFunction (die, include_inlines, sc_list)) +                                resolved_dies.insert(die.GetDIE());                          }                      }                  } @@ -4124,7 +2858,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,              die_offsets.clear();          } -        if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl)) +        if ((name_type_mask & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid()))          {              FindFunctions (name, m_function_selector_index, include_inlines, sc_list);          } @@ -4196,10 +2930,10 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inli  uint32_t  SymbolFileDWARF::FindTypes (const SymbolContext& sc,                               const ConstString &name,  -                            const lldb_private::ClangNamespaceDecl *namespace_decl,  +                            const CompilerDeclContext *parent_decl_ctx,                               bool append,                               uint32_t max_matches,  -                            TypeList& types) +                            TypeMap& types)  {      DWARFDebugInfo* info = DebugInfo();      if (info == NULL) @@ -4209,16 +2943,16 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,      if (log)      { -        if (namespace_decl) +        if (parent_decl_ctx)              GetObjectFile()->GetModule()->LogMessage (log, -                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)",  +                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list)",                                                        name.GetCString(), -                                                      static_cast<void*>(namespace_decl->GetNamespaceDecl()), -                                                      namespace_decl->GetQualifiedName().c_str(), +                                                      static_cast<const void*>(parent_decl_ctx), +                                                      parent_decl_ctx->GetName().AsCString("<NULL>"),                                                        append, max_matches);          else              GetObjectFile()->GetModule()->LogMessage (log, -                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)", +                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list)",                                                        name.GetCString(), append,                                                        max_matches);      } @@ -4227,7 +2961,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,      if (!append)          types.Clear(); -    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) +    if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))          return 0;      DIEArray die_offsets; @@ -4253,20 +2987,18 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,      if (num_die_matches)      {          const uint32_t initial_types_size = types.GetSize(); -        DWARFCompileUnit* dwarf_cu = NULL; -        const DWARFDebugInfoEntry* die = NULL;          DWARFDebugInfo* debug_info = DebugInfo();          for (size_t i=0; i<num_die_matches; ++i)          { -            const dw_offset_t die_offset = die_offsets[i]; -            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); +            const DIERef& die_ref = die_offsets[i]; +            DWARFDIE die = debug_info->GetDIE (die_ref);              if (die)              { -                if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die)) -                    continue; +                if (!DIEInDeclContext(parent_decl_ctx, die)) +                    continue; // The containing decl contexts don't match -                Type *matching_type = ResolveType (dwarf_cu, die); +                Type *matching_type = ResolveType (die, true, true);                  if (matching_type)                  {                      // We found a type pointer, now find the shared pointer form our type list @@ -4280,7 +3012,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,                  if (m_using_apple_tables)                  {                      GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", -                                                                               die_offset, name.GetCString()); +                                                                               die_ref.die_offset, name.GetCString());                  }              }             @@ -4288,20 +3020,20 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,          const uint32_t num_matches = types.GetSize() - initial_types_size;          if (log && num_matches)          { -            if (namespace_decl) +            if (parent_decl_ctx)              {                  GetObjectFile()->GetModule()->LogMessage (log, -                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u",  +                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",                                                            name.GetCString(), -                                                          static_cast<void*>(namespace_decl->GetNamespaceDecl()), -                                                          namespace_decl->GetQualifiedName().c_str(), +                                                          static_cast<const void*>(parent_decl_ctx), +                                                          parent_decl_ctx->GetName().AsCString("<NULL>"),                                                            append, max_matches,                                                            num_matches);              }              else              {                  GetObjectFile()->GetModule()->LogMessage (log, -                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u", +                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list) => %u",                                                            name.GetCString(),                                                             append, max_matches,                                                            num_matches); @@ -4309,14 +3041,112 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,          }          return num_matches;      } +    else +    { +        UpdateExternalModuleListIfNeeded(); + +        for (const auto &pair : m_external_type_modules) +        { +            ModuleSP external_module_sp = pair.second; +            if (external_module_sp) +            { +                SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor(); +                if (sym_vendor) +                { +                    const uint32_t num_external_matches = sym_vendor->FindTypes (sc, +                                                                                 name, +                                                                                 parent_decl_ctx, +                                                                                 append, +                                                                                 max_matches, +                                                                                 types); +                    if (num_external_matches) +                        return num_external_matches; +                } +            } +        } +    } + +    return 0; +} + + +size_t +SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context, +                            bool append, +                            TypeMap& types) +{ +    if (!append) +        types.Clear(); + +    if (context.empty()) +        return 0; + +    DIEArray die_offsets; + +    ConstString name = context.back().name; + +    if (m_using_apple_tables) +    { +        if (m_apple_types_ap.get()) +        { +            const char *name_cstr = name.GetCString(); +            m_apple_types_ap->FindByName (name_cstr, die_offsets); +        } +    } +    else +    { +        if (!m_indexed) +            Index (); + +        m_type_index.Find (name, die_offsets); +    } + +    const size_t num_die_matches = die_offsets.size(); + +    if (num_die_matches) +    { +        size_t num_matches = 0; +        DWARFDebugInfo* debug_info = DebugInfo(); +        for (size_t i=0; i<num_die_matches; ++i) +        { +            const DIERef& die_ref = die_offsets[i]; +            DWARFDIE die = debug_info->GetDIE (die_ref); + +            if (die) +            { +                std::vector<CompilerContext> die_context; +                die.GetDWOContext(die_context); +                if (die_context != context) +                    continue; + +                Type *matching_type = ResolveType (die, true, true); +                if (matching_type) +                { +                    // We found a type pointer, now find the shared pointer form our type list +                    types.InsertUnique (matching_type->shared_from_this()); +                    ++num_matches; +                } +            } +            else +            { +                if (m_using_apple_tables) +                { +                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", +                                                                               die_ref.die_offset, name.GetCString()); +                } +            } + +        } +        return num_matches; +    }      return 0;  } -ClangNamespaceDecl +CompilerDeclContext  SymbolFileDWARF::FindNamespace (const SymbolContext& sc,                                   const ConstString &name, -                                const lldb_private::ClangNamespaceDecl *parent_namespace_decl) +                                const CompilerDeclContext *parent_decl_ctx)  {      Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); @@ -4326,11 +3156,13 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,                                                    "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")",                                                     name.GetCString());      } -     -    if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl)) -        return ClangNamespaceDecl(); -    ClangNamespaceDecl namespace_decl; +    CompilerDeclContext namespace_decl_ctx; + +    if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) +        return namespace_decl_ctx; + +      DWARFDebugInfo* info = DebugInfo();      if (info)      { @@ -4354,28 +3186,26 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,              m_namespace_index.Find (name, die_offsets);          } -        DWARFCompileUnit* dwarf_cu = NULL; -        const DWARFDebugInfoEntry* die = NULL;          const size_t num_matches = die_offsets.size();          if (num_matches)          {              DWARFDebugInfo* debug_info = DebugInfo();              for (size_t i=0; i<num_matches; ++i)              { -                const dw_offset_t die_offset = die_offsets[i]; -                die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); -                 +                const DIERef& die_ref = die_offsets[i]; +                DWARFDIE die = debug_info->GetDIE (die_ref); +                  if (die)                  { -                    if (parent_namespace_decl && !DIEIsInNamespace (parent_namespace_decl, dwarf_cu, die)) -                        continue; +                    if (!DIEInDeclContext (parent_decl_ctx, die)) +                        continue; // The containing decl contexts don't match -                    clang::NamespaceDecl *clang_namespace_decl = ResolveNamespaceDIE (dwarf_cu, die); -                    if (clang_namespace_decl) +                    DWARFASTParser *dwarf_ast = die.GetDWARFParser(); +                    if (dwarf_ast)                      { -                        namespace_decl.SetASTContext (GetClangASTContext().getASTContext()); -                        namespace_decl.SetNamespaceDecl (clang_namespace_decl); -                        break; +                        namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF (die); +                        if (namespace_decl_ctx) +                            break;                      }                  }                  else @@ -4383,421 +3213,50 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,                      if (m_using_apple_tables)                      {                          GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n", -                                                                   die_offset, name.GetCString()); +                                                                   die_ref.die_offset, name.GetCString());                      }                  }                          }          }      } -    if (log && namespace_decl.GetNamespaceDecl()) +    if (log && namespace_decl_ctx)      {          GetObjectFile()->GetModule()->LogMessage (log, -                                                  "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"", +                                                  "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => CompilerDeclContext(%p/%p) \"%s\"",                                                    name.GetCString(), -                                                  static_cast<const void*>(namespace_decl.GetNamespaceDecl()), -                                                  namespace_decl.GetQualifiedName().c_str()); -    } - -    return namespace_decl; -} - -uint32_t -SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types) -{ -    // Remember how many sc_list are in the list before we search in case -    // we are appending the results to a variable list. -    uint32_t original_size = types.GetSize(); - -    const uint32_t num_die_offsets = die_offsets.size(); -    // Parse all of the types we found from the pubtypes matches -    uint32_t i; -    uint32_t num_matches = 0; -    for (i = 0; i < num_die_offsets; ++i) -    { -        Type *matching_type = ResolveTypeUID (die_offsets[i]); -        if (matching_type) -        { -            // We found a type pointer, now find the shared pointer form our type list -            types.InsertUnique (matching_type->shared_from_this()); -            ++num_matches; -            if (num_matches >= max_matches) -                break; -        } -    } - -    // Return the number of variable that were appended to the list -    return types.GetSize() - original_size; -} - - -size_t -SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, -                                       clang::DeclContext *containing_decl_ctx, -                                       DWARFCompileUnit* dwarf_cu, -                                       const DWARFDebugInfoEntry *parent_die, -                                       bool skip_artificial, -                                       bool &is_static, -                                       bool &is_variadic, -                                       std::vector<ClangASTType>& function_param_types, -                                       std::vector<clang::ParmVarDecl*>& function_param_decls, -                                       unsigned &type_quals) // , -                                       // ClangASTContext::TemplateParameterInfos &template_param_infos)) -{ -    if (parent_die == NULL) -        return 0; - -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - -    size_t arg_idx = 0; -    const DWARFDebugInfoEntry *die; -    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) -    { -        dw_tag_t tag = die->Tag(); -        switch (tag) -        { -        case DW_TAG_formal_parameter: -            { -                DWARFDebugInfoEntry::Attributes attributes; -                const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); -                if (num_attributes > 0) -                { -                    const char *name = NULL; -                    Declaration decl; -                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET; -                    bool is_artificial = false; -                    // one of None, Auto, Register, Extern, Static, PrivateExtern - -                    clang::StorageClass storage = clang::SC_None; -                    uint32_t i; -                    for (i=0; i<num_attributes; ++i) -                    { -                        const dw_attr_t attr = attributes.AttributeAtIndex(i); -                        DWARFFormValue form_value; -                        if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                        { -                            switch (attr) -                            { -                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break; -                            case DW_AT_type:        param_type_die_offset = form_value.Reference(); break; -                            case DW_AT_artificial:  is_artificial = form_value.Boolean(); break; -                            case DW_AT_location: -    //                          if (form_value.BlockData()) -    //                          { -    //                              const DWARFDataExtractor& debug_info_data = debug_info(); -    //                              uint32_t block_length = form_value.Unsigned(); -    //                              DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length); -    //                          } -    //                          else -    //                          { -    //                          } -    //                          break; -                            case DW_AT_const_value: -                            case DW_AT_default_value: -                            case DW_AT_description: -                            case DW_AT_endianity: -                            case DW_AT_is_optional: -                            case DW_AT_segment: -                            case DW_AT_variable_parameter: -                            default: -                            case DW_AT_abstract_origin: -                            case DW_AT_sibling: -                                break; -                            } -                        } -                    } - -                    bool skip = false; -                    if (skip_artificial) -                    { -                        if (is_artificial) -                        { -                            // In order to determine if a C++ member function is -                            // "const" we have to look at the const-ness of "this"... -                            // Ugly, but that -                            if (arg_idx == 0) -                            { -                                if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) -                                {                                     -                                    // Often times compilers omit the "this" name for the -                                    // specification DIEs, so we can't rely upon the name -                                    // being in the formal parameter DIE... -                                    if (name == NULL || ::strcmp(name, "this")==0) -                                    { -                                        Type *this_type = ResolveTypeUID (param_type_die_offset); -                                        if (this_type) -                                        {                               -                                            uint32_t encoding_mask = this_type->GetEncodingMask(); -                                            if (encoding_mask & Type::eEncodingIsPointerUID) -                                            { -                                                is_static = false; -                                                 -                                                if (encoding_mask & (1u << Type::eEncodingIsConstUID)) -                                                    type_quals |= clang::Qualifiers::Const; -                                                if (encoding_mask & (1u << Type::eEncodingIsVolatileUID)) -                                                    type_quals |= clang::Qualifiers::Volatile; -                                            } -                                        } -                                    } -                                } -                            } -                            skip = true; -                        } -                        else -                        { - -                            // HACK: Objective C formal parameters "self" and "_cmd"  -                            // are not marked as artificial in the DWARF... -                            CompileUnit *comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX); -                            if (comp_unit) -                            { -                                switch (comp_unit->GetLanguage()) -                                { -                                    case eLanguageTypeObjC: -                                    case eLanguageTypeObjC_plus_plus: -                                        if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0)) -                                            skip = true; -                                        break; -                                    default: -                                        break; -                                } -                            } -                        } -                    } - -                    if (!skip) -                    { -                        Type *type = ResolveTypeUID(param_type_die_offset); -                        if (type) -                        { -                            function_param_types.push_back (type->GetClangForwardType()); - -                            clang::ParmVarDecl *param_var_decl = GetClangASTContext().CreateParameterDeclaration (name,  -                                                                                                                  type->GetClangForwardType(),  -                                                                                                                  storage); -                            assert(param_var_decl); -                            function_param_decls.push_back(param_var_decl); -                             -                            GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset())); -                        } -                    } -                } -                arg_idx++; -            } -            break; - -        case DW_TAG_unspecified_parameters: -            is_variadic = true; -            break; - -        case DW_TAG_template_type_parameter: -        case DW_TAG_template_value_parameter: -            // The one caller of this was never using the template_param_infos, -            // and the local variable was taking up a large amount of stack space -            // in SymbolFileDWARF::ParseType() so this was removed. If we ever need -            // the template params back, we can add them back. -            // ParseTemplateDIE (dwarf_cu, die, template_param_infos); -            break; - -        default: -            break; -        } -    } -    return arg_idx; -} - -size_t -SymbolFileDWARF::ParseChildEnumerators -( -    const SymbolContext& sc, -    lldb_private::ClangASTType &clang_type, -    bool is_signed, -    uint32_t enumerator_byte_size, -    DWARFCompileUnit* dwarf_cu, -    const DWARFDebugInfoEntry *parent_die -) -{ -    if (parent_die == NULL) -        return 0; - -    size_t enumerators_added = 0; -    const DWARFDebugInfoEntry *die; -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); - -    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) -    { -        const dw_tag_t tag = die->Tag(); -        if (tag == DW_TAG_enumerator) -        { -            DWARFDebugInfoEntry::Attributes attributes; -            const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); -            if (num_child_attributes > 0) -            { -                const char *name = NULL; -                bool got_value = false; -                int64_t enum_value = 0; -                Declaration decl; - -                uint32_t i; -                for (i=0; i<num_child_attributes; ++i) -                { -                    const dw_attr_t attr = attributes.AttributeAtIndex(i); -                    DWARFFormValue form_value; -                    if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                    { -                        switch (attr) -                        { -                        case DW_AT_const_value: -                            got_value = true; -                            if (is_signed) -                                enum_value = form_value.Signed(); -                            else -                                enum_value = form_value.Unsigned(); -                            break; - -                        case DW_AT_name: -                            name = form_value.AsCString(&get_debug_str_data()); -                            break; - -                        case DW_AT_description: -                        default: -                        case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                        case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                        case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                        case DW_AT_sibling: -                            break; -                        } -                    } -                } - -                if (name && name[0] && got_value) -                { -                    clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(), -                                                                     decl, -                                                                     name, -                                                                     enum_value, -                                                                     enumerator_byte_size * 8); -                    ++enumerators_added; -                } -            } -        } +                                                  static_cast<const void*>(namespace_decl_ctx.GetTypeSystem()), +                                                  static_cast<const void*>(namespace_decl_ctx.GetOpaqueDeclContext()), +                                                  namespace_decl_ctx.GetName().AsCString("<NULL>"));      } -    return enumerators_added; -} - -void -SymbolFileDWARF::ParseChildArrayInfo -( -    const SymbolContext& sc, -    DWARFCompileUnit* dwarf_cu, -    const DWARFDebugInfoEntry *parent_die, -    int64_t& first_index, -    std::vector<uint64_t>& element_orders, -    uint32_t& byte_stride, -    uint32_t& bit_stride -) -{ -    if (parent_die == NULL) -        return; - -    const DWARFDebugInfoEntry *die; -    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64()); -    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) -    { -        const dw_tag_t tag = die->Tag(); -        switch (tag) -        { -        case DW_TAG_subrange_type: -            { -                DWARFDebugInfoEntry::Attributes attributes; -                const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); -                if (num_child_attributes > 0) -                { -                    uint64_t num_elements = 0; -                    uint64_t lower_bound = 0; -                    uint64_t upper_bound = 0; -                    bool upper_bound_valid = false; -                    uint32_t i; -                    for (i=0; i<num_child_attributes; ++i) -                    { -                        const dw_attr_t attr = attributes.AttributeAtIndex(i); -                        DWARFFormValue form_value; -                        if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                        { -                            switch (attr) -                            { -                            case DW_AT_name: -                                break; - -                            case DW_AT_count: -                                num_elements = form_value.Unsigned(); -                                break; - -                            case DW_AT_bit_stride: -                                bit_stride = form_value.Unsigned(); -                                break; - -                            case DW_AT_byte_stride: -                                byte_stride = form_value.Unsigned(); -                                break; - -                            case DW_AT_lower_bound: -                                lower_bound = form_value.Unsigned(); -                                break; - -                            case DW_AT_upper_bound: -                                upper_bound_valid = true; -                                upper_bound = form_value.Unsigned(); -                                break; - -                            default: -                            case DW_AT_abstract_origin: -                            case DW_AT_accessibility: -                            case DW_AT_allocated: -                            case DW_AT_associated: -                            case DW_AT_data_location: -                            case DW_AT_declaration: -                            case DW_AT_description: -                            case DW_AT_sibling: -                            case DW_AT_threads_scaled: -                            case DW_AT_type: -                            case DW_AT_visibility: -                                break; -                            } -                        } -                    } -                    if (num_elements == 0) -                    { -                        if (upper_bound_valid && upper_bound >= lower_bound) -                            num_elements = upper_bound - lower_bound + 1; -                    } - -                    element_orders.push_back (num_elements); -                } -            } -            break; -        } -    } +    return namespace_decl_ctx;  }  TypeSP -SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry* die) +SymbolFileDWARF::GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context)  {      TypeSP type_sp; -    if (die != NULL) +    if (die)      { -        assert(dwarf_cu != NULL); -        Type *type_ptr = m_die_to_type.lookup (die); +        Type *type_ptr = GetDIEToType().lookup (die.GetDIE());          if (type_ptr == NULL)          { -            CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(dwarf_cu); +            CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());              assert (lldb_cu);              SymbolContext sc(lldb_cu); -            type_sp = ParseType(sc, dwarf_cu, die, NULL); +            const DWARFDebugInfoEntry* parent_die = die.GetParent().GetDIE(); +            while (parent_die != nullptr) +                { +                    if (parent_die->Tag() == DW_TAG_subprogram) +                        break; +                    parent_die = parent_die->GetParent(); +                } +            SymbolContext sc_backup = sc; +            if (resolve_function_context && parent_die != nullptr && !GetFunction(DWARFDIE(die.GetCU(),parent_die), sc)) +                sc = sc_backup; + +            type_sp = ParseType(sc, die, NULL);          }          else if (type_ptr != DIE_IS_BEING_PARSED)          { @@ -4809,215 +3268,57 @@ SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfo      return type_sp;  } -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset) -{ -    if (die_offset != DW_INVALID_OFFSET) -    { -        DWARFCompileUnitSP cu_sp; -        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp); -        return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL); -    } -    return NULL; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextForDIEOffset (const SymbolContext &sc, dw_offset_t die_offset) -{ -    if (die_offset != DW_INVALID_OFFSET) -    { -        DWARFDebugInfo* debug_info = DebugInfo(); -        if (debug_info) -        { -            DWARFCompileUnitSP cu_sp; -            const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(die_offset, &cu_sp); -            if (die) -                return GetClangDeclContextForDIE (sc, cu_sp.get(), die); -        } -    } -    return NULL; -} - -clang::NamespaceDecl * -SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry *die) -{ -    if (die && die->Tag() == DW_TAG_namespace) -    { -        // See if we already parsed this namespace DIE and associated it with a -        // uniqued namespace declaration -        clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die]); -        if (namespace_decl) -            return namespace_decl; -        else -        { -            const char *namespace_name = die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL); -            clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL); -            namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx); -            Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -            if (log) -            { -                if (namespace_name) -                { -                    GetObjectFile()->GetModule()->LogMessage (log, -                                                              "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", -                                                              static_cast<void*>(GetClangASTContext().getASTContext()), -                                                              MakeUserID(die->GetOffset()), -                                                              namespace_name, -                                                              static_cast<void*>(namespace_decl), -                                                              static_cast<void*>(namespace_decl->getOriginalNamespace())); -                } -                else -                { -                    GetObjectFile()->GetModule()->LogMessage (log, -                                                              "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", -                                                              static_cast<void*>(GetClangASTContext().getASTContext()), -                                                              MakeUserID(die->GetOffset()), -                                                              static_cast<void*>(namespace_decl), -                                                              static_cast<void*>(namespace_decl->getOriginalNamespace())); -                } -            } - -            if (namespace_decl) -                LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die); -            return namespace_decl; -        } -    } -    return NULL; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) -{ -    clang::DeclContext *clang_decl_ctx = GetCachedClangDeclContextForDIE (die); -    if (clang_decl_ctx) -        return clang_decl_ctx; -    // If this DIE has a specification, or an abstract origin, then trace to those. -         -    dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET); -    if (die_offset != DW_INVALID_OFFSET) -        return GetClangDeclContextForDIEOffset (sc, die_offset); -     -    die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET); -    if (die_offset != DW_INVALID_OFFSET) -        return GetClangDeclContextForDIEOffset (sc, die_offset); -     -    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -    if (log) -        GetObjectFile()->GetModule()->LogMessage(log, "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu)); -    // This is the DIE we want.  Parse it, then query our map. -    bool assert_not_being_parsed = true; -    ResolveTypeUID (cu, die, assert_not_being_parsed);     - -    clang_decl_ctx = GetCachedClangDeclContextForDIE (die); - -    return clang_decl_ctx; -} - -clang::DeclContext * -SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry **decl_ctx_die_copy) -{ -    if (m_clang_tu_decl == NULL) -        m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl(); - -    const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die); - -    if (decl_ctx_die_copy) -        *decl_ctx_die_copy = decl_ctx_die; -     -    if (decl_ctx_die) -    { - -        DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die); -        if (pos != m_die_to_decl_ctx.end()) -            return pos->second; - -        switch (decl_ctx_die->Tag()) -        { -        case DW_TAG_compile_unit: -            return m_clang_tu_decl; - -        case DW_TAG_namespace: -            return ResolveNamespaceDIE (cu, decl_ctx_die); -            break; - -        case DW_TAG_structure_type: -        case DW_TAG_union_type: -        case DW_TAG_class_type: -            { -                Type* type = ResolveType (cu, decl_ctx_die); -                if (type) -                { -                    clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType (); -                    if (decl_ctx) -                    { -                        LinkDeclContextToDIE (decl_ctx, decl_ctx_die); -                        if (decl_ctx) -                            return decl_ctx; -                    } -                } -            } -            break; - -        default: -            break; -        } -    } -    return m_clang_tu_decl; -} - -const DWARFDebugInfoEntry * -SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) +DWARFDIE +SymbolFileDWARF::GetDeclContextDIEContainingDIE (const DWARFDIE &orig_die)  { -    if (cu && die) +    if (orig_die)      { -        const DWARFDebugInfoEntry * const decl_die = die; +        DWARFDIE die = orig_die; -        while (die != NULL) +        while (die)          {              // If this is the original DIE that we are searching for a declaration               // for, then don't look in the cache as we don't want our own decl               // context to be our decl context... -            if (decl_die != die) +            if (orig_die != die)              {             -                switch (die->Tag()) +                switch (die.Tag())                  {                      case DW_TAG_compile_unit:                      case DW_TAG_namespace:                      case DW_TAG_structure_type:                      case DW_TAG_union_type:                      case DW_TAG_class_type: +                    case DW_TAG_lexical_block: +                    case DW_TAG_subprogram:                          return die;                      default:                          break;                  }              } -             -            dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET); -            if (die_offset != DW_INVALID_OFFSET) + +            DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification); +            if (spec_die)              { -                DWARFCompileUnit *spec_cu = cu; -                const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu); -                const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die); -                if (spec_die_decl_ctx_die) -                    return spec_die_decl_ctx_die; +                DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die); +                if (decl_ctx_die) +                    return decl_ctx_die;              } -             -            die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET); -            if (die_offset != DW_INVALID_OFFSET) + +            DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin); +            if (abs_die)              { -                DWARFCompileUnit *abs_cu = cu; -                const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu); -                const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die); -                if (abs_die_decl_ctx_die) -                    return abs_die_decl_ctx_die; +                DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die); +                if (decl_ctx_die) +                    return decl_ctx_die;              } -             -            die = die->GetParent(); + +            die = die.GetParent();          }      } -    return NULL; +    return DWARFDIE();  } @@ -5075,7 +3376,7 @@ SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu)  // This function can be used when a DIE is found that is a forward declaration  // DIE and we want to try and find a type that has the complete definition.  TypeSP -SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,  +SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,                                                         const ConstString &type_name,                                                         bool must_be_implementation)  { @@ -5105,15 +3406,13 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry      const size_t num_matches = die_offsets.size(); -    DWARFCompileUnit* type_cu = NULL; -    const DWARFDebugInfoEntry* type_die = NULL;      if (num_matches)      {          DWARFDebugInfo* debug_info = DebugInfo();          for (size_t i=0; i<num_matches; ++i)          { -            const dw_offset_t die_offset = die_offsets[i]; -            type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu); +            const DIERef& die_ref = die_offsets[i]; +            DWARFDIE type_die = debug_info->GetDIE (die_ref);              if (type_die)              { @@ -5122,7 +3421,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry                  // Don't try and resolve the DIE we are looking for with the DIE itself!                  if (type_die != die)                  { -                    switch (type_die->Tag()) +                    switch (type_die.Tag())                      {                          case DW_TAG_class_type:                          case DW_TAG_structure_type: @@ -5135,22 +3434,22 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry                  if (try_resolving_type)                  { -                    if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type()) -                        try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0); +                    if (must_be_implementation && type_die.Supports_DW_AT_APPLE_objc_complete_type()) +                        try_resolving_type = type_die.GetAttributeValueAsUnsigned (DW_AT_APPLE_objc_complete_type, 0);                      if (try_resolving_type)                      { -                        Type *resolved_type = ResolveType (type_cu, type_die, false); +                        Type *resolved_type = ResolveType (type_die, false, true);                          if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)                          {                              DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n", -                                          MakeUserID(die->GetOffset()),  +                                          die.GetID(),                                            m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"), -                                          MakeUserID(type_die->GetOffset()),  -                                          MakeUserID(type_cu->GetOffset())); +                                          type_die.GetID(), +                                          type_cu->GetID());                              if (die) -                                m_die_to_type[die] = resolved_type; +                                GetDIEToType()[die.GetDIE()] = resolved_type;                              type_sp = resolved_type->shared_from_this();                              break;                          } @@ -5162,7 +3461,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry                  if (m_using_apple_tables)                  {                      GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", -                                                               die_offset, type_name.GetCString()); +                                                               die_ref.die_offset, type_name.GetCString());                  }              }             @@ -5185,19 +3484,12 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry  // when they don't.   //----------------------------------------------------------------------  bool -SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1, -                                       DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2) +SymbolFileDWARF::DIEDeclContextsMatch (const DWARFDIE &die1, +                                       const DWARFDIE &die2)  {      if (die1 == die2)          return true; -#if defined (LLDB_CONFIGURATION_DEBUG) -    // You can't and shouldn't call this function with a compile unit from -    // two different SymbolFileDWARF instances. -    assert (DebugInfo()->ContainsCompileUnit (cu1)); -    assert (DebugInfo()->ContainsCompileUnit (cu2)); -#endif -      DWARFDIECollection decl_ctx_1;      DWARFDIECollection decl_ctx_2;      //The declaration DIE stack is a stack of the declaration context  @@ -5215,8 +3507,8 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn      // all the way back to the compiler unit.      // First lets grab the decl contexts for both DIEs -    die1->GetDeclContextDIEs (this, cu1, decl_ctx_1); -    die2->GetDeclContextDIEs (this, cu2, decl_ctx_2); +    die1.GetDeclContextDIEs (decl_ctx_1); +    die2.GetDeclContextDIEs (decl_ctx_2);      // Make sure the context arrays have the same size, otherwise      // we are done      const size_t count1 = decl_ctx_1.Size(); @@ -5226,32 +3518,32 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn      // Make sure the DW_TAG values match all the way back up the      // compile unit. If they don't, then we are done. -    const DWARFDebugInfoEntry *decl_ctx_die1; -    const DWARFDebugInfoEntry *decl_ctx_die2; +    DWARFDIE decl_ctx_die1; +    DWARFDIE decl_ctx_die2;      size_t i;      for (i=0; i<count1; i++)      { -        decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i); -        decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i); -        if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag()) +        decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); +        decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); +        if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())              return false;      }  #if defined LLDB_CONFIGURATION_DEBUG      // Make sure the top item in the decl context die array is always       // DW_TAG_compile_unit. If it isn't then something went wrong in -    // the DWARFDebugInfoEntry::GetDeclContextDIEs() function... -    assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit); +    // the DWARFDIE::GetDeclContextDIEs() function... +    assert (decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit);  #endif      // Always skip the compile unit when comparing by only iterating up to      // "count - 1". Here we compare the names as we go.       for (i=0; i<count1 - 1; i++)      { -        decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i); -        decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i); -        const char *name1 = decl_ctx_die1->GetName(this, cu1); -        const char *name2 = decl_ctx_die2->GetName(this, cu2); +        decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i); +        decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i); +        const char *name1 = decl_ctx_die1.GetName(); +        const char *name2 = decl_ctx_die2.GetName();          // If the string was from a DW_FORM_strp, then the pointer will often          // be the same!          if (name1 == name2) @@ -5338,22 +3630,20 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &              const size_t num_matches = die_offsets.size(); -            DWARFCompileUnit* type_cu = NULL; -            const DWARFDebugInfoEntry* type_die = NULL;              if (num_matches)              {                  DWARFDebugInfo* debug_info = DebugInfo();                  for (size_t i=0; i<num_matches; ++i)                  { -                    const dw_offset_t die_offset = die_offsets[i]; -                    type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu); +                    const DIERef& die_ref = die_offsets[i]; +                    DWARFDIE type_die = debug_info->GetDIE (die_ref);                      if (type_die)                      {                          bool try_resolving_type = false;                          // Don't try and resolve the DIE we are looking for with the DIE itself! -                        const dw_tag_t type_tag = type_die->Tag(); +                        const dw_tag_t type_tag = type_die.Tag();                          // Make sure the tags match                          if (type_tag == tag)                          { @@ -5386,7 +3676,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &                          if (try_resolving_type)                          {                              DWARFDeclContext type_dwarf_decl_ctx; -                            type_die->GetDWARFDeclContext (this, type_cu, type_dwarf_decl_ctx); +                            type_die.GetDWARFDeclContext (type_dwarf_decl_ctx);                              if (log)                              { @@ -5394,14 +3684,14 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &                                                                            "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)",                                                                            DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),                                                                            dwarf_decl_ctx.GetQualifiedName(), -                                                                          type_die->GetOffset(), +                                                                          type_die.GetOffset(),                                                                            type_dwarf_decl_ctx.GetQualifiedName());                              }                              // Make sure the decl contexts match all the way up                              if (dwarf_decl_ctx == type_dwarf_decl_ctx)                              { -                                Type *resolved_type = ResolveType (type_cu, type_die, false); +                                Type *resolved_type = ResolveType (type_die, false);                                  if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)                                  {                                      type_sp = resolved_type->shared_from_this(); @@ -5414,12 +3704,12 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &                              if (log)                              {                                  std::string qualified_name; -                                type_die->GetQualifiedName(this, type_cu, qualified_name); +                                type_die.GetQualifiedName(qualified_name);                                  GetObjectFile()->GetModule()->LogMessage (log,                                                                            "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)",                                                                            DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),                                                                            dwarf_decl_ctx.GetQualifiedName(), -                                                                          type_die->GetOffset(), +                                                                          type_die.GetOffset(),                                                                            qualified_name.c_str());                              }                          } @@ -5429,7 +3719,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &                          if (m_using_apple_tables)                          {                              GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", -                                                                                       die_offset, type_name.GetCString()); +                                                                                       die_ref.die_offset, type_name.GetCString());                          }                      }             @@ -5440,1744 +3730,32 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &      return type_sp;  } -bool -SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile, -                                             Type *class_type, -                                             DWARFCompileUnit* src_cu, -                                             const DWARFDebugInfoEntry *src_class_die, -                                             DWARFCompileUnit* dst_cu, -                                             const DWARFDebugInfoEntry *dst_class_die, -                                             DWARFDIECollection &failures) -{ -    if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die) -        return false; -    if (src_class_die->Tag() != dst_class_die->Tag()) -        return false; -     -    // We need to complete the class type so we can get all of the method types -    // parsed so we can then unique those types to their equivalent counterparts -    // in "dst_cu" and "dst_class_die" -    class_type->GetClangFullType(); - -    const DWARFDebugInfoEntry *src_die; -    const DWARFDebugInfoEntry *dst_die; -    UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die; -    UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die; -    UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die_artificial; -    UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die_artificial; -    for (src_die = src_class_die->GetFirstChild(); src_die != NULL; src_die = src_die->GetSibling()) -    { -        if (src_die->Tag() == DW_TAG_subprogram) -        { -            // Make sure this is a declaration and not a concrete instance by looking -            // for DW_AT_declaration set to 1. Sometimes concrete function instances -            // are placed inside the class definitions and shouldn't be included in -            // the list of things are are tracking here. -            if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_declaration, 0) == 1) -            { -                const char *src_name = src_die->GetMangledName (src_symfile, src_cu); -                if (src_name) -                { -                    ConstString src_const_name(src_name); -                    if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_artificial, 0)) -                        src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die); -                    else -                        src_name_to_die.Append(src_const_name.GetCString(), src_die); -                } -            } -        } -    } -    for (dst_die = dst_class_die->GetFirstChild(); dst_die != NULL; dst_die = dst_die->GetSibling()) -    { -        if (dst_die->Tag() == DW_TAG_subprogram) -        { -            // Make sure this is a declaration and not a concrete instance by looking -            // for DW_AT_declaration set to 1. Sometimes concrete function instances -            // are placed inside the class definitions and shouldn't be included in -            // the list of things are are tracking here. -            if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_declaration, 0) == 1) -            { -                const char *dst_name = dst_die->GetMangledName (this, dst_cu); -                if (dst_name) -                { -                    ConstString dst_const_name(dst_name); -                    if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_artificial, 0)) -                        dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die); -                    else -                        dst_name_to_die.Append(dst_const_name.GetCString(), dst_die); -                } -            } -        } -    } -    const uint32_t src_size = src_name_to_die.GetSize (); -    const uint32_t dst_size = dst_name_to_die.GetSize (); -    Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION)); - -    // Is everything kosher so we can go through the members at top speed? -    bool fast_path = true; - -    if (src_size != dst_size) -    { -        if (src_size != 0 && dst_size != 0) -        { -            if (log) -                log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)", -                            src_class_die->GetOffset(), -                            dst_class_die->GetOffset(), -                            src_size, -                            dst_size); -        } - -        fast_path = false; -    } - -    uint32_t idx; - -    if (fast_path) -    { -        for (idx = 0; idx < src_size; ++idx) -        { -            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); -            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); - -            if (src_die->Tag() != dst_die->Tag()) -            { -                if (log) -                    log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)", -                                src_class_die->GetOffset(), -                                dst_class_die->GetOffset(), -                                src_die->GetOffset(), -                                DW_TAG_value_to_name(src_die->Tag()), -                                dst_die->GetOffset(), -                                DW_TAG_value_to_name(src_die->Tag())); -                fast_path = false; -            } - -            const char *src_name = src_die->GetMangledName (src_symfile, src_cu); -            const char *dst_name = dst_die->GetMangledName (this, dst_cu); - -            // Make sure the names match -            if (src_name == dst_name || (strcmp (src_name, dst_name) == 0)) -                continue; - -            if (log) -                log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)", -                            src_class_die->GetOffset(), -                            dst_class_die->GetOffset(), -                            src_die->GetOffset(), -                            src_name, -                            dst_die->GetOffset(), -                            dst_name); - -            fast_path = false; -        } -    } - -    // Now do the work of linking the DeclContexts and Types. -    if (fast_path) -    { -        // We can do this quickly.  Just run across the tables index-for-index since -        // we know each node has matching names and tags. -        for (idx = 0; idx < src_size; ++idx) -        { -            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx); -            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx); - -            clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die]; -            if (src_decl_ctx) -            { -                if (log) -                    log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", -                                 static_cast<void*>(src_decl_ctx), -                                 src_die->GetOffset(), dst_die->GetOffset()); -                LinkDeclContextToDIE (src_decl_ctx, dst_die); -            } -            else -            { -                if (log) -                    log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", -                                 src_die->GetOffset(), dst_die->GetOffset()); -            } - -            Type *src_child_type = m_die_to_type[src_die]; -            if (src_child_type) -            { -                if (log) -                    log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", -                                 static_cast<void*>(src_child_type), -                                 src_child_type->GetID(), -                                 src_die->GetOffset(), dst_die->GetOffset()); -                m_die_to_type[dst_die] = src_child_type; -            } -            else -            { -                if (log) -                    log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); -            } -        } -    } -    else -    { -        // We must do this slowly.  For each member of the destination, look -        // up a member in the source with the same name, check its tag, and -        // unique them if everything matches up.  Report failures. - -        if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) -        { -            src_name_to_die.Sort(); - -            for (idx = 0; idx < dst_size; ++idx) -            { -                const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx); -                dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx); -                src_die = src_name_to_die.Find(dst_name, NULL); - -                if (src_die && (src_die->Tag() == dst_die->Tag())) -                { -                    clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die]; -                    if (src_decl_ctx) -                    { -                        if (log) -                            log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", -                                         static_cast<void*>(src_decl_ctx), -                                         src_die->GetOffset(), -                                         dst_die->GetOffset()); -                        LinkDeclContextToDIE (src_decl_ctx, dst_die); -                    } -                    else -                    { -                        if (log) -                            log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); -                    } - -                    Type *src_child_type = m_die_to_type[src_die]; -                    if (src_child_type) -                    { -                        if (log) -                            log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", -                                         static_cast<void*>(src_child_type), -                                         src_child_type->GetID(), -                                         src_die->GetOffset(), -                                         dst_die->GetOffset()); -                        m_die_to_type[dst_die] = src_child_type; -                    } -                    else -                    { -                        if (log) -                            log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); -                    } -                } -                else -                { -                    if (log) -                        log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset()); - -                    failures.Append(dst_die); -                } -            } -        } -    } -     -    const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize (); -    const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize (); -     -    UniqueCStringMap<const DWARFDebugInfoEntry *> name_to_die_artificial_not_in_src; - -    if (src_size_artificial && dst_size_artificial) -    { -        dst_name_to_die_artificial.Sort(); - -        for (idx = 0; idx < src_size_artificial; ++idx) -        { -            const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx); -            src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx); -            dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL); - -            if (dst_die) -            { -                // Both classes have the artificial types, link them -                clang::DeclContext *src_decl_ctx = m_die_to_decl_ctx[src_die]; -                if (src_decl_ctx) -                { -                    if (log) -                        log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", -                                     static_cast<void*>(src_decl_ctx), -                                     src_die->GetOffset(), dst_die->GetOffset()); -                    LinkDeclContextToDIE (src_decl_ctx, dst_die); -                } -                else -                { -                    if (log) -                        log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); -                } - -                Type *src_child_type = m_die_to_type[src_die]; -                if (src_child_type) -                { -                    if (log) -                        log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", -                                     static_cast<void*>(src_child_type), -                                     src_child_type->GetID(), -                                     src_die->GetOffset(), dst_die->GetOffset()); -                    m_die_to_type[dst_die] = src_child_type; -                } -                else -                { -                    if (log) -                        log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset()); -                } -            } -        } -    } - -    if (dst_size_artificial) -    { -        for (idx = 0; idx < dst_size_artificial; ++idx) -        { -            const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx); -            dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx); -            if (log) -                log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial); -             -            failures.Append(dst_die); -        } -    } - -    return (failures.Size() != 0); -} -  TypeSP -SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new_ptr) +SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *type_is_new_ptr)  {      TypeSP type_sp; -    if (type_is_new_ptr) -        *type_is_new_ptr = false; - -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) -    static DIEStack g_die_stack; -    DIEStack::ScopedPopper scoped_die_logger(g_die_stack); -#endif - -    AccessType accessibility = eAccessNone; -    if (die != NULL) +    if (die)      { -        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -        if (log) -        { -            const DWARFDebugInfoEntry *context_die; -            clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die); - -            GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')", -                                                      die->GetOffset(), -                                                      static_cast<void*>(context), -                                                      context_die->GetOffset(), -                                                      DW_TAG_value_to_name(die->Tag()), -                                                      die->GetName(this, dwarf_cu)); - -#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE) -            scoped_die_logger.Push (dwarf_cu, die); -            g_die_stack.LogDIEs(log, this); -#endif -        } -// -//        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -//        if (log && dwarf_cu) -//        { -//            StreamString s; -//            die->DumpLocation (this, dwarf_cu, s); -//            GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); -//             -//        } - -        Type *type_ptr = m_die_to_type.lookup (die); -        TypeList* type_list = GetTypeList(); -        if (type_ptr == NULL) -        { -            ClangASTContext &ast = GetClangASTContext(); -            if (type_is_new_ptr) -                *type_is_new_ptr = true; - -            const dw_tag_t tag = die->Tag(); - -            bool is_forward_declaration = false; -            DWARFDebugInfoEntry::Attributes attributes; -            const char *type_name_cstr = NULL; -            ConstString type_name_const_str; -            Type::ResolveState resolve_state = Type::eResolveStateUnresolved; -            uint64_t byte_size = 0; -            Declaration decl; - -            Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; -            ClangASTType clang_type; -            DWARFFormValue form_value; -             -            dw_attr_t attr; - -            switch (tag) -            { -            case DW_TAG_base_type: -            case DW_TAG_pointer_type: -            case DW_TAG_reference_type: -            case DW_TAG_rvalue_reference_type: -            case DW_TAG_typedef: -            case DW_TAG_const_type: -            case DW_TAG_restrict_type: -            case DW_TAG_volatile_type: -            case DW_TAG_unspecified_type: -                { -                    // Set a bit that lets us know that we are currently parsing this -                    m_die_to_type[die] = DIE_IS_BEING_PARSED; - -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); -                    uint32_t encoding = 0; -                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID; - -                    if (num_attributes > 0) -                    { -                        uint32_t i; -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                                case DW_AT_name: - -                                    type_name_cstr = form_value.AsCString(&get_debug_str_data()); -                                    // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't -                                    // include the "&"... -                                    if (tag == DW_TAG_reference_type) -                                    { -                                        if (strchr (type_name_cstr, '&') == NULL) -                                            type_name_cstr = NULL; -                                    } -                                    if (type_name_cstr) -                                        type_name_const_str.SetCString(type_name_cstr); -                                    break; -                                case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break; -                                case DW_AT_encoding:    encoding = form_value.Unsigned(); break; -                                case DW_AT_type:        encoding_uid = form_value.Reference(); break; -                                default: -                                case DW_AT_sibling: -                                    break; -                                } -                            } -                        } -                    } - -                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); - -                    switch (tag) -                    { -                    default: -                        break; - -                    case DW_TAG_unspecified_type: -                        if (strcmp(type_name_cstr, "nullptr_t") == 0 || -                            strcmp(type_name_cstr, "decltype(nullptr)") == 0 ) -                        { -                            resolve_state = Type::eResolveStateFull; -                            clang_type = ast.GetBasicType(eBasicTypeNullPtr); -                            break; -                        } -                        // Fall through to base type below in case we can handle the type there... - -                    case DW_TAG_base_type: -                        resolve_state = Type::eResolveStateFull; -                        clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr,  -                                                                                   encoding,  -                                                                                   byte_size * 8); -                        break; - -                    case DW_TAG_pointer_type:           encoding_data_type = Type::eEncodingIsPointerUID;           break; -                    case DW_TAG_reference_type:         encoding_data_type = Type::eEncodingIsLValueReferenceUID;   break; -                    case DW_TAG_rvalue_reference_type:  encoding_data_type = Type::eEncodingIsRValueReferenceUID;   break; -                    case DW_TAG_typedef:                encoding_data_type = Type::eEncodingIsTypedefUID;           break; -                    case DW_TAG_const_type:             encoding_data_type = Type::eEncodingIsConstUID;             break; -                    case DW_TAG_restrict_type:          encoding_data_type = Type::eEncodingIsRestrictUID;          break; -                    case DW_TAG_volatile_type:          encoding_data_type = Type::eEncodingIsVolatileUID;          break; -                    } - -                    if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) -                    { -                        bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); - -                        if (translation_unit_is_objc) -                        { -                            if (type_name_cstr != NULL) -                            { -                                static ConstString g_objc_type_name_id("id"); -                                static ConstString g_objc_type_name_Class("Class"); -                                static ConstString g_objc_type_name_selector("SEL"); - -                                if (type_name_const_str == g_objc_type_name_id) -                                { -                                    if (log) -                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.", -                                                                                  die->GetOffset(),  -                                                                                  DW_TAG_value_to_name(die->Tag()),  -                                                                                  die->GetName(this, dwarf_cu)); -                                    clang_type = ast.GetBasicType(eBasicTypeObjCID); -                                    encoding_data_type = Type::eEncodingIsUID; -                                    encoding_uid = LLDB_INVALID_UID; -                                    resolve_state = Type::eResolveStateFull; - -                                } -                                else if (type_name_const_str == g_objc_type_name_Class) -                                { -                                    if (log) -                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.", -                                                                                  die->GetOffset(),  -                                                                                  DW_TAG_value_to_name(die->Tag()),  -                                                                                  die->GetName(this, dwarf_cu)); -                                    clang_type = ast.GetBasicType(eBasicTypeObjCClass); -                                    encoding_data_type = Type::eEncodingIsUID; -                                    encoding_uid = LLDB_INVALID_UID; -                                    resolve_state = Type::eResolveStateFull; -                                } -                                else if (type_name_const_str == g_objc_type_name_selector) -                                { -                                    if (log) -                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.", -                                                                                  die->GetOffset(),  -                                                                                  DW_TAG_value_to_name(die->Tag()),  -                                                                                  die->GetName(this, dwarf_cu)); -                                    clang_type = ast.GetBasicType(eBasicTypeObjCSel); -                                    encoding_data_type = Type::eEncodingIsUID; -                                    encoding_uid = LLDB_INVALID_UID; -                                    resolve_state = Type::eResolveStateFull; -                                } -                            } -                            else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID) -                            { -                                // Clang sometimes erroneously emits id as objc_object*.  In that case we fix up the type to "id". - -                                DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid); - -                                if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type) -                                { -                                    if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL)) -                                    { -                                        if (!strcmp(struct_name, "objc_object")) -                                        { -                                            if (log) -                                                GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.", -                                                                                          die->GetOffset(), -                                                                                          DW_TAG_value_to_name(die->Tag()), -                                                                                          die->GetName(this, dwarf_cu)); -                                            clang_type = ast.GetBasicType(eBasicTypeObjCID); -                                            encoding_data_type = Type::eEncodingIsUID; -                                            encoding_uid = LLDB_INVALID_UID; -                                            resolve_state = Type::eResolveStateFull; -                                        } -                                    } -                                } -                            } -                        } -                    } - -                    type_sp.reset( new Type (MakeUserID(die->GetOffset()), -                                             this,  -                                             type_name_const_str,  -                                             byte_size,  -                                             NULL,  -                                             encoding_uid,  -                                             encoding_data_type,  -                                             &decl,  -                                             clang_type,  -                                             resolve_state)); - -                    m_die_to_type[die] = type_sp.get(); - -//                  Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false); -//                  if (encoding_type != NULL) -//                  { -//                      if (encoding_type != DIE_IS_BEING_PARSED) -//                          type_sp->SetEncodingType(encoding_type); -//                      else -//                          m_indirect_fixups.push_back(type_sp.get()); -//                  } -                } -                break; - -            case DW_TAG_structure_type: -            case DW_TAG_union_type: -            case DW_TAG_class_type: -                { -                    // Set a bit that lets us know that we are currently parsing this -                    m_die_to_type[die] = DIE_IS_BEING_PARSED; -                    bool byte_size_valid = false; - -                    LanguageType class_language = eLanguageTypeUnknown; -                    bool is_complete_objc_class = false; -                    //bool struct_is_class = false; -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); -                    if (num_attributes > 0) -                    { -                        uint32_t i; -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                case DW_AT_decl_file: -                                    if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid()) -                                    { -                                        // llvm-gcc outputs invalid DW_AT_decl_file attributes that always -                                        // point to the compile unit file, so we clear this invalid value -                                        // so that we can still unique types efficiently. -                                        decl.SetFile(FileSpec ("<invalid>", false)); -                                    } -                                    else -                                        decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));  -                                    break; - -                                case DW_AT_decl_line: -                                    decl.SetLine(form_value.Unsigned());  -                                    break; - -                                case DW_AT_decl_column:  -                                    decl.SetColumn(form_value.Unsigned());  -                                    break; - -                                case DW_AT_name: -                                    type_name_cstr = form_value.AsCString(&get_debug_str_data()); -                                    type_name_const_str.SetCString(type_name_cstr); -                                    break; - -                                case DW_AT_byte_size:    -                                    byte_size = form_value.Unsigned();  -                                    byte_size_valid = true; -                                    break; - -                                case DW_AT_accessibility:  -                                    accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());  -                                    break; - -                                case DW_AT_declaration:  -                                    is_forward_declaration = form_value.Boolean(); -                                    break; - -                                case DW_AT_APPLE_runtime_class:  -                                    class_language = (LanguageType)form_value.Signed();  -                                    break; - -                                case DW_AT_APPLE_objc_complete_type: -                                    is_complete_objc_class = form_value.Signed();  -                                    break; - -                                case DW_AT_allocated: -                                case DW_AT_associated: -                                case DW_AT_data_location: -                                case DW_AT_description: -                                case DW_AT_start_scope: -                                case DW_AT_visibility: -                                default: -                                case DW_AT_sibling: -                                    break; -                                } -                            } -                        } -                    } -                     -                    // UniqueDWARFASTType is large, so don't create a local variables on the -                    // stack, put it on the heap. This function is often called recursively -                    // and clang isn't good and sharing the stack space for variables in different blocks. -                    std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); - -                    // Only try and unique the type if it has a name.  -                    if (type_name_const_str && -                        GetUniqueDWARFASTTypeMap().Find (type_name_const_str, -                                                         this, -                                                         dwarf_cu, -                                                         die, -                                                         decl, -                                                         byte_size_valid ? byte_size : -1, -                                                         *unique_ast_entry_ap)) -                    { -                        // We have already parsed this type or from another  -                        // compile unit. GCC loves to use the "one definition -                        // rule" which can result in multiple definitions -                        // of the same class over and over in each compile -                        // unit. -                        type_sp = unique_ast_entry_ap->m_type_sp; -                        if (type_sp) -                        { -                            m_die_to_type[die] = type_sp.get(); -                            return type_sp; -                        } -                    } - -                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - -                    int tag_decl_kind = -1; -                    AccessType default_accessibility = eAccessNone; -                    if (tag == DW_TAG_structure_type) -                    { -                        tag_decl_kind = clang::TTK_Struct; -                        default_accessibility = eAccessPublic; -                    } -                    else if (tag == DW_TAG_union_type) -                    { -                        tag_decl_kind = clang::TTK_Union; -                        default_accessibility = eAccessPublic; -                    } -                    else if (tag == DW_TAG_class_type) -                    { -                        tag_decl_kind = clang::TTK_Class; -                        default_accessibility = eAccessPrivate; -                    } - -                    if (byte_size_valid && byte_size == 0 && type_name_cstr && -                        die->HasChildren() == false &&  -                        sc.comp_unit->GetLanguage() == eLanguageTypeObjC) -                    { -                        // Work around an issue with clang at the moment where -                        // forward declarations for objective C classes are emitted -                        // as: -                        //  DW_TAG_structure_type [2]   -                        //  DW_AT_name( "ForwardObjcClass" ) -                        //  DW_AT_byte_size( 0x00 ) -                        //  DW_AT_decl_file( "..." ) -                        //  DW_AT_decl_line( 1 ) -                        // -                        // Note that there is no DW_AT_declaration and there are -                        // no children, and the byte size is zero. -                        is_forward_declaration = true; -                    } - -                    if (class_language == eLanguageTypeObjC || -                        class_language == eLanguageTypeObjC_plus_plus) -                    { -                        if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu)) -                        { -                            // We have a valid eSymbolTypeObjCClass class symbol whose -                            // name matches the current objective C class that we -                            // are trying to find and this DIE isn't the complete -                            // definition (we checked is_complete_objc_class above and -                            // know it is false), so the real definition is in here somewhere -                            type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); - -                            if (!type_sp && GetDebugMapSymfile ()) -                            { -                                // We weren't able to find a full declaration in -                                // this DWARF, see if we have a declaration anywhere     -                                // else... -                                type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true); -                            } - -                            if (type_sp) -                            { -                                if (log) -                                { -                                    GetObjectFile()->GetModule()->LogMessage (log, -                                                                              "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64, -                                                                              static_cast<void*>(this), -                                                                              die->GetOffset(),  -                                                                              DW_TAG_value_to_name(tag), -                                                                              type_name_cstr, -                                                                              type_sp->GetID()); -                                } - -                                // We found a real definition for this type elsewhere -                                // so lets use it and cache the fact that we found -                                // a complete type for this die -                                m_die_to_type[die] = type_sp.get(); -                                return type_sp; -                            } -                        } -                    } - - -                    if (is_forward_declaration) -                    { -                        // We have a forward declaration to a type and we need -                        // to try and find a full declaration. We look in the -                        // current type index just in case we have a forward -                        // declaration followed by an actual declarations in the -                        // DWARF. If this fails, we need to look elsewhere... -                        if (log) -                        { -                            GetObjectFile()->GetModule()->LogMessage (log, -                                                                      "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",  -                                                                      static_cast<void*>(this), -                                                                      die->GetOffset(),  -                                                                      DW_TAG_value_to_name(tag), -                                                                      type_name_cstr); -                        } - -                        DWARFDeclContext die_decl_ctx; -                        die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx); - -                        //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); -                        type_sp = FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); - -                        if (!type_sp && GetDebugMapSymfile ()) -                        { -                            // We weren't able to find a full declaration in -                            // this DWARF, see if we have a declaration anywhere     -                            // else... -                            type_sp = m_debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx); -                        } - -                        if (type_sp) -                        { -                            if (log) -                            { -                                GetObjectFile()->GetModule()->LogMessage (log, -                                                                          "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64, -                                                                          static_cast<void*>(this), -                                                                          die->GetOffset(),  -                                                                          DW_TAG_value_to_name(tag), -                                                                          type_name_cstr, -                                                                          type_sp->GetID()); -                            } - -                            // We found a real definition for this type elsewhere -                            // so lets use it and cache the fact that we found -                            // a complete type for this die -                            m_die_to_type[die] = type_sp.get(); -                            return type_sp; -                        } -                    } -                    assert (tag_decl_kind != -1); -                    bool clang_type_was_created = false; -                    clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); -                    if (!clang_type) -                    { -                        const DWARFDebugInfoEntry *decl_ctx_die; - -                        clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die); -                        if (accessibility == eAccessNone && decl_ctx) -                        { -                            // Check the decl context that contains this class/struct/union. -                            // If it is a class we must give it an accessibility. -                            const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind(); -                            if (DeclKindIsCXXClass (containing_decl_kind)) -                                accessibility = default_accessibility; -                        } - -                        ClangASTMetadata metadata; -                        metadata.SetUserID(MakeUserID(die->GetOffset())); -                        metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die)); - -                        if (type_name_cstr && strchr (type_name_cstr, '<')) -                        { -                            ClangASTContext::TemplateParameterInfos template_param_infos; -                            if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos)) -                            { -                                clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx, -                                                                                                        accessibility, -                                                                                                        type_name_cstr, -                                                                                                        tag_decl_kind, -                                                                                                        template_param_infos); - -                                clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx, -                                                                                                                                               class_template_decl, -                                                                                                                                               tag_decl_kind, -                                                                                                                                               template_param_infos); -                                clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl); -                                clang_type_was_created = true; - -                                GetClangASTContext().SetMetadata (class_template_decl, metadata); -                                GetClangASTContext().SetMetadata (class_specialization_decl, metadata); -                            } -                        } - -                        if (!clang_type_was_created) -                        { -                            clang_type_was_created = true; -                            clang_type = ast.CreateRecordType (decl_ctx,  -                                                               accessibility,  -                                                               type_name_cstr,  -                                                               tag_decl_kind,  -                                                               class_language, -                                                               &metadata); -                        } -                    } - -                    // Store a forward declaration to this class type in case any  -                    // parameters in any class methods need it for the clang  -                    // types for function prototypes. -                    LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); -                    type_sp.reset (new Type (MakeUserID(die->GetOffset()),  -                                             this,  -                                             type_name_const_str,  -                                             byte_size,  -                                             NULL,  -                                             LLDB_INVALID_UID,  -                                             Type::eEncodingIsUID,  -                                             &decl,  -                                             clang_type,  -                                             Type::eResolveStateForward)); - -                    type_sp->SetIsCompleteObjCClass(is_complete_objc_class); - - -                    // Add our type to the unique type map so we don't -                    // end up creating many copies of the same type over -                    // and over in the ASTContext for our module -                    unique_ast_entry_ap->m_type_sp = type_sp; -                    unique_ast_entry_ap->m_symfile = this; -                    unique_ast_entry_ap->m_cu = dwarf_cu; -                    unique_ast_entry_ap->m_die = die; -                    unique_ast_entry_ap->m_declaration = decl; -                    unique_ast_entry_ap->m_byte_size = byte_size; -                    GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,  -                                                       *unique_ast_entry_ap); - -                    if (is_forward_declaration && die->HasChildren()) -                    { -                        // Check to see if the DIE actually has a definition, some version of GCC will -                        // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram, -                        // members, or inheritance, so we can't trust it -                        const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); -                        while (child_die) -                        { -                            switch (child_die->Tag()) -                            { -                                case DW_TAG_inheritance: -                                case DW_TAG_subprogram: -                                case DW_TAG_member: -                                case DW_TAG_APPLE_property: -                                case DW_TAG_class_type: -                                case DW_TAG_structure_type: -                                case DW_TAG_enumeration_type: -                                case DW_TAG_typedef: -                                case DW_TAG_union_type: -                                    child_die = NULL; -                                    is_forward_declaration = false; -                                    break; -                                default: -                                    child_die = child_die->GetSibling(); -                                    break; -                            } -                        } -                    } - -                    if (!is_forward_declaration) -                    { -                        // Always start the definition for a class type so that -                        // if the class has child classes or types that require -                        // the class to be created for use as their decl contexts -                        // the class will be ready to accept these child definitions. -                        if (die->HasChildren() == false) -                        { -                            // No children for this struct/union/class, lets finish it -                            clang_type.StartTagDeclarationDefinition (); -                            clang_type.CompleteTagDeclarationDefinition (); - -                            if (tag == DW_TAG_structure_type) // this only applies in C -                            { -                                clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl(); - -                                if (record_decl) -                                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo())); -                            } -                        } -                        else if (clang_type_was_created) -                        { -                            // Start the definition if the class is not objective C since -                            // the underlying decls respond to isCompleteDefinition(). Objective -                            // C decls don't respond to isCompleteDefinition() so we can't -                            // start the declaration definition right away. For C++ class/union/structs -                            // we want to start the definition in case the class is needed as the -                            // declaration context for a contained class or type without the need -                            // to complete that type.. - -                            if (class_language != eLanguageTypeObjC && -                                class_language != eLanguageTypeObjC_plus_plus) -                                clang_type.StartTagDeclarationDefinition (); - -                            // Leave this as a forward declaration until we need -                            // to know the details of the type. lldb_private::Type -                            // will automatically call the SymbolFile virtual function -                            // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)" -                            // When the definition needs to be defined. -                            m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType(); -                            m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die; -                            clang_type.SetHasExternalStorage (true); -                        } -                    } - -                } -                break; - -            case DW_TAG_enumeration_type: -                { -                    // Set a bit that lets us know that we are currently parsing this -                    m_die_to_type[die] = DIE_IS_BEING_PARSED; - -                    lldb::user_id_t encoding_uid = DW_INVALID_OFFSET; - -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); -                    if (num_attributes > 0) -                    { -                        uint32_t i; - -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                case DW_AT_decl_file:       decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                                case DW_AT_decl_line:       decl.SetLine(form_value.Unsigned()); break; -                                case DW_AT_decl_column:     decl.SetColumn(form_value.Unsigned()); break; -                                case DW_AT_name: -                                    type_name_cstr = form_value.AsCString(&get_debug_str_data()); -                                    type_name_const_str.SetCString(type_name_cstr); -                                    break; -                                case DW_AT_type:            encoding_uid = form_value.Reference(); break; -                                case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break; -                                case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; -                                case DW_AT_declaration:     break; //is_forward_declaration = form_value.Boolean(); break; -                                case DW_AT_allocated: -                                case DW_AT_associated: -                                case DW_AT_bit_stride: -                                case DW_AT_byte_stride: -                                case DW_AT_data_location: -                                case DW_AT_description: -                                case DW_AT_start_scope: -                                case DW_AT_visibility: -                                case DW_AT_specification: -                                case DW_AT_abstract_origin: -                                case DW_AT_sibling: -                                    break; -                                } -                            } -                        } - -                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - -                        ClangASTType enumerator_clang_type; -                        clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die)); -                        if (!clang_type) -                        { -                            if (encoding_uid != DW_INVALID_OFFSET) -                            { -                                Type *enumerator_type = ResolveTypeUID(encoding_uid); -                                if (enumerator_type) -                                    enumerator_clang_type = enumerator_type->GetClangFullType(); -                            } - -                            if (!enumerator_clang_type) -                                enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, -                                                                                                      DW_ATE_signed, -                                                                                                      byte_size * 8); - -                            clang_type = ast.CreateEnumerationType (type_name_cstr,  -                                                                    GetClangDeclContextContainingDIE (dwarf_cu, die, NULL),  -                                                                    decl, -                                                                    enumerator_clang_type); -                        } -                        else -                        { -                            enumerator_clang_type = clang_type.GetEnumerationIntegerType (); -                        } - -                        LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die); - -                        type_sp.reset( new Type (MakeUserID(die->GetOffset()),  -                                                 this,  -                                                 type_name_const_str,  -                                                 byte_size,  -                                                 NULL,  -                                                 encoding_uid,  -                                                 Type::eEncodingIsUID, -                                                 &decl,  -                                                 clang_type,  -                                                 Type::eResolveStateForward)); - -                        clang_type.StartTagDeclarationDefinition (); -                        if (die->HasChildren()) -                        { -                            SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu)); -                            bool is_signed = false; -                            enumerator_clang_type.IsIntegerType(is_signed); -                            ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die); -                        } -                        clang_type.CompleteTagDeclarationDefinition (); -                    } -                } -                break; - -            case DW_TAG_inlined_subroutine: -            case DW_TAG_subprogram: -            case DW_TAG_subroutine_type: -                { -                    // Set a bit that lets us know that we are currently parsing this -                    m_die_to_type[die] = DIE_IS_BEING_PARSED; - -                    //const char *mangled = NULL; -                    dw_offset_t type_die_offset = DW_INVALID_OFFSET; -                    bool is_variadic = false; -                    bool is_inline = false; -                    bool is_static = false; -                    bool is_virtual = false; -                    bool is_explicit = false; -                    bool is_artificial = false; -                    dw_offset_t specification_die_offset = DW_INVALID_OFFSET; -                    dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET; -                    dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; - -                    unsigned type_quals = 0; -                    clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern - - -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); -                    if (num_attributes > 0) -                    { -                        uint32_t i; -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                                case DW_AT_name: -                                    type_name_cstr = form_value.AsCString(&get_debug_str_data()); -                                    type_name_const_str.SetCString(type_name_cstr); -                                    break; - -                                case DW_AT_linkage_name: -                                case DW_AT_MIPS_linkage_name:   break; // mangled = form_value.AsCString(&get_debug_str_data()); break; -                                case DW_AT_type:                type_die_offset = form_value.Reference(); break; -                                case DW_AT_accessibility:       accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; -                                case DW_AT_declaration:         break; // is_forward_declaration = form_value.Boolean(); break; -                                case DW_AT_inline:              is_inline = form_value.Boolean(); break; -                                case DW_AT_virtuality:          is_virtual = form_value.Boolean();  break; -                                case DW_AT_explicit:            is_explicit = form_value.Boolean();  break; -                                case DW_AT_artificial:          is_artificial = form_value.Boolean();  break; - - -                                case DW_AT_external: -                                    if (form_value.Unsigned()) -                                    { -                                        if (storage == clang::SC_None) -                                            storage = clang::SC_Extern; -                                        else -                                            storage = clang::SC_PrivateExtern; -                                    } -                                    break; - -                                case DW_AT_specification: -                                    specification_die_offset = form_value.Reference(); -                                    break; - -                                case DW_AT_abstract_origin: -                                    abstract_origin_die_offset = form_value.Reference(); -                                    break; - -                                case DW_AT_object_pointer: -                                    object_pointer_die_offset = form_value.Reference(); -                                    break; - -                                case DW_AT_allocated: -                                case DW_AT_associated: -                                case DW_AT_address_class: -                                case DW_AT_calling_convention: -                                case DW_AT_data_location: -                                case DW_AT_elemental: -                                case DW_AT_entry_pc: -                                case DW_AT_frame_base: -                                case DW_AT_high_pc: -                                case DW_AT_low_pc: -                                case DW_AT_prototyped: -                                case DW_AT_pure: -                                case DW_AT_ranges: -                                case DW_AT_recursive: -                                case DW_AT_return_addr: -                                case DW_AT_segment: -                                case DW_AT_start_scope: -                                case DW_AT_static_link: -                                case DW_AT_trampoline: -                                case DW_AT_visibility: -                                case DW_AT_vtable_elem_location: -                                case DW_AT_description: -                                case DW_AT_sibling: -                                    break; -                                } -                            } -                        } -                    } - -                    std::string object_pointer_name; -                    if (object_pointer_die_offset != DW_INVALID_OFFSET) -                    { -                        // Get the name from the object pointer die -                        StreamString s; -                        if (DWARFDebugInfoEntry::GetName (this, dwarf_cu, object_pointer_die_offset, s)) -                        { -                            object_pointer_name.assign(s.GetData()); -                        } -                    } - -                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - -                    ClangASTType return_clang_type; -                    Type *func_type = NULL; - -                    if (type_die_offset != DW_INVALID_OFFSET) -                        func_type = ResolveTypeUID(type_die_offset); - -                    if (func_type) -                        return_clang_type = func_type->GetClangForwardType(); -                    else -                        return_clang_type = ast.GetBasicType(eBasicTypeVoid); - - -                    std::vector<ClangASTType> function_param_types; -                    std::vector<clang::ParmVarDecl*> function_param_decls; - -                    // Parse the function children for the parameters - -                    const DWARFDebugInfoEntry *decl_ctx_die = NULL; -                    clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die); -                    const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind(); - -                    const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind); -                    // Start off static. This will be set to false in ParseChildParameters(...) -                    // if we find a "this" parameters as the first parameter -                    if (is_cxx_method) -                        is_static = true; -                     -                    if (die->HasChildren()) -                    { -                        bool skip_artificial = true; -                        ParseChildParameters (sc, -                                              containing_decl_ctx, -                                              dwarf_cu, -                                              die, -                                              skip_artificial, -                                              is_static, -                                              is_variadic, -                                              function_param_types, -                                              function_param_decls, -                                              type_quals); -                    } - -                    // clang_type will get the function prototype clang type after this call -                    clang_type = ast.CreateFunctionType (return_clang_type,  -                                                         function_param_types.data(), -                                                         function_param_types.size(),  -                                                         is_variadic,  -                                                         type_quals); - -                    bool ignore_containing_context = false; - -                    if (type_name_cstr) -                    { -                        bool type_handled = false; -                        if (tag == DW_TAG_subprogram) -                        { -                            ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true); -                            if (objc_method.IsValid(true)) -                            { -                                ClangASTType class_opaque_type; -                                ConstString class_name(objc_method.GetClassName()); -                                if (class_name) -                                { -                                    TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false)); - -                                    if (complete_objc_class_type_sp) -                                    { -                                        ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType(); -                                        if (type_clang_forward_type.IsObjCObjectOrInterfaceType ()) -                                            class_opaque_type = type_clang_forward_type; -                                    } -                                } - -                                if (class_opaque_type) -                                { -                                    // If accessibility isn't set to anything valid, assume public for  -                                    // now... -                                    if (accessibility == eAccessNone) -                                        accessibility = eAccessPublic; - -                                    clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr, -                                                                                                                           clang_type, -                                                                                                                           accessibility, -                                                                                                                           is_artificial); -                                    type_handled = objc_method_decl != NULL; -                                    if (type_handled) -                                    { -                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die); -                                        GetClangASTContext().SetMetadataAsUserID (objc_method_decl, MakeUserID(die->GetOffset())); -                                    } -                                    else -                                    { -                                        GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", -                                                                                   die->GetOffset(), -                                                                                   tag, -                                                                                   DW_TAG_value_to_name(tag)); -                                    } -                                } -                            } -                            else if (is_cxx_method) -                            { -                                // Look at the parent of this DIE and see if is is -                                // a class or struct and see if this is actually a -                                // C++ method -                                Type *class_type = ResolveType (dwarf_cu, decl_ctx_die); -                                if (class_type) -                                { -                                    if (class_type->GetID() != MakeUserID(decl_ctx_die->GetOffset())) -                                    { -                                        // We uniqued the parent class of this function to another class -                                        // so we now need to associate all dies under "decl_ctx_die" to -                                        // DIEs in the DIE for "class_type"... -                                        SymbolFileDWARF *class_symfile = NULL; -                                        DWARFCompileUnitSP class_type_cu_sp; -                                        const DWARFDebugInfoEntry *class_type_die = NULL; - -                                        SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); -                                        if (debug_map_symfile) -                                        { -                                            class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID())); -                                            class_type_die = class_symfile->DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp); -                                        } -                                        else -                                        { -                                            class_symfile = this; -                                            class_type_die = DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp); -                                        } -                                        if (class_type_die) -                                        { -                                            DWARFDIECollection failures; - -                                            CopyUniqueClassMethodTypes (class_symfile, -                                                                        class_type, -                                                                        class_type_cu_sp.get(), -                                                                        class_type_die, -                                                                        dwarf_cu, -                                                                        decl_ctx_die, -                                                                        failures); - -                                            // FIXME do something with these failures that's smarter than -                                            // just dropping them on the ground.  Unfortunately classes don't -                                            // like having stuff added to them after their definitions are -                                            // complete... - -                                            type_ptr = m_die_to_type[die]; -                                            if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) -                                            { -                                                type_sp = type_ptr->shared_from_this(); -                                                break; -                                            } -                                        } -                                    } - -                                    if (specification_die_offset != DW_INVALID_OFFSET) -                                    { -                                        // We have a specification which we are going to base our function -                                        // prototype off of, so we need this type to be completed so that the -                                        // m_die_to_decl_ctx for the method in the specification has a valid -                                        // clang decl context. -                                        class_type->GetClangForwardType(); -                                        // If we have a specification, then the function type should have been -                                        // made with the specification and not with this die. -                                        DWARFCompileUnitSP spec_cu_sp; -                                        const DWARFDebugInfoEntry* spec_die = DebugInfo()->GetDIEPtr(specification_die_offset, &spec_cu_sp); -                                        clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, spec_die); -                                        if (spec_clang_decl_ctx) -                                        { -                                            LinkDeclContextToDIE(spec_clang_decl_ctx, die); -                                        } -                                        else -                                        { -                                            GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x) has no decl\n", -                                                                                         MakeUserID(die->GetOffset()),  -                                                                                         specification_die_offset); -                                        } -                                        type_handled = true; -                                    } -                                    else if (abstract_origin_die_offset != DW_INVALID_OFFSET) -                                    { -                                        // We have a specification which we are going to base our function -                                        // prototype off of, so we need this type to be completed so that the -                                        // m_die_to_decl_ctx for the method in the abstract origin has a valid -                                        // clang decl context. -                                        class_type->GetClangForwardType(); - -                                        DWARFCompileUnitSP abs_cu_sp; -                                        const DWARFDebugInfoEntry* abs_die = DebugInfo()->GetDIEPtr(abstract_origin_die_offset, &abs_cu_sp); -                                        clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, abs_die); -                                        if (abs_clang_decl_ctx) -                                        { -                                            LinkDeclContextToDIE (abs_clang_decl_ctx, die); -                                        } -                                        else -                                        { -                                            GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x) has no decl\n", -                                                                                         MakeUserID(die->GetOffset()),  -                                                                                         abstract_origin_die_offset); -                                        } -                                        type_handled = true; -                                    } -                                    else -                                    { -                                        ClangASTType class_opaque_type = class_type->GetClangForwardType(); -                                        if (class_opaque_type.IsCXXClassType ()) -                                        { -                                            if (class_opaque_type.IsBeingDefined ()) -                                            { -                                                // Neither GCC 4.2 nor clang++ currently set a valid accessibility -                                                // in the DWARF for C++ methods... Default to public for now... -                                                if (accessibility == eAccessNone) -                                                    accessibility = eAccessPublic; - -                                                if (!is_static && !die->HasChildren()) -                                                { -                                                    // We have a C++ member function with no children (this pointer!) -                                                    // and clang will get mad if we try and make a function that isn't -                                                    // well formed in the DWARF, so we will just skip it... -                                                    type_handled = true; -                                                } -                                                else -                                                { -                                                    clang::CXXMethodDecl *cxx_method_decl; -                                                    // REMOVE THE CRASH DESCRIPTION BELOW -                                                    Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s", -                                                                                         type_name_cstr,  -                                                                                         class_type->GetName().GetCString(), -                                                                                         MakeUserID(die->GetOffset()), -                                                                                         m_obj_file->GetFileSpec().GetPath().c_str()); - -                                                    const bool is_attr_used = false; - -                                                    cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr, -                                                                                                                  clang_type, -                                                                                                                  accessibility, -                                                                                                                  is_virtual, -                                                                                                                  is_static, -                                                                                                                  is_inline, -                                                                                                                  is_explicit, -                                                                                                                  is_attr_used, -                                                                                                                  is_artificial); - -                                                    type_handled = cxx_method_decl != NULL; - -                                                    if (type_handled) -                                                    { -                                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die); - -                                                        Host::SetCrashDescription (NULL); - - -                                                        ClangASTMetadata metadata; -                                                        metadata.SetUserID(MakeUserID(die->GetOffset())); - -                                                        if (!object_pointer_name.empty()) -                                                        { -                                                            metadata.SetObjectPtrName(object_pointer_name.c_str()); -                                                            if (log) -                                                                log->Printf ("Setting object pointer name: %s on method object %p.\n", -                                                                             object_pointer_name.c_str(), -                                                                             static_cast<void*>(cxx_method_decl)); -                                                        } -                                                        GetClangASTContext().SetMetadata (cxx_method_decl, metadata); -                                                    } -                                                    else -                                                    { -                                                        ignore_containing_context = true; -                                                    } -                                                } -                                            } -                                            else -                                            { -                                                // We were asked to parse the type for a method in a class, yet the -                                                // class hasn't been asked to complete itself through the  -                                                // clang::ExternalASTSource protocol, so we need to just have the -                                                // class complete itself and do things the right way, then our  -                                                // DIE should then have an entry in the m_die_to_type map. First  -                                                // we need to modify the m_die_to_type so it doesn't think we are  -                                                // trying to parse this DIE anymore... -                                                m_die_to_type[die] = NULL; - -                                                // Now we get the full type to force our class type to complete itself  -                                                // using the clang::ExternalASTSource protocol which will parse all  -                                                // base classes and all methods (including the method for this DIE). -                                                class_type->GetClangFullType(); - -                                                // The type for this DIE should have been filled in the function call above -                                                type_ptr = m_die_to_type[die]; -                                                if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) -                                                { -                                                    type_sp = type_ptr->shared_from_this(); -                                                    break; -                                                } - -                                                // FIXME This is fixing some even uglier behavior but we really need to -                                                // uniq the methods of each class as well as the class itself. -                                                // <rdar://problem/11240464> -                                                type_handled = true; -                                            } -                                        } -                                    } -                                } -                            } -                        } - -                        if (!type_handled) -                        { -                            // We just have a function that isn't part of a class -                            clang::FunctionDecl *function_decl = ast.CreateFunctionDeclaration (ignore_containing_context ? GetClangASTContext().GetTranslationUnitDecl() : containing_decl_ctx, -                                                                                                type_name_cstr,  -                                                                                                clang_type,  -                                                                                                storage,  -                                                                                                is_inline); - -//                            if (template_param_infos.GetSize() > 0) -//                            { -//                                clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx, -//                                                                                                                  function_decl, -//                                                                                                                  type_name_cstr,  -//                                                                                                                  template_param_infos); -//                                 -//                                ast.CreateFunctionTemplateSpecializationInfo (function_decl, -//                                                                              func_template_decl, -//                                                                              template_param_infos); -//                            } -                            // Add the decl to our DIE to decl context map -                            assert (function_decl); -                            LinkDeclContextToDIE(function_decl, die); -                            if (!function_param_decls.empty()) -                                ast.SetFunctionParameters (function_decl,  -                                                           &function_param_decls.front(),  -                                                           function_param_decls.size()); - -                            ClangASTMetadata metadata; -                            metadata.SetUserID(MakeUserID(die->GetOffset())); - -                            if (!object_pointer_name.empty()) -                            { -                                metadata.SetObjectPtrName(object_pointer_name.c_str()); -                                if (log) -                                    log->Printf ("Setting object pointer name: %s on function object %p.", -                                                 object_pointer_name.c_str(), -                                                 static_cast<void*>(function_decl)); -                            } -                            GetClangASTContext().SetMetadata (function_decl, metadata); -                        } -                    } -                    type_sp.reset( new Type (MakeUserID(die->GetOffset()),  -                                             this,  -                                             type_name_const_str,  -                                             0,  -                                             NULL,  -                                             LLDB_INVALID_UID,  -                                             Type::eEncodingIsUID,  -                                             &decl,  -                                             clang_type,  -                                             Type::eResolveStateFull));                     -                    assert(type_sp.get()); -                } -                break; - -            case DW_TAG_array_type: -                { -                    // Set a bit that lets us know that we are currently parsing this -                    m_die_to_type[die] = DIE_IS_BEING_PARSED; - -                    lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; -                    int64_t first_index = 0; -                    uint32_t byte_stride = 0; -                    uint32_t bit_stride = 0; -                    bool is_vector = false; -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - -                    if (num_attributes > 0) -                    { -                        uint32_t i; -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break; -                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break; -                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                                case DW_AT_name: -                                    type_name_cstr = form_value.AsCString(&get_debug_str_data()); -                                    type_name_const_str.SetCString(type_name_cstr); -                                    break; - -                                case DW_AT_type:            type_die_offset = form_value.Reference(); break; -                                case DW_AT_byte_size:       break; // byte_size = form_value.Unsigned(); break; -                                case DW_AT_byte_stride:     byte_stride = form_value.Unsigned(); break; -                                case DW_AT_bit_stride:      bit_stride = form_value.Unsigned(); break; -                                case DW_AT_GNU_vector:      is_vector = form_value.Boolean(); break; -                                case DW_AT_accessibility:   break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; -                                case DW_AT_declaration:     break; // is_forward_declaration = form_value.Boolean(); break; -                                case DW_AT_allocated: -                                case DW_AT_associated: -                                case DW_AT_data_location: -                                case DW_AT_description: -                                case DW_AT_ordering: -                                case DW_AT_start_scope: -                                case DW_AT_visibility: -                                case DW_AT_specification: -                                case DW_AT_abstract_origin: -                                case DW_AT_sibling: -                                    break; -                                } -                            } -                        } - -                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr); - -                        Type *element_type = ResolveTypeUID(type_die_offset); - -                        if (element_type) -                        { -                            std::vector<uint64_t> element_orders; -                            ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride); -                            if (byte_stride == 0 && bit_stride == 0) -                                byte_stride = element_type->GetByteSize(); -                            ClangASTType array_element_type = element_type->GetClangForwardType(); -                            uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; -                            if (element_orders.size() > 0) -                            { -                                uint64_t num_elements = 0; -                                std::vector<uint64_t>::const_reverse_iterator pos; -                                std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend(); -                                for (pos = element_orders.rbegin(); pos != end; ++pos) -                                { -                                    num_elements = *pos; -                                    clang_type = ast.CreateArrayType (array_element_type, -                                                                      num_elements, -                                                                      is_vector); -                                    array_element_type = clang_type; -                                    array_element_bit_stride = num_elements ? -                                                               array_element_bit_stride * num_elements : -                                                               array_element_bit_stride; -                                } -                            } -                            else -                            { -                                clang_type = ast.CreateArrayType (array_element_type, 0, is_vector); -                            } -                            ConstString empty_name; -                            type_sp.reset( new Type (MakeUserID(die->GetOffset()),  -                                                     this,  -                                                     empty_name,  -                                                     array_element_bit_stride / 8,  -                                                     NULL,  -                                                     type_die_offset,  -                                                     Type::eEncodingIsUID,  -                                                     &decl,  -                                                     clang_type,  -                                                     Type::eResolveStateFull)); -                            type_sp->SetEncodingType (element_type); -                        } -                    } -                } -                break; +        TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType()); -            case DW_TAG_ptr_to_member_type: -                { -                    dw_offset_t type_die_offset = DW_INVALID_OFFSET; -                    dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET; - -                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); - -                    if (num_attributes > 0) { -                        uint32_t i; -                        for (i=0; i<num_attributes; ++i) -                        { -                            attr = attributes.AttributeAtIndex(i); -                            if (attributes.ExtractFormValueAtIndex(this, i, form_value)) -                            { -                                switch (attr) -                                { -                                    case DW_AT_type: -                                        type_die_offset = form_value.Reference(); break; -                                    case DW_AT_containing_type: -                                        containing_type_die_offset = form_value.Reference(); break; -                                } -                            } -                        } - -                        Type *pointee_type = ResolveTypeUID(type_die_offset); -                        Type *class_type = ResolveTypeUID(containing_type_die_offset); - -                        ClangASTType pointee_clang_type = pointee_type->GetClangForwardType(); -                        ClangASTType class_clang_type = class_type->GetClangLayoutType(); - -                        clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type); - -                        byte_size = clang_type.GetByteSize(nullptr); - -                        type_sp.reset( new Type (MakeUserID(die->GetOffset()),  -                                                 this,  -                                                 type_name_const_str,  -                                                 byte_size,  -                                                 NULL,  -                                                 LLDB_INVALID_UID,  -                                                 Type::eEncodingIsUID,  -                                                 NULL,  -                                                 clang_type,  -                                                 Type::eResolveStateForward)); -                    } - -                    break; -                } -            default: -                GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message", -                                                           die->GetOffset(), -                                                           tag, -                                                           DW_TAG_value_to_name(tag)); -                break; -            } - -            if (type_sp.get()) +        if (type_system) +        { +            DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); +            if (dwarf_ast)              { -                const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); -                dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; - -                SymbolContextScope * symbol_context_scope = NULL; -                if (sc_parent_tag == DW_TAG_compile_unit) +                Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); +                type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, type_is_new_ptr); +                if (type_sp)                  { -                    symbol_context_scope = sc.comp_unit; +                    TypeList* type_list = GetTypeList(); +                    if (type_list) +                        type_list->Insert(type_sp);                  } -                else if (sc.function != NULL && sc_parent_die) -                { -                    symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); -                    if (symbol_context_scope == NULL) -                        symbol_context_scope = sc.function; -                } - -                if (symbol_context_scope != NULL) -                { -                    type_sp->SetSymbolContextScope(symbol_context_scope); -                } - -                // We are ready to put this type into the uniqued list up at the module level -                type_list->Insert (type_sp); - -                m_die_to_type[die] = type_sp.get();              }          } -        else if (type_ptr != DIE_IS_BEING_PARSED) -        { -            type_sp = type_ptr->shared_from_this(); -        }      } +          return type_sp;  } @@ -7185,38 +3763,38 @@ size_t  SymbolFileDWARF::ParseTypes  (      const SymbolContext& sc,  -    DWARFCompileUnit* dwarf_cu,  -    const DWARFDebugInfoEntry *die,  +    const DWARFDIE &orig_die,      bool parse_siblings,       bool parse_children  )  {      size_t types_added = 0; -    while (die != NULL) +    DWARFDIE die = orig_die; +    while (die)      {          bool type_is_new = false; -        if (ParseType(sc, dwarf_cu, die, &type_is_new).get()) +        if (ParseType(sc, die, &type_is_new).get())          {              if (type_is_new)                  ++types_added;          } -        if (parse_children && die->HasChildren()) +        if (parse_children && die.HasChildren())          { -            if (die->Tag() == DW_TAG_subprogram) +            if (die.Tag() == DW_TAG_subprogram)              {                  SymbolContext child_sc(sc); -                child_sc.function = sc.comp_unit->FindFunctionByUID(MakeUserID(die->GetOffset())).get(); -                types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true); +                child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get(); +                types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true);              }              else -                types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true); +                types_added += ParseTypes(sc, die.GetFirstChild(), true, true);          }          if (parse_siblings) -            die = die->GetSibling(); +            die = die.GetSibling();          else -            die = NULL; +            die.Clear();      }      return types_added;  } @@ -7230,11 +3808,11 @@ SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)      DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);      if (dwarf_cu)      { -        dw_offset_t function_die_offset = sc.function->GetID(); -        const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset); +        const dw_offset_t function_die_offset = sc.function->GetID(); +        DWARFDIE function_die = dwarf_cu->GetDIE (function_die_offset);          if (function_die)          { -            ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, 0); +            ParseFunctionBlocks(sc, &sc.function->GetBlock (false), function_die, LLDB_INVALID_ADDRESS, 0);          }      } @@ -7254,18 +3832,18 @@ SymbolFileDWARF::ParseTypes (const SymbolContext &sc)          if (sc.function)          {              dw_offset_t function_die_offset = sc.function->GetID(); -            const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset); -            if (func_die && func_die->HasChildren()) +            DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset); +            if (func_die && func_die.HasChildren())              { -                types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true); +                types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true);              }          }          else          { -            const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE(); -            if (dwarf_cu_die && dwarf_cu_die->HasChildren()) +            DWARFDIE dwarf_cu_die = dwarf_cu->DIE(); +            if (dwarf_cu_die && dwarf_cu_die.HasChildren())              { -                types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true); +                types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);              }          }      } @@ -7284,17 +3862,12 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)          if (sc.function)          { -            DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get(); +            DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID())); -            if (dwarf_cu == NULL) -                return 0; -             -            const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID()); -             -            dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS); +            const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS);              if (func_lo_pc != LLDB_INVALID_ADDRESS)              { -                const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true); +                const size_t num_variables = ParseVariables(sc, function_die.GetFirstChild(), func_lo_pc, true, true);                  // Let all blocks know they have parse all their variables                  sc.function->GetBlock (false).SetDidParseVariables (true, true); @@ -7303,7 +3876,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)          }          else if (sc.comp_unit)          { -            DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get(); +            DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());              if (dwarf_cu == NULL)                  return 0; @@ -7316,8 +3889,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)                  variables.reset(new VariableList());                  sc.comp_unit->SetVariableList(variables); -                DWARFCompileUnit* match_dwarf_cu = NULL; -                const DWARFDebugInfoEntry* die = NULL;                  DIEArray die_offsets;                  if (m_using_apple_tables)                  { @@ -7340,7 +3911,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)                          Index ();                      m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(),  -                                                                 dwarf_cu->GetNextCompileUnitOffset(),                                                                    die_offsets);                  } @@ -7350,11 +3920,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)                      DWARFDebugInfo* debug_info = DebugInfo();                      for (size_t i=0; i<num_matches; ++i)                      { -                        const dw_offset_t die_offset = die_offsets[i]; -                        die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &match_dwarf_cu); +                        const DIERef& die_ref = die_offsets[i]; +                        DWARFDIE die = debug_info->GetDIE (die_ref);                          if (die)                          { -                            VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, LLDB_INVALID_ADDRESS)); +                            VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS));                              if (var_sp)                              {                                  variables->AddVariableIfUnique (var_sp); @@ -7365,7 +3935,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)                          {                              if (m_using_apple_tables)                              { -                                GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset); +                                GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_ref.die_offset);                              }                          }             @@ -7378,37 +3948,43 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)      return 0;  } -  VariableSP  SymbolFileDWARF::ParseVariableDIE  (      const SymbolContext& sc, -    DWARFCompileUnit* dwarf_cu, -    const DWARFDebugInfoEntry *die, +    const DWARFDIE &die,      const lldb::addr_t func_low_pc  )  { -    VariableSP var_sp (m_die_to_variable_sp[die]); +    if (die.GetDWARF() != this) +        return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc); + +    VariableSP var_sp; +    if (!die) +        return var_sp; + +    var_sp = GetDIEToVariable()[die.GetDIE()];      if (var_sp)          return var_sp;  // Already been parsed! -    const dw_tag_t tag = die->Tag(); +    const dw_tag_t tag = die.Tag();      ModuleSP module = GetObjectFile()->GetModule();      if ((tag == DW_TAG_variable) ||          (tag == DW_TAG_constant) ||          (tag == DW_TAG_formal_parameter && sc.function))      { -        DWARFDebugInfoEntry::Attributes attributes; -        const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); +        DWARFAttributes attributes; +        const size_t num_attributes = die.GetAttributes(attributes); +        DWARFDIE spec_die;          if (num_attributes > 0)          {              const char *name = NULL;              const char *mangled = NULL;              Declaration decl;              uint32_t i; -            lldb::user_id_t type_uid = LLDB_INVALID_UID; -            DWARFExpression location; +            DWARFFormValue type_die_form; +            DWARFExpression location(die.GetCU());              bool is_external = false;              bool is_artificial = false;              bool location_is_const_value_data = false; @@ -7421,17 +3997,17 @@ SymbolFileDWARF::ParseVariableDIE                  dw_attr_t attr = attributes.AttributeAtIndex(i);                  DWARFFormValue form_value; -                if (attributes.ExtractFormValueAtIndex(this, i, form_value)) +                if (attributes.ExtractFormValueAtIndex(i, form_value))                  {                      switch (attr)                      {                      case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;                      case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;                      case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; -                    case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break; +                    case DW_AT_name:        name = form_value.AsCString(); break;                      case DW_AT_linkage_name: -                    case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; -                    case DW_AT_type:        type_uid = form_value.Reference(); break; +                    case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(); break; +                    case DW_AT_type:        type_die_form = form_value; break;                      case DW_AT_external:    is_external = form_value.Boolean(); break;                      case DW_AT_const_value:                          // If we have already found a DW_AT_location attribute, ignore this attribute. @@ -7450,9 +4026,12 @@ SymbolFileDWARF::ParseVariableDIE                              else if (DWARFFormValue::IsDataForm(form_value.Form()))                              {                                  // Retrieve the value as a data expression. -                                const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); +                                DWARFFormValue::FixedFormSizes fixed_form_sizes = +                                    DWARFFormValue::GetFixedFormSizesForAddressSize ( +                                            attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), +                                            attributes.CompileUnitAtIndex(i)->IsDWARF64());                                  uint32_t data_offset = attributes.DIEOffsetAtIndex(i); -                                uint32_t data_length = fixed_form_sizes[form_value.Form()]; +                                uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());                                  if (data_length == 0)                                  {                                      const uint8_t *data_pointer = form_value.BlockData(); @@ -7474,14 +4053,17 @@ SymbolFileDWARF::ParseVariableDIE                                  // Retrieve the value as a string expression.                                  if (form_value.Form() == DW_FORM_strp)                                  { -                                    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64()); +                                    DWARFFormValue::FixedFormSizes fixed_form_sizes = +                                        DWARFFormValue::GetFixedFormSizesForAddressSize ( +                                                attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), +                                                attributes.CompileUnitAtIndex(i)->IsDWARF64());                                      uint32_t data_offset = attributes.DIEOffsetAtIndex(i); -                                    uint32_t data_length = fixed_form_sizes[form_value.Form()]; +                                    uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());                                      location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);                                  }                                  else                                  { -                                    const char *str = form_value.AsCString(&debug_info_data); +                                    const char *str = form_value.AsCString();                                      uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();                                      uint32_t string_length = strlen(str) + 1;                                      location.CopyOpcodeData(module, debug_info_data, string_offset, string_length); @@ -7503,10 +4085,10 @@ SymbolFileDWARF::ParseVariableDIE                              }                              else                              { -                                const DWARFDataExtractor&    debug_loc_data = get_debug_loc_data(); +                                const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();                                  const dw_offset_t debug_loc_offset = form_value.Unsigned(); -                                size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset); +                                size_t loc_list_length = DWARFExpression::LocationListSize(die.GetCU(), debug_loc_data, debug_loc_offset);                                  if (loc_list_length > 0)                                  {                                      location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length); @@ -7516,7 +4098,13 @@ SymbolFileDWARF::ParseVariableDIE                              }                          }                          break; - +                    case DW_AT_specification: +                    { +                        DWARFDebugInfo* debug_info = DebugInfo(); +                        if (debug_info) +                            spec_die = debug_info->GetDIE(DIERef(form_value)); +                        break; +                    }                      case DW_AT_artificial:      is_artificial = form_value.Boolean(); break;                      case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;                      case DW_AT_declaration: @@ -7528,16 +4116,18 @@ SymbolFileDWARF::ParseVariableDIE                      default:                      case DW_AT_abstract_origin:                      case DW_AT_sibling: -                    case DW_AT_specification:                          break;                      }                  }              } +            const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die); +            const dw_tag_t parent_tag = die.GetParent().Tag(); +            bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type); +              ValueType scope = eValueTypeInvalid; -            const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die); -            dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; +            const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);              SymbolContextScope * symbol_context_scope = NULL;              if (!mangled) @@ -7548,12 +4138,12 @@ SymbolFileDWARF::ParseVariableDIE                  // B which in turn is contained in a namespace A, the command "frame var j" returns                  // "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able                  // to generate a fully qualified name from the declaration context. -                if (die->GetParent()->Tag() == DW_TAG_compile_unit && -                    LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType())) +                if (parent_tag == DW_TAG_compile_unit && +                    Language::LanguageIsCPlusPlus(die.GetLanguage()))                  {                      DWARFDeclContext decl_ctx; -                    die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx); +                    die.GetDWARFDeclContext(decl_ctx);                      mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString();                  }              } @@ -7582,7 +4172,7 @@ SymbolFileDWARF::ParseVariableDIE                      {                          StreamString strm;                          location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL); -                        GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str()); +                        GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str());                      }                  } @@ -7670,7 +4260,10 @@ SymbolFileDWARF::ParseVariableDIE                  }                  else                  { -                    scope = eValueTypeVariableLocal; +                    if (location_is_const_value_data) +                        scope = eValueTypeVariableStatic; +                    else +                        scope = eValueTypeVariableLocal;                  }              } @@ -7683,7 +4276,7 @@ SymbolFileDWARF::ParseVariableDIE                  case DW_TAG_lexical_block:                      if (sc.function)                      { -                        symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); +                        symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());                          if (symbol_context_scope == NULL)                              symbol_context_scope = sc.function;                      } @@ -7697,12 +4290,12 @@ SymbolFileDWARF::ParseVariableDIE              if (symbol_context_scope)              { -                SymbolFileTypeSP type_sp(new SymbolFileType(*this, type_uid)); +                SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID()));                  if (const_value.Form() && type_sp && type_sp->GetType()) -                    location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), dwarf_cu->GetAddressByteSize()); +                    location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize()); -                var_sp.reset (new Variable (MakeUserID(die->GetOffset()),  +                var_sp.reset (new Variable (die.GetID(),                                              name,                                               mangled,                                              type_sp, @@ -7711,7 +4304,8 @@ SymbolFileDWARF::ParseVariableDIE                                              &decl,                                               location,                                               is_external,  -                                            is_artificial)); +                                            is_artificial, +                                            is_static_member));                  var_sp->SetLocationIsConstantValueData (location_is_const_value_data);              } @@ -7727,57 +4321,42 @@ SymbolFileDWARF::ParseVariableDIE          // was missing vital information to be able to be displayed in the debugger          // (missing location due to optimization, etc)) so we don't re-parse          // this DIE over and over later... -        m_die_to_variable_sp[die] = var_sp; +        GetDIEToVariable()[die.GetDIE()] = var_sp; +        if (spec_die) +            GetDIEToVariable()[spec_die.GetDIE()] = var_sp;      }      return var_sp;  } -const DWARFDebugInfoEntry * -SymbolFileDWARF::FindBlockContainingSpecification (dw_offset_t func_die_offset,  -                                                   dw_offset_t spec_block_die_offset, -                                                   DWARFCompileUnit **result_die_cu_handle) +DWARFDIE +SymbolFileDWARF::FindBlockContainingSpecification (const DIERef& func_die_ref, +                                                   dw_offset_t spec_block_die_offset)  {      // Give the concrete function die specified by "func_die_offset", find the       // concrete block whose DW_AT_specification or DW_AT_abstract_origin points      // to "spec_block_die_offset" -    DWARFDebugInfo* info = DebugInfo(); - -    const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint(func_die_offset, result_die_cu_handle); -    if (die) -    { -        assert (*result_die_cu_handle); -        return FindBlockContainingSpecification (*result_die_cu_handle, die, spec_block_die_offset, result_die_cu_handle); -    } -    return NULL; +    return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), spec_block_die_offset);  } -const DWARFDebugInfoEntry * -SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu, -                                                  const DWARFDebugInfoEntry *die, -                                                  dw_offset_t spec_block_die_offset, -                                                  DWARFCompileUnit **result_die_cu_handle) +DWARFDIE +SymbolFileDWARF::FindBlockContainingSpecification(const DWARFDIE &die, +                                                  dw_offset_t spec_block_die_offset)  {      if (die)      { -        switch (die->Tag()) +        switch (die.Tag())          {          case DW_TAG_subprogram:          case DW_TAG_inlined_subroutine:          case DW_TAG_lexical_block:              { -                if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset) -                { -                    *result_die_cu_handle = dwarf_cu; +                if (die.GetAttributeValueAsReference (DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)                      return die; -                } -                if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset) -                { -                    *result_die_cu_handle = dwarf_cu; +                if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)                      return die; -                }              }              break;          } @@ -7785,49 +4364,42 @@ SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,          // Give the concrete function die specified by "func_die_offset", find the           // concrete block whose DW_AT_specification or DW_AT_abstract_origin points          // to "spec_block_die_offset" -        for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); child_die != NULL; child_die = child_die->GetSibling()) +        for (DWARFDIE child_die = die.GetFirstChild(); child_die; child_die = child_die.GetSibling())          { -            const DWARFDebugInfoEntry *result_die = FindBlockContainingSpecification (dwarf_cu, -                                                                                      child_die, -                                                                                      spec_block_die_offset, -                                                                                      result_die_cu_handle); +            DWARFDIE result_die = FindBlockContainingSpecification (child_die, spec_block_die_offset);              if (result_die)                  return result_die;          }      } -    *result_die_cu_handle = NULL; -    return NULL; +    return DWARFDIE();  }  size_t -SymbolFileDWARF::ParseVariables -( -    const SymbolContext& sc, -    DWARFCompileUnit* dwarf_cu, -    const lldb::addr_t func_low_pc, -    const DWARFDebugInfoEntry *orig_die, -    bool parse_siblings, -    bool parse_children, -    VariableList* cc_variable_list -) +SymbolFileDWARF::ParseVariables (const SymbolContext& sc, +                                 const DWARFDIE &orig_die, +                                 const lldb::addr_t func_low_pc, +                                 bool parse_siblings, +                                 bool parse_children, +                                 VariableList* cc_variable_list)  { -    if (orig_die == NULL) +    if (!orig_die)          return 0;      VariableListSP variable_list_sp;      size_t vars_added = 0; -    const DWARFDebugInfoEntry *die = orig_die; -    while (die != NULL) +    DWARFDIE die = orig_die; +    while (die)      { -        dw_tag_t tag = die->Tag(); +        dw_tag_t tag = die.Tag();          // Check to see if we have already parsed this variable or constant? -        if (m_die_to_variable_sp[die]) +        VariableSP var_sp = GetDIEToVariable()[die.GetDIE()]; +        if (var_sp)          {              if (cc_variable_list) -                cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]); +                cc_variable_list->AddVariableIfUnique (var_sp);          }          else          { @@ -7838,8 +4410,8 @@ SymbolFileDWARF::ParseVariables              {                  if (variable_list_sp.get() == NULL)                  { -                    const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die); -                    dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0; +                    DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die); +                    dw_tag_t parent_tag = sc_parent_die.Tag();                      switch (parent_tag)                      {                          case DW_TAG_compile_unit: @@ -7855,10 +4427,10 @@ SymbolFileDWARF::ParseVariables                              else                              {                                  GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64 " %s.\n", -                                                                           MakeUserID(sc_parent_die->GetOffset()), -                                                                           DW_TAG_value_to_name (parent_tag), -                                                                           MakeUserID(orig_die->GetOffset()), -                                                                           DW_TAG_value_to_name (orig_die->Tag())); +                                                                           sc_parent_die.GetID(), +                                                                           sc_parent_die.GetTagAsCString(), +                                                                           orig_die.GetID(), +                                                                           orig_die.GetTagAsCString());                              }                              break; @@ -7869,19 +4441,17 @@ SymbolFileDWARF::ParseVariables                              {                                  // Check to see if we already have parsed the variables for the given scope -                                Block *block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset())); +                                Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());                                  if (block == NULL)                                  {                                      // This must be a specification or abstract origin with                                       // a concrete block counterpart in the current function. We need                                      // to find the concrete block so we can correctly add the                                       // variable to it -                                    DWARFCompileUnit *concrete_block_die_cu = dwarf_cu; -                                    const DWARFDebugInfoEntry *concrete_block_die = FindBlockContainingSpecification (sc.function->GetID(),  -                                                                                                                      sc_parent_die->GetOffset(),  -                                                                                                                      &concrete_block_die_cu); +                                    const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()), +                                                                                                          sc_parent_die.GetOffset());                                      if (concrete_block_die) -                                        block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(concrete_block_die->GetOffset())); +                                        block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID());                                  }                                  if (block != NULL) @@ -7899,15 +4469,15 @@ SymbolFileDWARF::ParseVariables                          default:                               GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64 " %s.\n", -                                                                        MakeUserID(orig_die->GetOffset()), -                                                                        DW_TAG_value_to_name (orig_die->Tag())); +                                                                        orig_die.GetID(), +                                                                        orig_die.GetTagAsCString());                              break;                      }                  }                  if (variable_list_sp)                  { -                    VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc)); +                    VariableSP var_sp (ParseVariableDIE(sc, die, func_low_pc));                      if (var_sp)                      {                          variable_list_sp->AddVariableIfUnique (var_sp); @@ -7921,15 +4491,15 @@ SymbolFileDWARF::ParseVariables          bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram); -        if (!skip_children && parse_children && die->HasChildren()) +        if (!skip_children && parse_children && die.HasChildren())          { -            vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list); +            vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, true, cc_variable_list);          }          if (parse_siblings) -            die = die->GetSibling(); +            die = die.GetSibling();          else -            die = NULL; +            die.Clear();      }      return vars_added;  } @@ -7950,24 +4520,6 @@ SymbolFileDWARF::GetPluginVersion()  }  void -SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl) -{ -    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; -    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); -    if (clang_type) -        symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -} - -void -SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl) -{ -    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; -    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); -    if (clang_type) -        symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -} - -void  SymbolFileDWARF::DumpIndexes ()  {      StreamFile s(stdout, false); @@ -7982,147 +4534,7 @@ SymbolFileDWARF::DumpIndexes ()      s.Printf("\nObjective C class selectors:\n");    m_objc_class_selectors_index.Dump (&s);      s.Printf("\nGlobals and statics:\n");   m_global_index.Dump (&s);       s.Printf("\nTypes:\n");                 m_type_index.Dump (&s); -    s.Printf("\nNamepaces:\n");             m_namespace_index.Dump (&s); -} - -void -SymbolFileDWARF::SearchDeclContext (const clang::DeclContext *decl_context,  -                                    const char *name,  -                                    llvm::SmallVectorImpl <clang::NamedDecl *> *results) -{     -    DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find(decl_context); -     -    if (iter == m_decl_ctx_to_die.end()) -        return; -     -    for (DIEPointerSet::iterator pos = iter->second.begin(), end = iter->second.end(); pos != end; ++pos) -    { -        const DWARFDebugInfoEntry *context_die = *pos; -     -        if (!results) -            return; -         -        DWARFDebugInfo* info = DebugInfo(); -         -        DIEArray die_offsets; -         -        DWARFCompileUnit* dwarf_cu = NULL; -        const DWARFDebugInfoEntry* die = NULL; -         -        if (m_using_apple_tables) -        { -            if (m_apple_types_ap.get()) -                m_apple_types_ap->FindByName (name, die_offsets); -        } -        else -        { -            if (!m_indexed) -                Index (); -             -            m_type_index.Find (ConstString(name), die_offsets); -        } -         -        const size_t num_matches = die_offsets.size(); -         -        if (num_matches) -        { -            for (size_t i = 0; i < num_matches; ++i) -            { -                const dw_offset_t die_offset = die_offsets[i]; -                die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu); - -                if (die->GetParent() != context_die) -                    continue; -                 -                Type *matching_type = ResolveType (dwarf_cu, die); -                 -                clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType(); -                 -                if (const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr())) -                { -                    clang::TagDecl *tag_decl = tag_type->getDecl(); -                    results->push_back(tag_decl); -                } -                else if (const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(qual_type.getTypePtr())) -                { -                    clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl(); -                    results->push_back(typedef_decl);  -                } -            } -        } -    } -} - -void -SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton, -                                                 const clang::DeclContext *decl_context, -                                                 clang::DeclarationName decl_name, -                                                 llvm::SmallVectorImpl <clang::NamedDecl *> *results) -{ -     -    switch (decl_context->getDeclKind()) -    { -    case clang::Decl::Namespace: -    case clang::Decl::TranslationUnit: -        { -            SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; -            symbol_file_dwarf->SearchDeclContext (decl_context, decl_name.getAsString().c_str(), results); -        } -        break; -    default: -        break; -    } -} - -bool -SymbolFileDWARF::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, -                                  uint64_t &alignment, -                                  llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                                  llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                                  llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ -    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton; -    return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets); -} - -bool -SymbolFileDWARF::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment, -                                  llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                                  llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                                  llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ -    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); -    RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl); -    bool success = false; -    base_offsets.clear(); -    vbase_offsets.clear(); -    if (pos != m_record_decl_to_layout_map.end()) -    { -        bit_size = pos->second.bit_size; -        alignment = pos->second.alignment; -        field_offsets.swap(pos->second.field_offsets); -        base_offsets.swap (pos->second.base_offsets); -        vbase_offsets.swap (pos->second.vbase_offsets); -        m_record_decl_to_layout_map.erase(pos); -        success = true; -    } -    else -    { -        bit_size = 0; -        alignment = 0; -        field_offsets.clear(); -    } -     -    if (log) -        GetObjectFile()->GetModule()->LogMessage (log,  -                                                  "SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i", -                                                  static_cast<const void*>(record_decl), -                                                  bit_size, alignment, -                                                  static_cast<uint32_t>(field_offsets.size()), -                                                  static_cast<uint32_t>(base_offsets.size()), -                                                  static_cast<uint32_t>(vbase_offsets.size()), -                                                  success); -    return success; +    s.Printf("\nNamespaces:\n");            m_namespace_index.Dump (&s);  } @@ -8142,4 +4554,8 @@ SymbolFileDWARF::GetDebugMapSymfile ()      return m_debug_map_symfile;  } - +DWARFExpression::LocationListFormat +SymbolFileDWARF::GetLocationListFormat() const +{ +    return DWARFExpression::RegularLocationList; +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2f0b3f05b153e..c2e78a417b7ac 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -14,24 +14,22 @@  // C++ Includes  #include <list>  #include <map> +#include <mutex>  #include <set> +#include <unordered_map>  #include <vector>  // Other libraries and framework includes -#include "clang/AST/CharUnits.h" -#include "clang/AST/ExternalASTSource.h"  #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h"  #include "lldb/lldb-private.h" -#include "lldb/Core/ClangForward.h"  #include "lldb/Core/ConstString.h"  #include "lldb/Core/dwarf.h"  #include "lldb/Core/Flags.h"  #include "lldb/Core/RangeMap.h"  #include "lldb/Core/UniqueCStringMap.h" -#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/DebugMacros.h"  #include "lldb/Symbol/SymbolFile.h"  #include "lldb/Symbol/SymbolContext.h" @@ -61,12 +59,18 @@ class DWARFDIECollection;  class DWARFFormValue;  class SymbolFileDWARFDebugMap; +#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1) +  class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID  {  public:      friend class SymbolFileDWARFDebugMap; +    friend class SymbolFileDWARFDwo;      friend class DebugMapModule;      friend class DWARFCompileUnit; +    friend class DWARFASTParserClang; +    friend class DWARFASTParserGo; +      //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------ @@ -76,6 +80,9 @@ public:      static void      Terminate(); +    static void +    DebuggerInitialize(lldb_private::Debugger &debugger); +      static lldb_private::ConstString      GetPluginNameStatic(); @@ -84,481 +91,419 @@ public:      static lldb_private::SymbolFile*      CreateInstance (lldb_private::ObjectFile* obj_file); +      //------------------------------------------------------------------      // Constructors and Destructors      //------------------------------------------------------------------ -                            SymbolFileDWARF(lldb_private::ObjectFile* ofile); -    virtual                 ~SymbolFileDWARF(); -    virtual uint32_t        CalculateAbilities (); -    virtual void            InitializeObject(); +    SymbolFileDWARF(lldb_private::ObjectFile* ofile); + +    ~SymbolFileDWARF() override; + +    uint32_t +    CalculateAbilities () override; + +    void +    InitializeObject() override;      //------------------------------------------------------------------      // Compile Unit function calls      //------------------------------------------------------------------ -    virtual uint32_t        GetNumCompileUnits(); -    virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index); - -    virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc); -    virtual size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc); -    virtual bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc); -    virtual bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files); -    virtual bool            ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules); -    virtual size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc); -    virtual size_t          ParseTypes (const lldb_private::SymbolContext& sc); -    virtual size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc); - -    virtual lldb_private::Type* ResolveTypeUID(lldb::user_id_t type_uid); -    virtual bool            ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type); - -    virtual lldb_private::Type* ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed = true); -    virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid); -    virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid); - -    virtual uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc); -    virtual uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list); -    virtual uint32_t        FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables); -    virtual uint32_t        FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables); -    virtual uint32_t        FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); -    virtual uint32_t        FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); -    virtual uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types); -    virtual lldb_private::TypeList * -                            GetTypeList (); -    virtual size_t          GetTypes (lldb_private::SymbolContextScope *sc_scope, -                                      uint32_t type_mask, -                                      lldb_private::TypeList &type_list); - -    virtual lldb_private::ClangASTContext & -                            GetClangASTContext (); - -    virtual lldb_private::ClangNamespaceDecl -            FindNamespace (const lldb_private::SymbolContext& sc,  -                           const lldb_private::ConstString &name,  -                           const lldb_private::ClangNamespaceDecl *parent_namespace_decl); +    uint32_t +    GetNumCompileUnits() override; -    //------------------------------------------------------------------ -    // ClangASTContext callbacks for external source lookups. -    //------------------------------------------------------------------ -    static void -    CompleteTagDecl (void *baton, clang::TagDecl *); -     -    static void -    CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); +    lldb::CompUnitSP +    ParseCompileUnitAtIndex(uint32_t index) override; + +    lldb::LanguageType +    ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override; + +    size_t +    ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override; + +    bool +    ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; + +    bool +    ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override; + +    bool +    ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, +                                  lldb_private::FileSpecList& support_files) override; + +    bool +    ParseImportedModules (const lldb_private::SymbolContext &sc, +                          std::vector<lldb_private::ConstString> &imported_modules) override; + +    size_t +    ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; + +    size_t +    ParseTypes (const lldb_private::SymbolContext& sc) override; + +    size_t +    ParseVariablesForContext (const lldb_private::SymbolContext& sc) override; + +    lldb_private::Type * +    ResolveTypeUID(lldb::user_id_t type_uid) override; + +    bool +    CompleteType (lldb_private::CompilerType& compiler_type) override; + +    lldb_private::Type * +    ResolveType (const DWARFDIE &die, +                 bool assert_not_being_parsed = true, +                 bool resolve_function_context = false); + +    lldb_private::CompilerDecl +    GetDeclForUID (lldb::user_id_t uid) override; + +    lldb_private::CompilerDeclContext +    GetDeclContextForUID (lldb::user_id_t uid) override; + +    lldb_private::CompilerDeclContext +    GetDeclContextContainingUID (lldb::user_id_t uid) override; + +    void +    ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override; -    static void -    FindExternalVisibleDeclsByName (void *baton, -                                    const clang::DeclContext *DC, -                                    clang::DeclarationName Name, -                                    llvm::SmallVectorImpl <clang::NamedDecl *> *results); - -    static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, -                                 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                                 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                                 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); - -    bool LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, -                          llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); - -    struct LayoutInfo -    { -        LayoutInfo () : -            bit_size(0), -            alignment(0), -            field_offsets(), -            base_offsets(), -            vbase_offsets() -        { -        } -        uint64_t bit_size; -        uint64_t alignment; -        llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; -        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; -        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets; -    }; + +    uint32_t +    ResolveSymbolContext (const lldb_private::Address& so_addr, +                          uint32_t resolve_scope, +                          lldb_private::SymbolContext& sc) override; + +    uint32_t +    ResolveSymbolContext (const lldb_private::FileSpec& file_spec, +                          uint32_t line, +                          bool check_inlines, +                          uint32_t resolve_scope, +                          lldb_private::SymbolContextList& sc_list) override; + +    uint32_t +    FindGlobalVariables (const lldb_private::ConstString &name, +                         const lldb_private::CompilerDeclContext *parent_decl_ctx, +                         bool append, +                         uint32_t max_matches, +                         lldb_private::VariableList& variables) override; + +    uint32_t +    FindGlobalVariables (const lldb_private::RegularExpression& regex, +                         bool append, +                         uint32_t max_matches, +                         lldb_private::VariableList& variables) override; + +    uint32_t +    FindFunctions (const lldb_private::ConstString &name, +                   const lldb_private::CompilerDeclContext *parent_decl_ctx, +                   uint32_t name_type_mask, +                   bool include_inlines, +                   bool append, +                   lldb_private::SymbolContextList& sc_list) override; + +    uint32_t +    FindFunctions (const lldb_private::RegularExpression& regex, +                   bool include_inlines, +                   bool append, +                   lldb_private::SymbolContextList& sc_list) override; + +    uint32_t +    FindTypes (const lldb_private::SymbolContext& sc, +               const lldb_private::ConstString &name, +               const lldb_private::CompilerDeclContext *parent_decl_ctx, +               bool append, +               uint32_t max_matches, +               lldb_private::TypeMap& types) override; + +    size_t +    FindTypes (const std::vector<lldb_private::CompilerContext> &context, +               bool append, +               lldb_private::TypeMap& types) override; + +    lldb_private::TypeList * +    GetTypeList () override; + +    size_t +    GetTypes (lldb_private::SymbolContextScope *sc_scope, +              uint32_t type_mask, +              lldb_private::TypeList &type_list) override; + +    lldb_private::TypeSystem * +    GetTypeSystemForLanguage (lldb::LanguageType language) override; + +    lldb_private::CompilerDeclContext +    FindNamespace (const lldb_private::SymbolContext& sc, +                   const lldb_private::ConstString &name, +                   const lldb_private::CompilerDeclContext *parent_decl_ctx) override; + +      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); - -    virtual uint32_t -    GetPluginVersion(); +    lldb_private::ConstString +    GetPluginName() override; -    // Approach 2 - count + accessor -    // Index compile units would scan the initial compile units and register -    // them with the module. This would only be done on demand if and only if -    // the compile units were needed. -    //virtual size_t        GetCompUnitCount() = 0; -    //virtual CompUnitSP    GetCompUnitAtIndex(size_t cu_idx) = 0; +    uint32_t +    GetPluginVersion() override;      const lldb_private::DWARFDataExtractor&     get_debug_abbrev_data (); +    const lldb_private::DWARFDataExtractor&     get_debug_addr_data ();      const lldb_private::DWARFDataExtractor&     get_debug_aranges_data ();      const lldb_private::DWARFDataExtractor&     get_debug_frame_data ();      const lldb_private::DWARFDataExtractor&     get_debug_info_data ();      const lldb_private::DWARFDataExtractor&     get_debug_line_data (); +    const lldb_private::DWARFDataExtractor&     get_debug_macro_data ();      const lldb_private::DWARFDataExtractor&     get_debug_loc_data ();      const lldb_private::DWARFDataExtractor&     get_debug_ranges_data ();      const lldb_private::DWARFDataExtractor&     get_debug_str_data (); +    const lldb_private::DWARFDataExtractor&     get_debug_str_offsets_data ();      const lldb_private::DWARFDataExtractor&     get_apple_names_data ();      const lldb_private::DWARFDataExtractor&     get_apple_types_data ();      const lldb_private::DWARFDataExtractor&     get_apple_namespaces_data ();      const lldb_private::DWARFDataExtractor&     get_apple_objc_data (); -    DWARFDebugAbbrev*       DebugAbbrev(); -    const DWARFDebugAbbrev* DebugAbbrev() const; +    DWARFDebugAbbrev* +    DebugAbbrev(); -    DWARFDebugInfo*         DebugInfo(); -    const DWARFDebugInfo*   DebugInfo() const; +    const DWARFDebugAbbrev* +    DebugAbbrev() const; -    DWARFDebugRanges*       DebugRanges(); -    const DWARFDebugRanges* DebugRanges() const; +    DWARFDebugInfo* +    DebugInfo(); -    const lldb_private::DWARFDataExtractor& -    GetCachedSectionData (uint32_t got_flag,  -                          lldb::SectionType sect_type,  -                          lldb_private::DWARFDataExtractor &data); +    const DWARFDebugInfo* +    DebugInfo() const; + +    DWARFDebugRanges* +    DebugRanges(); + +    const DWARFDebugRanges* +    DebugRanges() const;      static bool      SupportedVersion(uint16_t version); -    clang::DeclContext * -    GetCachedClangDeclContextForDIE (const DWARFDebugInfoEntry *die) -    { -        DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die); -        if (pos != m_die_to_decl_ctx.end()) -            return pos->second; -        else -            return NULL; -    } +    DWARFDIE +    GetDeclContextDIEContainingDIE (const DWARFDIE &die); -    clang::DeclContext * -    GetClangDeclContextForDIE (const lldb_private::SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die); -     -    clang::DeclContext * -    GetClangDeclContextForDIEOffset (const lldb_private::SymbolContext &sc, dw_offset_t die_offset); -     -    clang::DeclContext * -    GetClangDeclContextContainingDIE (DWARFCompileUnit *cu,  -                                      const DWARFDebugInfoEntry *die, -                                      const DWARFDebugInfoEntry **decl_ctx_die); - -    clang::DeclContext * -    GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset); +    bool +    HasForwardDeclForClangType (const lldb_private::CompilerType &compiler_type); -    const DWARFDebugInfoEntry * -    GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die); +    lldb_private::CompileUnit* +    GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, +                                uint32_t cu_idx = UINT32_MAX); -    void -    SearchDeclContext (const clang::DeclContext *decl_context,  -                       const char *name,  -                       llvm::SmallVectorImpl <clang::NamedDecl *> *results); -     -    lldb_private::Flags& -    GetFlags () +    lldb::user_id_t +    MakeUserID (dw_offset_t die_offset) const      { -        return m_flags; +        return GetID() | die_offset;      } -    const lldb_private::Flags& -    GetFlags () const -    { -        return m_flags; -    } +    size_t +    GetObjCMethodDIEOffsets (lldb_private::ConstString class_name, +                             DIEArray &method_die_offsets);      bool -    HasForwardDeclForClangType (const lldb_private::ClangASTType &clang_type); +    Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); + +    lldb_private::DebugMacrosSP +    ParseDebugMacros(lldb::offset_t *offset); + +    static DWARFDIE +    GetParentSymbolContextDIE(const DWARFDIE &die); + +    virtual lldb::CompUnitSP +    ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx); + +    virtual lldb_private::DWARFExpression::LocationListFormat +    GetLocationListFormat() const; + +    lldb::ModuleSP +    GetDWOModule (lldb_private::ConstString name);  protected: +    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; +    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; +    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType; +    typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE; -    enum +    struct DWARFDataSegment      { -        flagsGotDebugAbbrevData     = (1 << 0), -        flagsGotDebugArangesData    = (1 << 1), -        flagsGotDebugFrameData      = (1 << 2), -        flagsGotDebugInfoData       = (1 << 3), -        flagsGotDebugLineData       = (1 << 4), -        flagsGotDebugLocData        = (1 << 5), -        flagsGotDebugMacInfoData    = (1 << 6), -        flagsGotDebugPubNamesData   = (1 << 7), -        flagsGotDebugPubTypesData   = (1 << 8), -        flagsGotDebugRangesData     = (1 << 9), -        flagsGotDebugStrData        = (1 << 10), -        flagsGotAppleNamesData      = (1 << 11), -        flagsGotAppleTypesData      = (1 << 12), -        flagsGotAppleNamespacesData = (1 << 13), -        flagsGotAppleObjCData       = (1 << 14) +        std::once_flag                   m_flag; +        lldb_private::DWARFDataExtractor m_data;      }; -     -    bool                    NamespaceDeclMatchesThisSymbolFile (const lldb_private::ClangNamespaceDecl *namespace_decl); - -    bool                    DIEIsInNamespace (const lldb_private::ClangNamespaceDecl *namespace_decl,  -                                              DWARFCompileUnit* dwarf_cu,  -                                              const DWARFDebugInfoEntry* die);      DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF); -    lldb::CompUnitSP        ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx); -    DWARFCompileUnit*       GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit); -    DWARFCompileUnit*       GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu); -    lldb_private::CompileUnit*      GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX); -    bool                    GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc); -    lldb_private::Function *        ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die); -    size_t                  ParseFunctionBlocks (const lldb_private::SymbolContext& sc, -                                                 lldb_private::Block *parent_block, -                                                 DWARFCompileUnit* dwarf_cu, -                                                 const DWARFDebugInfoEntry *die, -                                                 lldb::addr_t subprogram_low_pc, -                                                 uint32_t depth); -    size_t                  ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children); -    lldb::TypeSP            ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new); -    lldb_private::Type*     ResolveTypeUID (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed); - -    lldb::VariableSP        ParseVariableDIE( -                                const lldb_private::SymbolContext& sc, -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *die, -                                const lldb::addr_t func_low_pc); - -    size_t                  ParseVariables( -                                const lldb_private::SymbolContext& sc, -                                DWARFCompileUnit* dwarf_cu, -                                const lldb::addr_t func_low_pc, -                                const DWARFDebugInfoEntry *die, -                                bool parse_siblings, -                                bool parse_children, -                                lldb_private::VariableList* cc_variable_list = NULL); - -    class DelayedAddObjCClassProperty; -    typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList; -     -    bool                    ClassOrStructIsVirtual ( -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *parent_die); - -    size_t                  ParseChildMembers( -                                const lldb_private::SymbolContext& sc, -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *die, -                                lldb_private::ClangASTType &class_clang_type, -                                const lldb::LanguageType class_language, -                                std::vector<clang::CXXBaseSpecifier *>& base_classes, -                                std::vector<int>& member_accessibilities, -                                DWARFDIECollection& member_function_dies, -                                DelayedPropertyList& delayed_properties, -                                lldb::AccessType &default_accessibility, -                                bool &is_a_class, -                                LayoutInfo &layout_info); - -    size_t                  ParseChildParameters( -                                const lldb_private::SymbolContext& sc, -                                clang::DeclContext *containing_decl_ctx, -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *parent_die, -                                bool skip_artificial, -                                bool &is_static, -                                bool &is_variadic, -                                std::vector<lldb_private::ClangASTType>& function_args, -                                std::vector<clang::ParmVarDecl*>& function_param_decls, -                                unsigned &type_quals); -                                // lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); // not currently needed -     -     -    size_t                  ParseChildEnumerators( -                                const lldb_private::SymbolContext& sc, -                                lldb_private::ClangASTType &clang_type, -                                bool is_signed, -                                uint32_t enumerator_byte_size, -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *enum_die); - -    void                    ParseChildArrayInfo( -                                const lldb_private::SymbolContext& sc, -                                DWARFCompileUnit* dwarf_cu, -                                const DWARFDebugInfoEntry *parent_die, -                                int64_t& first_index, -                                std::vector<uint64_t>& element_orders, -                                uint32_t& byte_stride, -                                uint32_t& bit_stride); - -                            // Given a die_offset, figure out the symbol context representing that die. -    bool                    ResolveFunction (dw_offset_t offset, -                                             DWARFCompileUnit *&dwarf_cu, -                                             bool include_inlines, -                                             lldb_private::SymbolContextList& sc_list); -                             -    bool                    ResolveFunction (DWARFCompileUnit *cu, -                                             const DWARFDebugInfoEntry *die, -                                             bool include_inlines, -                                             lldb_private::SymbolContextList& sc_list); - -    bool                    FunctionDieMatchesPartialName ( -                                const DWARFDebugInfoEntry* die, -                                const DWARFCompileUnit *dwarf_cu, -                                uint32_t name_type_mask, -                                const char *partial_name, -                                const char *base_name_start, -                                const char *base_name_end); - -    void                    FindFunctions( -                                const lldb_private::ConstString &name,  -                                const NameToDIE &name_to_die, -                                bool include_inlines, -                                lldb_private::SymbolContextList& sc_list); - -    void                    FindFunctions ( -                                const lldb_private::RegularExpression ®ex,  -                                const NameToDIE &name_to_die, -                                bool include_inlines, -                                lldb_private::SymbolContextList& sc_list); - -    void                    FindFunctions ( -                                const lldb_private::RegularExpression ®ex,  -                                const DWARFMappedHash::MemoryTable &memory_table, -                                bool include_inlines, -                                lldb_private::SymbolContextList& sc_list); - -    lldb::TypeSP            FindDefinitionTypeForDWARFDeclContext ( -                                const DWARFDeclContext &die_decl_ctx); - -    lldb::TypeSP            FindCompleteObjCDefinitionTypeForDIE ( -                                const DWARFDebugInfoEntry *die,  -                                const lldb_private::ConstString &type_name, -                                bool must_be_implementation); - -    bool                    Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu); - -    lldb::TypeSP            FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name, -                                                            bool header_definition_ok); - -    lldb_private::Symbol *  GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name); - -    void                    ParseFunctions (const DIEArray &die_offsets, -                                            bool include_inlines, -                                            lldb_private::SymbolContextList& sc_list); -    lldb::TypeSP            GetTypeForDIE (DWARFCompileUnit *cu,  -                                           const DWARFDebugInfoEntry* die); - -    uint32_t                FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, lldb_private::TypeList& types); - -    void                    Index(); -     -    void                    DumpIndexes(); -    void                    SetDebugMapModule (const lldb::ModuleSP &module_sp) -                            { -                                m_debug_map_module_wp = module_sp; -                            } +    const lldb_private::DWARFDataExtractor& +    GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment); + +    virtual void +    LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data); + +    bool +    DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx); + +    bool +    DIEInDeclContext (const lldb_private::CompilerDeclContext *parent_decl_ctx, +                      const DWARFDIE &die); + +    virtual DWARFCompileUnit* +    GetDWARFCompileUnit (lldb_private::CompileUnit *comp_unit); + +    DWARFCompileUnit* +    GetNextUnparsedDWARFCompileUnit (DWARFCompileUnit* prev_cu); + +    bool +    GetFunction (const DWARFDIE &die, +                 lldb_private::SymbolContext& sc); + +    lldb_private::Function * +    ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, +                              const DWARFDIE &die); + +    size_t +    ParseFunctionBlocks (const lldb_private::SymbolContext& sc, +                         lldb_private::Block *parent_block, +                         const DWARFDIE &die, +                         lldb::addr_t subprogram_low_pc, +                         uint32_t depth); + +    size_t +    ParseTypes (const lldb_private::SymbolContext& sc, +                const DWARFDIE &die, +                bool parse_siblings, +                bool parse_children); + +    lldb::TypeSP +    ParseType (const lldb_private::SymbolContext& sc, +               const DWARFDIE &die, +               bool *type_is_new); + +    lldb_private::Type * +    ResolveTypeUID (const DWARFDIE &die, +                    bool assert_not_being_parsed); + +    lldb::VariableSP +    ParseVariableDIE(const lldb_private::SymbolContext& sc, +                     const DWARFDIE &die, +                     const lldb::addr_t func_low_pc); + +    size_t +    ParseVariables (const lldb_private::SymbolContext& sc, +                    const DWARFDIE &orig_die, +                    const lldb::addr_t func_low_pc, +                    bool parse_siblings, +                    bool parse_children, +                    lldb_private::VariableList* cc_variable_list = NULL); + +    bool +    ClassOrStructIsVirtual (const DWARFDIE &die); + +    // Given a die_offset, figure out the symbol context representing that die. +    bool +    ResolveFunction (const DIERef& die_ref, +                     bool include_inlines, +                     lldb_private::SymbolContextList& sc_list); + +    bool +    ResolveFunction (const DWARFDIE &die, +                     bool include_inlines, +                     lldb_private::SymbolContextList& sc_list); + +    void +    FindFunctions(const lldb_private::ConstString &name, +                  const NameToDIE &name_to_die, +                  bool include_inlines, +                  lldb_private::SymbolContextList& sc_list); + +    void +    FindFunctions (const lldb_private::RegularExpression ®ex, +                   const NameToDIE &name_to_die, +                   bool include_inlines, +                   lldb_private::SymbolContextList& sc_list); + +    void +    FindFunctions (const lldb_private::RegularExpression ®ex, +                   const DWARFMappedHash::MemoryTable &memory_table, +                   bool include_inlines, +                   lldb_private::SymbolContextList& sc_list); + +    virtual lldb::TypeSP +    FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx); + +    lldb::TypeSP +    FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, +                                          const lldb_private::ConstString &type_name, +                                          bool must_be_implementation); + +    lldb::TypeSP +    FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name, +                                    bool header_definition_ok); + +    lldb_private::Symbol * +    GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name); + +    void +    ParseFunctions (const DIEArray &die_offsets, +                    bool include_inlines, +                    lldb_private::SymbolContextList& sc_list); + +    lldb::TypeSP +    GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context = false); + +    void +    Index(); -    SymbolFileDWARFDebugMap * -                            GetDebugMapSymfile (); +    void +    DumpIndexes(); -    const DWARFDebugInfoEntry * -                            FindBlockContainingSpecification (dw_offset_t func_die_offset,  -                                                              dw_offset_t spec_block_die_offset, -                                                              DWARFCompileUnit **dwarf_cu_handle); +    void +    SetDebugMapModule (const lldb::ModuleSP &module_sp) +    { +        m_debug_map_module_wp = module_sp; +    } + +    SymbolFileDWARFDebugMap * +    GetDebugMapSymfile (); -    const DWARFDebugInfoEntry * -                            FindBlockContainingSpecification (DWARFCompileUnit* dwarf_cu, -                                                              const DWARFDebugInfoEntry *die, -                                                              dw_offset_t spec_block_die_offset, -                                                              DWARFCompileUnit **dwarf_cu_handle); +    DWARFDIE +    FindBlockContainingSpecification (const DIERef& func_die_ref, dw_offset_t spec_block_die_offset); -    clang::NamespaceDecl * -    ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die); +    DWARFDIE +    FindBlockContainingSpecification (const DWARFDIE &die, dw_offset_t spec_block_die_offset); -    UniqueDWARFASTTypeMap & +    virtual UniqueDWARFASTTypeMap &      GetUniqueDWARFASTTypeMap (); - -    void                    LinkDeclContextToDIE (clang::DeclContext *decl_ctx, -                                                  const DWARFDebugInfoEntry *die) -                            { -                                m_die_to_decl_ctx[die] = decl_ctx; -                                // There can be many DIEs for a single decl context -                                m_decl_ctx_to_die[decl_ctx].insert(die); -                            }      bool      UserIDMatches (lldb::user_id_t uid) const      {          const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull; -        if (high_uid) +        if (high_uid != 0 && GetID() != 0)              return high_uid == GetID();          return true;      } -    lldb::user_id_t -    MakeUserID (dw_offset_t die_offset) const -    { -        return GetID() | die_offset; -    } - -    static bool -    DeclKindIsCXXClass (clang::Decl::Kind decl_kind) -    { -        switch (decl_kind) -        { -            case clang::Decl::CXXRecord: -            case clang::Decl::ClassTemplateSpecialization: -                return true; -            default: -                break; -        } -        return false; -    } -     -    bool -    ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu, -                                 const DWARFDebugInfoEntry *parent_die, -                                 lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); -      bool -    ParseTemplateDIE (DWARFCompileUnit* dwarf_cu, -                      const DWARFDebugInfoEntry *die, -                      lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - -    clang::ClassTemplateDecl * -    ParseClassTemplateDecl (clang::DeclContext *decl_ctx, -                            lldb::AccessType access_type, -                            const char *parent_name, -                            int tag_decl_kind, -                            const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - -    bool -    DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1, -                          DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2); +    DIEDeclContextsMatch (const DWARFDIE &die1, +                          const DWARFDIE &die2);      bool -    ClassContainsSelector (DWARFCompileUnit *dwarf_cu, -                           const DWARFDebugInfoEntry *class_die, +    ClassContainsSelector (const DWARFDIE &class_die,                             const lldb_private::ConstString &selector);      bool -    CopyUniqueClassMethodTypes (SymbolFileDWARF *class_symfile, -                                lldb_private::Type *class_type, -                                DWARFCompileUnit* src_cu, -                                const DWARFDebugInfoEntry *src_class_die, -                                DWARFCompileUnit* dst_cu, -                                const DWARFDebugInfoEntry *dst_class_die, -                                DWARFDIECollection &failures); - -    bool      FixupAddress (lldb_private::Address &addr);      typedef std::set<lldb_private::Type *> TypeSet; -    typedef struct { -        lldb_private::ConstString   m_name; -        lldb::ModuleSP              m_module_sp; -    } ClangModuleInfo; -     -    typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap; +    typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;      void -    GetTypes (DWARFCompileUnit* dwarf_cu, -              const DWARFDebugInfoEntry *die, +    GetTypes (const DWARFDIE &die,                dw_offset_t min_die_offset,                dw_offset_t max_die_offset,                uint32_t type_mask, @@ -572,23 +517,37 @@ protected:      void      UpdateExternalModuleListIfNeeded(); +    virtual DIEToTypePtr& +    GetDIEToType() { return m_die_to_type; } + +    virtual DIEToVariableSP& +    GetDIEToVariable() { return m_die_to_variable_sp; } +     +    virtual DIEToClangType& +    GetForwardDeclDieToClangType() { return m_forward_decl_die_to_clang_type; } + +    virtual ClangTypeToDIE& +    GetForwardDeclClangTypeToDie() { return m_forward_decl_clang_type_to_die; } +      lldb::ModuleWP                        m_debug_map_module_wp;      SymbolFileDWARFDebugMap *             m_debug_map_symfile; -    clang::TranslationUnitDecl *          m_clang_tu_decl; -    lldb_private::Flags                   m_flags; -    lldb_private::DWARFDataExtractor      m_dwarf_data;  -    lldb_private::DWARFDataExtractor      m_data_debug_abbrev; -    lldb_private::DWARFDataExtractor      m_data_debug_aranges; -    lldb_private::DWARFDataExtractor      m_data_debug_frame; -    lldb_private::DWARFDataExtractor      m_data_debug_info; -    lldb_private::DWARFDataExtractor      m_data_debug_line; -    lldb_private::DWARFDataExtractor      m_data_debug_loc; -    lldb_private::DWARFDataExtractor      m_data_debug_ranges; -    lldb_private::DWARFDataExtractor      m_data_debug_str; -    lldb_private::DWARFDataExtractor      m_data_apple_names; -    lldb_private::DWARFDataExtractor      m_data_apple_types; -    lldb_private::DWARFDataExtractor      m_data_apple_namespaces; -    lldb_private::DWARFDataExtractor      m_data_apple_objc; +    lldb_private::DWARFDataExtractor      m_dwarf_data; + +    DWARFDataSegment                      m_data_debug_abbrev; +    DWARFDataSegment                      m_data_debug_addr; +    DWARFDataSegment                      m_data_debug_aranges; +    DWARFDataSegment                      m_data_debug_frame; +    DWARFDataSegment                      m_data_debug_info; +    DWARFDataSegment                      m_data_debug_line; +    DWARFDataSegment                      m_data_debug_macro; +    DWARFDataSegment                      m_data_debug_loc; +    DWARFDataSegment                      m_data_debug_ranges; +    DWARFDataSegment                      m_data_debug_str; +    DWARFDataSegment                      m_data_debug_str_offsets; +    DWARFDataSegment                      m_data_apple_names; +    DWARFDataSegment                      m_data_apple_types; +    DWARFDataSegment                      m_data_apple_namespaces; +    DWARFDataSegment                      m_data_apple_objc;      // The unique pointer items below are generated on demand if and when someone accesses      // them through a non const version of this class. @@ -600,6 +559,10 @@ protected:      std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;      std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;      std::unique_ptr<GlobalVariableMap>  m_global_aranges_ap; + +    typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> DebugMacrosMap; +    DebugMacrosMap m_debug_macros_map; +      ExternalTypeModuleMap               m_external_type_modules;      NameToDIE                           m_function_basename_index;  // All concrete functions      NameToDIE                           m_function_fullname_index;  // All concrete functions @@ -610,28 +573,16 @@ protected:      NameToDIE                           m_type_index;               // All type DIE offsets      NameToDIE                           m_namespace_index;          // All type DIE offsets      bool                                m_indexed:1, -                                        m_is_external_ast_source:1,                                          m_using_apple_tables:1,                                          m_fetched_external_modules:1;      lldb_private::LazyBool              m_supports_DW_AT_APPLE_objc_complete_type;      std::unique_ptr<DWARFDebugRanges>     m_ranges;      UniqueDWARFASTTypeMap m_unique_ast_type_map; -    typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet; -    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap; -    typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap; -    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr; -    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP; -    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType; -    typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE; -    typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap; -    DIEToDeclContextMap m_die_to_decl_ctx; -    DeclContextToDIEMap m_decl_ctx_to_die;      DIEToTypePtr m_die_to_type;      DIEToVariableSP m_die_to_variable_sp;      DIEToClangType m_forward_decl_die_to_clang_type;      ClangTypeToDIE m_forward_decl_clang_type_to_die; -    RecordDeclToLayoutMap m_record_decl_to_layout_map;  };  #endif  // SymbolFileDWARF_SymbolFileDWARF_h_ diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index de972acd7ed7a..be25dfc99deea 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1,4 +1,4 @@ -//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===// +//===-- SymbolFileDWARFDebugMap.cpp -----------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -7,6 +7,10 @@  //  //===----------------------------------------------------------------------===// +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "SymbolFileDWARFDebugMap.h"  #include "DWARFDebugAranges.h" @@ -24,11 +28,11 @@  #endif  #include "lldb/Core/Timer.h" -#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/LineTable.h"  #include "lldb/Symbol/ObjectFile.h"  #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.h"  #include "lldb/Symbol/VariableList.h"  #include "LogChannelDWARF.h" @@ -41,9 +45,6 @@ using namespace lldb_private;  // (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"  // (so we can fixup the symbol file id. - - -  const SymbolFileDWARFDebugMap::FileRangeMap &  SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile)  { @@ -173,7 +174,6 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa      return file_range_map;  } -  class DebugMapModule : public Module  {  public: @@ -190,14 +190,10 @@ public:      {      } -    virtual -    ~DebugMapModule () -    { -    } +    ~DebugMapModule() override = default; -     -    virtual SymbolVendor* -    GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) +    SymbolVendor* +    GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) override      {          // Scope for locker          if (m_symfile_ap.get() || can_create == false) @@ -259,7 +255,6 @@ SymbolFileDWARFDebugMap::Terminate()      PluginManager::UnregisterPlugin (CreateInstance);  } -  lldb_private::ConstString  SymbolFileDWARFDebugMap::GetPluginNameStatic()  { @@ -279,7 +274,6 @@ SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)      return new SymbolFileDWARFDebugMap (obj_file);  } -  SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :      SymbolFile(ofile),      m_flags(), @@ -290,7 +284,6 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :  {  } -  SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()  {  } @@ -298,15 +291,6 @@ SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()  void  SymbolFileDWARFDebugMap::InitializeObject()  { -    // Install our external AST source callbacks so we can complete Clang types. -    llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap ( -        new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl, -                                             SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl, -                                             NULL, -                                             SymbolFileDWARFDebugMap::LayoutRecordType, -                                             this)); - -    GetClangASTContext().SetExternalSource (ast_source_ap);  }  void @@ -517,7 +501,6 @@ SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_inf      return NULL;  } -  bool  SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec)  { @@ -532,8 +515,6 @@ SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec      return false;  } - -  ObjectFile *  SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx)  { @@ -561,7 +542,6 @@ SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit      return NULL;  } -  uint32_t  SymbolFileDWARFDebugMap::GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info)  { @@ -637,7 +617,6 @@ SymbolFileDWARFDebugMap::GetNumCompileUnits()      return m_compile_unit_infos.size();  } -  CompUnitSP  SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)  { @@ -660,7 +639,8 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)                                                                                      NULL,                                                                                      so_file_spec,                                                                                      cu_id, -                                                                                    eLanguageTypeUnknown)); +                                                                                    eLanguageTypeUnknown, +                                                                                    false));                  if (m_compile_unit_infos[cu_idx].compile_unit_sp)                  { @@ -687,7 +667,6 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc)      return NULL;  } -  size_t  SymbolFileDWARFDebugMap::GetCompUnitInfosForModule (const lldb_private::Module *module, std::vector<CompileUnitInfo *>& cu_infos)  { @@ -728,6 +707,15 @@ SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc)  }  bool +SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros (const SymbolContext& sc) +{ +    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); +    if (oso_dwarf) +        return oso_dwarf->ParseCompileUnitDebugMacros (sc); +    return false; +} + +bool  SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)  {      SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); @@ -754,7 +742,6 @@ SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)      return 0;  } -  size_t  SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)  { @@ -764,7 +751,6 @@ SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)      return 0;  } -  size_t  SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)  { @@ -774,8 +760,6 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)      return 0;  } - -  Type*  SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)  { @@ -787,10 +771,22 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)  }  bool -SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type) +SymbolFileDWARFDebugMap::CompleteType (CompilerType& compiler_type)  { -    // We have a struct/union/class/enum that needs to be fully resolved. -    return false; +    bool success = false; +    if (compiler_type) +    { +        ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { +            if (oso_dwarf->HasForwardDeclForClangType (compiler_type)) +            { +                oso_dwarf->CompleteType (compiler_type); +                success = true; +                return true; +            } +            return false; +        }); +    } +    return success;  }  uint32_t @@ -834,7 +830,6 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3      return resolved_flags;  } -  uint32_t  SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)  { @@ -871,7 +866,7 @@ uint32_t  SymbolFileDWARFDebugMap::PrivateFindGlobalVariables  (      const ConstString &name, -    const ClangNamespaceDecl *namespace_decl, +    const CompilerDeclContext *parent_decl_ctx,      const std::vector<uint32_t> &indexes,   // Indexes into the symbol table that match "name"      uint32_t max_matches,      VariableList& variables @@ -888,7 +883,7 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables              SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);              if (oso_dwarf)              { -                if (oso_dwarf->FindGlobalVariables(name, namespace_decl, true, max_matches, variables)) +                if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true, max_matches, variables))                      if (variables.GetSize() > max_matches)                          break;              } @@ -898,7 +893,11 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables  }  uint32_t -SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) +SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, +                                              const CompilerDeclContext *parent_decl_ctx, +                                              bool append, +                                              uint32_t max_matches, +                                              VariableList& variables)  {      // If we aren't appending the results to this list, then clear the list @@ -913,7 +912,7 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla      ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {          const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (name, -                                                                     namespace_decl, +                                                                     parent_decl_ctx,                                                                       true,                                                                       max_matches,                                                                       variables); @@ -941,7 +940,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla      return variables.GetSize() - original_size;  } -  uint32_t  SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)  { @@ -983,7 +981,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bo      return variables.GetSize() - original_size;  } -  int  SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)  { @@ -998,7 +995,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr      return 1;  } -  int  SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)  { @@ -1013,7 +1009,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr,      return 1;  } -  SymbolFileDWARFDebugMap::CompileUnitInfo*  SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr)  { @@ -1062,7 +1057,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID (user_id_t symbol_id,      return comp_unit_info;  } -  static void  RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextList &sc_list, uint32_t start_idx)  { @@ -1091,7 +1085,12 @@ RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextLis  }  uint32_t -SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) +SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, +                                       const CompilerDeclContext *parent_decl_ctx, +                                       uint32_t name_type_mask, +                                       bool include_inlines, +                                       bool append, +                                       SymbolContextList& sc_list)  {      Timer scoped_timer (__PRETTY_FUNCTION__,                          "SymbolFileDWARFDebugMap::FindFunctions (name = %s)", @@ -1105,7 +1104,7 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames      ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {          uint32_t sc_idx = sc_list.GetSize(); -        if (oso_dwarf->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, true, sc_list)) +        if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, true, sc_list))          {              RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx);          } @@ -1115,7 +1114,6 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames      return sc_list.GetSize() - initial_size;  } -  uint32_t  SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)  { @@ -1150,8 +1148,7 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,      Timer scoped_timer (__PRETTY_FUNCTION__,                          "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",                          type_mask); -     -     +      uint32_t initial_size = type_list.GetSize();      SymbolFileDWARF *oso_dwarf = NULL;      if (sc_scope) @@ -1177,7 +1174,6 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,      return type_list.GetSize() - initial_size;  } -  TypeSP  SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)  { @@ -1189,8 +1185,6 @@ SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclC      return type_sp;  } - -  bool  SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso)  { @@ -1210,7 +1204,7 @@ SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWAR  }  TypeSP -SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,  +SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,                                                                 const ConstString &type_name,                                                                 bool must_be_implementation)  { @@ -1280,10 +1274,10 @@ SymbolFileDWARFDebugMap::FindTypes  (      const SymbolContext& sc,       const ConstString &name, -    const ClangNamespaceDecl *namespace_decl, -    bool append,  +    const CompilerDeclContext *parent_decl_ctx, +    bool append,      uint32_t max_matches,  -    TypeList& types +    TypeMap& types  )  {      if (!append) @@ -1296,12 +1290,12 @@ SymbolFileDWARFDebugMap::FindTypes      {          oso_dwarf = GetSymbolFile (sc);          if (oso_dwarf) -            return oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types); +            return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);      }      else      {          ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { -            oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types); +            oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);              return false;          });      } @@ -1320,24 +1314,24 @@ SymbolFileDWARFDebugMap::FindTypes  //} -ClangNamespaceDecl +CompilerDeclContext  SymbolFileDWARFDebugMap::FindNamespace (const lldb_private::SymbolContext& sc,                                           const lldb_private::ConstString &name, -                                        const ClangNamespaceDecl *parent_namespace_decl) +                                        const CompilerDeclContext *parent_decl_ctx)  { -    ClangNamespaceDecl matching_namespace; +    CompilerDeclContext matching_namespace;      SymbolFileDWARF *oso_dwarf;      if (sc.comp_unit)      {          oso_dwarf = GetSymbolFile (sc);          if (oso_dwarf) -            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl); +            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);      }      else      {          ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { -            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl); +            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);              return (bool)matching_namespace;          }); @@ -1401,7 +1395,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf)      return NULL;  } -  void  SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp)  { @@ -1427,78 +1420,33 @@ SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompU      }  } - -void -SymbolFileDWARFDebugMap::CompleteTagDecl (void *baton, clang::TagDecl *decl) -{ -    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; -    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); -    if (clang_type) -    { -        symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { -            if (oso_dwarf->HasForwardDeclForClangType (clang_type)) -            { -                oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -                return true; -            } -            return false; -        }); -    } -} - -void -SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl) -{ -    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; -    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl); -    if (clang_type) -    { -        symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { -            if (oso_dwarf->HasForwardDeclForClangType (clang_type)) -            { -                oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type); -                return true; -            } -            return false; -        }); -    } -} - -bool -SymbolFileDWARFDebugMap::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, -                                          uint64_t &alignment, -                                          llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                                          llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets) -{ -    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton; -    bool laid_out = false; -    symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { -        return (laid_out = oso_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets)); -    }); -    return laid_out; -} - - - -clang::DeclContext* -SymbolFileDWARFDebugMap::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARFDebugMap::GetDeclContextForUID (lldb::user_id_t type_uid)  {      const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);      SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);      if (oso_dwarf) -        return oso_dwarf->GetClangDeclContextContainingTypeUID (type_uid); -    return NULL; +        return oso_dwarf->GetDeclContextForUID (type_uid); +    return CompilerDeclContext();  } -clang::DeclContext* -SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) +CompilerDeclContext +SymbolFileDWARFDebugMap::GetDeclContextContainingUID (lldb::user_id_t type_uid)  {      const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);      SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);      if (oso_dwarf) -        return oso_dwarf->GetClangDeclContextForTypeUID (sc, type_uid); -    return NULL; +        return oso_dwarf->GetDeclContextContainingUID (type_uid); +    return CompilerDeclContext(); +} + +void +SymbolFileDWARFDebugMap::ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) +{ +    ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { +        oso_dwarf->ParseDeclsForContext (decl_ctx); +        return true; // Keep iterating +    });  }  bool @@ -1613,7 +1561,6 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA                  const FileRangeMap::Entry* entry = file_range_map.GetEntryAtIndex(idx);                  if (entry)                  { -                    printf ("[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", entry->GetRangeBase(), entry->GetRangeEnd());                      debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(), entry->GetRangeEnd());                      num_line_entries_added++;                  } @@ -1622,4 +1569,3 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA      }      return num_line_entries_added;  } - diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index ce0cfd744f0b5..1eb33c927bdfb 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -14,19 +14,14 @@  #include <vector>  #include <bitset> -#include "clang/AST/CharUnits.h" -  #include "lldb/Core/RangeMap.h"  #include "lldb/Symbol/SymbolFile.h"  #include "UniqueDWARFASTType.h"  class SymbolFileDWARF; -class DWARFCompileUnit;  class DWARFDebugAranges; -class DWARFDebugInfoEntry;  class DWARFDeclContext; -class DebugMapModule;  class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile  { @@ -57,7 +52,6 @@ public:      ~SymbolFileDWARFDebugMap () override;      uint32_t        CalculateAbilities () override; -      void            InitializeObject() override;      //------------------------------------------------------------------ @@ -69,6 +63,7 @@ public:      lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override;      size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override;      bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override; +    bool            ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override;      bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override;      bool            ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override;      size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; @@ -76,39 +71,26 @@ public:      size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc) override;      lldb_private::Type* ResolveTypeUID (lldb::user_id_t type_uid) override; -    clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) override; -    clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) override; -    bool            ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type) override; +    lldb_private::CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) override; +    lldb_private::CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) override; +    void ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override; + +    bool            CompleteType (lldb_private::CompilerType& compiler_type) override;      uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc) override;      uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list) override; -    uint32_t        FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override; +    uint32_t        FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;      uint32_t        FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override; -    uint32_t        FindFunctions (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override; +    uint32_t        FindFunctions (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;      uint32_t        FindFunctions (const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override; -    uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types) override; -    lldb_private::ClangNamespaceDecl +    uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::TypeMap& types) override; +    lldb_private::CompilerDeclContext                      FindNamespace (const lldb_private::SymbolContext& sc,                                     const lldb_private::ConstString &name, -                                   const lldb_private::ClangNamespaceDecl *parent_namespace_decl) override; +                                   const lldb_private::CompilerDeclContext *parent_decl_ctx) override;      size_t          GetTypes (lldb_private::SymbolContextScope *sc_scope,                                uint32_t type_mask,                                lldb_private::TypeList &type_list) override; - -    //------------------------------------------------------------------ -    // ClangASTContext callbacks for external source lookups. -    //------------------------------------------------------------------ -    static void -    CompleteTagDecl (void *baton, clang::TagDecl *); -     -    static void -    CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *); - -    static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, -                                 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, -                                 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets, -                                 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets); -      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ @@ -128,6 +110,7 @@ protected:      friend class DWARFCompileUnit;      friend class SymbolFileDWARF;      friend class DebugMapModule; +    friend class DWARFASTParserClang;      struct OSOInfo      {          lldb::ModuleSP module_sp; @@ -259,7 +242,7 @@ protected:      uint32_t      PrivateFindGlobalVariables (const lldb_private::ConstString &name, -                                const lldb_private::ClangNamespaceDecl *namespace_decl, +                                const lldb_private::CompilerDeclContext *parent_decl_ctx,                                  const std::vector<uint32_t> &name_symbol_indexes,                                  uint32_t max_matches,                                  lldb_private::VariableList& variables); @@ -281,7 +264,7 @@ protected:      Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso);      lldb::TypeSP -    FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,  +    FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,                                            const lldb_private::ConstString &type_name,                                            bool must_be_implementation); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp new file mode 100644 index 0000000000000..326c397c83d56 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -0,0 +1,131 @@ +//===-- SymbolFileDWARFDwo.cpp ----------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFileDWARFDwo.h" + +#include "lldb/Core/Section.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfo.h" + +using namespace lldb; +using namespace lldb_private; + +SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu) : +    SymbolFileDWARF(objfile.get()), +    m_obj_file_sp(objfile), +    m_base_dwarf_cu(dwarf_cu) +{ +    SetID(((lldb::user_id_t)dwarf_cu->GetOffset())<<32); +} + +void +SymbolFileDWARFDwo::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data) +{ +    const SectionList* section_list = m_obj_file->GetSectionList(false /* update_module_section_list */); +    if (section_list) +    { +        SectionSP section_sp (section_list->FindSectionByType(sect_type, true)); +        if (section_sp) +        { +            // See if we memory mapped the DWARF segment? +            if (m_dwarf_data.GetByteSize()) +            { +                data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize()); +                return; +            } + +            if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0) +                return; + +            data.Clear(); +        } +    } + +    SymbolFileDWARF::LoadSectionData(sect_type, data); +} + +lldb::CompUnitSP +SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) +{ +    assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible compile unit"); +    return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX); +} + +DWARFCompileUnit* +SymbolFileDWARFDwo::GetCompileUnit() +{ +    // Only dwo files with 1 compile unit is supported +    if (GetNumCompileUnits() == 1) +        return DebugInfo()->GetCompileUnitAtIndex(0); +    else +        return nullptr; +} + +DWARFCompileUnit* +SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) +{ +    return GetCompileUnit(); +} + +SymbolFileDWARF::DIEToTypePtr& +SymbolFileDWARFDwo::GetDIEToType() +{ +    return GetBaseSymbolFile()->GetDIEToType(); +} + +SymbolFileDWARF::DIEToVariableSP& +SymbolFileDWARFDwo::GetDIEToVariable() +{ +    return GetBaseSymbolFile()->GetDIEToVariable(); +} + +SymbolFileDWARF::DIEToClangType& +SymbolFileDWARFDwo::GetForwardDeclDieToClangType() +{ +    return GetBaseSymbolFile()->GetForwardDeclDieToClangType(); +} + +SymbolFileDWARF::ClangTypeToDIE& +SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie() +{ +    return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie(); +} + +UniqueDWARFASTTypeMap& +SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap() +{ +    return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap(); +} + +lldb::TypeSP +SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) +{ +    return GetBaseSymbolFile()->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); +} + +SymbolFileDWARF* +SymbolFileDWARFDwo::GetBaseSymbolFile() +{ +    return m_base_dwarf_cu->GetSymbolFileDWARF(); +} + +DWARFExpression::LocationListFormat +SymbolFileDWARFDwo::GetLocationListFormat() const +{ +    return DWARFExpression::SplitDwarfLocationList; +} + +TypeSystem* +SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) +{ +    return GetBaseSymbolFile()->GetTypeSystemForLanguage(language); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h new file mode 100644 index 0000000000000..39ed6502229b5 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -0,0 +1,70 @@ +//===-- SymbolFileDWARFDwo.h ------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ +#define SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "SymbolFileDWARF.h" + +class SymbolFileDWARFDwo : public SymbolFileDWARF +{ +public: +    SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu); + +    ~SymbolFileDWARFDwo() override = default; +     +    lldb::CompUnitSP +    ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) override; + +    DWARFCompileUnit* +    GetCompileUnit(); + +    DWARFCompileUnit* +    GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override; + +    lldb_private::DWARFExpression::LocationListFormat +    GetLocationListFormat() const override; + +    lldb_private::TypeSystem* +    GetTypeSystemForLanguage(lldb::LanguageType language) override; + +protected: +    void +    LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data) override; + +    DIEToTypePtr& +    GetDIEToType() override; + +    DIEToVariableSP& +    GetDIEToVariable() override; +     +    DIEToClangType& +    GetForwardDeclDieToClangType() override; + +    ClangTypeToDIE& +    GetForwardDeclClangTypeToDie() override; + +    UniqueDWARFASTTypeMap& +    GetUniqueDWARFASTTypeMap() override; + +    lldb::TypeSP +    FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) override; + +    SymbolFileDWARF* +    GetBaseSymbolFile(); + +    lldb::ObjectFileSP m_obj_file_sp; +    DWARFCompileUnit* m_base_dwarf_cu; +}; + +#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_ diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp index 94044c0feb30f..2ca407b9e48a0 100644 --- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp +++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp @@ -15,58 +15,51 @@  // Project includes  #include "lldb/Symbol/Declaration.h" -#include "DWARFDebugInfoEntry.h" -  bool -UniqueDWARFASTTypeList::Find  -( -    SymbolFileDWARF *symfile, -    const DWARFCompileUnit *cu, -    const DWARFDebugInfoEntry *die,  -    const lldb_private::Declaration &decl, -    const int32_t byte_size, -    UniqueDWARFASTType &entry -) const +UniqueDWARFASTTypeList::Find (const DWARFDIE &die, +                              const lldb_private::Declaration &decl, +                              const int32_t byte_size, +                              UniqueDWARFASTType &entry) const  { -    collection::const_iterator pos, end = m_collection.end(); -    for (pos = m_collection.begin(); pos != end; ++pos) +    for (const UniqueDWARFASTType &udt : m_collection)      {          // Make sure the tags match -        if (pos->m_die->Tag() == die->Tag()) +        if (udt.m_die.Tag() == die.Tag())          {              // Validate byte sizes of both types only if both are valid. -            if (pos->m_byte_size < 0 || byte_size < 0 || pos->m_byte_size == byte_size) +            if (udt.m_byte_size < 0 || byte_size < 0 || udt.m_byte_size == byte_size)              {                  // Make sure the file and line match -                if (pos->m_declaration == decl) +                if (udt.m_declaration == decl)                  {                      // The type has the same name, and was defined on the same                      // file and line. Now verify all of the parent DIEs match. -                    const DWARFDebugInfoEntry *parent_arg_die = die->GetParent(); -                    const DWARFDebugInfoEntry *parend_pos_die = pos->m_die->GetParent(); +                    DWARFDIE parent_arg_die = die.GetParent(); +                    DWARFDIE parent_pos_die = udt.m_die.GetParent();                      bool match = true;                      bool done = false; -                    while (!done && match && parent_arg_die && parend_pos_die) +                    while (!done && match && parent_arg_die && parent_pos_die)                      { -                        if (parent_arg_die->Tag() == parend_pos_die->Tag()) +                        const dw_tag_t parent_arg_tag = parent_arg_die.Tag(); +                        const dw_tag_t parent_pos_tag = parent_pos_die.Tag(); +                        if (parent_arg_tag == parent_pos_tag)                          { -                            const dw_tag_t tag = parent_arg_die->Tag(); -                            switch (tag) +                            switch (parent_arg_tag)                              {                              case DW_TAG_class_type:                              case DW_TAG_structure_type:                              case DW_TAG_union_type:                              case DW_TAG_namespace:                                  { -                                    const char *parent_arg_die_name = parent_arg_die->GetName(symfile, cu); +                                    const char *parent_arg_die_name = parent_arg_die.GetName();                                      if (parent_arg_die_name == NULL)  // Anonymous (i.e. no-name) struct                                      {                                          match = false;                                      }                                      else                                      { -                                        const char *parent_pos_die_name = parend_pos_die->GetName(pos->m_symfile, pos->m_cu); -                                        if (parent_pos_die_name == NULL || strcmp (parent_arg_die_name, parent_pos_die_name)) +                                        const char *parent_pos_die_name = parent_pos_die.GetName(); +                                        if (parent_pos_die_name == NULL || ((parent_arg_die_name != parent_pos_die_name) && strcmp (parent_arg_die_name, parent_pos_die_name)))                                              match = false;                                      }                                  } @@ -77,13 +70,13 @@ UniqueDWARFASTTypeList::Find                                  break;                              }                          } -                        parent_arg_die = parent_arg_die->GetParent(); -                        parend_pos_die = parend_pos_die->GetParent(); +                        parent_arg_die = parent_arg_die.GetParent(); +                        parent_pos_die = parent_pos_die.GetParent();                      }                      if (match)                      { -                        entry = *pos; +                        entry = udt;                          return true;                      }                  } diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h index c85e175235ca6..b7b18efd87690 100644 --- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h +++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h @@ -19,10 +19,7 @@  // Project includes  #include "lldb/Symbol/Declaration.h" - -class DWARFCompileUnit; -class DWARFDebugInfoEntry; -class SymbolFileDWARF; +#include "DWARFDIE.h"  class UniqueDWARFASTType  { @@ -32,23 +29,17 @@ public:  	//------------------------------------------------------------------  	UniqueDWARFASTType () :          m_type_sp (), -        m_symfile (NULL), -        m_cu (NULL), -        m_die (NULL), +        m_die (),          m_declaration (),          m_byte_size (-1) // Set to negative value to make sure we have a valid value      {      }  	UniqueDWARFASTType (lldb::TypeSP &type_sp, -                        SymbolFileDWARF *symfile, -                        DWARFCompileUnit *cu, -                        DWARFDebugInfoEntry *die, +                        const DWARFDIE &die,                          const lldb_private::Declaration &decl,                          int32_t byte_size) :          m_type_sp (type_sp), -        m_symfile (symfile), -        m_cu (cu),          m_die (die),          m_declaration (decl),          m_byte_size (byte_size) @@ -57,8 +48,6 @@ public:      UniqueDWARFASTType (const UniqueDWARFASTType &rhs) :          m_type_sp (rhs.m_type_sp), -        m_symfile (rhs.m_symfile), -        m_cu (rhs.m_cu),          m_die (rhs.m_die),          m_declaration (rhs.m_declaration),          m_byte_size (rhs.m_byte_size) @@ -75,8 +64,6 @@ public:          if (this != &rhs)          {              m_type_sp = rhs.m_type_sp; -            m_symfile = rhs.m_symfile; -            m_cu = rhs.m_cu;              m_die = rhs.m_die;              m_declaration = rhs.m_declaration;              m_byte_size = rhs.m_byte_size; @@ -85,9 +72,7 @@ public:      }      lldb::TypeSP m_type_sp; -    SymbolFileDWARF *m_symfile; -    const DWARFCompileUnit *m_cu; -    const DWARFDebugInfoEntry *m_die; +    DWARFDIE m_die;      lldb_private::Declaration m_declaration;      int32_t m_byte_size;  }; @@ -117,9 +102,7 @@ public:      }      bool -    Find (SymbolFileDWARF *symfile, -          const DWARFCompileUnit *cu, -          const DWARFDebugInfoEntry *die,  +    Find (const DWARFDIE &die,            const lldb_private::Declaration &decl,            const int32_t byte_size,            UniqueDWARFASTType &entry) const; @@ -149,10 +132,8 @@ public:      }      bool -    Find (const lldb_private::ConstString &name,  -          SymbolFileDWARF *symfile, -          const DWARFCompileUnit *cu, -          const DWARFDebugInfoEntry *die,  +    Find (const lldb_private::ConstString &name, +          const DWARFDIE &die,            const lldb_private::Declaration &decl,            const int32_t byte_size,            UniqueDWARFASTType &entry) const @@ -161,7 +142,7 @@ public:          collection::const_iterator pos = m_collection.find (unique_name_cstr);          if (pos != m_collection.end())          { -            return pos->second.Find (symfile, cu, die, decl, byte_size, entry); +            return pos->second.Find (die, decl, byte_size, entry);          }          return false;      } diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 09b919782608f..d3dd1ae923e02 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -12,7 +12,6 @@  #include "lldb/Core/PluginManager.h"  #include "lldb/Core/RegularExpression.h"  #include "lldb/Core/Timer.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h"  #include "lldb/Symbol/CompileUnit.h"  #include "lldb/Symbol/Function.h"  #include "lldb/Symbol/ObjectFile.h" @@ -79,14 +78,6 @@ SymbolFileSymtab::~SymbolFileSymtab()  {  } -ClangASTContext &        -SymbolFileSymtab::GetClangASTContext () -{     -    ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext(); -     -    return ast; -} -  uint32_t  SymbolFileSymtab::CalculateAbilities ()  { @@ -115,6 +106,7 @@ SymbolFileSymtab::CalculateAbilities ()              if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes))              {                  symtab->SortSymbolIndexesByValue(m_code_indexes, true); +                abilities |= Functions;              }              if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes)) @@ -161,7 +153,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)      {          const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);          if (cu_symbol) -            cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown)); +            cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false));      }      return cu_sp;  } @@ -261,6 +253,12 @@ SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)  }  bool +SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc) +{ +    return false; +} + +bool  SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)  {      return false; @@ -299,17 +297,11 @@ SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)  }  bool -SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type) +SymbolFileSymtab::CompleteType (lldb_private::CompilerType& compiler_type)  {      return false;  } -ClangNamespaceDecl  -SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl) -{ -    return ClangNamespaceDecl(); -} -  uint32_t  SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)  { @@ -326,63 +318,6 @@ SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve      return resolved_flags;  } -uint32_t -SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) -{ -    return 0; -} - -uint32_t -SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) -{ -    return 0; -} - -uint32_t -SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) -{ -    return 0; -} - -uint32_t -SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines,  bool append, SymbolContextList& sc_list) -{ -    Timer scoped_timer (__PRETTY_FUNCTION__, -                        "SymbolFileSymtab::FindFunctions (name = '%s')", -                        name.GetCString()); -    // If we ever support finding STABS or COFF debug info symbols,  -    // we will need to add support here. We are not trying to find symbols -    // here, just "lldb_private::Function" objects that come from complete  -    // debug information. Any symbol queries should go through the symbol -    // table itself in the module's object file. -    return 0; -} - -uint32_t -SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) -{ -    Timer scoped_timer (__PRETTY_FUNCTION__, -                        "SymbolFileSymtab::FindFunctions (regex = '%s')", -                        regex.GetText()); -    // If we ever support finding STABS or COFF debug info symbols,  -    // we will need to add support here. We are not trying to find symbols -    // here, just "lldb_private::Function" objects that come from complete  -    // debug information. Any symbol queries should go through the symbol -    // table itself in the module's object file. -    return 0; -} - -uint32_t -SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,  -                             const lldb_private::ConstString &name,  -                             const ClangNamespaceDecl *namespace_decl,  -                             bool append,  -                             uint32_t max_matches,  -                             lldb_private::TypeList& types) -{ -    return 0; -} -  //------------------------------------------------------------------  // PluginInterface protocol  //------------------------------------------------------------------ diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h index d606419a0d948..4648da49cb9fa 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h @@ -10,14 +10,26 @@  #ifndef liblldb_SymbolFileSymtab_h_  #define liblldb_SymbolFileSymtab_h_ +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes  #include "lldb/Symbol/SymbolFile.h"  #include "lldb/Symbol/Symtab.h" -#include <vector>  class SymbolFileSymtab : public lldb_private::SymbolFile  {  public:      //------------------------------------------------------------------ +    // Constructors and Destructors +    //------------------------------------------------------------------ +    SymbolFileSymtab(lldb_private::ObjectFile* obj_file); + +    ~SymbolFileSymtab() override; + +    //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------      static void @@ -35,94 +47,71 @@ public:      static lldb_private::SymbolFile*      CreateInstance (lldb_private::ObjectFile* obj_file); -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ -    SymbolFileSymtab(lldb_private::ObjectFile* obj_file); - -    virtual -    ~SymbolFileSymtab(); - -    virtual uint32_t        CalculateAbilities (); +    uint32_t +    CalculateAbilities() override;      //------------------------------------------------------------------      // Compile Unit function calls      //------------------------------------------------------------------ -    virtual uint32_t -    GetNumCompileUnits(); - -    virtual lldb::CompUnitSP -    ParseCompileUnitAtIndex(uint32_t index); - -    virtual lldb::LanguageType -    ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc); - -    virtual size_t -    ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc); - -    virtual bool -    ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc); +    uint32_t +    GetNumCompileUnits() override; -    virtual bool -    ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files); -     -    virtual bool -    ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules); - -    virtual size_t -    ParseFunctionBlocks (const lldb_private::SymbolContext& sc); - -    virtual size_t -    ParseTypes (const lldb_private::SymbolContext& sc); +    lldb::CompUnitSP +    ParseCompileUnitAtIndex(uint32_t index) override; -    virtual size_t -    ParseVariablesForContext (const lldb_private::SymbolContext& sc); +    lldb::LanguageType +    ParseCompileUnitLanguage(const lldb_private::SymbolContext& sc) override; -    virtual lldb_private::Type* -    ResolveTypeUID(lldb::user_id_t type_uid); +    size_t +    ParseCompileUnitFunctions(const lldb_private::SymbolContext& sc) override; -    virtual bool -    ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type); +    bool +    ParseCompileUnitLineTable(const lldb_private::SymbolContext& sc) override; -    virtual uint32_t -    ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc); +    bool +    ParseCompileUnitDebugMacros(const lldb_private::SymbolContext& sc) override; -    virtual uint32_t -    ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list); +    bool +    ParseCompileUnitSupportFiles(const lldb_private::SymbolContext& sc, +                                 lldb_private::FileSpecList &support_files) override; +     +    bool +    ParseImportedModules(const lldb_private::SymbolContext &sc, +                         std::vector<lldb_private::ConstString> &imported_modules) override; -    virtual uint32_t -    FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables); +    size_t +    ParseFunctionBlocks(const lldb_private::SymbolContext& sc) override; -    virtual uint32_t -    FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables); +    size_t +    ParseTypes(const lldb_private::SymbolContext& sc) override; -    virtual uint32_t -    FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); +    size_t +    ParseVariablesForContext(const lldb_private::SymbolContext& sc) override; -    virtual uint32_t -    FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list); +    lldb_private::Type* +    ResolveTypeUID(lldb::user_id_t type_uid) override; -    virtual uint32_t -    FindTypes (const lldb_private::SymbolContext& sc,const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types); +    bool +    CompleteType(lldb_private::CompilerType& compiler_type) override; -    virtual size_t -    GetTypes (lldb_private::SymbolContextScope *sc_scope, -              uint32_t type_mask, -              lldb_private::TypeList &type_list); +    uint32_t +    ResolveSymbolContext(const lldb_private::Address& so_addr, +                         uint32_t resolve_scope, +                         lldb_private::SymbolContext& sc) override; -    virtual lldb_private::ClangNamespaceDecl -    FindNamespace (const lldb_private::SymbolContext& sc,  -                   const lldb_private::ConstString &name,  -                   const lldb_private::ClangNamespaceDecl *parent_namespace_decl); +    size_t +    GetTypes(lldb_private::SymbolContextScope *sc_scope, +             uint32_t type_mask, +             lldb_private::TypeList &type_list) override;      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  protected:      typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap; @@ -133,13 +122,9 @@ protected:      lldb_private::Symtab::IndexCollection m_data_indexes;      lldb_private::Symtab::NameToIndexMap m_objc_class_name_to_index;      TypeMap m_objc_class_types; - -    lldb_private::ClangASTContext & -    GetClangASTContext ();  private:      DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab);  }; - -#endif  // liblldb_SymbolFileSymtab_h_ +#endif // liblldb_SymbolFileSymtab_h_ diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp index a9f8f36e610e2..3cd1b68d7b0f3 100644 --- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp +++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp @@ -142,17 +142,19 @@ SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::                      static const SectionType g_sections[] =                      { -                        eSectionTypeDWARFDebugAranges, -                        eSectionTypeDWARFDebugInfo,                          eSectionTypeDWARFDebugAbbrev, +                        eSectionTypeDWARFDebugAddr, +                        eSectionTypeDWARFDebugAranges,                          eSectionTypeDWARFDebugFrame, +                        eSectionTypeDWARFDebugInfo,                          eSectionTypeDWARFDebugLine, -                        eSectionTypeDWARFDebugStr,                          eSectionTypeDWARFDebugLoc,                          eSectionTypeDWARFDebugMacInfo,                          eSectionTypeDWARFDebugPubNames,                          eSectionTypeDWARFDebugPubTypes,                          eSectionTypeDWARFDebugRanges, +                        eSectionTypeDWARFDebugStr, +                        eSectionTypeDWARFDebugStrOffsets,                          eSectionTypeELFSymbolTable,                      };                      for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx) diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h index acd62b6cc3ab7..425ff9efc59c1 100644 --- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h +++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h @@ -1,4 +1,4 @@ -//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===// +//===-- SymbolVendorELF.h ---------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,6 +10,10 @@  #ifndef liblldb_SymbolVendorELF_h_  #define liblldb_SymbolVendorELF_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Symbol/SymbolVendor.h" @@ -17,6 +21,13 @@ class SymbolVendorELF : public lldb_private::SymbolVendor  {  public:      //------------------------------------------------------------------ +    // Constructors and Destructors +    //------------------------------------------------------------------ +    SymbolVendorELF (const lldb::ModuleSP &module_sp); + +    ~SymbolVendorELF() override; + +    //------------------------------------------------------------------      // Static Functions      //------------------------------------------------------------------      static void @@ -35,24 +46,16 @@ public:      CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);      //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ -    SymbolVendorELF (const lldb::ModuleSP &module_sp); - -    virtual -    ~SymbolVendorELF(); - -    //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  private:      DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF);  }; -#endif  // liblldb_SymbolVendorELF_h_ +#endif // liblldb_SymbolVendorELF_h_ diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index 8f5d92697501c..eb5fec34fc200 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -117,21 +117,13 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&                  // cache the pc register number (in whatever register numbering this UnwindPlan uses) for                  // quick reference during instruction parsing. -                uint32_t pc_reg_num = LLDB_INVALID_REGNUM;                  RegisterInfo pc_reg_info; -                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) -                    pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()]; -                else -                    pc_reg_num = LLDB_INVALID_REGNUM; +                m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info);                  // cache the return address register number (in whatever register numbering this UnwindPlan uses) for                  // quick reference during instruction parsing. -                uint32_t ra_reg_num = LLDB_INVALID_REGNUM;                  RegisterInfo ra_reg_info; -                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info)) -                    ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()]; -                else -                    ra_reg_num = LLDB_INVALID_REGNUM; +                m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);                  for (size_t idx=0; idx<num_instructions; ++idx)                  { @@ -511,7 +503,8 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,          log->PutCString(strm.GetData());      } -    SetRegisterValue (*reg_info, reg_value); +    if (!instruction->IsInstructionConditional()) +        SetRegisterValue (*reg_info, reg_value);      switch (context.type)      { @@ -573,18 +566,45 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,          case EmulateInstruction::eContextPopRegisterOffStack:              { -                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; -                const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; -                if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) +                if (!instruction->IsInstructionConditional())                  { -                    m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false); -                    m_curr_row_modified = true; +                    const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; +                    const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric]; +                    if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP) +                    { +                        switch (context.info_type) +                        { +                            case EmulateInstruction::eInfoTypeAddress: +                                if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() && +                                    context.info.address == m_pushed_regs[reg_num]) +                                { +                                    m_curr_row->SetRegisterLocationToSame(reg_num, +                                                                          false /*must_replace*/); +                                    m_curr_row_modified = true; +                                } +                                break; +                            case EmulateInstruction::eInfoTypeISA: +                                assert((generic_regnum == LLDB_REGNUM_GENERIC_PC || +                                        generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) && +                                       "eInfoTypeISA used for poping a register other the the PC/FLAGS"); +                                if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) +                                { +                                    m_curr_row->SetRegisterLocationToSame(reg_num, +                                                                          false /*must_replace*/); +                                    m_curr_row_modified = true; +                                } +                                break; +                            default: +                                assert(false && "unhandled case, add code to handle this!"); +                                break; +                        } +                    }                  }              }              break;          case EmulateInstruction::eContextSetFramePointer: -            if (!m_fp_is_cfa) +            if (!m_fp_is_cfa && !instruction->IsInstructionConditional())              {                  m_fp_is_cfa = true;                  m_cfa_reg_info = *reg_info; @@ -599,7 +619,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,          case EmulateInstruction::eContextAdjustStackPointer:              // If we have created a frame using the frame pointer, don't follow              // subsequent adjustments to the stack pointer. -            if (!m_fp_is_cfa) +            if (!m_fp_is_cfa && !instruction->IsInstructionConditional())              {                  m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(                          m_curr_row->GetCFAValue().GetRegisterNumber(), diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h index bf6d017370cc2..61d3ece3f6c36 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h @@ -1,4 +1,4 @@ -//===-- UnwindAssemblyInstEmulation.h ----------------------------*- C++ -*-===// +//===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,6 +10,10 @@  #ifndef liblldb_UnwindAssemblyInstEmulation_h_  #define liblldb_UnwindAssemblyInstEmulation_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Core/EmulateInstruction.h"  #include "lldb/Core/RegisterValue.h" @@ -19,32 +23,28 @@  class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly  {  public: +    ~UnwindAssemblyInstEmulation() override = default; -    virtual -    ~UnwindAssemblyInstEmulation ()  -    { -    } - -    virtual bool -    GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,  -                                          lldb_private::Thread& thread,  -                                          lldb_private::UnwindPlan& unwind_plan); +    bool +    GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func, +                                         lldb_private::Thread& thread, +                                         lldb_private::UnwindPlan& unwind_plan) override; -    virtual bool -    AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func, -                                   lldb_private::Thread& thread, -                                   lldb_private::UnwindPlan& unwind_plan); +    bool +    AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func, +                                  lldb_private::Thread& thread, +                                  lldb_private::UnwindPlan& unwind_plan) override; -    virtual bool -    GetFastUnwindPlan (lldb_private::AddressRange& func,  -                       lldb_private::Thread& thread,  -                       lldb_private::UnwindPlan &unwind_plan); +    bool +    GetFastUnwindPlan(lldb_private::AddressRange& func, +                      lldb_private::Thread& thread, +                      lldb_private::UnwindPlan &unwind_plan) override;      // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch). -    virtual bool -    FirstNonPrologueInsn (lldb_private::AddressRange& func,  -                          const lldb_private::ExecutionContext &exe_ctx,  -                          lldb_private::Address& first_non_prologue_insn); +    bool +    FirstNonPrologueInsn(lldb_private::AddressRange& func, +                         const lldb_private::ExecutionContext &exe_ctx, +                         lldb_private::Address& first_non_prologue_insn) override;      static lldb_private::UnwindAssembly *      CreateInstance (const lldb_private::ArchSpec &arch); @@ -64,14 +64,36 @@ public:      static const char *      GetPluginDescriptionStatic(); -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  private: -     +    // Call CreateInstance to get an instance of this class +    UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch, +                                lldb_private::EmulateInstruction *inst_emulator) : +        UnwindAssembly (arch), +        m_inst_emulator_ap (inst_emulator), +        m_range_ptr (NULL), +        m_thread_ptr (NULL), +        m_unwind_plan_ptr (NULL), +        m_curr_row (), +        m_cfa_reg_info (), +        m_fp_is_cfa (false), +        m_register_values (), +        m_pushed_regs(), +        m_curr_row_modified (false), +        m_forward_branch_offset (0) +    { +        if (m_inst_emulator_ap.get()) +        { +            m_inst_emulator_ap->SetBaton (this); +            m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister); +        } +    } +      static size_t      ReadMemory (lldb_private::EmulateInstruction *instruction,                  void *baton, @@ -101,7 +123,6 @@ private:                     const lldb_private::RegisterInfo *reg_info,                     const lldb_private::RegisterValue ®_value); -  //    size_t  //    ReadMemory (lldb_private::EmulateInstruction *instruction,  //                const lldb_private::EmulateInstruction::Context &context,  @@ -127,29 +148,6 @@ private:                     const lldb_private::RegisterInfo *reg_info,                     const lldb_private::RegisterValue ®_value); -    // Call CreateInstance to get an instance of this class -    UnwindAssemblyInstEmulation (const lldb_private::ArchSpec &arch, -                                 lldb_private::EmulateInstruction *inst_emulator) : -        UnwindAssembly (arch), -        m_inst_emulator_ap (inst_emulator), -        m_range_ptr (NULL), -        m_thread_ptr (NULL), -        m_unwind_plan_ptr (NULL), -        m_curr_row (), -        m_cfa_reg_info (), -        m_fp_is_cfa (false), -        m_register_values (), -        m_pushed_regs(), -        m_curr_row_modified (false), -        m_forward_branch_offset (0) -    { -        if (m_inst_emulator_ap.get()) -        { -            m_inst_emulator_ap->SetBaton (this); -            m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister); -        } -    } -      static uint64_t       MakeRegisterKindValuePair (const lldb_private::RegisterInfo ®_info); diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h index 8a4fe7c09800c..4d43a6e02b731 100644 --- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h +++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h @@ -1,4 +1,4 @@ -//===-- UnwindAssembly-x86.h -------------------------------------*- C++ -*-===// +//===-- UnwindAssembly-x86.h ------------------------------------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -10,42 +10,44 @@  #ifndef liblldb_UnwindAssembly_x86_h_  #define liblldb_UnwindAssembly_x86_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes  #include "llvm-c/Disassembler.h" +// Project includes  #include "lldb/lldb-private.h"  #include "lldb/Target/UnwindAssembly.h"  class UnwindAssembly_x86 : public lldb_private::UnwindAssembly  {  public: +    ~UnwindAssembly_x86() override; -    ~UnwindAssembly_x86 (); +    bool +    GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func, +                                         lldb_private::Thread& thread, +                                         lldb_private::UnwindPlan& unwind_plan) override; -    virtual bool -    GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,  -                                          lldb_private::Thread& thread,  -                                          lldb_private::UnwindPlan& unwind_plan); +    bool +    AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func, +                                  lldb_private::Thread& thread, +                                  lldb_private::UnwindPlan& unwind_plan) override; -    virtual bool -    AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func, -                                   lldb_private::Thread& thread, -                                   lldb_private::UnwindPlan& unwind_plan); - -    virtual bool -    GetFastUnwindPlan (lldb_private::AddressRange& func,  -                       lldb_private::Thread& thread,  -                       lldb_private::UnwindPlan &unwind_plan); +    bool +    GetFastUnwindPlan(lldb_private::AddressRange& func, +                      lldb_private::Thread& thread, +                      lldb_private::UnwindPlan &unwind_plan) override;      // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch). -    virtual bool -    FirstNonPrologueInsn (lldb_private::AddressRange& func,  -                          const lldb_private::ExecutionContext &exe_ctx, -                          lldb_private::Address& first_non_prologue_insn); +    bool +    FirstNonPrologueInsn(lldb_private::AddressRange& func, +                         const lldb_private::ExecutionContext &exe_ctx, +                         lldb_private::Address& first_non_prologue_insn) override;      static lldb_private::UnwindAssembly *      CreateInstance (const lldb_private::ArchSpec &arch); -      //------------------------------------------------------------------      // PluginInterface protocol      //------------------------------------------------------------------ @@ -61,11 +63,11 @@ public:      static const char *      GetPluginDescriptionStatic(); -    virtual lldb_private::ConstString -    GetPluginName(); +    lldb_private::ConstString +    GetPluginName() override; -    virtual uint32_t -    GetPluginVersion(); +    uint32_t +    GetPluginVersion() override;  private:      UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu); @@ -74,5 +76,4 @@ private:      lldb_private::ArchSpec m_arch;  }; -  #endif // liblldb_UnwindAssembly_x86_h_  | 
