summaryrefslogtreecommitdiffstats
path: root/lldb/source/Utility
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Utility')
-rw-r--r--lldb/source/Utility/ARM_DWARF_Registers.h190
-rw-r--r--lldb/source/Utility/ARM_GCC_Registers.h35
-rw-r--r--lldb/source/Utility/PseudoTerminal.cpp336
-rw-r--r--lldb/source/Utility/PseudoTerminal.h267
-rw-r--r--lldb/source/Utility/StringExtractor.cpp360
-rw-r--r--lldb/source/Utility/StringExtractor.h126
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.cpp89
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.h73
8 files changed, 1476 insertions, 0 deletions
diff --git a/lldb/source/Utility/ARM_DWARF_Registers.h b/lldb/source/Utility/ARM_DWARF_Registers.h
new file mode 100644
index 00000000000..40b973be6da
--- /dev/null
+++ b/lldb/source/Utility/ARM_DWARF_Registers.h
@@ -0,0 +1,190 @@
+//===-- 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_
+
+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
+};
+
+#endif utility_ARM_DWARF_Registers_h_
+
diff --git a/lldb/source/Utility/ARM_GCC_Registers.h b/lldb/source/Utility/ARM_GCC_Registers.h
new file mode 100644
index 00000000000..fe1327b5e14
--- /dev/null
+++ b/lldb/source/Utility/ARM_GCC_Registers.h
@@ -0,0 +1,35 @@
+//===-- 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
+};
+
+#endif utility_ARM_GCC_Registers_h_
+
diff --git a/lldb/source/Utility/PseudoTerminal.cpp b/lldb/source/Utility/PseudoTerminal.cpp
new file mode 100644
index 00000000000..9bbecae6e6d
--- /dev/null
+++ b/lldb/source/Utility/PseudoTerminal.cpp
@@ -0,0 +1,336 @@
+//===-- 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 "PseudoTerminal.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+
+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/lldb/source/Utility/PseudoTerminal.h b/lldb/source/Utility/PseudoTerminal.h
new file mode 100644
index 00000000000..5d680745a32
--- /dev/null
+++ b/lldb/source/Utility/PseudoTerminal.h
@@ -0,0 +1,267 @@
+//===-- PseudoTerminal.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_PseudoTerminal_h_
+#define liblldb_PseudoTerminal_h_
+#if defined(__cplusplus)
+
+
+#include <fcntl.h>
+#include <termios.h>
+#include <string>
+
+#include "lldb/lldb-defines.h"
+
+namespace lldb_utility {
+
+//----------------------------------------------------------------------
+/// @class PseudoTerminal PseudoTerminal.h "lldb/Core/PseudoTerminal.h"
+/// @brief A pseudo terminal helper class.
+///
+/// The pseudo terminal class abtracts the use of pseudo terminals on
+/// the host system.
+//----------------------------------------------------------------------
+class PseudoTerminal
+{
+public:
+ enum
+ {
+ invalid_fd = -1, ///< Invalid file descriptor value
+ };
+
+ //------------------------------------------------------------------
+ /// Default constructor
+ ///
+ /// Constructs this object with invalid master and slave file
+ /// descriptors.
+ //------------------------------------------------------------------
+ PseudoTerminal ();
+
+ //------------------------------------------------------------------
+ /// Destructor
+ ///
+ /// The destructor will close the master and slave file descriptors
+ /// if they are valid and ownwership has not been released using
+ /// one of:
+ /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+ /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+ //------------------------------------------------------------------
+ ~PseudoTerminal ();
+
+ //------------------------------------------------------------------
+ /// Close the master file descriptor if it is valid.
+ //------------------------------------------------------------------
+ void
+ CloseMasterFileDescriptor ();
+
+ //------------------------------------------------------------------
+ /// Close the slave file descriptor if it is valid.
+ //------------------------------------------------------------------
+ void
+ CloseSlaveFileDescriptor ();
+
+ //------------------------------------------------------------------
+ /// Fork a child process that uses pseudo terminals for its stdio.
+ ///
+ /// In the parent process, a call to this function results in a pid
+ /// being returned. If the pid is valid, the master file descriptor
+ /// can be used for 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. The file handles can be released
+ /// using either:
+ /// @li PseudoTerminal::ReleaseMasterFileDescriptor()
+ /// @li PseudoTerminal::ReleaseSaveFileDescriptor()
+ ///
+ /// @param[out] error
+ /// An pointer to an error that can describe any errors that
+ /// occur. This can be NULL if no error status is desired.
+ ///
+ /// @return
+ /// @li \b Parent process: a child process ID that is greater
+ /// than zero, or -1 if the fork fails.
+ /// @li \b Child process: zero.
+ //------------------------------------------------------------------
+ pid_t
+ Fork (char *error_str, size_t error_len);
+
+ //------------------------------------------------------------------
+ /// The master file descriptor accessor.
+ ///
+ /// This object retains ownership of the master file descriptor when
+ /// this accessor is used. Users can call the member function
+ /// PseudoTerminal::ReleaseMasterFileDescriptor() if this
+ /// object should release ownership of the slave file descriptor.
+ ///
+ /// @return
+ /// The master file descriptor, or PseudoTerminal::invalid_fd
+ /// if the master file descriptor is not currently valid.
+ ///
+ /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+ //------------------------------------------------------------------
+ int
+ GetMasterFileDescriptor () const;
+
+ //------------------------------------------------------------------
+ /// The slave file descriptor accessor.
+ ///
+ /// This object retains ownership of the slave file descriptor when
+ /// this accessor is used. Users can call the member function
+ /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this
+ /// object should release ownership of the slave file descriptor.
+ ///
+ /// @return
+ /// The slave file descriptor, or PseudoTerminal::invalid_fd
+ /// if the slave file descriptor is not currently valid.
+ ///
+ /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+ //------------------------------------------------------------------
+ int
+ GetSlaveFileDescriptor () const;
+
+ //------------------------------------------------------------------
+ /// Get the name of the slave pseudo terminal.
+ ///
+ /// A master pseudo terminal should already be valid prior to
+ /// calling this function.
+ ///
+ /// @param[out] error
+ /// An pointer to an error that can describe any errors that
+ /// occur. This can be NULL if no error status is desired.
+ ///
+ /// @return
+ /// The name of the slave pseudo terminal as a NULL terminated
+ /// C. This string that comes from static memory, so a copy of
+ /// the string should be made as subsequent calls can change
+ /// this value. NULL is returned if this object doesn't have
+ /// a valid master pseudo terminal opened or if the call to
+ /// \c ptsname() fails.
+ ///
+ /// @see PseudoTerminal::OpenFirstAvailableMaster()
+ //------------------------------------------------------------------
+ const char*
+ GetSlaveName (char *error_str, size_t error_len) const;
+
+ //------------------------------------------------------------------
+ /// Open the first available pseudo terminal.
+ ///
+ /// Opens the first available pseudo terminal with \a oflag as the
+ /// permissions. The opened master file descriptor is stored in this
+ /// object and can be accessed by calling the
+ /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients
+ /// can call the PseudoTerminal::ReleaseMasterFileDescriptor()
+ /// accessor function if they wish to use the master file descriptor
+ /// beyond the lifespan of this object.
+ ///
+ /// If this object still has a valid master file descriptor when its
+ /// destructor is called, it will close it.
+ ///
+ /// @param[in] oflag
+ /// Flags to use when calling \c posix_openpt(\a oflag).
+ /// A value of "O_RDWR|O_NOCTTY" is suggested.
+ ///
+ /// @param[out] error
+ /// An pointer to an error that can describe any errors that
+ /// occur. This can be NULL if no error status is desired.
+ ///
+ /// @return
+ /// @li \b true when the a master files descriptor is
+ /// successfully opened.
+ /// @li \b false if anything goes wrong.
+ ///
+ /// @see PseudoTerminal::GetMasterFileDescriptor()
+ /// @see PseudoTerminal::ReleaseMasterFileDescriptor()
+ //------------------------------------------------------------------
+ bool
+ OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len);
+
+ //------------------------------------------------------------------
+ /// Open the slave for the current master pseudo terminal.
+ ///
+ /// A master pseudo terminal should already be valid prior to
+ /// calling this function. The opened slave file descriptor is
+ /// stored in this object and can be accessed by calling the
+ /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients
+ /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor()
+ /// accessor function if they wish to use the slave file descriptor
+ /// beyond the lifespan of this object.
+ ///
+ /// If this object still has a valid slave file descriptor when its
+ /// destructor is called, it will close it.
+ ///
+ /// @param[in] oflag
+ /// Flags to use when calling \c open(\a oflag).
+ ///
+ /// @param[out] error
+ /// An pointer to an error that can describe any errors that
+ /// occur. This can be NULL if no error status is desired.
+ ///
+ /// @return
+ /// @li \b true when the a master files descriptor is
+ /// successfully opened.
+ /// @li \b false if anything goes wrong.
+ ///
+ /// @see PseudoTerminal::OpenFirstAvailableMaster()
+ /// @see PseudoTerminal::GetSlaveFileDescriptor()
+ /// @see PseudoTerminal::ReleaseSlaveFileDescriptor()
+ //------------------------------------------------------------------
+ bool
+ OpenSlave (int oflag, char *error_str, size_t error_len);
+
+ //------------------------------------------------------------------
+ /// Release the master file descriptor.
+ ///
+ /// Releases 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.
+ ///
+ /// @return
+ /// The master file descriptor, or PseudoTerminal::invalid_fd
+ /// if the mast file descriptor is not currently valid.
+ //------------------------------------------------------------------
+ int
+ ReleaseMasterFileDescriptor ();
+
+ //------------------------------------------------------------------
+ /// Release the slave file descriptor.
+ ///
+ /// 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.
+ ///
+ /// @return
+ /// The slave file descriptor, or PseudoTerminal::invalid_fd
+ /// if the slave file descriptor is not currently valid.
+ //------------------------------------------------------------------
+ int
+ ReleaseSlaveFileDescriptor ();
+
+protected:
+ //------------------------------------------------------------------
+ // Member variables
+ //------------------------------------------------------------------
+ int m_master_fd; ///< The file descriptor for the master.
+ int m_slave_fd; ///< The file descriptor for the slave.
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PseudoTerminal);
+
+};
+
+} // namespace lldb
+
+#endif // #if defined(__cplusplus)
+#endif // #ifndef liblldb_PseudoTerminal_h_
diff --git a/lldb/source/Utility/StringExtractor.cpp b/lldb/source/Utility/StringExtractor.cpp
new file mode 100644
index 00000000000..d2f69f95b7c
--- /dev/null
+++ b/lldb/source/Utility/StringExtractor.cpp
@@ -0,0 +1,360 @@
+//===-- 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 "StringExtractor.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+static inline int
+xdigit_to_sint (char ch)
+{
+ ch = tolower(ch);
+ if (ch >= 'a' && ch <= 'f')
+ return 10 + ch - 'a';
+ return ch - '0';
+}
+
+static inline unsigned int
+xdigit_to_uint (uint8_t ch)
+{
+ ch = tolower(ch);
+ 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 = UINT32_MAX;
+ return fail_value;
+}
+
+uint32_t
+StringExtractor::GetNumHexASCIICharsAtFilePos (uint32_t max) const
+{
+ uint32_t idx = m_index;
+ const size_t size = m_packet.size();
+ while (idx < size && idx - m_index < max && isxdigit(m_packet[idx]))
+ ++idx;
+ return idx - m_index;
+}
+//----------------------------------------------------------------------
+// Extract a signed character from two hex ASCII chars in the packet
+// string
+//----------------------------------------------------------------------
+int8_t
+StringExtractor::GetHexS8 (int8_t fail_value)
+{
+ if (GetNumHexASCIICharsAtFilePos(2))
+ {
+ char hi_nibble_char = m_packet[m_index];
+ char lo_nibble_char = m_packet[m_index+1];
+
+ if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
+ {
+ char hi_nibble = xdigit_to_sint (hi_nibble_char);
+ char lo_nibble = xdigit_to_sint (lo_nibble_char);
+ m_index += 2;
+ return (hi_nibble << 4) + lo_nibble;
+ }
+ }
+ m_index = UINT32_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)
+{
+ if (GetNumHexASCIICharsAtFilePos(2))
+ {
+ uint8_t hi_nibble_char = m_packet[m_index];
+ uint8_t lo_nibble_char = m_packet[m_index+1];
+
+ if (isxdigit(hi_nibble_char) && isxdigit(lo_nibble_char))
+ {
+ uint8_t hi_nibble = xdigit_to_sint (hi_nibble_char);
+ uint8_t lo_nibble = xdigit_to_sint (lo_nibble_char);
+ m_index += 2;
+ return (hi_nibble << 4) + lo_nibble;
+ }
+ }
+ m_index = UINT32_MAX;
+ 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 = UINT32_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 = UINT32_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 = UINT32_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 = UINT32_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 && m_index != UINT32_MAX;
+ ++i, shift_amount += 8)
+ {
+ result |= ((uint64_t)GetHexU8() << shift_amount);
+ }
+ }
+ else
+ {
+ // Big Endian
+ for (i = 0; i < byte_size && m_index != UINT32_MAX; ++i)
+ {
+ result <<= 8;
+ result |= GetHexU8();
+ }
+ }
+ }
+ m_index = UINT32_MAX;
+ return fail_value;
+}
+
+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 = UINT32_MAX;
+ return false;
+}
diff --git a/lldb/source/Utility/StringExtractor.h b/lldb/source/Utility/StringExtractor.h
new file mode 100644
index 00000000000..e2312f71ad7
--- /dev/null
+++ b/lldb/source/Utility/StringExtractor.h
@@ -0,0 +1,126 @@
+//===-- 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>
+
+// 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 != UINT32_MAX;
+ }
+
+ uint32_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;
+ }
+
+ bool
+ Empty()
+ {
+ return m_packet.empty();
+ }
+
+ uint32_t
+ GetBytesLeft ()
+ {
+ if (m_index < m_packet.size())
+ return m_packet.size() - m_index;
+ return 0;
+ }
+ char
+ GetChar (char fail_value = '\0');
+
+ int8_t
+ GetHexS8 (int8_t fail_value = 0);
+
+ uint8_t
+ GetHexU8 (uint8_t fail_value = 0);
+
+ bool
+ GetNameColonValue (std::string &name, std::string &value);
+
+ 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);
+
+protected:
+ //------------------------------------------------------------------
+ // For StringExtractor only
+ //------------------------------------------------------------------
+ std::string m_packet; // The string in which to extract data.
+ uint32_t m_index; // When extracting data from a packet, this index
+ // will march along as things get extracted. If set
+ // to UINT32_MAX the end of the packet data was
+ // reached when decoding information
+
+ uint32_t
+ GetNumHexASCIICharsAtFilePos (uint32_t max = UINT32_MAX) const;
+};
+
+#endif // utility_StringExtractor_h_
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
new file mode 100644
index 00000000000..f7dcc4181f3
--- /dev/null
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -0,0 +1,89 @@
+//===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StringExtractorGDBRemote.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+
+
+StringExtractorGDBRemote::Type
+StringExtractorGDBRemote::GetType () 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;
+}
+
+bool
+StringExtractorGDBRemote::IsOKPacket() const
+{
+ return GetType () == eOK;
+}
+
+
+bool
+StringExtractorGDBRemote::IsUnsupportedPacket() const
+{
+ return GetType () == eUnsupported;
+}
+
+bool
+StringExtractorGDBRemote::IsNormalPacket() const
+{
+ return GetType () == eResponse;
+}
+
+bool
+StringExtractorGDBRemote::IsErrorPacket() const
+{
+ return GetType () == eError &&
+ m_packet.size() == 3 &&
+ isxdigit(m_packet[1]) &&
+ isxdigit(m_packet[2]);
+}
+
+uint8_t
+StringExtractorGDBRemote::GetError ()
+{
+ if (GetType() == eError)
+ {
+ SetFilePos(1);
+ return GetHexU8(255);
+ }
+ return 0;
+}
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h
new file mode 100644
index 00000000000..813ddad2e27
--- /dev/null
+++ b/lldb/source/Utility/StringExtractorGDBRemote.h
@@ -0,0 +1,73 @@
+//===-- 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 "StringExtractor.h"
+
+class StringExtractorGDBRemote : public StringExtractor
+{
+public:
+
+ StringExtractorGDBRemote() :
+ StringExtractor ()
+ {
+ }
+
+ StringExtractorGDBRemote(const char *cstr) :
+ StringExtractor (cstr)
+ {
+ }
+ StringExtractorGDBRemote(const StringExtractorGDBRemote& rhs) :
+ StringExtractor (rhs)
+ {
+ }
+
+ virtual ~StringExtractorGDBRemote()
+ {
+ }
+
+ enum Type
+ {
+ eUnsupported = 0,
+ eAck,
+ eNack,
+ eError,
+ eOK,
+ eResponse
+ };
+
+ StringExtractorGDBRemote::Type
+ GetType () const;
+
+ bool
+ IsOKPacket() const;
+
+ bool
+ IsUnsupportedPacket() const;
+
+ bool
+ IsNormalPacket () const;
+
+ bool
+ IsErrorPacket() 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_
OpenPOWER on IntegriCloud