diff options
Diffstat (limited to 'source/Utility')
-rw-r--r-- | source/Utility/ARM_DWARF_Registers.cpp | 435 | ||||
-rw-r--r-- | source/Utility/ARM_DWARF_Registers.h | 217 | ||||
-rw-r--r-- | source/Utility/ARM_GCC_Registers.h | 146 | ||||
-rw-r--r-- | source/Utility/KQueue.cpp | 87 | ||||
-rw-r--r-- | source/Utility/KQueue.h | 72 | ||||
-rw-r--r-- | source/Utility/PseudoTerminal.cpp | 339 | ||||
-rw-r--r-- | source/Utility/Range.cpp | 103 | ||||
-rw-r--r-- | source/Utility/RefCounter.cpp | 25 | ||||
-rw-r--r-- | source/Utility/SharingPtr.cpp | 158 | ||||
-rw-r--r-- | source/Utility/StringExtractor.cpp | 397 | ||||
-rw-r--r-- | source/Utility/StringExtractor.h | 141 | ||||
-rw-r--r-- | source/Utility/StringExtractorGDBRemote.cpp | 182 | ||||
-rw-r--r-- | source/Utility/StringExtractorGDBRemote.h | 103 | ||||
-rw-r--r-- | source/Utility/TimeSpecTimeout.cpp | 48 | ||||
-rw-r--r-- | source/Utility/TimeSpecTimeout.h | 90 | ||||
-rw-r--r-- | source/Utility/UuidCompatibility.h | 18 |
16 files changed, 2561 insertions, 0 deletions
diff --git a/source/Utility/ARM_DWARF_Registers.cpp b/source/Utility/ARM_DWARF_Registers.cpp new file mode 100644 index 000000000000..491ba040863e --- /dev/null +++ b/source/Utility/ARM_DWARF_Registers.cpp @@ -0,0 +1,435 @@ +//===-- ARM_DWARF_Registers.c -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ARM_DWARF_Registers.h" +#include <string.h> + +#include <string.h> + +using namespace lldb; +using namespace lldb_private; + +const char * +GetARMDWARFRegisterName (unsigned reg_num) +{ + switch (reg_num) + { + case dwarf_r0: return "r0"; + case dwarf_r1: return "r1"; + case dwarf_r2: return "r2"; + case dwarf_r3: return "r3"; + case dwarf_r4: return "r4"; + case dwarf_r5: return "r5"; + case dwarf_r6: return "r6"; + case dwarf_r7: return "r7"; + case dwarf_r8: return "r8"; + case dwarf_r9: return "r9"; + case dwarf_r10: return "r10"; + case dwarf_r11: return "r11"; + case dwarf_r12: return "r12"; + case dwarf_sp: return "sp"; + case dwarf_lr: return "lr"; + case dwarf_pc: return "pc"; + case dwarf_cpsr:return "cpsr"; + + case dwarf_s0: return "s0"; + case dwarf_s1: return "s1"; + case dwarf_s2: return "s2"; + case dwarf_s3: return "s3"; + case dwarf_s4: return "s4"; + case dwarf_s5: return "s5"; + case dwarf_s6: return "s6"; + case dwarf_s7: return "s7"; + case dwarf_s8: return "s8"; + case dwarf_s9: return "s9"; + case dwarf_s10: return "s10"; + case dwarf_s11: return "s11"; + case dwarf_s12: return "s12"; + case dwarf_s13: return "s13"; + case dwarf_s14: return "s14"; + case dwarf_s15: return "s15"; + case dwarf_s16: return "s16"; + case dwarf_s17: return "s17"; + case dwarf_s18: return "s18"; + case dwarf_s19: return "s19"; + case dwarf_s20: return "s20"; + case dwarf_s21: return "s21"; + case dwarf_s22: return "s22"; + case dwarf_s23: return "s23"; + case dwarf_s24: return "s24"; + case dwarf_s25: return "s25"; + case dwarf_s26: return "s26"; + case dwarf_s27: return "s27"; + case dwarf_s28: return "s28"; + case dwarf_s29: return "s29"; + case dwarf_s30: return "s30"; + case dwarf_s31: return "s31"; + + // FPA Registers 0-7 + case dwarf_f0: return "f0"; + case dwarf_f1: return "f1"; + case dwarf_f2: return "f2"; + case dwarf_f3: return "f3"; + case dwarf_f4: return "f4"; + case dwarf_f5: return "f5"; + case dwarf_f6: return "f6"; + case dwarf_f7: return "f7"; + + // Intel wireless MMX general purpose registers 0 - 7 + // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7) + case dwarf_wCGR0: return "wCGR0/ACC0"; + case dwarf_wCGR1: return "wCGR1/ACC1"; + case dwarf_wCGR2: return "wCGR2/ACC2"; + case dwarf_wCGR3: return "wCGR3/ACC3"; + case dwarf_wCGR4: return "wCGR4/ACC4"; + case dwarf_wCGR5: return "wCGR5/ACC5"; + case dwarf_wCGR6: return "wCGR6/ACC6"; + case dwarf_wCGR7: return "wCGR7/ACC7"; + + // Intel wireless MMX data registers 0 - 15 + case dwarf_wR0: return "wR0"; + case dwarf_wR1: return "wR1"; + case dwarf_wR2: return "wR2"; + case dwarf_wR3: return "wR3"; + case dwarf_wR4: return "wR4"; + case dwarf_wR5: return "wR5"; + case dwarf_wR6: return "wR6"; + case dwarf_wR7: return "wR7"; + case dwarf_wR8: return "wR8"; + case dwarf_wR9: return "wR9"; + case dwarf_wR10: return "wR10"; + case dwarf_wR11: return "wR11"; + case dwarf_wR12: return "wR12"; + case dwarf_wR13: return "wR13"; + case dwarf_wR14: return "wR14"; + case dwarf_wR15: return "wR15"; + + case dwarf_spsr: return "spsr"; + case dwarf_spsr_fiq: return "spsr_fiq"; + case dwarf_spsr_irq: return "spsr_irq"; + case dwarf_spsr_abt: return "spsr_abt"; + case dwarf_spsr_und: return "spsr_und"; + case dwarf_spsr_svc: return "spsr_svc"; + + case dwarf_r8_usr: return "r8_usr"; + case dwarf_r9_usr: return "r9_usr"; + case dwarf_r10_usr: return "r10_usr"; + case dwarf_r11_usr: return "r11_usr"; + case dwarf_r12_usr: return "r12_usr"; + case dwarf_r13_usr: return "r13_usr"; + case dwarf_r14_usr: return "r14_usr"; + case dwarf_r8_fiq: return "r8_fiq"; + case dwarf_r9_fiq: return "r9_fiq"; + case dwarf_r10_fiq: return "r10_fiq"; + case dwarf_r11_fiq: return "r11_fiq"; + case dwarf_r12_fiq: return "r12_fiq"; + case dwarf_r13_fiq: return "r13_fiq"; + case dwarf_r14_fiq: return "r14_fiq"; + case dwarf_r13_irq: return "r13_irq"; + case dwarf_r14_irq: return "r14_irq"; + case dwarf_r13_abt: return "r13_abt"; + case dwarf_r14_abt: return "r14_abt"; + case dwarf_r13_und: return "r13_und"; + case dwarf_r14_und: return "r14_und"; + case dwarf_r13_svc: return "r13_svc"; + case dwarf_r14_svc: return "r14_svc"; + + // Intel wireless MMX control register in co-processor 0 - 7 + case dwarf_wC0: return "wC0"; + case dwarf_wC1: return "wC1"; + case dwarf_wC2: return "wC2"; + case dwarf_wC3: return "wC3"; + case dwarf_wC4: return "wC4"; + case dwarf_wC5: return "wC5"; + case dwarf_wC6: return "wC6"; + case dwarf_wC7: return "wC7"; + + // VFP-v3/Neon + case dwarf_d0: return "d0"; + case dwarf_d1: return "d1"; + case dwarf_d2: return "d2"; + case dwarf_d3: return "d3"; + case dwarf_d4: return "d4"; + case dwarf_d5: return "d5"; + case dwarf_d6: return "d6"; + case dwarf_d7: return "d7"; + case dwarf_d8: return "d8"; + case dwarf_d9: return "d9"; + case dwarf_d10: return "d10"; + case dwarf_d11: return "d11"; + case dwarf_d12: return "d12"; + case dwarf_d13: return "d13"; + case dwarf_d14: return "d14"; + case dwarf_d15: return "d15"; + case dwarf_d16: return "d16"; + case dwarf_d17: return "d17"; + case dwarf_d18: return "d18"; + case dwarf_d19: return "d19"; + case dwarf_d20: return "d20"; + case dwarf_d21: return "d21"; + case dwarf_d22: return "d22"; + case dwarf_d23: return "d23"; + case dwarf_d24: return "d24"; + case dwarf_d25: return "d25"; + case dwarf_d26: return "d26"; + case dwarf_d27: return "d27"; + case dwarf_d28: return "d28"; + case dwarf_d29: return "d29"; + case dwarf_d30: return "d30"; + case dwarf_d31: return "d31"; + + // NEON 128-bit vector registers (overlays the d registers) + case dwarf_q0: return "q0"; + case dwarf_q1: return "q1"; + case dwarf_q2: return "q2"; + case dwarf_q3: return "q3"; + case dwarf_q4: return "q4"; + case dwarf_q5: return "q5"; + case dwarf_q6: return "q6"; + case dwarf_q7: return "q7"; + case dwarf_q8: return "q8"; + case dwarf_q9: return "q9"; + case dwarf_q10: return "q10"; + case dwarf_q11: return "q11"; + case dwarf_q12: return "q12"; + case dwarf_q13: return "q13"; + case dwarf_q14: return "q14"; + case dwarf_q15: return "q15"; + } + return 0; +} + +bool +GetARMDWARFRegisterInfo (unsigned reg_num, RegisterInfo ®_info) +{ + ::memset (®_info, 0, sizeof(RegisterInfo)); + ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); + + if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) + { + reg_info.byte_size = 16; + reg_info.format = eFormatVectorOfUInt8; + reg_info.encoding = eEncodingVector; + } + + if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) + { + reg_info.byte_size = 8; + reg_info.format = eFormatFloat; + reg_info.encoding = eEncodingIEEE754; + } + else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) + { + reg_info.byte_size = 4; + reg_info.format = eFormatFloat; + reg_info.encoding = eEncodingIEEE754; + } + else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) + { + reg_info.byte_size = 12; + reg_info.format = eFormatFloat; + reg_info.encoding = eEncodingIEEE754; + } + else + { + reg_info.byte_size = 4; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } + + reg_info.kinds[eRegisterKindDWARF] = reg_num; + + switch (reg_num) + { + case dwarf_r0: reg_info.name = "r0"; break; + case dwarf_r1: reg_info.name = "r1"; break; + case dwarf_r2: reg_info.name = "r2"; break; + case dwarf_r3: reg_info.name = "r3"; break; + case dwarf_r4: reg_info.name = "r4"; break; + case dwarf_r5: reg_info.name = "r5"; break; + case dwarf_r6: reg_info.name = "r6"; break; + case dwarf_r7: reg_info.name = "r7"; reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; + case dwarf_r8: reg_info.name = "r8"; break; + case dwarf_r9: reg_info.name = "r9"; break; + case dwarf_r10: reg_info.name = "r10"; break; + case dwarf_r11: reg_info.name = "r11"; break; + case dwarf_r12: reg_info.name = "r12"; break; + case dwarf_sp: reg_info.name = "sp"; reg_info.alt_name = "r13"; reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; + case dwarf_lr: reg_info.name = "lr"; reg_info.alt_name = "r14"; reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; + case dwarf_pc: reg_info.name = "pc"; reg_info.alt_name = "r15"; reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; + case dwarf_cpsr:reg_info.name = "cpsr"; reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; + + case dwarf_s0: reg_info.name = "s0"; break; + case dwarf_s1: reg_info.name = "s1"; break; + case dwarf_s2: reg_info.name = "s2"; break; + case dwarf_s3: reg_info.name = "s3"; break; + case dwarf_s4: reg_info.name = "s4"; break; + case dwarf_s5: reg_info.name = "s5"; break; + case dwarf_s6: reg_info.name = "s6"; break; + case dwarf_s7: reg_info.name = "s7"; break; + case dwarf_s8: reg_info.name = "s8"; break; + case dwarf_s9: reg_info.name = "s9"; break; + case dwarf_s10: reg_info.name = "s10"; break; + case dwarf_s11: reg_info.name = "s11"; break; + case dwarf_s12: reg_info.name = "s12"; break; + case dwarf_s13: reg_info.name = "s13"; break; + case dwarf_s14: reg_info.name = "s14"; break; + case dwarf_s15: reg_info.name = "s15"; break; + case dwarf_s16: reg_info.name = "s16"; break; + case dwarf_s17: reg_info.name = "s17"; break; + case dwarf_s18: reg_info.name = "s18"; break; + case dwarf_s19: reg_info.name = "s19"; break; + case dwarf_s20: reg_info.name = "s20"; break; + case dwarf_s21: reg_info.name = "s21"; break; + case dwarf_s22: reg_info.name = "s22"; break; + case dwarf_s23: reg_info.name = "s23"; break; + case dwarf_s24: reg_info.name = "s24"; break; + case dwarf_s25: reg_info.name = "s25"; break; + case dwarf_s26: reg_info.name = "s26"; break; + case dwarf_s27: reg_info.name = "s27"; break; + case dwarf_s28: reg_info.name = "s28"; break; + case dwarf_s29: reg_info.name = "s29"; break; + case dwarf_s30: reg_info.name = "s30"; break; + case dwarf_s31: reg_info.name = "s31"; break; + + // FPA Registers 0-7 + case dwarf_f0: reg_info.name = "f0"; break; + case dwarf_f1: reg_info.name = "f1"; break; + case dwarf_f2: reg_info.name = "f2"; break; + case dwarf_f3: reg_info.name = "f3"; break; + case dwarf_f4: reg_info.name = "f4"; break; + case dwarf_f5: reg_info.name = "f5"; break; + case dwarf_f6: reg_info.name = "f6"; break; + case dwarf_f7: reg_info.name = "f7"; break; + + // Intel wireless MMX general purpose registers 0 - 7 + // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7) + case dwarf_wCGR0: reg_info.name = "wCGR0/ACC0"; break; + case dwarf_wCGR1: reg_info.name = "wCGR1/ACC1"; break; + case dwarf_wCGR2: reg_info.name = "wCGR2/ACC2"; break; + case dwarf_wCGR3: reg_info.name = "wCGR3/ACC3"; break; + case dwarf_wCGR4: reg_info.name = "wCGR4/ACC4"; break; + case dwarf_wCGR5: reg_info.name = "wCGR5/ACC5"; break; + case dwarf_wCGR6: reg_info.name = "wCGR6/ACC6"; break; + case dwarf_wCGR7: reg_info.name = "wCGR7/ACC7"; break; + + // Intel wireless MMX data registers 0 - 15 + case dwarf_wR0: reg_info.name = "wR0"; break; + case dwarf_wR1: reg_info.name = "wR1"; break; + case dwarf_wR2: reg_info.name = "wR2"; break; + case dwarf_wR3: reg_info.name = "wR3"; break; + case dwarf_wR4: reg_info.name = "wR4"; break; + case dwarf_wR5: reg_info.name = "wR5"; break; + case dwarf_wR6: reg_info.name = "wR6"; break; + case dwarf_wR7: reg_info.name = "wR7"; break; + case dwarf_wR8: reg_info.name = "wR8"; break; + case dwarf_wR9: reg_info.name = "wR9"; break; + case dwarf_wR10: reg_info.name = "wR10"; break; + case dwarf_wR11: reg_info.name = "wR11"; break; + case dwarf_wR12: reg_info.name = "wR12"; break; + case dwarf_wR13: reg_info.name = "wR13"; break; + case dwarf_wR14: reg_info.name = "wR14"; break; + case dwarf_wR15: reg_info.name = "wR15"; break; + + case dwarf_spsr: reg_info.name = "spsr"; break; + case dwarf_spsr_fiq: reg_info.name = "spsr_fiq"; break; + case dwarf_spsr_irq: reg_info.name = "spsr_irq"; break; + case dwarf_spsr_abt: reg_info.name = "spsr_abt"; break; + case dwarf_spsr_und: reg_info.name = "spsr_und"; break; + case dwarf_spsr_svc: reg_info.name = "spsr_svc"; break; + + case dwarf_r8_usr: reg_info.name = "r8_usr"; break; + case dwarf_r9_usr: reg_info.name = "r9_usr"; break; + case dwarf_r10_usr: reg_info.name = "r10_usr"; break; + case dwarf_r11_usr: reg_info.name = "r11_usr"; break; + case dwarf_r12_usr: reg_info.name = "r12_usr"; break; + case dwarf_r13_usr: reg_info.name = "r13_usr"; break; + case dwarf_r14_usr: reg_info.name = "r14_usr"; break; + case dwarf_r8_fiq: reg_info.name = "r8_fiq"; break; + case dwarf_r9_fiq: reg_info.name = "r9_fiq"; break; + case dwarf_r10_fiq: reg_info.name = "r10_fiq"; break; + case dwarf_r11_fiq: reg_info.name = "r11_fiq"; break; + case dwarf_r12_fiq: reg_info.name = "r12_fiq"; break; + case dwarf_r13_fiq: reg_info.name = "r13_fiq"; break; + case dwarf_r14_fiq: reg_info.name = "r14_fiq"; break; + case dwarf_r13_irq: reg_info.name = "r13_irq"; break; + case dwarf_r14_irq: reg_info.name = "r14_irq"; break; + case dwarf_r13_abt: reg_info.name = "r13_abt"; break; + case dwarf_r14_abt: reg_info.name = "r14_abt"; break; + case dwarf_r13_und: reg_info.name = "r13_und"; break; + case dwarf_r14_und: reg_info.name = "r14_und"; break; + case dwarf_r13_svc: reg_info.name = "r13_svc"; break; + case dwarf_r14_svc: reg_info.name = "r14_svc"; break; + + // Intel wireless MMX control register in co-processor 0 - 7 + case dwarf_wC0: reg_info.name = "wC0"; break; + case dwarf_wC1: reg_info.name = "wC1"; break; + case dwarf_wC2: reg_info.name = "wC2"; break; + case dwarf_wC3: reg_info.name = "wC3"; break; + case dwarf_wC4: reg_info.name = "wC4"; break; + case dwarf_wC5: reg_info.name = "wC5"; break; + case dwarf_wC6: reg_info.name = "wC6"; break; + case dwarf_wC7: reg_info.name = "wC7"; break; + + // VFP-v3/Neon + case dwarf_d0: reg_info.name = "d0"; break; + case dwarf_d1: reg_info.name = "d1"; break; + case dwarf_d2: reg_info.name = "d2"; break; + case dwarf_d3: reg_info.name = "d3"; break; + case dwarf_d4: reg_info.name = "d4"; break; + case dwarf_d5: reg_info.name = "d5"; break; + case dwarf_d6: reg_info.name = "d6"; break; + case dwarf_d7: reg_info.name = "d7"; break; + case dwarf_d8: reg_info.name = "d8"; break; + case dwarf_d9: reg_info.name = "d9"; break; + case dwarf_d10: reg_info.name = "d10"; break; + case dwarf_d11: reg_info.name = "d11"; break; + case dwarf_d12: reg_info.name = "d12"; break; + case dwarf_d13: reg_info.name = "d13"; break; + case dwarf_d14: reg_info.name = "d14"; break; + case dwarf_d15: reg_info.name = "d15"; break; + case dwarf_d16: reg_info.name = "d16"; break; + case dwarf_d17: reg_info.name = "d17"; break; + case dwarf_d18: reg_info.name = "d18"; break; + case dwarf_d19: reg_info.name = "d19"; break; + case dwarf_d20: reg_info.name = "d20"; break; + case dwarf_d21: reg_info.name = "d21"; break; + case dwarf_d22: reg_info.name = "d22"; break; + case dwarf_d23: reg_info.name = "d23"; break; + case dwarf_d24: reg_info.name = "d24"; break; + case dwarf_d25: reg_info.name = "d25"; break; + case dwarf_d26: reg_info.name = "d26"; break; + case dwarf_d27: reg_info.name = "d27"; break; + case dwarf_d28: reg_info.name = "d28"; break; + case dwarf_d29: reg_info.name = "d29"; break; + case dwarf_d30: reg_info.name = "d30"; break; + case dwarf_d31: reg_info.name = "d31"; break; + + // NEON 128-bit vector registers (overlays the d registers) + case dwarf_q0: reg_info.name = "q0"; break; + case dwarf_q1: reg_info.name = "q1"; break; + case dwarf_q2: reg_info.name = "q2"; break; + case dwarf_q3: reg_info.name = "q3"; break; + case dwarf_q4: reg_info.name = "q4"; break; + case dwarf_q5: reg_info.name = "q5"; break; + case dwarf_q6: reg_info.name = "q6"; break; + case dwarf_q7: reg_info.name = "q7"; break; + case dwarf_q8: reg_info.name = "q8"; break; + case dwarf_q9: reg_info.name = "q9"; break; + case dwarf_q10: reg_info.name = "q10"; break; + case dwarf_q11: reg_info.name = "q11"; break; + case dwarf_q12: reg_info.name = "q12"; break; + case dwarf_q13: reg_info.name = "q13"; break; + case dwarf_q14: reg_info.name = "q14"; break; + case dwarf_q15: reg_info.name = "q15"; break; + + default: return false; + } + return true; +} diff --git a/source/Utility/ARM_DWARF_Registers.h b/source/Utility/ARM_DWARF_Registers.h new file mode 100644 index 000000000000..6850d3e80f11 --- /dev/null +++ b/source/Utility/ARM_DWARF_Registers.h @@ -0,0 +1,217 @@ +//===-- ARM_DWARF_Registers.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_ARM_DWARF_Registers_h_ +#define utility_ARM_DWARF_Registers_h_ + +#include "lldb/lldb-private.h" + +enum +{ + 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_sp, + dwarf_lr, + dwarf_pc, + dwarf_cpsr, + + dwarf_s0 = 64, + dwarf_s1, + dwarf_s2, + dwarf_s3, + dwarf_s4, + dwarf_s5, + dwarf_s6, + dwarf_s7, + dwarf_s8, + dwarf_s9, + dwarf_s10, + dwarf_s11, + dwarf_s12, + dwarf_s13, + dwarf_s14, + dwarf_s15, + dwarf_s16, + dwarf_s17, + dwarf_s18, + dwarf_s19, + dwarf_s20, + dwarf_s21, + dwarf_s22, + dwarf_s23, + dwarf_s24, + dwarf_s25, + dwarf_s26, + dwarf_s27, + dwarf_s28, + dwarf_s29, + dwarf_s30, + dwarf_s31, + + // FPA Registers 0-7 + dwarf_f0 = 96, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + + // Intel wireless MMX general purpose registers 0 - 7 + dwarf_wCGR0 = 104, + dwarf_wCGR1, + dwarf_wCGR2, + dwarf_wCGR3, + dwarf_wCGR4, + dwarf_wCGR5, + dwarf_wCGR6, + dwarf_wCGR7, + + // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7) + dwarf_ACC0 = 104, + dwarf_ACC1, + dwarf_ACC2, + dwarf_ACC3, + dwarf_ACC4, + dwarf_ACC5, + dwarf_ACC6, + dwarf_ACC7, + + // Intel wireless MMX data registers 0 - 15 + dwarf_wR0 = 112, + dwarf_wR1, + dwarf_wR2, + dwarf_wR3, + dwarf_wR4, + dwarf_wR5, + dwarf_wR6, + dwarf_wR7, + dwarf_wR8, + dwarf_wR9, + dwarf_wR10, + dwarf_wR11, + dwarf_wR12, + dwarf_wR13, + dwarf_wR14, + dwarf_wR15, + + dwarf_spsr = 128, + dwarf_spsr_fiq, + dwarf_spsr_irq, + dwarf_spsr_abt, + dwarf_spsr_und, + dwarf_spsr_svc, + + dwarf_r8_usr = 144, + dwarf_r9_usr, + dwarf_r10_usr, + dwarf_r11_usr, + dwarf_r12_usr, + dwarf_r13_usr, + dwarf_r14_usr, + dwarf_r8_fiq, + dwarf_r9_fiq, + dwarf_r10_fiq, + dwarf_r11_fiq, + dwarf_r12_fiq, + dwarf_r13_fiq, + dwarf_r14_fiq, + dwarf_r13_irq, + dwarf_r14_irq, + dwarf_r13_abt, + dwarf_r14_abt, + dwarf_r13_und, + dwarf_r14_und, + dwarf_r13_svc, + dwarf_r14_svc, + + // Intel wireless MMX control register in co-processor 0 - 7 + dwarf_wC0 = 192, + dwarf_wC1, + dwarf_wC2, + dwarf_wC3, + dwarf_wC4, + dwarf_wC5, + dwarf_wC6, + dwarf_wC7, + + // VFP-v3/Neon + dwarf_d0 = 256, + dwarf_d1, + dwarf_d2, + dwarf_d3, + dwarf_d4, + dwarf_d5, + dwarf_d6, + dwarf_d7, + dwarf_d8, + dwarf_d9, + dwarf_d10, + dwarf_d11, + dwarf_d12, + dwarf_d13, + dwarf_d14, + dwarf_d15, + dwarf_d16, + dwarf_d17, + dwarf_d18, + dwarf_d19, + dwarf_d20, + dwarf_d21, + dwarf_d22, + dwarf_d23, + dwarf_d24, + dwarf_d25, + dwarf_d26, + dwarf_d27, + dwarf_d28, + dwarf_d29, + dwarf_d30, + dwarf_d31, + + // Neon quadword registers + dwarf_q0 = 288, + dwarf_q1, + dwarf_q2, + dwarf_q3, + dwarf_q4, + dwarf_q5, + dwarf_q6, + dwarf_q7, + dwarf_q8, + dwarf_q9, + dwarf_q10, + dwarf_q11, + dwarf_q12, + dwarf_q13, + dwarf_q14, + dwarf_q15 +}; + +const char * +GetARMDWARFRegisterName (unsigned reg_num); + +bool +GetARMDWARFRegisterInfo (unsigned reg_num, + lldb_private::RegisterInfo ®_info); + +#endif // utility_ARM_DWARF_Registers_h_ + diff --git a/source/Utility/ARM_GCC_Registers.h b/source/Utility/ARM_GCC_Registers.h new file mode 100644 index 000000000000..974d01bfc78a --- /dev/null +++ b/source/Utility/ARM_GCC_Registers.h @@ -0,0 +1,146 @@ +//===-- ARM_GCC_Registers.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_ARM_GCC_Registers_h_ +#define utility_ARM_GCC_Registers_h_ + +enum +{ + gcc_r0 = 0, + gcc_r1, + gcc_r2, + gcc_r3, + gcc_r4, + gcc_r5, + gcc_r6, + gcc_r7, + gcc_r8, + gcc_r9, + gcc_r10, + gcc_r11, + gcc_r12, + gcc_sp, + gcc_lr, + gcc_pc, + gcc_cpsr +}; + +enum +{ +// Name Nr Rel Offset Size Type Raw value + gdb_arm_r0 = 0, // 0 0 4 int32_t + gdb_arm_r1 = 1, // 1 4 4 int32_t + gdb_arm_r2 = 2, // 2 8 4 int32_t + gdb_arm_r3 = 3, // 3 12 4 int32_t + gdb_arm_r4 = 4, // 4 16 4 int32_t + gdb_arm_r5 = 5, // 5 20 4 int32_t + gdb_arm_r6 = 6, // 6 24 4 int32_t + gdb_arm_r7 = 7, // 7 28 4 int32_t + gdb_arm_r8 = 8, // 8 32 4 int32_t + gdb_arm_r9 = 9, // 9 36 4 int32_t + gdb_arm_r10 = 10, // 10 40 4 int32_t + gdb_arm_r11 = 11, // 11 44 4 int32_t + gdb_arm_r12 = 12, // 12 48 4 int32_t + gdb_arm_sp = 13, // 13 52 4 int32_t + gdb_arm_lr = 14, // 14 56 4 int32_t + gdb_arm_pc = 15, // 15 60 4 int32_t + gdb_arm_f0 = 16, // 16 64 12 _arm_ext_littlebyte_bigword + gdb_arm_f1 = 17, // 17 76 12 _arm_ext_littlebyte_bigword + gdb_arm_f2 = 18, // 18 88 12 _arm_ext_littlebyte_bigword + gdb_arm_f3 = 19, // 19 100 12 _arm_ext_littlebyte_bigword + gdb_arm_f4 = 20, // 20 112 12 _arm_ext_littlebyte_bigword + gdb_arm_f5 = 21, // 21 124 12 _arm_ext_littlebyte_bigword + gdb_arm_f6 = 22, // 22 136 12 _arm_ext_littlebyte_bigword + gdb_arm_f7 = 23, // 23 148 12 _arm_ext_littlebyte_bigword + gdb_arm_f8 = 24, // 24 160 12 _arm_ext_littlebyte_bigword + gdb_arm_cpsr = 25, // 25 172 4 int32_t + gdb_arm_s0 = 26, // 26 176 4 _ieee_single_little + gdb_arm_s1 = 27, // 27 180 4 _ieee_single_little + gdb_arm_s2 = 28, // 28 184 4 _ieee_single_little + gdb_arm_s3 = 29, // 29 188 4 _ieee_single_little + gdb_arm_s4 = 30, // 30 192 4 _ieee_single_little + gdb_arm_s5 = 31, // 31 196 4 _ieee_single_little + gdb_arm_s6 = 32, // 32 200 4 _ieee_single_little + gdb_arm_s7 = 33, // 33 204 4 _ieee_single_little + gdb_arm_s8 = 34, // 34 208 4 _ieee_single_little + gdb_arm_s9 = 35, // 35 212 4 _ieee_single_little + gdb_arm_s10 = 36, // 36 216 4 _ieee_single_little + gdb_arm_s11 = 37, // 37 220 4 _ieee_single_little + gdb_arm_s12 = 38, // 38 224 4 _ieee_single_little + gdb_arm_s13 = 39, // 39 228 4 _ieee_single_little + gdb_arm_s14 = 40, // 40 232 4 _ieee_single_little + gdb_arm_s15 = 41, // 41 236 4 _ieee_single_little + gdb_arm_s16 = 42, // 42 240 4 _ieee_single_little + gdb_arm_s17 = 43, // 43 244 4 _ieee_single_little + gdb_arm_s18 = 44, // 44 248 4 _ieee_single_little + gdb_arm_s19 = 45, // 45 252 4 _ieee_single_little + gdb_arm_s20 = 46, // 46 256 4 _ieee_single_little + gdb_arm_s21 = 47, // 47 260 4 _ieee_single_little + gdb_arm_s22 = 48, // 48 264 4 _ieee_single_little + gdb_arm_s23 = 49, // 49 268 4 _ieee_single_little + gdb_arm_s24 = 50, // 50 272 4 _ieee_single_little + gdb_arm_s25 = 51, // 51 276 4 _ieee_single_little + gdb_arm_s26 = 52, // 52 280 4 _ieee_single_little + gdb_arm_s27 = 53, // 53 284 4 _ieee_single_little + gdb_arm_s28 = 54, // 54 288 4 _ieee_single_little + gdb_arm_s29 = 55, // 55 292 4 _ieee_single_little + gdb_arm_s30 = 56, // 56 296 4 _ieee_single_little + gdb_arm_s31 = 57, // 57 300 4 _ieee_single_little + gdb_arm_fpscr = 58, // 58 304 4 int32_t + gdb_arm_d16 = 59, // 59 308 8 _ieee_double_little + gdb_arm_d17 = 60, // 60 316 8 _ieee_double_little + gdb_arm_d18 = 61, // 61 324 8 _ieee_double_little + gdb_arm_d19 = 62, // 62 332 8 _ieee_double_little + gdb_arm_d20 = 63, // 63 340 8 _ieee_double_little + gdb_arm_d21 = 64, // 64 348 8 _ieee_double_little + gdb_arm_d22 = 65, // 65 356 8 _ieee_double_little + gdb_arm_d23 = 66, // 66 364 8 _ieee_double_little + gdb_arm_d24 = 67, // 67 372 8 _ieee_double_little + gdb_arm_d25 = 68, // 68 380 8 _ieee_double_little + gdb_arm_d26 = 69, // 69 388 8 _ieee_double_little + gdb_arm_d27 = 70, // 70 396 8 _ieee_double_little + gdb_arm_d28 = 71, // 71 404 8 _ieee_double_little + gdb_arm_d29 = 72, // 72 412 8 _ieee_double_little + gdb_arm_d30 = 73, // 73 420 8 _ieee_double_little + gdb_arm_d31 = 74, // 74 428 8 _ieee_double_little + gdb_arm_d0 = 75, // 0 436 8 _ieee_double_little + gdb_arm_d1 = 76, // 1 444 8 _ieee_double_little + gdb_arm_d2 = 77, // 2 452 8 _ieee_double_little + gdb_arm_d3 = 78, // 3 460 8 _ieee_double_little + gdb_arm_d4 = 79, // 4 468 8 _ieee_double_little + gdb_arm_d5 = 80, // 5 476 8 _ieee_double_little + gdb_arm_d6 = 81, // 6 484 8 _ieee_double_little + gdb_arm_d7 = 82, // 7 492 8 _ieee_double_little + gdb_arm_d8 = 83, // 8 500 8 _ieee_double_little + gdb_arm_d9 = 84, // 9 508 8 _ieee_double_little + gdb_arm_d10 = 85, // 10 516 8 _ieee_double_little + gdb_arm_d11 = 86, // 11 524 8 _ieee_double_little + gdb_arm_d12 = 87, // 12 532 8 _ieee_double_little + gdb_arm_d13 = 88, // 13 540 8 _ieee_double_little + gdb_arm_d14 = 89, // 14 548 8 _ieee_double_little + gdb_arm_d15 = 90, // 15 556 8 _ieee_double_little + gdb_arm_q0 = 91, // 16 564 16 _vec128 + gdb_arm_q1 = 92, // 17 580 16 _vec128 + gdb_arm_q2 = 93, // 18 596 16 _vec128 + gdb_arm_q3 = 94, // 19 612 16 _vec128 + gdb_arm_q4 = 95, // 20 628 16 _vec128 + gdb_arm_q5 = 96, // 21 644 16 _vec128 + gdb_arm_q6 = 97, // 22 660 16 _vec128 + gdb_arm_q7 = 98, // 23 676 16 _vec128 + gdb_arm_q8 = 99, // 24 692 16 _vec128 + gdb_arm_q9 = 100, // 25 708 16 _vec128 + gdb_arm_q10 = 101, // 26 724 16 _vec128 + gdb_arm_q11 = 102, // 27 740 16 _vec128 + gdb_arm_q12 = 103, // 28 756 16 _vec128 + gdb_arm_q13 = 104, // 29 772 16 _vec128 + gdb_arm_q14 = 105, // 30 788 16 _vec128 + gdb_arm_q15 = 106 // 31 804 16 _vec128 +}; +#endif // utility_ARM_GCC_Registers_h_ + diff --git a/source/Utility/KQueue.cpp b/source/Utility/KQueue.cpp new file mode 100644 index 000000000000..c0aace448951 --- /dev/null +++ b/source/Utility/KQueue.cpp @@ -0,0 +1,87 @@ +//===--------------------- KQueue.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "KQueue.h" + +#ifdef LLDB_USE_KQUEUES + +#include "lldb/Core/Error.h" + +#include "Utility/TimeSpecTimeout.h" + +using namespace lldb_private; + +int +KQueue::GetFD (bool can_create) +{ + if (!IsValid () && can_create) + m_fd = kqueue(); + return m_fd; +} + +int +KQueue::Close () +{ + const int fd = m_fd; + if (fd >= 0) + { + m_fd = -1; + return close(fd); + } + return 0; +} + +int +KQueue::WaitForEvents (struct kevent *events, int num_events, Error &error, uint32_t timeout_usec) +{ + const int fd_kqueue = GetFD(false); + if (fd_kqueue >= 0) + { + TimeSpecTimeout timeout; + const struct timespec *timeout_ptr = timeout.SetRelativeTimeoutMircoSeconds32 (timeout_usec); + int result = ::kevent(fd_kqueue, NULL, 0, events, num_events, timeout_ptr); + if (result == -1) + error.SetErrorToErrno(); + else + error.Clear(); + return result; + } + else + { + error.SetErrorString("invalid kqueue fd"); + } + return 0; +} + +bool +KQueue::AddFDEvent (int fd, bool read, bool write, bool vnode) +{ + const int fd_kqueue = GetFD(true); + if (fd_kqueue >= 0) + { + struct kevent event; + event.ident = fd; + event.filter = 0; + if (read) + event.filter |= EVFILT_READ; + if (write) + event.filter |= EVFILT_WRITE; + if (vnode) + event.filter |= EVFILT_VNODE; + event.flags = EV_ADD | EV_CLEAR; + event.fflags = 0; + event.data = 0; + event.udata = NULL; + int err = ::kevent(fd_kqueue, &event, 1, NULL, 0, NULL); + return err == 0; + } + return false; +} + +#endif diff --git a/source/Utility/KQueue.h b/source/Utility/KQueue.h new file mode 100644 index 000000000000..c5680aaa6314 --- /dev/null +++ b/source/Utility/KQueue.h @@ -0,0 +1,72 @@ +//===--------------------- KQueue.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_KQueue_h_ +#define utility_KQueue_h_ + +#if defined(__APPLE__) +#define LLDB_USE_KQUEUES +#endif + +#ifdef LLDB_USE_KQUEUES + +#include <sys/types.h> +#include <sys/event.h> +#include <sys/time.h> + +#include "lldb/lldb-defines.h" + +namespace lldb_private { + +class KQueue +{ +public: + KQueue() : + m_fd(-1) + { + } + + ~KQueue() + { + Close(); + } + + bool + IsValid () const + { + return m_fd >= 0; + } + + int + GetFD (bool can_create); + + int + Close (); + + bool + AddFDEvent (int fd, + bool read, + bool write, + bool vnode); + + int + WaitForEvents (struct kevent *events, + int num_events, + Error &error, + uint32_t timeout_usec = UINT32_MAX); // UINT32_MAX means infinite timeout + +protected: + int m_fd; // The kqueue fd +}; + +} // namespace lldb_private + +#endif // #ifdef LLDB_USE_KQUEUES + +#endif // #ifndef utility_KQueue_h_ diff --git a/source/Utility/PseudoTerminal.cpp b/source/Utility/PseudoTerminal.cpp new file mode 100644 index 000000000000..e4b444c36873 --- /dev/null +++ b/source/Utility/PseudoTerminal.cpp @@ -0,0 +1,339 @@ +//===-- PseudoTerminal.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/PseudoTerminal.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#if defined(TIOCSCTTY) +#include <sys/ioctl.h> +#endif + +using namespace lldb_utility; + +//---------------------------------------------------------------------- +// PseudoTerminal constructor +//---------------------------------------------------------------------- +PseudoTerminal::PseudoTerminal () : + m_master_fd(invalid_fd), + m_slave_fd(invalid_fd) +{ +} + +//---------------------------------------------------------------------- +// Destructor +// +// The destructor will close the master and slave file descriptors +// if they are valid and ownwership has not been released using the +// ReleaseMasterFileDescriptor() or the ReleaseSaveFileDescriptor() +// member functions. +//---------------------------------------------------------------------- +PseudoTerminal::~PseudoTerminal () +{ + CloseMasterFileDescriptor(); + CloseSlaveFileDescriptor(); +} + +//---------------------------------------------------------------------- +// Close the master file descriptor if it is valid. +//---------------------------------------------------------------------- +void +PseudoTerminal::CloseMasterFileDescriptor () +{ + if (m_master_fd >= 0) + { + ::close (m_master_fd); + m_master_fd = invalid_fd; + } +} + +//---------------------------------------------------------------------- +// Close the slave file descriptor if it is valid. +//---------------------------------------------------------------------- +void +PseudoTerminal::CloseSlaveFileDescriptor () +{ + if (m_slave_fd >= 0) + { + ::close (m_slave_fd); + m_slave_fd = invalid_fd; + } +} + +//---------------------------------------------------------------------- +// Open the first available pseudo terminal with OFLAG as the +// permissions. The file descriptor is stored in this object and can +// be accessed with the MasterFileDescriptor() accessor. The +// ownership of the master file descriptor can be released using +// the ReleaseMasterFileDescriptor() accessor. If this object has +// a valid master files descriptor when its destructor is called, it +// will close the master file descriptor, therefore clients must +// call ReleaseMasterFileDescriptor() if they wish to use the master +// file descriptor after this object is out of scope or destroyed. +// +// RETURNS: +// Zero when successful, non-zero indicating an error occurred. +//---------------------------------------------------------------------- +bool +PseudoTerminal::OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len) +{ + if (error_str) + error_str[0] = '\0'; + + // Open the master side of a pseudo terminal + m_master_fd = ::posix_openpt (oflag); + if (m_master_fd < 0) + { + if (error_str) + ::strerror_r (errno, error_str, error_len); + return false; + } + + // Grant access to the slave pseudo terminal + if (::grantpt (m_master_fd) < 0) + { + if (error_str) + ::strerror_r (errno, error_str, error_len); + CloseMasterFileDescriptor (); + return false; + } + + // Clear the lock flag on the slave pseudo terminal + if (::unlockpt (m_master_fd) < 0) + { + if (error_str) + ::strerror_r (errno, error_str, error_len); + CloseMasterFileDescriptor (); + return false; + } + + return true; +} + +//---------------------------------------------------------------------- +// Open the slave pseudo terminal for the current master pseudo +// terminal. A master pseudo terminal should already be valid prior to +// calling this function (see OpenFirstAvailableMaster()). +// The file descriptor is stored this object's member variables and can +// be accessed via the GetSlaveFileDescriptor(), or released using the +// ReleaseSlaveFileDescriptor() member function. +// +// RETURNS: +// Zero when successful, non-zero indicating an error occurred. +//---------------------------------------------------------------------- +bool +PseudoTerminal::OpenSlave (int oflag, char *error_str, size_t error_len) +{ + if (error_str) + error_str[0] = '\0'; + + CloseSlaveFileDescriptor(); + + // Open the master side of a pseudo terminal + const char *slave_name = GetSlaveName (error_str, error_len); + + if (slave_name == NULL) + return false; + + m_slave_fd = ::open (slave_name, oflag); + + if (m_slave_fd < 0) + { + if (error_str) + ::strerror_r (errno, error_str, error_len); + return false; + } + + return true; +} + + + +//---------------------------------------------------------------------- +// Get the name of the slave pseudo terminal. A master pseudo terminal +// should already be valid prior to calling this function (see +// OpenFirstAvailableMaster()). +// +// RETURNS: +// NULL if no valid master pseudo terminal or if ptsname() fails. +// The name of the slave pseudo terminal as a NULL terminated C string +// that comes from static memory, so a copy of the string should be +// made as subsequent calls can change this value. +//---------------------------------------------------------------------- +const char* +PseudoTerminal::GetSlaveName (char *error_str, size_t error_len) const +{ + if (error_str) + error_str[0] = '\0'; + + if (m_master_fd < 0) + { + if (error_str) + ::snprintf (error_str, error_len, "%s", "master file descriptor is invalid"); + return NULL; + } + const char *slave_name = ::ptsname (m_master_fd); + + if (error_str && slave_name == NULL) + ::strerror_r (errno, error_str, error_len); + + return slave_name; +} + + +//---------------------------------------------------------------------- +// Fork a child process and have its stdio routed to a pseudo terminal. +// +// In the parent process when a valid pid is returned, the master file +// descriptor can be used as a read/write access to stdio of the +// child process. +// +// In the child process the stdin/stdout/stderr will already be routed +// to the slave pseudo terminal and the master file descriptor will be +// closed as it is no longer needed by the child process. +// +// This class will close the file descriptors for the master/slave +// when the destructor is called, so be sure to call +// ReleaseMasterFileDescriptor() or ReleaseSlaveFileDescriptor() if any +// file descriptors are going to be used past the lifespan of this +// object. +// +// RETURNS: +// in the parent process: the pid of the child, or -1 if fork fails +// in the child process: zero +//---------------------------------------------------------------------- +lldb::pid_t +PseudoTerminal::Fork (char *error_str, size_t error_len) +{ + if (error_str) + error_str[0] = '\0'; + + pid_t pid = LLDB_INVALID_PROCESS_ID; + if (OpenFirstAvailableMaster (O_RDWR, error_str, error_len)) + { + // Successfully opened our master pseudo terminal + + pid = ::fork (); + if (pid < 0) + { + // Fork failed + if (error_str) + ::strerror_r (errno, error_str, error_len); + } + else if (pid == 0) + { + // Child Process + ::setsid(); + + if (OpenSlave (O_RDWR, error_str, error_len)) + { + // Successfully opened slave + // We are done with the master in the child process so lets close it + CloseMasterFileDescriptor (); + +#if defined(TIOCSCTTY) + // Acquire the controlling terminal + if (::ioctl (m_slave_fd, TIOCSCTTY, (char *)0) < 0) + { + if (error_str) + ::strerror_r (errno, error_str, error_len); + } +#endif + // Duplicate all stdio file descriptors to the slave pseudo terminal + if (::dup2 (m_slave_fd, STDIN_FILENO) != STDIN_FILENO) + { + if (error_str && !error_str[0]) + ::strerror_r (errno, error_str, error_len); + } + + if (::dup2 (m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) + { + if (error_str && !error_str[0]) + ::strerror_r (errno, error_str, error_len); + } + + if (::dup2 (m_slave_fd, STDERR_FILENO) != STDERR_FILENO) + { + if (error_str && !error_str[0]) + ::strerror_r (errno, error_str, error_len); + } + } + } + else + { + // Parent Process + // Do nothing and let the pid get returned! + } + } + return pid; +} + +//---------------------------------------------------------------------- +// The master file descriptor accessor. This object retains ownership +// of the master file descriptor when this accessor is used. Use +// ReleaseMasterFileDescriptor() if you wish this object to release +// ownership of the master file descriptor. +// +// Returns the master file descriptor, or -1 if the master file +// descriptor is not currently valid. +//---------------------------------------------------------------------- +int +PseudoTerminal::GetMasterFileDescriptor () const +{ + return m_master_fd; +} + +//---------------------------------------------------------------------- +// The slave file descriptor accessor. +// +// Returns the slave file descriptor, or -1 if the slave file +// descriptor is not currently valid. +//---------------------------------------------------------------------- +int +PseudoTerminal::GetSlaveFileDescriptor () const +{ + return m_slave_fd; +} + +//---------------------------------------------------------------------- +// Release ownership of the master pseudo terminal file descriptor +// without closing it. The destructor for this class will close the +// master file descriptor if the ownership isn't released using this +// call and the master file descriptor has been opened. +//---------------------------------------------------------------------- +int +PseudoTerminal::ReleaseMasterFileDescriptor () +{ + // Release ownership of the master pseudo terminal file + // descriptor without closing it. (the destructor for this + // class will close it otherwise!) + int fd = m_master_fd; + m_master_fd = invalid_fd; + return fd; +} + +//---------------------------------------------------------------------- +// Release ownership of the slave pseudo terminal file descriptor +// without closing it. The destructor for this class will close the +// slave file descriptor if the ownership isn't released using this +// call and the slave file descriptor has been opened. +//---------------------------------------------------------------------- +int +PseudoTerminal::ReleaseSlaveFileDescriptor () +{ + // Release ownership of the slave pseudo terminal file + // descriptor without closing it (the destructor for this + // class will close it otherwise!) + int fd = m_slave_fd; + m_slave_fd = invalid_fd; + return fd; +} + diff --git a/source/Utility/Range.cpp b/source/Utility/Range.cpp new file mode 100644 index 000000000000..158d1e729d48 --- /dev/null +++ b/source/Utility/Range.cpp @@ -0,0 +1,103 @@ +//===--------------------- Range.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/Range.h" + +using namespace lldb_utility; + +Range::Range (const Range& rng) : +m_low(rng.m_low), +m_high(rng.m_high) +{ + InitRange(); +} + +Range::Range (Range::ValueType low, + Range::ValueType high) : +m_low(low), +m_high(high) +{ + InitRange(); +} + +void +Range::InitRange () +{ + if (m_low == OPEN_END) + { + if (m_high == OPEN_END) + m_low = 0; + else + { + // make an empty range + m_low = 1; + m_high = 0; + } + } +} + +Range& +Range::operator = (const Range& rhs) +{ + if (&rhs != this) + { + this->m_low = rhs.m_low; + this->m_high = rhs.m_high; + } + return *this; +} + +void +Range::Flip () +{ + std::swap(m_high, m_low); +} + +void +Range::Intersection (const Range& other) +{ + m_low = std::max(m_low,other.m_low); + m_high = std::min(m_high,other.m_high); +} + +void +Range::Union (const Range& other) +{ + m_low = std::min(m_low,other.m_low); + m_high = std::max(m_high,other.m_high); +} + +void +Range::Iterate (RangeCallback callback) +{ + ValueType counter = m_low; + while (counter <= m_high) + { + bool should_continue = callback(counter); + if (!should_continue) + return; + counter++; + } +} + +bool +Range::IsEmpty () +{ + return (m_low > m_high); +} + +Range::ValueType +Range::GetSize () +{ + if (m_high == OPEN_END) + return OPEN_END; + if (m_high >= m_low) + return m_high - m_low + 1; + return 0; +} diff --git a/source/Utility/RefCounter.cpp b/source/Utility/RefCounter.cpp new file mode 100644 index 000000000000..c3acedd2f056 --- /dev/null +++ b/source/Utility/RefCounter.cpp @@ -0,0 +1,25 @@ +//===---------------------RefCounter.cpp ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/RefCounter.h" + +namespace lldb_utility { + +RefCounter::RefCounter(RefCounter::value_type* ctr): +m_counter(ctr) +{ + increment(m_counter); +} + +RefCounter::~RefCounter() +{ + decrement(m_counter); +} + +} // namespace lldb_utility diff --git a/source/Utility/SharingPtr.cpp b/source/Utility/SharingPtr.cpp new file mode 100644 index 000000000000..f64d7e3995b8 --- /dev/null +++ b/source/Utility/SharingPtr.cpp @@ -0,0 +1,158 @@ +//===---------------------SharingPtr.cpp ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/SharingPtr.h" + +#if defined (ENABLE_SP_LOGGING) + +// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignements +// and allow them to be queried using a pointer by a call to: +#include <execinfo.h> +#include <map> +#include <assert.h> +#include "lldb/Host/Mutex.h" + +#include <vector> + +class Backtrace +{ +public: + Backtrace (); + + ~Backtrace (); + + void + GetFrames (); + + void + Dump () const; + +private: + void *m_sp_this; + std::vector<void *> m_frames; +}; + + +Backtrace::Backtrace () : m_frames() +{ +} + +Backtrace::~Backtrace () +{ +} + +void +Backtrace::GetFrames () +{ + void *frames[1024]; + const int count = ::backtrace (frames, sizeof(frames)/sizeof(void*)); + if (count > 2) + m_frames.assign (frames + 2, frames + (count - 2)); +} + +void +Backtrace::Dump () const +{ + if (!m_frames.empty()) + ::backtrace_symbols_fd (m_frames.data(), m_frames.size(), STDOUT_FILENO); + write (STDOUT_FILENO, "\n\n", 2); +} + +extern "C" void track_sp (void *sp_this, void *ptr, long use_count) +{ + typedef std::pair<void *, Backtrace> PtrBacktracePair; + typedef std::map<void *, PtrBacktracePair> PtrToBacktraceMap; + static lldb_private::Mutex g_mutex(lldb_private::Mutex::eMutexTypeNormal); + lldb_private::Mutex::Locker locker (g_mutex); + static PtrToBacktraceMap g_map; + + if (sp_this) + { + printf ("sp(%p) -> %p %lu\n", sp_this, ptr, use_count); + + if (ptr) + { + Backtrace bt; + bt.GetFrames(); + g_map[sp_this] = std::make_pair(ptr, bt); + } + else + { + g_map.erase (sp_this); + } + } + else + { + if (ptr) + printf ("Searching for shared pointers that are tracking %p: ", ptr); + else + printf ("Dump all live shared pointres: "); + + uint32_t matches = 0; + PtrToBacktraceMap::iterator pos, end = g_map.end(); + for (pos = g_map.begin(); pos != end; ++pos) + { + if (ptr == NULL || pos->second.first == ptr) + { + ++matches; + printf ("\nsp(%p): %p\n", pos->first, pos->second.first); + pos->second.second.Dump(); + } + } + if (matches == 0) + { + printf ("none.\n"); + } + } +} +// Put dump_sp_refs in the lldb namespace to it gets through our exports lists filter in the LLDB.framework or lldb.so +namespace lldb { + + void dump_sp_refs (void *ptr) + { + // Use a specially crafted call to "track_sp" which will + // dump info on all live shared pointers that reference "ptr" + track_sp (NULL, ptr, 0); + } + +} + +#endif + +namespace lldb_private { + +namespace imp +{ + + + shared_count::~shared_count() + { + } + + void + shared_count::add_shared() + { + increment(shared_owners_); + } + + void + shared_count::release_shared() + { + if (decrement(shared_owners_) == -1) + { + on_zero_shared(); + delete this; + } + } + +} // imp + + +} // namespace lldb + diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp new file mode 100644 index 000000000000..2f4bcecda8f3 --- /dev/null +++ b/source/Utility/StringExtractor.cpp @@ -0,0 +1,397 @@ +//===-- StringExtractor.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Utility/StringExtractor.h" + +// C Includes +#include <stdlib.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes + +static const uint8_t +g_hex_ascii_to_hex_integer[256] = { + + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, + 0x8, 0x9, 255, 255, 255, 255, 255, 255, + 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, +}; + +static inline int +xdigit_to_sint (char ch) +{ + if (ch >= 'a' && ch <= 'f') + return 10 + ch - 'a'; + if (ch >= 'A' && ch <= 'F') + return 10 + ch - 'A'; + return ch - '0'; +} + +static inline unsigned int +xdigit_to_uint (uint8_t ch) +{ + if (ch >= 'a' && ch <= 'f') + return 10u + ch - 'a'; + if (ch >= 'A' && ch <= 'F') + return 10u + ch - 'A'; + return ch - '0'; +} + +//---------------------------------------------------------------------- +// StringExtractor constructor +//---------------------------------------------------------------------- +StringExtractor::StringExtractor() : + m_packet(), + m_index (0) +{ +} + + +StringExtractor::StringExtractor(const char *packet_cstr) : + m_packet(), + m_index (0) +{ + if (packet_cstr) + m_packet.assign (packet_cstr); +} + + +//---------------------------------------------------------------------- +// StringExtractor copy constructor +//---------------------------------------------------------------------- +StringExtractor::StringExtractor(const StringExtractor& rhs) : + m_packet (rhs.m_packet), + m_index (rhs.m_index) +{ + +} + +//---------------------------------------------------------------------- +// StringExtractor assignment operator +//---------------------------------------------------------------------- +const StringExtractor& +StringExtractor::operator=(const StringExtractor& rhs) +{ + if (this != &rhs) + { + m_packet = rhs.m_packet; + m_index = rhs.m_index; + + } + return *this; +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +StringExtractor::~StringExtractor() +{ +} + + +char +StringExtractor::GetChar (char fail_value) +{ + if (m_index < m_packet.size()) + { + char ch = m_packet[m_index]; + ++m_index; + return ch; + } + m_index = UINT64_MAX; + return fail_value; +} + +//---------------------------------------------------------------------- +// Extract an unsigned character from two hex ASCII chars in the packet +// string +//---------------------------------------------------------------------- +uint8_t +StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail) +{ + uint32_t i = m_index; + if ((i + 2) <= m_packet.size()) + { + const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i])]; + const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i+1])]; + if (hi_nibble < 16 && lo_nibble < 16) + { + m_index += 2; + return (hi_nibble << 4) + lo_nibble; + } + } + if (set_eof_on_fail || m_index >= m_packet.size()) + m_index = UINT64_MAX; + return fail_value; +} + +uint32_t +StringExtractor::GetU32 (uint32_t fail_value, int base) +{ + if (m_index < m_packet.size()) + { + char *end = NULL; + const char *start = m_packet.c_str(); + const char *uint_cstr = start + m_index; + uint32_t result = ::strtoul (uint_cstr, &end, base); + + if (end && end != uint_cstr) + { + m_index = end - start; + return result; + } + } + return fail_value; +} + + +uint32_t +StringExtractor::GetHexMaxU32 (bool little_endian, uint32_t fail_value) +{ + uint32_t result = 0; + uint32_t nibble_count = 0; + + if (little_endian) + { + uint32_t shift_amount = 0; + while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + // Make sure we don't exceed the size of a uint32_t... + if (nibble_count >= (sizeof(uint32_t) * 2)) + { + m_index = UINT64_MAX; + return fail_value; + } + + uint8_t nibble_lo; + uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); + ++m_index; + if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + nibble_lo = xdigit_to_sint (m_packet[m_index]); + ++m_index; + result |= ((uint32_t)nibble_hi << (shift_amount + 4)); + result |= ((uint32_t)nibble_lo << shift_amount); + nibble_count += 2; + shift_amount += 8; + } + else + { + result |= ((uint32_t)nibble_hi << shift_amount); + nibble_count += 1; + shift_amount += 4; + } + + } + } + else + { + while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + // Make sure we don't exceed the size of a uint32_t... + if (nibble_count >= (sizeof(uint32_t) * 2)) + { + m_index = UINT64_MAX; + return fail_value; + } + + uint8_t nibble = xdigit_to_sint (m_packet[m_index]); + // Big Endian + result <<= 4; + result |= nibble; + + ++m_index; + ++nibble_count; + } + } + return result; +} + +uint64_t +StringExtractor::GetHexMaxU64 (bool little_endian, uint64_t fail_value) +{ + uint64_t result = 0; + uint32_t nibble_count = 0; + + if (little_endian) + { + uint32_t shift_amount = 0; + while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + // Make sure we don't exceed the size of a uint64_t... + if (nibble_count >= (sizeof(uint64_t) * 2)) + { + m_index = UINT64_MAX; + return fail_value; + } + + uint8_t nibble_lo; + uint8_t nibble_hi = xdigit_to_sint (m_packet[m_index]); + ++m_index; + if (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + nibble_lo = xdigit_to_sint (m_packet[m_index]); + ++m_index; + result |= ((uint64_t)nibble_hi << (shift_amount + 4)); + result |= ((uint64_t)nibble_lo << shift_amount); + nibble_count += 2; + shift_amount += 8; + } + else + { + result |= ((uint64_t)nibble_hi << shift_amount); + nibble_count += 1; + shift_amount += 4; + } + + } + } + else + { + while (m_index < m_packet.size() && ::isxdigit (m_packet[m_index])) + { + // Make sure we don't exceed the size of a uint64_t... + if (nibble_count >= (sizeof(uint64_t) * 2)) + { + m_index = UINT64_MAX; + return fail_value; + } + + uint8_t nibble = xdigit_to_sint (m_packet[m_index]); + // Big Endian + result <<= 4; + result |= nibble; + + ++m_index; + ++nibble_count; + } + } + return result; +} + +size_t +StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_value) +{ + uint8_t *dst = (uint8_t*)dst_void; + size_t bytes_extracted = 0; + while (bytes_extracted < dst_len && GetBytesLeft ()) + { + dst[bytes_extracted] = GetHexU8 (fail_fill_value); + if (IsGood()) + ++bytes_extracted; + else + break; + } + + for (size_t i = bytes_extracted; i < dst_len; ++i) + dst[i] = fail_fill_value; + + return bytes_extracted; +} + + +// Consume ASCII hex nibble character pairs until we have decoded byte_size +// bytes of data. + +uint64_t +StringExtractor::GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value) +{ + if (byte_size <= 8 && GetBytesLeft() >= byte_size * 2) + { + uint64_t result = 0; + uint32_t i; + if (little_endian) + { + // Little Endian + uint32_t shift_amount; + for (i = 0, shift_amount = 0; + i < byte_size && IsGood(); + ++i, shift_amount += 8) + { + result |= ((uint64_t)GetHexU8() << shift_amount); + } + } + else + { + // Big Endian + for (i = 0; i < byte_size && IsGood(); ++i) + { + result <<= 8; + result |= GetHexU8(); + } + } + } + m_index = UINT64_MAX; + return fail_value; +} + +size_t +StringExtractor::GetHexByteString (std::string &str) +{ + str.clear(); + char ch; + while ((ch = GetHexU8()) != '\0') + str.append(1, ch); + return str.size(); +} + +bool +StringExtractor::GetNameColonValue (std::string &name, std::string &value) +{ + // Read something in the form of NNNN:VVVV; where NNNN is any character + // that is not a colon, followed by a ':' character, then a value (one or + // more ';' chars), followed by a ';' + if (m_index < m_packet.size()) + { + const size_t colon_idx = m_packet.find (':', m_index); + if (colon_idx != std::string::npos) + { + const size_t semicolon_idx = m_packet.find (';', colon_idx); + if (semicolon_idx != std::string::npos) + { + name.assign (m_packet, m_index, colon_idx - m_index); + value.assign (m_packet, colon_idx + 1, semicolon_idx - (colon_idx + 1)); + m_index = semicolon_idx + 1; + return true; + } + } + } + m_index = UINT64_MAX; + return false; +} diff --git a/source/Utility/StringExtractor.h b/source/Utility/StringExtractor.h new file mode 100644 index 000000000000..0ded3101fcca --- /dev/null +++ b/source/Utility/StringExtractor.h @@ -0,0 +1,141 @@ +//===-- StringExtractor.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_StringExtractor_h_ +#define utility_StringExtractor_h_ + +// C Includes +// C++ Includes +#include <string> +#include <stdint.h> + +// Other libraries and framework includes +// Project includes + +class StringExtractor +{ +public: + + enum { + BigEndian = 0, + LittleEndian = 1 + }; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StringExtractor(); + StringExtractor(const char *packet_cstr); + StringExtractor(const StringExtractor& rhs); + virtual ~StringExtractor(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const StringExtractor& + operator=(const StringExtractor& rhs); + + // Returns true if the file position is still valid for the data + // contained in this string extractor object. + bool + IsGood() const + { + return m_index != UINT64_MAX; + } + + uint64_t + GetFilePos () const + { + return m_index; + } + + void + SetFilePos (uint32_t idx) + { + m_index = idx; + } + + void + Clear () + { + m_packet.clear(); + m_index = 0; + } + + std::string & + GetStringRef () + { + return m_packet; + } + + const std::string & + GetStringRef () const + { + return m_packet; + } + + bool + Empty() + { + return m_packet.empty(); + } + + size_t + GetBytesLeft () + { + if (m_index < m_packet.size()) + return m_packet.size() - m_index; + return 0; + } + char + GetChar (char fail_value = '\0'); + + uint8_t + GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true); + + bool + GetNameColonValue (std::string &name, std::string &value); + + uint32_t + GetU32 (uint32_t fail_value, int base = 0); + + uint32_t + GetHexMaxU32 (bool little_endian, uint32_t fail_value); + + uint64_t + GetHexMaxU64 (bool little_endian, uint64_t fail_value); + + size_t + GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value); + + uint64_t + GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value); + + size_t + GetHexByteString (std::string &str); + + const char * + Peek () + { + if (m_index < m_packet.size()) + return m_packet.c_str() + m_index; + return NULL; + } + +protected: + //------------------------------------------------------------------ + // For StringExtractor only + //------------------------------------------------------------------ + std::string m_packet; // The string in which to extract data. + uint64_t m_index; // When extracting data from a packet, this index + // will march along as things get extracted. If set + // to UINT64_MAX the end of the packet data was + // reached when decoding information +}; + +#endif // utility_StringExtractor_h_ diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp new file mode 100644 index 000000000000..7e06a0f59bc9 --- /dev/null +++ b/source/Utility/StringExtractorGDBRemote.cpp @@ -0,0 +1,182 @@ +//===-- StringExtractorGDBRemote.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 +// Other libraries and framework includes +// Project includes +#include "Utility/StringExtractorGDBRemote.h" + + + +StringExtractorGDBRemote::ResponseType +StringExtractorGDBRemote::GetResponseType () const +{ + if (m_packet.empty()) + return eUnsupported; + + switch (m_packet[0]) + { + case 'E': + if (m_packet.size() == 3 && + isxdigit(m_packet[1]) && + isxdigit(m_packet[2])) + return eError; + break; + + case 'O': + if (m_packet.size() == 2 && m_packet[1] == 'K') + return eOK; + break; + + case '+': + if (m_packet.size() == 1) + return eAck; + break; + + case '-': + if (m_packet.size() == 1) + return eNack; + break; + } + return eResponse; +} + +StringExtractorGDBRemote::ServerPacketType +StringExtractorGDBRemote::GetServerPacketType () const +{ +#define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0)) +#define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0) + + // Empty is not a supported packet... + if (m_packet.empty()) + return eServerPacketType_invalid; + + const size_t packet_size = m_packet.size(); + const char *packet_cstr = m_packet.c_str(); + switch (m_packet[0]) + { + case '\x03': + if (packet_size == 1) return eServerPacketType_interrupt; + break; + + case '-': + if (packet_size == 1) return eServerPacketType_nack; + break; + + case '+': + if (packet_size == 1) return eServerPacketType_ack; + break; + + case 'A': + return eServerPacketType_A; + + case 'Q': + switch (packet_cstr[1]) + { + case 'E': + if (PACKET_STARTS_WITH ("QEnvironment:")) return eServerPacketType_QEnvironment; + break; + + case 'S': + if (PACKET_MATCHES ("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode; + else if (PACKET_STARTS_WITH ("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR; + else if (PACKET_STARTS_WITH ("QSetSTDIN:")) return eServerPacketType_QSetSTDIN; + else if (PACKET_STARTS_WITH ("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT; + else if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR; + else if (PACKET_STARTS_WITH ("QSetWorkingDir:")) return eServerPacketType_QSetWorkingDir; + break; + } + break; + + case 'q': + switch (packet_cstr[1]) + { + case 's': + if (PACKET_MATCHES ("qsProcessInfo")) return eServerPacketType_qsProcessInfo; + break; + + case 'f': + if (PACKET_STARTS_WITH ("qfProcessInfo")) return eServerPacketType_qfProcessInfo; + break; + + case 'C': + if (packet_size == 2) return eServerPacketType_qC; + break; + + case 'G': + if (PACKET_STARTS_WITH ("qGroupName:")) return eServerPacketType_qGroupName; + break; + + case 'H': + if (PACKET_MATCHES ("qHostInfo")) return eServerPacketType_qHostInfo; + break; + + case 'L': + if (PACKET_MATCHES ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer; + if (PACKET_MATCHES ("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess; + break; + + case 'P': + if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID; + break; + + case 'S': + if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest; + break; + + case 'U': + if (PACKET_STARTS_WITH ("qUserName:")) return eServerPacketType_qUserName; + break; + } + break; + } + return eServerPacketType_unimplemented; +} + +bool +StringExtractorGDBRemote::IsOKResponse() const +{ + return GetResponseType () == eOK; +} + + +bool +StringExtractorGDBRemote::IsUnsupportedResponse() const +{ + return GetResponseType () == eUnsupported; +} + +bool +StringExtractorGDBRemote::IsNormalResponse() const +{ + return GetResponseType () == eResponse; +} + +bool +StringExtractorGDBRemote::IsErrorResponse() const +{ + return GetResponseType () == eError && + m_packet.size() == 3 && + isxdigit(m_packet[1]) && + isxdigit(m_packet[2]); +} + +uint8_t +StringExtractorGDBRemote::GetError () +{ + if (GetResponseType() == eError) + { + SetFilePos(1); + return GetHexU8(255); + } + return 0; +} diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h new file mode 100644 index 000000000000..5a24d894b105 --- /dev/null +++ b/source/Utility/StringExtractorGDBRemote.h @@ -0,0 +1,103 @@ +//===-- StringExtractorGDBRemote.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_StringExtractorGDBRemote_h_ +#define utility_StringExtractorGDBRemote_h_ + +// C Includes +// C++ Includes +#include <string> +// Other libraries and framework includes +// Project includes +#include "Utility/StringExtractor.h" + +class StringExtractorGDBRemote : public StringExtractor +{ +public: + + StringExtractorGDBRemote() : + StringExtractor () + { + } + + StringExtractorGDBRemote(const char *cstr) : + StringExtractor (cstr) + { + } + StringExtractorGDBRemote(const StringExtractorGDBRemote& rhs) : + StringExtractor (rhs) + { + } + + virtual ~StringExtractorGDBRemote() + { + } + + enum ServerPacketType + { + eServerPacketType_nack = 0, + eServerPacketType_ack, + eServerPacketType_invalid, + eServerPacketType_unimplemented, + eServerPacketType_interrupt, // CTRL+c packet or "\x03" + eServerPacketType_A, // Program arguments packet + eServerPacketType_qfProcessInfo, + eServerPacketType_qsProcessInfo, + eServerPacketType_qC, + eServerPacketType_qGroupName, + eServerPacketType_qHostInfo, + eServerPacketType_qLaunchGDBServer, + eServerPacketType_qLaunchSuccess, + eServerPacketType_qProcessInfoPID, + eServerPacketType_qSpeedTest, + eServerPacketType_qUserName, + eServerPacketType_QEnvironment, + eServerPacketType_QSetDisableASLR, + eServerPacketType_QSetSTDIN, + eServerPacketType_QSetSTDOUT, + eServerPacketType_QSetSTDERR, + eServerPacketType_QSetWorkingDir, + eServerPacketType_QStartNoAckMode + }; + + ServerPacketType + GetServerPacketType () const; + + enum ResponseType + { + eUnsupported = 0, + eAck, + eNack, + eError, + eOK, + eResponse + }; + + ResponseType + GetResponseType () const; + + bool + IsOKResponse() const; + + bool + IsUnsupportedResponse() const; + + bool + IsNormalResponse () const; + + bool + IsErrorResponse() const; + + // Returns zero if the packet isn't a EXX packet where XX are two hex + // digits. Otherwise the error encoded in XX is returned. + uint8_t + GetError(); +}; + +#endif // utility_StringExtractorGDBRemote_h_ diff --git a/source/Utility/TimeSpecTimeout.cpp b/source/Utility/TimeSpecTimeout.cpp new file mode 100644 index 000000000000..33b3b4e6c391 --- /dev/null +++ b/source/Utility/TimeSpecTimeout.cpp @@ -0,0 +1,48 @@ +//===--------------------- TimeSpecTimeout.cpp ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "TimeSpecTimeout.h" + +using namespace lldb_private; + +const struct timespec * +TimeSpecTimeout::SetAbsoluteTimeoutMircoSeconds32 (uint32_t timeout_usec) +{ + if (timeout_usec == UINT32_MAX) + { + m_infinite = true; + } + else + { + m_infinite = false; + TimeValue time_value(TimeValue::Now()); + time_value.OffsetWithMicroSeconds(timeout_usec); + m_timespec = time_value.GetAsTimeSpec(); + } + return GetTimeSpecPtr (); +} + +const struct timespec * +TimeSpecTimeout::SetRelativeTimeoutMircoSeconds32 (uint32_t timeout_usec) +{ + if (timeout_usec == UINT32_MAX) + { + m_infinite = true; + } + else + { + m_infinite = false; + TimeValue time_value; + time_value.OffsetWithMicroSeconds(timeout_usec); + m_timespec = time_value.GetAsTimeSpec(); + } + return GetTimeSpecPtr (); +} + + diff --git a/source/Utility/TimeSpecTimeout.h b/source/Utility/TimeSpecTimeout.h new file mode 100644 index 000000000000..32cdd067658c --- /dev/null +++ b/source/Utility/TimeSpecTimeout.h @@ -0,0 +1,90 @@ +//===--------------------- TimeSpecTimeout.h --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_TimeSpecTimeout_h_ +#define utility_TimeSpecTimeout_h_ + +#include "lldb/Host/TimeValue.h" + +namespace lldb_private { + +class TimeSpecTimeout +{ +public: + TimeSpecTimeout() : + m_infinite (false) + { + m_timespec.tv_sec = 0; + m_timespec.tv_nsec = 0; + } + ~TimeSpecTimeout() + { + } + + //---------------------------------------------------------------------- + /// Sets the timespec pointer correctly given a timeout relative to the + /// current time. This function should be called immediately prior to + /// calling the function you will use this timeout with since time can + /// elapse between when this function is called and when the timeout is + /// used. + /// + /// @param[in] timeout_usec + /// The timeout in micro seconds. If timeout_usec is UINT32_MAX, the + /// timeout should be set to INFINITE. Otherwise the current time is + /// filled into the timespec and \a timeout_usec is added to the + /// current time. + /// + /// @return + /// If the timeout is INFINITE, then return NULL, otherwise return + /// a pointer to the timespec with the appropriate timeout value. + //---------------------------------------------------------------------- + const struct timespec * + SetAbsoluteTimeoutMircoSeconds32 (uint32_t timeout_usec); + + //---------------------------------------------------------------------- + /// Sets the timespec pointer correctly given a relative time in micro + /// seconds. + /// + /// @param[in] timeout_usec + /// The timeout in micro seconds. If timeout_usec is UINT32_MAX, the + /// timeout should be set to INFINITE. Otherwise \a timeout_usec + /// is correctly placed into the timespec. + /// + /// @return + /// If the timeout is INFINITE, then return NULL, otherwise return + /// a pointer to the timespec with the appropriate timeout value. + //---------------------------------------------------------------------- + const struct timespec * + SetRelativeTimeoutMircoSeconds32 (uint32_t timeout_usec); + + //---------------------------------------------------------------------- + /// Gets the timespec pointer that is appropriate for the timeout + /// specified. This function should only be used after a call to + /// SetRelativeTimeoutXXX() functions. + /// + /// @return + /// If the timeout is INFINITE, then return NULL, otherwise return + /// a pointer to the timespec with the appropriate timeout value. + //---------------------------------------------------------------------- + const struct timespec * + GetTimeSpecPtr () const + { + if (m_infinite) + return NULL; + return &m_timespec; + } + +protected: + struct timespec m_timespec; + bool m_infinite; +}; + +} // namespace lldb_private + +#endif // #ifndef utility_TimeSpecTimeout_h_ diff --git a/source/Utility/UuidCompatibility.h b/source/Utility/UuidCompatibility.h new file mode 100644 index 000000000000..df26f77ab52d --- /dev/null +++ b/source/Utility/UuidCompatibility.h @@ -0,0 +1,18 @@ +//===-- UuidCompatibility.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Include this header if your system does not have a definition of uuid_t + +#ifndef utility_UUID_COMPATIBILITY_H +#define utility_UUID_COMPATIBILITY_H + +// uuid_t is guaranteed to always be a 16-byte array +typedef unsigned char uuid_t[16]; + +#endif // utility_UUID_COMPATIBILITY_H |