From scallanan at apple.com Wed Jan 4 11:36:30 2012 From: scallanan at apple.com (Sean Callanan) Date: Wed, 04 Jan 2012 17:36:30 -0000 Subject: [Lldb-commits] [lldb] r147536 - /lldb/trunk/source/Core/DataExtractor.cpp Message-ID: <20120104173630.F3C872A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 11:36:30 2012 New Revision: 147536 URL: http://llvm.org/viewvc/llvm-project?rev=147536&view=rev Log: Instead of blindly printing a string when eFormatCString is specified, I have made DataExtractor::Dump properly escape the string. This prevents LLDB from printing characters that confuse terminals. Modified: lldb/trunk/source/Core/DataExtractor.cpp Modified: lldb/trunk/source/Core/DataExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=147536&r1=147535&r2=147536&view=diff ============================================================================== --- lldb/trunk/source/Core/DataExtractor.cpp (original) +++ lldb/trunk/source/Core/DataExtractor.cpp Wed Jan 4 11:36:30 2012 @@ -1577,13 +1577,43 @@ case eFormatCString: { const char *cstr = GetCStr(&offset); - if (cstr) - s->Printf("\"%s\"", cstr); - else + + if (!cstr) { s->Printf("NULL"); offset = UINT32_MAX; } + else + { + s->PutChar('\"'); + + while (const char c = *cstr) + { + if (isprint(c)) + { + s->PutChar(c); + } + else + { + switch (c) + { + case '\033': s->Printf ("\\e"); break; + case '\a': s->Printf ("\\a"); break; + case '\b': s->Printf ("\\b"); break; + case '\f': s->Printf ("\\f"); break; + case '\n': s->Printf ("\\n"); break; + case '\r': s->Printf ("\\r"); break; + case '\t': s->Printf ("\\t"); break; + case '\v': s->Printf ("\\v"); break; + default: s->Printf ("\\x%2.2x", c); break; + } + } + + ++cstr; + } + + s->PutChar('\"'); + } } break; From scallanan at apple.com Wed Jan 4 13:11:25 2012 From: scallanan at apple.com (Sean Callanan) Date: Wed, 04 Jan 2012 19:11:25 -0000 Subject: [Lldb-commits] [lldb] r147540 - in /lldb/trunk/source/Interpreter: CommandObject.cpp Options.cpp Message-ID: <20120104191125.A21202A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 13:11:25 2012 New Revision: 147540 URL: http://llvm.org/viewvc/llvm-project?rev=147540&view=rev Log: Fixed the help text for raw commands like "expr" to include -- in sample command lines. Now LLDB prints expression [-f ] -- instead of expression [-f ] and also adds a new example line: expression to show that in the absense of arguments the -- can be ommitted. Modified: lldb/trunk/source/Interpreter/CommandObject.cpp lldb/trunk/source/Interpreter/Options.cpp Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=147540&r1=147539&r2=147540&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Wed Jan 4 13:11:25 2012 @@ -89,6 +89,8 @@ if (m_arguments.size() > 0) { syntax_str.Printf (" "); + if (WantsRawCommandString()) + syntax_str.Printf("-- "); GetFormattedCommandArguments (syntax_str); } m_cmd_syntax = syntax_str.GetData (); Modified: lldb/trunk/source/Interpreter/Options.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/Options.cpp?rev=147540&r1=147539&r2=147540&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/Options.cpp (original) +++ lldb/trunk/source/Interpreter/Options.cpp Wed Jan 4 13:11:25 2012 @@ -555,9 +555,24 @@ } } } + if (arguments_str.GetSize() > 0) + { + if (cmd->WantsRawCommandString()) + strm.Printf(" --"); + strm.Printf (" %s", arguments_str.GetData()); + } } + + if (cmd->WantsRawCommandString() && + arguments_str.GetSize() > 0) + { + strm.PutChar('\n'); + strm.Indent(name); + strm.Printf(" %s", arguments_str.GetData()); + } + strm.Printf ("\n\n"); // Now print out all the detailed information about the various options: long form, short form and help text: From scallanan at apple.com Wed Jan 4 15:20:39 2012 From: scallanan at apple.com (Sean Callanan) Date: Wed, 04 Jan 2012 21:20:39 -0000 Subject: [Lldb-commits] [lldb] r147549 - /lldb/trunk/www/lldb-gdb.html Message-ID: <20120104212039.86C572A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 15:20:39 2012 New Revision: 147549 URL: http://llvm.org/viewvc/llvm-project?rev=147549&view=rev Log: Added examples of commands that list and delete breakpoints. Modified: lldb/trunk/www/lldb-gdb.html Modified: lldb/trunk/www/lldb-gdb.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/lldb-gdb.html?rev=147549&r1=147548&r2=147549&view=diff ============================================================================== --- lldb/trunk/www/lldb-gdb.html (original) +++ lldb/trunk/www/lldb-gdb.html Wed Jan 4 15:20:39 2012 @@ -267,6 +267,28 @@ + List all breakpoints. + + + (lldb) breakpoint list
+ (lldb) br l
+ + + (gdb) info break
+ + + + Delete a breakpoint. + + + (lldb) breakpoint delete 1
+ (lldb) br del 1
+ + + (gdb) delete 1
+ + +

From scallanan at apple.com Wed Jan 4 15:42:46 2012 From: scallanan at apple.com (Sean Callanan) Date: Wed, 04 Jan 2012 21:42:46 -0000 Subject: [Lldb-commits] [lldb] r147551 - /lldb/trunk/source/Expression/IRInterpreter.cpp Message-ID: <20120104214246.64C5A2A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 15:42:46 2012 New Revision: 147551 URL: http://llvm.org/viewvc/llvm-project?rev=147551&view=rev Log: Added logging to track when the IR interpreter resolves values in registers. Modified: lldb/trunk/source/Expression/IRInterpreter.cpp Modified: lldb/trunk/source/Expression/IRInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRInterpreter.cpp?rev=147551&r1=147550&r2=147551&view=diff ============================================================================== --- lldb/trunk/source/Expression/IRInterpreter.cpp (original) +++ lldb/trunk/source/Expression/IRInterpreter.cpp Wed Jan 4 15:42:46 2012 @@ -653,6 +653,16 @@ if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX) return Memory::Region(); + if (log) + { + log->Printf("Made an allocation for register variable %s", PrintValue(value).c_str()); + log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str()); + log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base); + log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base); + if (indirect_variable) + log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base); + } + if (indirect_variable) { DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region); From gclayton at apple.com Wed Jan 4 16:56:43 2012 From: gclayton at apple.com (Greg Clayton) Date: Wed, 04 Jan 2012 22:56:43 -0000 Subject: [Lldb-commits] [lldb] r147559 - in /lldb/trunk: include/lldb/API/SBFrame.h include/lldb/Expression/DWARFExpression.h include/lldb/Host/File.h scripts/build-lldb-llvm-clang source/Core/ConnectionFileDescriptor.cpp source/Expression/DWARFExpression.cpp source/Host/common/File.cpp source/Host/common/FileSpec.cpp source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Message-ID: <20120104225643.AD7C31BE003@llvm.org> Author: gclayton Date: Wed Jan 4 16:56:43 2012 New Revision: 147559 URL: http://llvm.org/viewvc/llvm-project?rev=147559&view=rev Log: Be better at detecting when DWARF changes and handle this more gracefully than asserting and exiting. Also fixed up a bunch of system calls that weren't properly checking for EINTR. Modified: lldb/trunk/include/lldb/API/SBFrame.h lldb/trunk/include/lldb/Expression/DWARFExpression.h lldb/trunk/include/lldb/Host/File.h lldb/trunk/scripts/build-lldb-llvm-clang lldb/trunk/source/Core/ConnectionFileDescriptor.cpp lldb/trunk/source/Expression/DWARFExpression.cpp lldb/trunk/source/Host/common/File.cpp lldb/trunk/source/Host/common/FileSpec.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Modified: lldb/trunk/include/lldb/API/SBFrame.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFrame.h?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBFrame.h (original) +++ lldb/trunk/include/lldb/API/SBFrame.h Wed Jan 4 16:56:43 2012 @@ -16,8 +16,6 @@ namespace lldb { -class SBValue; - class SBFrame { public: Modified: lldb/trunk/include/lldb/Expression/DWARFExpression.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/DWARFExpression.h?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/include/lldb/Expression/DWARFExpression.h (original) +++ lldb/trunk/include/lldb/Expression/DWARFExpression.h Wed Jan 4 16:56:43 2012 @@ -142,6 +142,10 @@ /// @param[in] file_addr /// The file address to search for in the location. /// + /// @param[out] error + /// If the location stream contains unknown DW_OP opcodes or the + /// data is missing, \a error will be set to \b true. + /// /// @return /// True if IsLocationList() is false and the \a file_addr was /// is contained in a DW_OP_addr location opcode or if \a file_addr @@ -149,7 +153,7 @@ /// otherwise. //------------------------------------------------------------------ bool - LocationContains_DW_OP_addr (lldb::addr_t file_addr = LLDB_INVALID_ADDRESS) const; + LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &error) const; bool Update_DW_OP_addr (lldb::addr_t file_addr); Modified: lldb/trunk/include/lldb/Host/File.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/File.h?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/include/lldb/Host/File.h (original) +++ lldb/trunk/include/lldb/Host/File.h Wed Jan 4 16:56:43 2012 @@ -35,9 +35,10 @@ eOpenOptionRead = (1u << 0), // Open file for reading eOpenOptionWrite = (1u << 1), // Open file for writing eOpenOptionAppend = (1u << 2), // Don't truncate file when opening, append to end of file - eOpenOptionNonBlocking = (1u << 3), // File reads - eOpenOptionCanCreate = (1u << 4), // Create file if doesn't already exist - eOpenOptionCanCreateNewOnly = (1u << 5) // Can create file only if it doesn't already exist + eOpenOptionTruncate = (1u << 3), // Truncate file when opening + eOpenOptionNonBlocking = (1u << 4), // File reads + eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist + eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist }; enum Permissions @@ -362,6 +363,34 @@ Read (void *dst, size_t &num_bytes, off_t &offset); //------------------------------------------------------------------ + /// Read bytes from a file from the specified file offset. + /// + /// NOTE: This function is thread safe in that clients manager their + /// own file position markers and reads on other threads won't mess + /// up the current read. + /// + /// @param[in/out] num_bytes + /// The number of bytes to read form the current file position + /// which gets modified with the number of bytes that were read. + /// + /// @param[in/out] offset + /// The offset within the file from which to read \a num_bytes + /// bytes. This offset gets incremented by the number of bytes + /// that were read. + /// + /// @param[out] data_buffer_sp + /// A data buffer to create and fill in that will contain any + /// data that is read from the file. This buffer will be reset + /// if an error occurs. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Read (size_t &num_bytes, off_t &offset, lldb::DataBufferSP &data_buffer_sp); + + //------------------------------------------------------------------ /// Write bytes to a file at the specified file offset. /// /// NOTE: This function is thread safe in that clients manager their Modified: lldb/trunk/scripts/build-lldb-llvm-clang URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/build-lldb-llvm-clang?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/scripts/build-lldb-llvm-clang (original) +++ lldb/trunk/scripts/build-lldb-llvm-clang Wed Jan 4 16:56:43 2012 @@ -22,13 +22,11 @@ # change directory to "./llvm" cd llvm -rm -rf test # Checkout Clang # change directory to "./llvm/tools" cd tools svn co -q -r $CLANG_REVISION http://llvm.org/svn/llvm-project/cfe/trunk clang -rm -rf clang/test # change directory to "./llvm" cd .. @@ -65,8 +63,11 @@ make -j8 clang-only VERBOSE=1 PROJECT_NAME='llvm' make -j8 tools-only VERBOSE=1 PROJECT_NAME='llvm' EDIS_VERSION=1 elif [ "$LLVM_CONFIGURATION" = "BuildAndIntegration" ]; then - # Configure "BuildAndIntegration" build - rm -rf ./scripts/*.diff + # Don't configure or build for "BuildAndIntegration", this configuration + # is a preparation step for a build submission + + # Remove all patches, and the llvm and clang "test" directories + rm -rf ./scripts/*.diff ./llvm/test ./llvm/tools/clang/test else echo "checked out llvm (revision $LLVM_REVISION) and clang (revision $CLANG_REVISION)." exit 0 Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Wed Jan 4 16:56:43 2012 @@ -188,7 +188,10 @@ { // file:///PATH const char *path = s + strlen("file://"); - m_fd_send = m_fd_recv = ::open (path, O_RDWR); + do + { + m_fd_send = m_fd_recv = ::open (path, O_RDWR); + } while (m_fd_send == -1 && errno == EINTR); if (m_fd_send == -1) { if (error_ptr) @@ -269,14 +272,22 @@ case eFDTypeFile: // Other FD requireing read/write status = BytesAvailable (timeout_usec, error_ptr); if (status == eConnectionStatusSuccess) - bytes_read = ::read (m_fd_recv, dst, dst_len); + { + do + { + bytes_read = ::read (m_fd_recv, dst, dst_len); + } while (bytes_read < 0 && errno == EINTR); + } break; case eFDTypeSocket: // Socket requiring send/recv if (SetSocketReceiveTimeout (timeout_usec)) { status = eConnectionStatusSuccess; - bytes_read = ::recv (m_fd_recv, dst, dst_len, 0); + do + { + bytes_read = ::recv (m_fd_recv, dst, dst_len, 0); + } while (bytes_read < 0 && errno == EINTR); } break; @@ -286,7 +297,10 @@ status = eConnectionStatusSuccess; SocketAddress from (m_udp_send_sockaddr); socklen_t from_len = m_udp_send_sockaddr.GetLength(); - bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len); + do + { + bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len); + } while (bytes_read < 0 && errno == EINTR); } break; } @@ -392,21 +406,30 @@ switch (m_fd_send_type) { case eFDTypeFile: // Other FD requireing read/write - bytes_sent = ::write (m_fd_send, src, src_len); + do + { + bytes_sent = ::write (m_fd_send, src, src_len); + } while (bytes_sent < 0 && errno == EINTR); break; case eFDTypeSocket: // Socket requiring send/recv - bytes_sent = ::send (m_fd_send, src, src_len, 0); + do + { + bytes_sent = ::send (m_fd_send, src, src_len, 0); + } while (bytes_sent < 0 && errno == EINTR); break; case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom assert (m_udp_send_sockaddr.GetFamily() != 0); - bytes_sent = ::sendto (m_fd_send, - src, - src_len, - 0, - m_udp_send_sockaddr, - m_udp_send_sockaddr.GetLength()); + do + { + bytes_sent = ::sendto (m_fd_send, + src, + src_len, + 0, + m_udp_send_sockaddr, + m_udp_send_sockaddr.GetLength()); + } while (bytes_sent < 0 && errno == EINTR); break; } Modified: lldb/trunk/source/Expression/DWARFExpression.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Expression/DWARFExpression.cpp (original) +++ lldb/trunk/source/Expression/DWARFExpression.cpp Wed Jan 4 16:56:43 2012 @@ -992,18 +992,15 @@ } default: - { - Host::SetCrashDescriptionWithFormat ("Unhandled DW_OP_XXX opcode: %d, add support for it.", op); - assert (!"Unhandled DW_OP_XXX opcode - look for actual value in Crash Description string."); - } - break; + break; } return UINT32_MAX; } bool -DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr) const +DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr, bool &error) const { + error = false; if (IsLocationList()) return false; uint32_t offset = 0; @@ -1023,7 +1020,10 @@ { const uint32_t op_arg_size = GetOpcodeDataSize (m_data, offset, op); if (op_arg_size == UINT32_MAX) + { + error = true; break; + } offset += op_arg_size; } } Modified: lldb/trunk/source/Host/common/File.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/File.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Host/common/File.cpp (original) +++ lldb/trunk/source/Host/common/File.cpp Wed Jan 4 16:56:43 2012 @@ -10,11 +10,13 @@ #include "lldb/Host/File.h" +#include #include #include #include #include +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Host/Config.h" #include "lldb/Host/FileSpec.h" @@ -135,7 +137,12 @@ { const char *mode = GetStreamOpenModeFromOptions (m_options); if (mode) - m_stream = ::fdopen (m_descriptor, mode); + { + do + { + m_stream = ::fdopen (m_descriptor, mode); + } while (m_stream == NULL && errno == EINTR); + } } } return m_stream; @@ -184,40 +191,54 @@ Close (); int oflag = 0; - if (options & eOpenOptionRead && - options & eOpenOptionWrite ) - oflag |= O_RDWR; - else if (options & eOpenOptionRead) + const bool read = options & eOpenOptionRead; + const bool write = options & eOpenOptionWrite; + if (write) + { + if (read) + oflag |= O_RDWR; + else + oflag |= O_WRONLY; + + if (options & eOpenOptionAppend) + oflag |= O_APPEND; + + if (options & eOpenOptionTruncate) + oflag |= O_TRUNC; + + if (options & eOpenOptionCanCreate) + oflag |= O_CREAT; + + if (options & eOpenOptionCanCreateNewOnly) + oflag |= O_CREAT | O_EXCL; + } + else if (read) + { oflag |= O_RDONLY; - else if (options & eOpenOptionWrite) - oflag |= O_WRONLY; + } if (options & eOpenOptionNonBlocking) oflag |= O_NONBLOCK; - if (options & eOpenOptionAppend) - oflag |= O_APPEND; - else - oflag |= O_TRUNC; - - if (options & eOpenOptionCanCreate) - oflag |= O_CREAT; - - if (options & eOpenOptionCanCreateNewOnly) - oflag |= O_CREAT | O_EXCL; - mode_t mode = 0; - if (permissions & ePermissionsUserRead) mode |= S_IRUSR; - if (permissions & ePermissionsUserWrite) mode |= S_IWUSR; - if (permissions & ePermissionsUserExecute) mode |= S_IXUSR; - if (permissions & ePermissionsGroupRead) mode |= S_IRGRP; - if (permissions & ePermissionsGroupWrite) mode |= S_IWGRP; - if (permissions & ePermissionsGroupExecute) mode |= S_IXGRP; - if (permissions & ePermissionsWorldRead) mode |= S_IROTH; - if (permissions & ePermissionsWorldWrite) mode |= S_IWOTH; - if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH; + if (oflag & O_CREAT) + { + if (permissions & ePermissionsUserRead) mode |= S_IRUSR; + if (permissions & ePermissionsUserWrite) mode |= S_IWUSR; + if (permissions & ePermissionsUserExecute) mode |= S_IXUSR; + if (permissions & ePermissionsGroupRead) mode |= S_IRGRP; + if (permissions & ePermissionsGroupWrite) mode |= S_IWGRP; + if (permissions & ePermissionsGroupExecute) mode |= S_IXGRP; + if (permissions & ePermissionsWorldRead) mode |= S_IROTH; + if (permissions & ePermissionsWorldWrite) mode |= S_IWOTH; + if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH; + } + + do + { + m_descriptor = ::open(path, oflag, mode); + } while (m_descriptor < 0 && errno == EINTR); - m_descriptor = ::open(path, oflag, mode); if (!DescriptorIsValid()) error.SetErrorToErrno(); else @@ -357,7 +378,13 @@ Error error; if (StreamIsValid()) { - if (::fflush (m_stream) == EOF) + int err = 0; + do + { + err = ::fflush (m_stream); + } while (err == EOF && errno == EINTR); + + if (err == EOF) error.SetErrorToErrno(); } else if (!DescriptorIsValid()) @@ -374,7 +401,13 @@ Error error; if (DescriptorIsValid()) { - if (::fsync (m_descriptor) == -1) + int err = 0; + do + { + err = ::fsync (m_descriptor); + } while (err == -1 && errno == EINTR); + + if (err == -1) error.SetErrorToErrno(); } else @@ -388,9 +421,14 @@ File::Read (void *buf, size_t &num_bytes) { Error error; + ssize_t bytes_read = -1; if (DescriptorIsValid()) { - ssize_t bytes_read = ::read (m_descriptor, buf, num_bytes); + do + { + bytes_read = ::read (m_descriptor, buf, num_bytes); + } while (bytes_read < 0 && errno == EINTR); + if (bytes_read == -1) { error.SetErrorToErrno(); @@ -401,7 +439,8 @@ } else if (StreamIsValid()) { - size_t bytes_read = ::fread (buf, 1, num_bytes, m_stream); + bytes_read = ::fread (buf, 1, num_bytes, m_stream); + if (bytes_read == 0) { if (::feof(m_stream)) @@ -425,9 +464,14 @@ File::Write (const void *buf, size_t &num_bytes) { Error error; + ssize_t bytes_written = -1; if (DescriptorIsValid()) { - ssize_t bytes_written = ::write (m_descriptor, buf, num_bytes); + do + { + bytes_written = ::write (m_descriptor, buf, num_bytes); + } while (bytes_written < 0 && errno == EINTR); + if (bytes_written == -1) { error.SetErrorToErrno(); @@ -438,7 +482,8 @@ } else if (StreamIsValid()) { - size_t bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); + bytes_written = ::fwrite (buf, 1, num_bytes, m_stream); + if (bytes_written == 0) { if (::feof(m_stream)) @@ -467,7 +512,12 @@ int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { - ssize_t bytes_read = ::pread (fd, buf, num_bytes, offset); + ssize_t bytes_read = -1; + do + { + bytes_read = ::pread (fd, buf, num_bytes, offset); + } while (bytes_read < 0 && errno == EINTR); + if (bytes_read < 0) { num_bytes = 0; @@ -488,13 +538,71 @@ } Error +File::Read (size_t &num_bytes, off_t &offset, DataBufferSP &data_buffer_sp) +{ + Error error; + + if (num_bytes > 0) + { + int fd = GetDescriptor(); + if (fd != kInvalidDescriptor) + { + struct stat file_stats; + if (::fstat (fd, &file_stats) == 0) + { + if (file_stats.st_size > offset) + { + const size_t bytes_left = file_stats.st_size - offset; + if (num_bytes > bytes_left) + num_bytes = bytes_left; + + std::auto_ptr data_heap_ap; + data_heap_ap.reset(new DataBufferHeap(num_bytes, '\0')); + + if (data_heap_ap.get()) + { + error = Read (data_heap_ap->GetBytes(), num_bytes, offset); + if (error.Success()) + { + // Make sure we read exactly what we asked for and if we got + // less, adjust the array + if (num_bytes < data_heap_ap->GetByteSize()) + data_heap_ap->SetByteSize(num_bytes); + data_buffer_sp.reset(data_heap_ap.release()); + return error; + } + } + } + else + error.SetErrorString("file is empty"); + } + else + error.SetErrorToErrno(); + } + else + error.SetErrorString("invalid file handle"); + } + else + error.SetErrorString("invalid file handle"); + + num_bytes = 0; + data_buffer_sp.reset(); + return error; +} + +Error File::Write (const void *buf, size_t &num_bytes, off_t &offset) { Error error; int fd = GetDescriptor(); if (fd != kInvalidDescriptor) { - ssize_t bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); + ssize_t bytes_written = -1; + do + { + bytes_written = ::pwrite (m_descriptor, buf, num_bytes, offset); + } while (bytes_written < 0 && errno == EINTR); + if (bytes_written < 0) { num_bytes = 0; Modified: lldb/trunk/source/Host/common/FileSpec.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/FileSpec.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Host/common/FileSpec.cpp (original) +++ lldb/trunk/source/Host/common/FileSpec.cpp Wed Jan 4 16:56:43 2012 @@ -24,6 +24,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataBufferMemoryMap.h" @@ -776,29 +777,15 @@ char resolved_path[PATH_MAX]; if (GetPath(resolved_path, sizeof(resolved_path))) { - int fd = ::open (resolved_path, O_RDONLY, 0); - if (fd != -1) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == 0) - { - // Read bytes directly into our basic_string buffer - if (file_stats.st_size > 0) - { - off_t lseek_result = 0; - if (file_offset > 0) - lseek_result = ::lseek (fd, file_offset, SEEK_SET); - - if (lseek_result == file_offset) - { - ssize_t n = ::read (fd, dst, dst_len); - if (n >= 0) - bytes_read = n; - } - } - } + Error error; + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) + { + off_t file_offset_after_seek = file_offset; + bytes_read = dst_len; + error = file.Read(dst, bytes_read, file_offset_after_seek); } - close(fd); } return bytes_read; } @@ -821,49 +808,11 @@ char resolved_path[PATH_MAX]; if (GetPath(resolved_path, sizeof(resolved_path))) { - int fd = ::open (resolved_path, O_RDONLY, 0); - if (fd != -1) - { - struct stat file_stats; - if (::fstat (fd, &file_stats) == 0) - { - if (file_stats.st_size > 0) - { - off_t lseek_result = 0; - if (file_offset > 0) - lseek_result = ::lseek (fd, file_offset, SEEK_SET); - - if (lseek_result < 0) - { - // Get error from errno - } - else if (lseek_result == file_offset) - { - const size_t bytes_left = file_stats.st_size - file_offset; - size_t num_bytes_to_read = file_size; - if (num_bytes_to_read > bytes_left) - num_bytes_to_read = bytes_left; - - std::auto_ptr data_heap_ap; - data_heap_ap.reset(new DataBufferHeap(num_bytes_to_read, '\0')); - - if (data_heap_ap.get()) - { - ssize_t bytesRead = ::read (fd, (void *)data_heap_ap->GetBytes(), data_heap_ap->GetByteSize()); - if (bytesRead >= 0) - { - // Make sure we read exactly what we asked for and if we got - // less, adjust the array - if ((size_t)bytesRead < data_heap_ap->GetByteSize()) - data_heap_ap->SetByteSize(bytesRead); - data_sp.reset(data_heap_ap.release()); - } - } - } - } - } - } - close(fd); + Error error; + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) + error = file.Read (file_size, file_offset, data_sp); } return data_sp; } Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp Wed Jan 4 16:56:43 2012 @@ -720,19 +720,16 @@ std::vector die_offsets; bool set_frame_base_loclist_addr = false; - const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu); + dw_offset_t offset; + const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); if (abbrevDecl) { const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); - uint32_t offset = m_offset; if (!debug_info_data.ValidOffset(offset)) return false; - // Skip the abbreviation code - debug_info_data.Skip_LEB128(&offset); - const uint32_t numAttributes = abbrevDecl->NumAttributes(); uint32_t i; dw_attr_t attr; @@ -914,9 +911,13 @@ s.Printf("\n0x%8.8x: ", m_offset); s.Indent(); - if (abbrCode) + if (abbrCode != m_abbr_idx) + { + s.Printf( "error: DWARF has been modified\n"); + } + else if (abbrCode) { - const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu); + const DWARFAbbreviationDeclaration* abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration (abbrCode); if (abbrevDecl) { @@ -1156,17 +1157,15 @@ uint32_t curr_depth ) const { - const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu); + uint32_t offset; + const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); if (abbrevDecl) { - if (fixed_form_sizes == NULL) - fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize()); - uint32_t offset = GetOffset(); const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); - // Skip the abbreviation code so we are at the data for the attributes - debug_info_data.Skip_LEB128(&offset); + if (fixed_form_sizes == NULL) + fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize()); const uint32_t num_attributes = abbrevDecl->NumAttributes(); uint32_t i; @@ -1255,7 +1254,8 @@ dw_offset_t* end_attr_offset_ptr ) const { - const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(cu); + uint32_t offset; + const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); if (abbrevDecl) { @@ -1263,13 +1263,8 @@ if (attr_idx != DW_INVALID_INDEX) { - uint32_t offset = GetOffset(); - const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); - // Skip the abbreviation code so we are at the data for the attributes - debug_info_data.Skip_LEB128(&offset); - uint32_t idx=0; while (idxGetFormByIndex(idx++), debug_info_data, &offset, cu); @@ -1583,7 +1578,7 @@ else { bool result = true; - const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr(cu); + const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset); switch (abbrevDecl->Tag()) { @@ -2071,10 +2066,29 @@ } const DWARFAbbreviationDeclaration* -DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (const DWARFCompileUnit *cu) const +DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit *cu, + dw_offset_t &offset) const { - if (m_abbr_idx) - return cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx); + offset = GetOffset(); + + const DWARFAbbreviationDeclaration* abbrev_decl = cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx); + if (abbrev_decl) + { + // Make sure the abbreviation code still matches. If it doesn't and + // the DWARF data was mmap'ed, the backing file might have been modified + // which is bad news. + const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset); + + if (abbrev_decl->Code() == abbrev_code) + return abbrev_decl; + + dwarf2Data->ReportError ("0x%8.8x: the DWARF debug info has been modified (abbrev code was %u, and is now %u)", + GetOffset(), + (uint32_t)abbrev_decl->Code(), + (uint32_t)abbrev_code); + } + offset = DW_INVALID_OFFSET; return NULL; } Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h Wed Jan 4 16:56:43 2012 @@ -300,7 +300,9 @@ lldb_private::DWARFExpression *frame_base = NULL) const; const DWARFAbbreviationDeclaration* - GetAbbreviationDeclarationPtr (const DWARFCompileUnit *cu) const; + GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data, + const DWARFCompileUnit *cu, + dw_offset_t &offset) const; dw_tag_t Tag () const Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=147559&r1=147558&r2=147559&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jan 4 16:56:43 2012 @@ -5553,10 +5553,19 @@ scope = eValueTypeVariableArgument; else { + bool op_error = false; // Check if the location has a DW_OP_addr with any address value... addr_t location_has_op_addr = false; if (!location_is_const_value_data) - location_has_op_addr = location.LocationContains_DW_OP_addr (); + { + location_has_op_addr = location.LocationContains_DW_OP_addr (LLDB_INVALID_ADDRESS, op_error); + if (op_error) + { + StreamString strm; + location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL); + ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str()); + } + } if (location_has_op_addr) { @@ -5584,7 +5593,7 @@ // location for the variable, and set the variable's // symbol context scope to be that of the main executable // so the file address will resolve correctly. - if (location.LocationContains_DW_OP_addr (0)) + if (location.LocationContains_DW_OP_addr (0, op_error)) { // we have a possible uninitialized extern global From dawn at burble.org Wed Jan 4 17:26:04 2012 From: dawn at burble.org (dawn at burble.org) Date: Wed, 4 Jan 2012 15:26:04 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD Message-ID: <20120104232604.GA29483@bloodbath.burble.org> This patch combines common code from Linux and FreeBSD into a new POSIX platform. It also contains fixes for 64bit FreeBSD. The patch is based on changes by Mark Peek and "K. Macy" in their github repo located at https://github.com/fbsd/lldb. Ok to commit? Thanks! -Dawn -------------- next part -------------- Index: include/lldb/Host/Host.h =================================================================== --- include/lldb/Host/Host.h (revision 147560) +++ include/lldb/Host/Host.h (working copy) @@ -355,7 +355,10 @@ static Error LaunchProcess (ProcessLaunchInfo &launch_info); - + + static lldb::DataBufferSP + GetAuxvData (lldb_private::Process *process); + static lldb::TargetSP GetDummyTarget (Debugger &debugger); Index: source/Plugins/Platform/Linux/PlatformLinux.h =================================================================== --- source/Plugins/Platform/Linux/PlatformLinux.h (revision 147560) +++ source/Plugins/Platform/Linux/PlatformLinux.h (working copy) @@ -104,6 +104,7 @@ Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Listener &listener, Error &error); + // Linux processes can not be launched by spawning and attaching. virtual bool CanDebugProcess () { Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (revision 147560) +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (working copy) @@ -27,16 +27,13 @@ Platform * PlatformFreeBSD::CreateInstance () { - // The only time we create an instance is when we are creating a remote - // freebsd platform - const bool is_host = false; - return new PlatformFreeBSD (is_host); + return new PlatformFreeBSD (true); } const char * PlatformFreeBSD::GetPluginNameStatic() { - return "PlatformFreeBSD"; + return "plugin.platform.freebsd"; } const char * @@ -66,7 +63,7 @@ { #if defined (__FreeBSD__) PlatformSP default_platform_sp (CreateInstance()); - //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); Platform::SetDefaultPlatform (default_platform_sp); #endif PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false), @@ -79,7 +76,7 @@ void PlatformFreeBSD::Terminate () { - PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); + PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); } //------------------------------------------------------------------ @@ -385,17 +382,16 @@ bool PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) { - bool sucess = false; + bool success = false; if (IsHost()) { - sucess = Platform::GetProcessInfo (pid, process_info); + success = Platform::GetProcessInfo (pid, process_info); } - else + else if (m_remote_platform_sp) { - if (m_remote_platform_sp) - sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); + success = m_remote_platform_sp->GetProcessInfo (pid, process_info); } - return sucess; + return success; } @@ -438,11 +434,11 @@ } lldb::ProcessSP -PlatformFreeBSD::Attach(lldb::pid_t pid, - Debugger &debugger, - Target *target, - Listener &listener, - Error &error) +PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, + Debugger &debugger, + Target *target, + Listener &listener, + Error &error) { lldb::ProcessSP process_sp; if (IsHost()) @@ -457,6 +453,7 @@ emptyFileSpec, emptyArchSpec, false, + m_remote_platform_sp, new_target_sp); target = new_target_sp.get(); } @@ -472,13 +469,13 @@ process_sp = target->CreateProcess (listener, "gdb-remote"); if (process_sp) - error = process_sp->Attach (pid); + error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); else error.SetErrorString ("the platform is not currently connected"); } Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (revision 147560) +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (working copy) @@ -132,12 +132,16 @@ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); virtual lldb::ProcessSP - Attach(lldb::pid_t pid, + Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Listener &listener, lldb_private::Error &error); + // FreeBSD processes can not be launched by spawning and attaching. + virtual bool + CanDebugProcess () { return false; } + // Only on PlatformMacOSX: virtual lldb_private::Error GetFile (const lldb_private::FileSpec &platform_file, Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (working copy) @@ -1,191 +0,0 @@ -//===-- AuxVector.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 -#include -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" - -#include "AuxVector.h" - -using namespace lldb; -using namespace lldb_private; - -static bool -GetMaxU64(DataExtractor &data, - uint32_t *offset, uint64_t *value, unsigned int byte_size) -{ - uint32_t saved_offset = *offset; - *value = data.GetMaxU64(offset, byte_size); - return *offset != saved_offset; -} - -static bool -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, - uint32_t *offset, unsigned int byte_size) -{ - if (!GetMaxU64(data, offset, &entry.type, byte_size)) - return false; - - if (!GetMaxU64(data, offset, &entry.value, byte_size)) - return false; - - return true; -} - -DataBufferSP -AuxVector::GetAuxvData() -{ - static const size_t path_size = 128; - static char path[path_size]; - DataBufferSP buf_sp; - int fd; - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) - return buf_sp; - - if ((fd = open(path, O_RDONLY, 0)) < 0) - return buf_sp; - - size_t bytes_read = 0; - std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); - for (;;) - { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - bytes_read += status; - - if (status == 0) - { - buf_ap->SetByteSize(bytes_read); - buf_sp.reset(buf_ap.release()); - break; - } - - if (avail - status == 0) - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); - } - - return buf_sp; -} - -void -AuxVector::ParseAuxv(DataExtractor &data) -{ - const unsigned int byte_size = m_process->GetAddressByteSize(); - uint32_t offset = 0; - - for (;;) - { - Entry entry; - - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) - break; - - if (entry.type == AT_NULL) - break; - - if (entry.type == AT_IGNORE) - continue; - - m_auxv.push_back(entry); - } -} - -AuxVector::AuxVector(Process *process) - : m_process(process) -{ - DataExtractor data; - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - data.SetData(GetAuxvData()); - data.SetByteOrder(m_process->GetByteOrder()); - data.SetAddressByteSize(m_process->GetAddressByteSize()); - - ParseAuxv(data); - - if (log) - DumpToLog(log); -} - -AuxVector::iterator -AuxVector::FindEntry(EntryType type) const -{ - for (iterator I = begin(); I != end(); ++I) - { - if (I->type == static_cast(type)) - return I; - } - - return end(); -} - -void -AuxVector::DumpToLog(LogSP log) const -{ - if (!log) - return; - - log->PutCString("AuxVector: "); - for (iterator I = begin(); I != end(); ++I) - { - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); - } -} - -const char * -AuxVector::GetEntryName(EntryType type) -{ - const char *name; - -#define ENTRY_NAME(_type) _type: name = #_type - switch (type) - { - default: - name = "unkown"; - break; - - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - } -#undef ENTRY_NAME - - return name; -} - Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (working copy) @@ -1,322 +0,0 @@ -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "DYLDRendezvous.h" - -using namespace lldb; -using namespace lldb_private; - -/// Locates the address of the rendezvous structure. Returns the address on -/// success and LLDB_INVALID_ADDRESS on failure. -static addr_t -ResolveRendezvousAddress(Process *process) -{ - addr_t info_location; - addr_t info_addr; - Error error; - size_t size; - - info_location = process->GetImageInfoAddress(); - - if (info_location == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - info_addr = 0; - size = process->DoReadMemory(info_location, &info_addr, - process->GetAddressByteSize(), error); - if (size != process->GetAddressByteSize() || error.Fail()) - return LLDB_INVALID_ADDRESS; - - if (info_addr == 0) - return LLDB_INVALID_ADDRESS; - - return info_addr; -} - -DYLDRendezvous::DYLDRendezvous(Process *process) - : m_process(process), - m_rendezvous_addr(LLDB_INVALID_ADDRESS), - m_current(), - m_previous(), - m_soentries(), - m_added_soentries(), - m_removed_soentries() -{ -} - -bool -DYLDRendezvous::Resolve() -{ - const size_t word_size = 4; - Rendezvous info; - size_t address_size; - size_t padding; - addr_t info_addr; - addr_t cursor; - - address_size = m_process->GetAddressByteSize(); - padding = address_size - word_size; - - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) - cursor = info_addr = ResolveRendezvousAddress(m_process); - else - cursor = info_addr = m_rendezvous_addr; - - if (cursor == LLDB_INVALID_ADDRESS) - return false; - - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) - return false; - - // The rendezvous was successfully read. Update our internal state. - m_rendezvous_addr = info_addr; - m_previous = m_current; - m_current = info; - - return UpdateSOEntries(); -} - -bool -DYLDRendezvous::IsValid() -{ - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; -} - -bool -DYLDRendezvous::UpdateSOEntries() -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - // When the previous and current states are consistent this is the first - // time we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return TakeSnapshot(m_soentries); - - // If we are about to add or remove a shared object clear out the current - // state and take a snapshot of the currently loaded images. - if (m_current.state == eAdd || m_current.state == eDelete) - { - assert(m_previous.state == eConsistent); - m_soentries.clear(); - m_added_soentries.clear(); - m_removed_soentries.clear(); - return TakeSnapshot(m_soentries); - } - assert(m_current.state == eConsistent); - - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return UpdateSOEntriesForAddition(); - else if (m_previous.state == eDelete) - return UpdateSOEntriesForDeletion(); - - return false; -} - -bool -DYLDRendezvous::UpdateSOEntriesForAddition() -{ - SOEntry entry; - iterator pos; - - assert(m_previous.state == eAdd); - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) - { - m_soentries.push_back(entry); - m_added_soentries.push_back(entry); - } - } - - return true; -} - -bool -DYLDRendezvous::UpdateSOEntriesForDeletion() -{ - SOEntryList entry_list; - iterator pos; - - assert(m_previous.state == eDelete); - - if (!TakeSnapshot(entry_list)) - return false; - - for (iterator I = begin(); I != end(); ++I) - { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) - m_removed_soentries.push_back(*I); - } - - m_soentries = entry_list; - return true; -} - -bool -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - entry_list.push_back(entry); - } - - return true; -} - -addr_t -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) -{ - size_t bytes_read; - Error error; - - bytes_read = m_process->DoReadMemory(addr, dst, size, error); - if (bytes_read != size || error.Fail()) - return 0; - - return addr + bytes_read; -} - -std::string -DYLDRendezvous::ReadStringFromMemory(addr_t addr) -{ - std::string str; - Error error; - size_t size; - char c; - - if (addr == LLDB_INVALID_ADDRESS) - return std::string(); - - for (;;) { - size = m_process->DoReadMemory(addr, &c, 1, error); - if (size != 1 || error.Fail()) - return std::string(); - if (c == 0) - break; - else { - str.push_back(c); - addr++; - } - } - - return str; -} - -bool -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) -{ - size_t address_size = m_process->GetAddressByteSize(); - - entry.clear(); - - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.next, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) - return false; - - entry.path = ReadStringFromMemory(entry.path_addr); - - return true; -} - -void -DYLDRendezvous::DumpToLog(LogSP log) const -{ - int state = GetState(); - - if (!log) - return; - - log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %lx", GetRendezvousAddress()); - log->Printf(" Version: %d", GetVersion()); - log->Printf(" Link : %lx", GetLinkMapAddress()); - log->Printf(" Break : %lx", GetBreakAddress()); - log->Printf(" LDBase : %lx", GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) ? "consistent" : - (state == eAdd) ? "add" : - (state == eDelete) ? "delete" : "unknown"); - - iterator I = begin(); - iterator E = end(); - - if (I != E) - log->PutCString("DYLDRendezvous SOEntries:"); - - for (int i = 1; I != E; ++I, ++i) - { - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); - log->Printf(" Base : %lx", I->base_addr); - log->Printf(" Path : %lx", I->path_addr); - log->Printf(" Dyn : %lx", I->dyn_addr); - log->Printf(" Next : %lx", I->next); - log->Printf(" Prev : %lx", I->prev); - } -} Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (working copy) @@ -1,97 +0,0 @@ -//===-- AuxVector.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_AuxVector_H_ -#define liblldb_AuxVector_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/lldb-forward-rtti.h" - -namespace lldb_private { -class DataExtractor; -} - -/// @class AuxVector -/// @brief Represents a processes auxiliary vector. -/// -/// When a process is loaded on Linux a vector of values is placed onto the -/// stack communicating operating system specific information. On construction -/// this class locates and parses this information and provides a simple -/// read-only interface to the entries found. -class AuxVector { - -public: - AuxVector(lldb_private::Process *process); - - struct Entry { - uint64_t type; - uint64_t value; - - Entry() : type(0), value(0) { } - }; - - /// Constants describing the type of entry. - enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). - }; - -private: - typedef std::vector EntryVector; - -public: - typedef EntryVector::const_iterator iterator; - - iterator begin() const { return m_auxv.begin(); } - iterator end() const { return m_auxv.end(); } - - iterator - FindEntry(EntryType type) const; - - static const char * - GetEntryName(const Entry &entry) { - return GetEntryName(static_cast(entry.type)); - } - - static const char * - GetEntryName(EntryType type); - - void - DumpToLog(lldb::LogSP log) const; - -private: - lldb_private::Process *m_process; - EntryVector m_auxv; - - lldb::DataBufferSP - GetAuxvData(); - - void - ParseAuxv(lldb_private::DataExtractor &data); -}; - -#endif Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (working copy) @@ -1,227 +0,0 @@ -//===-- DYLDRendezvous.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_Rendezvous_H_ -#define liblldb_Rendezvous_H_ - -// C Includes -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -class Process; -} - -/// @class DYLDRendezvous -/// @brief Interface to the runtime linker. -/// -/// A structure is present in a processes memory space which is updated by the -/// runtime liker each time a module is loaded or unloaded. This class provides -/// an interface to this structure and maintains a consistent snapshot of the -/// currently loaded modules. -class DYLDRendezvous { - - // This structure is used to hold the contents of the debug rendezvous - // information (struct r_debug) as found in the inferiors memory. Note that - // the layout of this struct is not binary compatible, it is simply large - // enough to hold the information on both 32 and 64 bit platforms. - struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; - - Rendezvous() - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } - }; - -public: - DYLDRendezvous(lldb_private::Process *process); - - /// Update the internal snapshot of runtime linker rendezvous and recompute - /// the currently loaded modules. - /// - /// This method should be called once one start up, then once each time the - /// runtime linker enters the function given by GetBreakAddress(). - /// - /// @returns true on success and false on failure. - /// - /// @see GetBreakAddress(). - bool - Resolve(); - - /// @returns true if this rendezvous has been located in the inferiors - /// address space and false otherwise. - bool - IsValid(); - - /// @returns the address of the rendezvous structure in the inferiors - /// address space. - lldb::addr_t - GetRendezvousAddress() const { return m_rendezvous_addr; } - - /// @returns the version of the rendezvous protocol being used. - int - GetVersion() const { return m_current.version; } - - /// @returns address in the inferiors address space containing the linked - /// list of shared object descriptors. - lldb::addr_t - GetLinkMapAddress() const { return m_current.map_addr; } - - /// A breakpoint should be set at this address and Resolve called on each - /// hit. - /// - /// @returns the address of a function called by the runtime linker each - /// time a module is loaded/unloaded, or about to be loaded/unloaded. - /// - /// @see Resolve() - lldb::addr_t - GetBreakAddress() const { return m_current.brk; } - - /// Returns the current state of the rendezvous structure. - int - GetState() const { return m_current.state; } - - /// @returns the base address of the runtime linker in the inferiors address - /// space. - lldb::addr_t - GetLDBase() const { return m_current.ldbase; } - - /// @returns true if modules have been loaded into the inferior since the - /// last call to Resolve(). - bool - ModulesDidLoad() const { return !m_added_soentries.empty(); } - - /// @returns true if modules have been unloaded from the inferior since the - /// last call to Resolve(). - bool - ModulesDidUnload() const { return !m_removed_soentries.empty(); } - - void - DumpToLog(lldb::LogSP log) const; - - /// @brief Constants describing the state of the rendezvous. - /// - /// @see GetState(). - enum RendezvousState { - eConsistent, - eAdd, - eDelete - }; - - /// @brief Structure representing the shared objects currently loaded into - /// the inferior process. - /// - /// This object is a rough analogue to the struct link_map object which - /// actually lives in the inferiors memory. - struct SOEntry { - lldb::addr_t base_addr; ///< Base address of the loaded object. - lldb::addr_t path_addr; ///< String naming the shared object. - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. - lldb::addr_t next; ///< Address of next so_entry. - lldb::addr_t prev; ///< Address of previous so_entry. - std::string path; ///< File name of shared object. - - SOEntry() { clear(); } - - bool operator ==(const SOEntry &entry) { - return this->path == entry.path; - } - - void clear() { - base_addr = 0; - path_addr = 0; - dyn_addr = 0; - next = 0; - prev = 0; - path.clear(); - } - }; - -protected: - typedef std::list SOEntryList; - -public: - typedef SOEntryList::const_iterator iterator; - - /// Iterators over all currently loaded modules. - iterator begin() const { return m_soentries.begin(); } - iterator end() const { return m_soentries.end(); } - - /// Iterators over all modules loaded into the inferior since the last call - /// to Resolve(). - iterator loaded_begin() const { return m_added_soentries.begin(); } - iterator loaded_end() const { return m_added_soentries.end(); } - - /// Iterators over all modules unloaded from the inferior since the last - /// call to Resolve(). - iterator unloaded_begin() const { return m_removed_soentries.begin(); } - iterator unloaded_end() const { return m_removed_soentries.end(); } - -protected: - lldb_private::Process *m_process; - - /// Location of the r_debug structure in the inferiors address space. - lldb::addr_t m_rendezvous_addr; - - /// Current and previous snapshots of the rendezvous structure. - Rendezvous m_current; - Rendezvous m_previous; - - /// List of SOEntry objects corresponding to the current link map state. - SOEntryList m_soentries; - - /// List of SOEntry's added to the link map since the last call to Resolve(). - SOEntryList m_added_soentries; - - /// List of SOEntry's removed from the link map since the last call to - /// Resolve(). - SOEntryList m_removed_soentries; - - /// Reads @p size bytes from the inferiors address space starting at @p - /// addr. - /// - /// @returns addr + size if the read was successful and false otherwise. - lldb::addr_t - ReadMemory(lldb::addr_t addr, void *dst, size_t size); - - /// Reads a null-terminated C string from the memory location starting at @p - /// addr. - std::string - ReadStringFromMemory(lldb::addr_t addr); - - /// Reads an SOEntry starting at @p addr. - bool - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); - - /// Updates the current set of SOEntries, the set of added entries, and the - /// set of removed entries. - bool - UpdateSOEntries(); - - bool - UpdateSOEntriesForAddition(); - - bool - UpdateSOEntriesForDeletion(); - - /// Reads the current list of shared objects according to the link map - /// supplied by the runtime linker. - bool - TakeSnapshot(SOEntryList &entry_list); -}; - -#endif Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (working copy) @@ -1,423 +0,0 @@ -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" - -#include "AuxVector.h" -#include "DynamicLoaderLinuxDYLD.h" - -using namespace lldb; -using namespace lldb_private; - -void -DynamicLoaderLinuxDYLD::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); -} - -void -DynamicLoaderLinuxDYLD::Terminate() -{ -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginName() -{ - return "DynamicLoaderLinuxDYLD"; -} - -const char * -DynamicLoaderLinuxDYLD::GetShortPluginName() -{ - return "linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginNameStatic() -{ - return "dynamic-loader.linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() -{ - return "Dynamic loader plug-in that watches for shared library " - "loads/unloads in Linux processes."; -} - -void -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - -uint32_t -DynamicLoaderLinuxDYLD::GetPluginVersion() -{ - return 1; -} - -DynamicLoader * -DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force) -{ - bool create = force; - if (!create) - { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Linux) - create = true; - } - - if (create) - return new DynamicLoaderLinuxDYLD (process); - return NULL; -} - -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) - : DynamicLoader(process), - m_rendezvous(process), - m_load_offset(LLDB_INVALID_ADDRESS), - m_entry_point(LLDB_INVALID_ADDRESS), - m_auxv(NULL) -{ -} - -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() -{ -} - -void -DynamicLoaderLinuxDYLD::DidAttach() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -void -DynamicLoaderLinuxDYLD::DidLaunch() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - ProbeEntry(); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -Error -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - -Error -DynamicLoaderLinuxDYLD::CanLoadImage() -{ - return Error(); -} - -void -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) -{ - ObjectFile *obj_file = module->GetObjectFile(); - SectionList *sections = obj_file->GetSectionList(); - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); - const size_t num_sections = sections->GetSize(); - - for (unsigned i = 0; i < num_sections; ++i) - { - Section *section = sections->GetSectionAtIndex(i).get(); - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); - - // If the file address of the section is zero then this is not an - // allocatable/loadable section (property of ELF sh_addr). Skip it. - if (new_load_addr == base_addr) - continue; - - if (old_load_addr == LLDB_INVALID_ADDRESS || - old_load_addr != new_load_addr) - load_list.SetSectionLoadAddress(section, new_load_addr); - } -} - -void -DynamicLoaderLinuxDYLD::ProbeEntry() -{ - Breakpoint *entry_break; - addr_t entry; - - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return; - - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); -} - -// The runtime linker has run and initialized the rendezvous structure once the -// process has hit its entry point. When we hit the corresponding breakpoint we -// interrogate the rendezvous structure to get the load addresses of all -// dependent modules for the process. Similarly, we can discover the runtime -// linker function and setup a breakpoint to notify us of any dynamically loaded -// modules (via dlopen). -bool -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->LoadAllCurrentModules(); - dyld_instance->SetRendezvousBreakpoint(); - return false; // Continue running. -} - -void -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() -{ - Breakpoint *dyld_break; - addr_t break_addr; - - break_addr = m_rendezvous.GetBreakAddress(); - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); -} - -bool -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->RefreshModules(); - - // Return true to stop the target, false to just let the target run. - return dyld_instance->GetStopWhenImagesChange(); -} - -void -DynamicLoaderLinuxDYLD::RefreshModules() -{ - if (!m_rendezvous.Resolve()) - return; - - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); - - if (m_rendezvous.ModulesDidLoad()) - { - ModuleList new_modules; - - E = m_rendezvous.loaded_end(); - for (I = m_rendezvous.loaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - new_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidLoad(new_modules); - } - - if (m_rendezvous.ModulesDidUnload()) - { - ModuleList old_modules; - - E = m_rendezvous.unloaded_end(); - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); - if (module_sp.get()) - old_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidUnload(old_modules); - } -} - -ThreadPlanSP -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) -{ - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ThreadPlanSP thread_plan_sp; - - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *sym = context.symbol; - - if (sym == NULL || !sym->IsTrampoline()) - return thread_plan_sp; - - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); - if (!sym_name) - return thread_plan_sp; - - SymbolContextList target_symbols; - Target &target = thread.GetProcess().GetTarget(); - ModuleList &images = target.GetImages(); - - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); - size_t num_targets = target_symbols.GetSize(); - if (!num_targets) - return thread_plan_sp; - - typedef std::vector AddressVector; - AddressVector addrs; - for (size_t i = 0; i < num_targets; ++i) - { - SymbolContext context; - AddressRange range; - if (target_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange(eSymbolContextEverything, 0, false, range); - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); - if (addr != LLDB_INVALID_ADDRESS) - addrs.push_back(addr); - } - } - - if (addrs.size() > 0) - { - AddressVector::iterator start = addrs.begin(); - AddressVector::iterator end = addrs.end(); - - std::sort(start, end); - addrs.erase(std::unique(start, end), end); - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); - } - - return thread_plan_sp; -} - -void -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() -{ - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - ModuleList module_list; - - if (!m_rendezvous.Resolve()) - return; - - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) - { - FileSpec file(I->path.c_str(), false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - module_list.Append(module_sp); - } - - m_process->GetTarget().ModulesDidLoad(module_list); -} - -ModuleSP -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) - { - UpdateLoadedSections(module_sp, base_addr); - } - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) - { - UpdateLoadedSections(module_sp, base_addr); - modules.Append(module_sp); - } - - return module_sp; -} - -addr_t -DynamicLoaderLinuxDYLD::ComputeLoadOffset() -{ - addr_t virt_entry; - - if (m_load_offset != LLDB_INVALID_ADDRESS) - return m_load_offset; - - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - ModuleSP module = m_process->GetTarget().GetExecutableModule(); - ObjectFile *exe = module->GetObjectFile(); - Address file_entry = exe->GetEntryPointAddress(); - - if (!file_entry.IsValid()) - return LLDB_INVALID_ADDRESS; - - m_load_offset = virt_entry - file_entry.GetFileAddress(); - return m_load_offset; -} - -addr_t -DynamicLoaderLinuxDYLD::GetEntryPoint() -{ - if (m_entry_point != LLDB_INVALID_ADDRESS) - return m_entry_point; - - if (m_auxv.get() == NULL) - return LLDB_INVALID_ADDRESS; - - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); - - if (I == m_auxv->end()) - return LLDB_INVALID_ADDRESS; - - m_entry_point = static_cast(I->value); - return m_entry_point; -} Index: source/Plugins/DynamicLoader/Linux-DYLD/Makefile =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/Makefile (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/Makefile (working copy) @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderLinux -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (working copy) @@ -1,165 +0,0 @@ -//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_ -#define liblldb_DynamicLoaderLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Target/DynamicLoader.h" - -#include "DYLDRendezvous.h" - -class AuxVector; - -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader -{ -public: - - static void - Initialize(); - - static void - Terminate(); - - static const char * - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - DynamicLoaderLinuxDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderLinuxDYLD(); - - //------------------------------------------------------------------ - // DynamicLoader protocol - //------------------------------------------------------------------ - - virtual void - DidAttach(); - - virtual void - DidLaunch(); - - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); - - virtual lldb_private::Error - CanLoadImage(); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual const char * - GetPluginName(); - - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - -protected: - /// Runtime linker rendezvous structure. - DYLDRendezvous m_rendezvous; - - /// Virtual load address of the inferior process. - lldb::addr_t m_load_offset; - - /// Virtual entry address of the inferior process. - lldb::addr_t m_entry_point; - - /// Auxiliary vector of the inferior process. - std::auto_ptr m_auxv; - - /// Enables a breakpoint on a function called by the runtime - /// linker each time a module is loaded or unloaded. - void - SetRendezvousBreakpoint(); - - /// Callback routine which updates the current list of loaded modules based - /// on the information supplied by the runtime linker. - static bool - RendezvousBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set - /// of loaded modules. - void - RefreshModules(); - - /// Updates the load address of every allocatable section in @p module. - /// - /// @param module The module to traverse. - /// - /// @param base_addr The virtual base address @p module is loaded at. - void - UpdateLoadedSections(lldb::ModuleSP module, - lldb::addr_t base_addr = 0); - - /// Locates or creates a module given by @p file and updates/loads the - /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); - - /// Resolves the entry point for the current inferior process and sets a - /// breakpoint at that address. - void - ProbeEntry(); - - /// Callback routine invoked when we hit the breakpoint on process entry. - /// - /// This routine is responsible for resolving the load addresses of all - /// dependent modules required by the inferior and setting up the rendezvous - /// breakpoint. - static bool - EntryBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper for the entry breakpoint callback. Resolves the load addresses - /// of all dependent modules. - void - LoadAllCurrentModules(); - - /// Computes a value for m_load_offset returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - ComputeLoadOffset(); - - /// Computes a value for m_entry_point returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - GetEntryPoint(); - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); -}; - -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) @@ -0,0 +1,165 @@ +//===-- DynamicLoaderPOSIX.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_DynamicLoaderPOSIX_H_ +#define liblldb_DynamicLoaderPOSIX_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Target/DynamicLoader.h" + +#include "DYLDRendezvous.h" + +class AuxVector; + +class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader +{ +public: + + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance(lldb_private::Process *process, bool force); + + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + + virtual + ~DynamicLoaderPOSIXDYLD(); + + //------------------------------------------------------------------ + // DynamicLoader protocol + //------------------------------------------------------------------ + + virtual void + DidAttach(); + + virtual void + DidLaunch(); + + virtual lldb::ThreadPlanSP + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others); + + virtual lldb_private::Error + CanLoadImage(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + + virtual void + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + + virtual lldb_private::Error + ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); + + virtual lldb_private::Log * + EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + +protected: + /// Runtime linker rendezvous structure. + DYLDRendezvous m_rendezvous; + + /// Virtual load address of the inferior process. + lldb::addr_t m_load_offset; + + /// Virtual entry address of the inferior process. + lldb::addr_t m_entry_point; + + /// Auxiliary vector of the inferior process. + std::auto_ptr m_auxv; + + /// Enables a breakpoint on a function called by the runtime + /// linker each time a module is loaded or unloaded. + void + SetRendezvousBreakpoint(); + + /// Callback routine which updates the current list of loaded modules based + /// on the information supplied by the runtime linker. + static bool + RendezvousBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set + /// of loaded modules. + void + RefreshModules(); + + /// Updates the load address of every allocatable section in @p module. + /// + /// @param module The module to traverse. + /// + /// @param base_addr The virtual base address @p module is loaded at. + void + UpdateLoadedSections(lldb::ModuleSP module, + lldb::addr_t base_addr = 0); + + /// Locates or creates a module given by @p file and updates/loads the + /// resulting module at the virtual base address @p base_addr. + lldb::ModuleSP + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); + + /// Resolves the entry point for the current inferior process and sets a + /// breakpoint at that address. + void + ProbeEntry(); + + /// Callback routine invoked when we hit the breakpoint on process entry. + /// + /// This routine is responsible for resolving the load addresses of all + /// dependent modules required by the inferior and setting up the rendezvous + /// breakpoint. + static bool + EntryBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + /// Helper for the entry breakpoint callback. Resolves the load addresses + /// of all dependent modules. + void + LoadAllCurrentModules(); + + /// Computes a value for m_load_offset returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t + ComputeLoadOffset(); + + /// Computes a value for m_entry_point returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t + GetEntryPoint(); + +private: + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); +}; + +#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) @@ -0,0 +1,153 @@ +//===-- AuxVector.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 +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" + +#include "AuxVector.h" + +using namespace lldb; +using namespace lldb_private; + +static bool +GetMaxU64(DataExtractor &data, + uint32_t *offset, uint64_t *value, unsigned int byte_size) +{ + uint32_t saved_offset = *offset; + *value = data.GetMaxU64(offset, byte_size); + return *offset != saved_offset; +} + +static bool +ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, + uint32_t *offset, unsigned int byte_size) +{ + if (!GetMaxU64(data, offset, &entry.type, byte_size)) + return false; + + if (!GetMaxU64(data, offset, &entry.value, byte_size)) + return false; + + return true; +} + +DataBufferSP +AuxVector::GetAuxvData() +{ + + return lldb_private::Host::GetAuxvData(m_process); +} + +void +AuxVector::ParseAuxv(DataExtractor &data) +{ + const unsigned int byte_size = m_process->GetAddressByteSize(); + uint32_t offset = 0; + + for (;;) + { + Entry entry; + + if (!ParseAuxvEntry(data, entry, &offset, byte_size)) + break; + + if (entry.type == AT_NULL) + break; + + if (entry.type == AT_IGNORE) + continue; + + m_auxv.push_back(entry); + } +} + +AuxVector::AuxVector(Process *process) + : m_process(process) +{ + DataExtractor data; + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + data.SetData(GetAuxvData()); + data.SetByteOrder(m_process->GetByteOrder()); + data.SetAddressByteSize(m_process->GetAddressByteSize()); + + ParseAuxv(data); + + if (log) + DumpToLog(log); +} + +AuxVector::iterator +AuxVector::FindEntry(EntryType type) const +{ + for (iterator I = begin(); I != end(); ++I) + { + if (I->type == static_cast(type)) + return I; + } + + return end(); +} + +void +AuxVector::DumpToLog(LogSP log) const +{ + if (!log) + return; + + log->PutCString("AuxVector: "); + for (iterator I = begin(); I != end(); ++I) + { + log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); + } +} + +const char * +AuxVector::GetEntryName(EntryType type) +{ + const char *name; + +#define ENTRY_NAME(_type) _type: name = #_type + switch (type) + { + default: + name = "unkown"; + break; + + case ENTRY_NAME(AT_NULL); break; + case ENTRY_NAME(AT_IGNORE); break; + case ENTRY_NAME(AT_EXECFD); break; + case ENTRY_NAME(AT_PHDR); break; + case ENTRY_NAME(AT_PHENT); break; + case ENTRY_NAME(AT_PHNUM); break; + case ENTRY_NAME(AT_PAGESZ); break; + case ENTRY_NAME(AT_BASE); break; + case ENTRY_NAME(AT_FLAGS); break; + case ENTRY_NAME(AT_ENTRY); break; + case ENTRY_NAME(AT_NOTELF); break; + case ENTRY_NAME(AT_UID); break; + case ENTRY_NAME(AT_EUID); break; + case ENTRY_NAME(AT_GID); break; + case ENTRY_NAME(AT_EGID); break; + case ENTRY_NAME(AT_CLKTCK); break; + } +#undef ENTRY_NAME + + return name; +} + Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) @@ -0,0 +1,330 @@ +//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "DYLDRendezvous.h" + +using namespace lldb; +using namespace lldb_private; + +/// Locates the address of the rendezvous structure. Returns the address on +/// success and LLDB_INVALID_ADDRESS on failure. +static addr_t +ResolveRendezvousAddress(Process *process) +{ + addr_t info_location; + addr_t info_addr; + Error error; + size_t size; + + info_location = process->GetImageInfoAddress(); + + if (info_location == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + info_addr = 0; + size = process->DoReadMemory(info_location, &info_addr, + process->GetAddressByteSize(), error); + if (size != process->GetAddressByteSize() || error.Fail()) + return LLDB_INVALID_ADDRESS; + + if (info_addr == 0) + return LLDB_INVALID_ADDRESS; + + return info_addr; +} + +DYLDRendezvous::DYLDRendezvous(Process *process) + : m_process(process), + m_rendezvous_addr(LLDB_INVALID_ADDRESS), + m_current(), + m_previous(), + m_soentries(), + m_added_soentries(), + m_removed_soentries() +{ + // Cache a copy of the executable path + m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX); +} + +bool +DYLDRendezvous::Resolve() +{ + const size_t word_size = 4; + Rendezvous info; + size_t address_size; + size_t padding; + addr_t info_addr; + addr_t cursor; + + address_size = m_process->GetAddressByteSize(); + padding = address_size - word_size; + + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) + cursor = info_addr = ResolveRendezvousAddress(m_process); + else + cursor = info_addr = m_rendezvous_addr; + + if (cursor == LLDB_INVALID_ADDRESS) + return false; + + if (!(cursor = ReadMemory(cursor, &info.version, word_size))) + return false; + + if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) + return false; + + if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) + return false; + + if (!(cursor = ReadMemory(cursor, &info.state, word_size))) + return false; + + if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) + return false; + + // The rendezvous was successfully read. Update our internal state. + m_rendezvous_addr = info_addr; + m_previous = m_current; + m_current = info; + + return UpdateSOEntries(); +} + +bool +DYLDRendezvous::IsValid() +{ + return m_rendezvous_addr != LLDB_INVALID_ADDRESS; +} + +bool +DYLDRendezvous::UpdateSOEntries() +{ + SOEntry entry; + + if (m_current.map_addr == 0) + return false; + + // When the previous and current states are consistent this is the first + // time we have been asked to update. Just take a snapshot of the currently + // loaded modules. + if (m_previous.state == eConsistent && m_current.state == eConsistent) + return TakeSnapshot(m_soentries); + + // If we are about to add or remove a shared object clear out the current + // state and take a snapshot of the currently loaded images. + if (m_current.state == eAdd || m_current.state == eDelete) + { + assert(m_previous.state == eConsistent); + m_soentries.clear(); + m_added_soentries.clear(); + m_removed_soentries.clear(); + return TakeSnapshot(m_soentries); + } + assert(m_current.state == eConsistent); + + // Otherwise check the previous state to determine what to expect and update + // accordingly. + if (m_previous.state == eAdd) + return UpdateSOEntriesForAddition(); + else if (m_previous.state == eDelete) + return UpdateSOEntriesForDeletion(); + + return false; +} + +bool +DYLDRendezvous::UpdateSOEntriesForAddition() +{ + SOEntry entry; + iterator pos; + + assert(m_previous.state == eAdd); + + if (m_current.map_addr == 0) + return false; + + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) + { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; + + // Only add shared libraries and not the executable. + // On Linux this is indicated by an empty path in the entry. + // On FreeBSD it is the name of the executable. + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + continue; + + pos = std::find(m_soentries.begin(), m_soentries.end(), entry); + if (pos == m_soentries.end()) + { + m_soentries.push_back(entry); + m_added_soentries.push_back(entry); + } + } + + return true; +} + +bool +DYLDRendezvous::UpdateSOEntriesForDeletion() +{ + SOEntryList entry_list; + iterator pos; + + assert(m_previous.state == eDelete); + + if (!TakeSnapshot(entry_list)) + return false; + + for (iterator I = begin(); I != end(); ++I) + { + pos = std::find(entry_list.begin(), entry_list.end(), *I); + if (pos == entry_list.end()) + m_removed_soentries.push_back(*I); + } + + m_soentries = entry_list; + return true; +} + +bool +DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) +{ + SOEntry entry; + + if (m_current.map_addr == 0) + return false; + + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) + { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; + + // Only add shared libraries and not the executable. + // On Linux this is indicated by an empty path in the entry. + // On FreeBSD it is the name of the executable. + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + continue; + + entry_list.push_back(entry); + } + + return true; +} + +addr_t +DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) +{ + size_t bytes_read; + Error error; + + bytes_read = m_process->DoReadMemory(addr, dst, size, error); + if (bytes_read != size || error.Fail()) + return 0; + + return addr + bytes_read; +} + +std::string +DYLDRendezvous::ReadStringFromMemory(addr_t addr) +{ + std::string str; + Error error; + size_t size; + char c; + + if (addr == LLDB_INVALID_ADDRESS) + return std::string(); + + for (;;) { + size = m_process->DoReadMemory(addr, &c, 1, error); + if (size != 1 || error.Fail()) + return std::string(); + if (c == 0) + break; + else { + str.push_back(c); + addr++; + } + } + + return str; +} + +bool +DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) +{ + size_t address_size = m_process->GetAddressByteSize(); + + entry.clear(); + + if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.next, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.prev, address_size))) + return false; + + entry.path = ReadStringFromMemory(entry.path_addr); + + return true; +} + +void +DYLDRendezvous::DumpToLog(LogSP log) const +{ + int state = GetState(); + + if (!log) + return; + + log->PutCString("DYLDRendezvous:"); + log->Printf(" Address: %lx", GetRendezvousAddress()); + log->Printf(" Version: %d", GetVersion()); + log->Printf(" Link : %lx", GetLinkMapAddress()); + log->Printf(" Break : %lx", GetBreakAddress()); + log->Printf(" LDBase : %lx", GetLDBase()); + log->Printf(" State : %s", + (state == eConsistent) ? "consistent" : + (state == eAdd) ? "add" : + (state == eDelete) ? "delete" : "unknown"); + + iterator I = begin(); + iterator E = end(); + + if (I != E) + log->PutCString("DYLDRendezvous SOEntries:"); + + for (int i = 1; I != E; ++I, ++i) + { + log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); + log->Printf(" Base : %lx", I->base_addr); + log->Printf(" Path : %lx", I->path_addr); + log->Printf(" Dyn : %lx", I->dyn_addr); + log->Printf(" Next : %lx", I->next); + log->Printf(" Prev : %lx", I->prev); + } +} Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) @@ -0,0 +1,97 @@ +//===-- AuxVector.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_AuxVector_H_ +#define liblldb_AuxVector_H_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/lldb-forward-rtti.h" + +namespace lldb_private { +class DataExtractor; +} + +/// @class AuxVector +/// @brief Represents a processes auxiliary vector. +/// +/// When a process is loaded on Linux a vector of values is placed onto the +/// stack communicating operating system specific information. On construction +/// this class locates and parses this information and provides a simple +/// read-only interface to the entries found. +class AuxVector { + +public: + AuxVector(lldb_private::Process *process); + + struct Entry { + uint64_t type; + uint64_t value; + + Entry() : type(0), value(0) { } + }; + + /// Constants describing the type of entry. + enum EntryType { + AT_NULL = 0, ///< End of auxv. + AT_IGNORE = 1, ///< Ignore entry. + AT_EXECFD = 2, ///< File descriptor of program. + AT_PHDR = 3, ///< Program headers. + AT_PHENT = 4, ///< Size of program header. + AT_PHNUM = 5, ///< Number of program headers. + AT_PAGESZ = 6, ///< Page size. + AT_BASE = 7, ///< Interpreter base address. + AT_FLAGS = 8, ///< Flags. + AT_ENTRY = 9, ///< Program entry point. + AT_NOTELF = 10, ///< Set if program is not an ELF. + AT_UID = 11, ///< UID. + AT_EUID = 12, ///< Effective UID. + AT_GID = 13, ///< GID. + AT_EGID = 14, ///< Effective GID. + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). + }; + +private: + typedef std::vector EntryVector; + +public: + typedef EntryVector::const_iterator iterator; + + iterator begin() const { return m_auxv.begin(); } + iterator end() const { return m_auxv.end(); } + + iterator + FindEntry(EntryType type) const; + + static const char * + GetEntryName(const Entry &entry) { + return GetEntryName(static_cast(entry.type)); + } + + static const char * + GetEntryName(EntryType type); + + void + DumpToLog(lldb::LogSP log) const; + +private: + lldb_private::Process *m_process; + EntryVector m_auxv; + + lldb::DataBufferSP + GetAuxvData(); + + void + ParseAuxv(lldb_private::DataExtractor &data); +}; + +#endif Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) @@ -0,0 +1,230 @@ +//===-- DYLDRendezvous.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_Rendezvous_H_ +#define liblldb_Rendezvous_H_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { +class Process; +} + +/// @class DYLDRendezvous +/// @brief Interface to the runtime linker. +/// +/// A structure is present in a processes memory space which is updated by the +/// runtime liker each time a module is loaded or unloaded. This class provides +/// an interface to this structure and maintains a consistent snapshot of the +/// currently loaded modules. +class DYLDRendezvous { + + // This structure is used to hold the contents of the debug rendezvous + // information (struct r_debug) as found in the inferiors memory. Note that + // the layout of this struct is not binary compatible, it is simply large + // enough to hold the information on both 32 and 64 bit platforms. + struct Rendezvous { + uint64_t version; + lldb::addr_t map_addr; + lldb::addr_t brk; + uint64_t state; + lldb::addr_t ldbase; + + Rendezvous() + : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } + }; + +public: + DYLDRendezvous(lldb_private::Process *process); + + /// Update the internal snapshot of runtime linker rendezvous and recompute + /// the currently loaded modules. + /// + /// This method should be called once one start up, then once each time the + /// runtime linker enters the function given by GetBreakAddress(). + /// + /// @returns true on success and false on failure. + /// + /// @see GetBreakAddress(). + bool + Resolve(); + + /// @returns true if this rendezvous has been located in the inferiors + /// address space and false otherwise. + bool + IsValid(); + + /// @returns the address of the rendezvous structure in the inferiors + /// address space. + lldb::addr_t + GetRendezvousAddress() const { return m_rendezvous_addr; } + + /// @returns the version of the rendezvous protocol being used. + int + GetVersion() const { return m_current.version; } + + /// @returns address in the inferiors address space containing the linked + /// list of shared object descriptors. + lldb::addr_t + GetLinkMapAddress() const { return m_current.map_addr; } + + /// A breakpoint should be set at this address and Resolve called on each + /// hit. + /// + /// @returns the address of a function called by the runtime linker each + /// time a module is loaded/unloaded, or about to be loaded/unloaded. + /// + /// @see Resolve() + lldb::addr_t + GetBreakAddress() const { return m_current.brk; } + + /// Returns the current state of the rendezvous structure. + int + GetState() const { return m_current.state; } + + /// @returns the base address of the runtime linker in the inferiors address + /// space. + lldb::addr_t + GetLDBase() const { return m_current.ldbase; } + + /// @returns true if modules have been loaded into the inferior since the + /// last call to Resolve(). + bool + ModulesDidLoad() const { return !m_added_soentries.empty(); } + + /// @returns true if modules have been unloaded from the inferior since the + /// last call to Resolve(). + bool + ModulesDidUnload() const { return !m_removed_soentries.empty(); } + + void + DumpToLog(lldb::LogSP log) const; + + /// @brief Constants describing the state of the rendezvous. + /// + /// @see GetState(). + enum RendezvousState { + eConsistent, + eAdd, + eDelete + }; + + /// @brief Structure representing the shared objects currently loaded into + /// the inferior process. + /// + /// This object is a rough analogue to the struct link_map object which + /// actually lives in the inferiors memory. + struct SOEntry { + lldb::addr_t base_addr; ///< Base address of the loaded object. + lldb::addr_t path_addr; ///< String naming the shared object. + lldb::addr_t dyn_addr; ///< Dynamic section of shared object. + lldb::addr_t next; ///< Address of next so_entry. + lldb::addr_t prev; ///< Address of previous so_entry. + std::string path; ///< File name of shared object. + + SOEntry() { clear(); } + + bool operator ==(const SOEntry &entry) { + return this->path == entry.path; + } + + void clear() { + base_addr = 0; + path_addr = 0; + dyn_addr = 0; + next = 0; + prev = 0; + path.clear(); + } + }; + +protected: + typedef std::list SOEntryList; + +public: + typedef SOEntryList::const_iterator iterator; + + /// Iterators over all currently loaded modules. + iterator begin() const { return m_soentries.begin(); } + iterator end() const { return m_soentries.end(); } + + /// Iterators over all modules loaded into the inferior since the last call + /// to Resolve(). + iterator loaded_begin() const { return m_added_soentries.begin(); } + iterator loaded_end() const { return m_added_soentries.end(); } + + /// Iterators over all modules unloaded from the inferior since the last + /// call to Resolve(). + iterator unloaded_begin() const { return m_removed_soentries.begin(); } + iterator unloaded_end() const { return m_removed_soentries.end(); } + +protected: + lldb_private::Process *m_process; + + // Cached copy of executable pathname + char m_exe_path[PATH_MAX]; + + /// Location of the r_debug structure in the inferiors address space. + lldb::addr_t m_rendezvous_addr; + + /// Current and previous snapshots of the rendezvous structure. + Rendezvous m_current; + Rendezvous m_previous; + + /// List of SOEntry objects corresponding to the current link map state. + SOEntryList m_soentries; + + /// List of SOEntry's added to the link map since the last call to Resolve(). + SOEntryList m_added_soentries; + + /// List of SOEntry's removed from the link map since the last call to + /// Resolve(). + SOEntryList m_removed_soentries; + + /// Reads @p size bytes from the inferiors address space starting at @p + /// addr. + /// + /// @returns addr + size if the read was successful and false otherwise. + lldb::addr_t + ReadMemory(lldb::addr_t addr, void *dst, size_t size); + + /// Reads a null-terminated C string from the memory location starting at @p + /// addr. + std::string + ReadStringFromMemory(lldb::addr_t addr); + + /// Reads an SOEntry starting at @p addr. + bool + ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); + + /// Updates the current set of SOEntries, the set of added entries, and the + /// set of removed entries. + bool + UpdateSOEntries(); + + bool + UpdateSOEntriesForAddition(); + + bool + UpdateSOEntriesForDeletion(); + + /// Reads the current list of shared objects according to the link map + /// supplied by the runtime linker. + bool + TakeSnapshot(SOEntryList &entry_list); +}; + +#endif Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) @@ -0,0 +1,425 @@ +//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" + +#include "AuxVector.h" +#include "DynamicLoaderPOSIXDYLD.h" + +using namespace lldb; +using namespace lldb_private; + +void +DynamicLoaderPOSIXDYLD::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +DynamicLoaderPOSIXDYLD::Terminate() +{ +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginName() +{ + return "DynamicLoaderPOSIXDYLD"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetShortPluginName() +{ + return "linux-dyld"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginNameStatic() +{ + return "dynamic-loader.linux-dyld"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() +{ + return "Dynamic loader plug-in that watches for shared library " + "loads/unloads in POSIX processes."; +} + +void +DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) +{ +} + +uint32_t +DynamicLoaderPOSIXDYLD::GetPluginVersion() +{ + return 1; +} + +DynamicLoader * +DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) +{ + bool create = force; + if (!create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::Linux || + triple_ref.getOS() == llvm::Triple::FreeBSD) + create = true; + } + + if (create) + return new DynamicLoaderPOSIXDYLD (process); + return NULL; +} + +DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) + : DynamicLoader(process), + m_rendezvous(process), + m_load_offset(LLDB_INVALID_ADDRESS), + m_entry_point(LLDB_INVALID_ADDRESS), + m_auxv(NULL) +{ +} + +DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() +{ +} + +void +DynamicLoaderPOSIXDYLD::DidAttach() +{ + ModuleSP executable; + addr_t load_offset; + + m_auxv.reset(new AuxVector(m_process)); + + executable = m_process->GetTarget().GetExecutableModule(); + load_offset = ComputeLoadOffset(); + + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) + { + ModuleList module_list; + module_list.Append(executable); + UpdateLoadedSections(executable, load_offset); + LoadAllCurrentModules(); + m_process->GetTarget().ModulesDidLoad(module_list); + } +} + +void +DynamicLoaderPOSIXDYLD::DidLaunch() +{ + ModuleSP executable; + addr_t load_offset; + + m_auxv.reset(new AuxVector(m_process)); + + executable = m_process->GetTarget().GetExecutableModule(); + load_offset = ComputeLoadOffset(); + + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) + { + ModuleList module_list; + module_list.Append(executable); + UpdateLoadedSections(executable, load_offset); + ProbeEntry(); + m_process->GetTarget().ModulesDidLoad(module_list); + } +} + +Error +DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) +{ + return Error(); +} + +Log * +DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) +{ + return NULL; +} + +Error +DynamicLoaderPOSIXDYLD::CanLoadImage() +{ + return Error(); +} + +void +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) +{ + ObjectFile *obj_file = module->GetObjectFile(); + SectionList *sections = obj_file->GetSectionList(); + SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); + const size_t num_sections = sections->GetSize(); + + for (unsigned i = 0; i < num_sections; ++i) + { + Section *section = sections->GetSectionAtIndex(i).get(); + lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; + lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); + + // If the file address of the section is zero then this is not an + // allocatable/loadable section (property of ELF sh_addr). Skip it. + if (new_load_addr == base_addr) + continue; + + if (old_load_addr == LLDB_INVALID_ADDRESS || + old_load_addr != new_load_addr) + load_list.SetSectionLoadAddress(section, new_load_addr); + } +} + +void +DynamicLoaderPOSIXDYLD::ProbeEntry() +{ + Breakpoint *entry_break; + addr_t entry; + + if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + return; + + entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); + entry_break->SetCallback(EntryBreakpointHit, this, true); +} + +// The runtime linker has run and initialized the rendezvous structure once the +// process has hit its entry point. When we hit the corresponding breakpoint we +// interrogate the rendezvous structure to get the load addresses of all +// dependent modules for the process. Similarly, we can discover the runtime +// linker function and setup a breakpoint to notify us of any dynamically loaded +// modules (via dlopen). +bool +DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) +{ + DynamicLoaderPOSIXDYLD* dyld_instance; + + dyld_instance = static_cast(baton); + dyld_instance->LoadAllCurrentModules(); + dyld_instance->SetRendezvousBreakpoint(); + return false; // Continue running. +} + +void +DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() +{ + Breakpoint *dyld_break; + addr_t break_addr; + + break_addr = m_rendezvous.GetBreakAddress(); + dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); +} + +bool +DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) +{ + DynamicLoaderPOSIXDYLD* dyld_instance; + + dyld_instance = static_cast(baton); + dyld_instance->RefreshModules(); + + // Return true to stop the target, false to just let the target run. + return dyld_instance->GetStopWhenImagesChange(); +} + +void +DynamicLoaderPOSIXDYLD::RefreshModules() +{ + if (!m_rendezvous.Resolve()) + return; + + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + if (m_rendezvous.ModulesDidLoad()) + { + ModuleList new_modules; + + E = m_rendezvous.loaded_end(); + for (I = m_rendezvous.loaded_begin(); I != E; ++I) + { + FileSpec file(I->path.c_str(), true); + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); + if (module_sp.get()) + new_modules.Append(module_sp); + } + m_process->GetTarget().ModulesDidLoad(new_modules); + } + + if (m_rendezvous.ModulesDidUnload()) + { + ModuleList old_modules; + + E = m_rendezvous.unloaded_end(); + for (I = m_rendezvous.unloaded_begin(); I != E; ++I) + { + FileSpec file(I->path.c_str(), true); + ModuleSP module_sp = + loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); + if (module_sp.get()) + old_modules.Append(module_sp); + } + m_process->GetTarget().ModulesDidUnload(old_modules); + } +} + +ThreadPlanSP +DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) +{ + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + ThreadPlanSP thread_plan_sp; + + StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); + const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); + Symbol *sym = context.symbol; + + if (sym == NULL || !sym->IsTrampoline()) + return thread_plan_sp; + + const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); + if (!sym_name) + return thread_plan_sp; + + SymbolContextList target_symbols; + Target &target = thread.GetProcess().GetTarget(); + ModuleList &images = target.GetImages(); + + images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); + size_t num_targets = target_symbols.GetSize(); + if (!num_targets) + return thread_plan_sp; + + typedef std::vector AddressVector; + AddressVector addrs; + for (size_t i = 0; i < num_targets; ++i) + { + SymbolContext context; + AddressRange range; + if (target_symbols.GetContextAtIndex(i, context)) + { + context.GetAddressRange(eSymbolContextEverything, 0, false, range); + lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); + if (addr != LLDB_INVALID_ADDRESS) + addrs.push_back(addr); + } + } + + if (addrs.size() > 0) + { + AddressVector::iterator start = addrs.begin(); + AddressVector::iterator end = addrs.end(); + + std::sort(start, end); + addrs.erase(std::unique(start, end), end); + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); + } + + return thread_plan_sp; +} + +void +DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() +{ + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + ModuleList module_list; + + if (!m_rendezvous.Resolve()) + return; + + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) + { + FileSpec file(I->path.c_str(), false); + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); + if (module_sp.get()) + module_list.Append(module_sp); + } + + m_process->GetTarget().ModulesDidLoad(module_list); +} + +ModuleSP +DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) +{ + Target &target = m_process->GetTarget(); + ModuleList &modules = target.GetImages(); + ModuleSP module_sp; + + if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) + { + UpdateLoadedSections(module_sp, base_addr); + } + else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) + { + UpdateLoadedSections(module_sp, base_addr); + modules.Append(module_sp); + } + + return module_sp; +} + +addr_t +DynamicLoaderPOSIXDYLD::ComputeLoadOffset() +{ + addr_t virt_entry; + + if (m_load_offset != LLDB_INVALID_ADDRESS) + return m_load_offset; + + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + ModuleSP module = m_process->GetTarget().GetExecutableModule(); + ObjectFile *exe = module->GetObjectFile(); + Address file_entry = exe->GetEntryPointAddress(); + + if (!file_entry.IsValid()) + return LLDB_INVALID_ADDRESS; + + m_load_offset = virt_entry - file_entry.GetFileAddress(); + return m_load_offset; +} + +addr_t +DynamicLoaderPOSIXDYLD::GetEntryPoint() +{ + if (m_entry_point != LLDB_INVALID_ADDRESS) + return m_entry_point; + + if (m_auxv.get() == NULL) + return LLDB_INVALID_ADDRESS; + + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + + if (I == m_auxv->end()) + return LLDB_INVALID_ADDRESS; + + m_entry_point = static_cast(I->value); + return m_entry_point; +} Index: source/Plugins/DynamicLoader/POSIX-DYLD/Makefile =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) @@ -0,0 +1,14 @@ +##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginDynamicLoaderPOSIX +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Makefile =================================================================== --- source/Plugins/Makefile (revision 147560) +++ source/Plugins/Makefile (working copy) @@ -30,7 +30,11 @@ endif ifeq ($(HOST_OS),Linux) -DIRS += Process/Linux DynamicLoader/Linux-DYLD +DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD endif +ifeq ($(HOST_OS),FreeBSD) +DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD +endif + include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/Linux/ProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy) @@ -20,10 +20,10 @@ #include "lldb/Target/Target.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "ProcessMonitor.h" -#include "LinuxThread.h" +#include "POSIXThread.h" using namespace lldb; using namespace lldb_private; @@ -50,42 +50,21 @@ CreateInstance); Log::Callbacks log_callbacks = { - ProcessLinuxLog::DisableLog, - ProcessLinuxLog::EnableLog, - ProcessLinuxLog::ListLogCategories + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories }; Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); } } -void -ProcessLinux::Terminate() -{ -} - -const char * -ProcessLinux::GetPluginNameStatic() -{ - return "plugin.process.linux"; -} - -const char * -ProcessLinux::GetPluginDescriptionStatic() -{ - return "Process plugin for Linux"; -} - - //------------------------------------------------------------------------------ // Constructors and destructors. ProcessLinux::ProcessLinux(Target& target, Listener &listener) - : Process(target, listener), - m_monitor(NULL), - m_module(NULL), - m_in_limbo(false), - m_exit_now(false) + : ProcessPOSIX(target, listener) { #if 0 // FIXME: Putting this code in the ctor and saving the byte order in a @@ -98,409 +77,28 @@ #endif } -ProcessLinux::~ProcessLinux() -{ - delete m_monitor; -} - -//------------------------------------------------------------------------------ -// Process protocol. - -bool -ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target.GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - return false; -} - -Error -ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid) -{ - Error error; - assert(m_monitor == NULL); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID()); - - m_monitor = new ProcessMonitor(this, pid, error); - - if (!error.Success()) - return error; - - SetID(pid); - return error; -} - -Error -ProcessLinux::WillLaunch(Module* module) -{ - Error error; - return error; -} - -Error -ProcessLinux::DoLaunch (Module *module, - const ProcessLaunchInfo &launch_info) -{ - Error error; - assert(m_monitor == NULL); - - SetPrivateState(eStateLaunching); - - const char *stdin_path = NULL; - const char *stdout_path = NULL; - const char *stderr_path = NULL; - const char *working_dir = launch_info.GetWorkingDirectory(); - - const ProcessLaunchInfo::FileAction *file_action; - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdin_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdout_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stderr_path = file_action->GetPath(); - } - - m_monitor = new ProcessMonitor (this, - module, - launch_info.GetArguments().GetConstArgumentVector(), - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), - stdin_path, - stdout_path, - stderr_path, - error); - - m_module = module; - - if (!error.Success()) - return error; - - SetID(m_monitor->GetPID()); - return error; -} - void -ProcessLinux::DidLaunch() +ProcessLinux::Terminate() { } - -Error -ProcessLinux::DoResume() +const char * +ProcessLinux::GetPluginNameStatic() { - StateType state = GetPrivateState(); - - assert(state == eStateStopped || state == eStateCrashed); - - // We are about to resume a thread that will cause the process to exit so - // set our exit status now. Do not change our state if the inferior - // crashed. - if (state == eStateStopped) - { - if (m_in_limbo) - SetExitStatus(m_exit_status, NULL); - else - SetPrivateState(eStateRunning); - } - - bool did_resume = false; - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - LinuxThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - did_resume = thread->Resume() || did_resume; - } - assert(did_resume && "Process resume failed!"); - - return Error(); + return "linux"; } -addr_t -ProcessLinux::GetImageInfoAddress() +const char * +ProcessLinux::GetPluginDescriptionStatic() { - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(); - - if (addr.IsValid()) - return addr.GetLoadAddress(target); - else - return LLDB_INVALID_ADDRESS; + return "Process plugin for Linux"; } -Error -ProcessLinux::DoHalt(bool &caused_stop) -{ - Error error; - if (IsStopped()) - { - caused_stop = false; - } - else if (kill(GetID(), SIGSTOP)) - { - caused_stop = false; - error.SetErrorToErrno(); - } - else - { - caused_stop = true; - } - - return error; -} - -Error -ProcessLinux::DoDetach() -{ - Error error; - - error = m_monitor->Detach(); - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - -Error -ProcessLinux::DoSignal(int signal) -{ - Error error; - - if (kill(GetID(), signal)) - error.SetErrorToErrno(); - - return error; -} - -Error -ProcessLinux::DoDestroy() -{ - Error error; - - if (!HasExited()) - { - // Drive the exit event to completion (do not keep the inferior in - // limbo). - m_exit_now = true; - - if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) - { - error.SetErrorToErrno(); - return error; - } - - SetPrivateState(eStateExited); - } - - return error; -} - -void -ProcessLinux::SendMessage(const ProcessMessage &message) -{ - Mutex::Locker lock(m_message_mutex); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected process message!"); - break; - - case ProcessMessage::eInvalidMessage: - return; - - case ProcessMessage::eLimboMessage: - m_in_limbo = true; - m_exit_status = message.GetExitStatus(); - if (m_exit_now) - { - SetPrivateState(eStateExited); - m_monitor->Detach(); - } - else - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eExitMessage: - m_exit_status = message.GetExitStatus(); - SetExitStatus(m_exit_status, NULL); - break; - - case ProcessMessage::eTraceMessage: - case ProcessMessage::eBreakpointMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eCrashMessage: - SetPrivateState(eStateCrashed); - break; - } - - m_message_queue.push(message); -} - -void -ProcessLinux::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s()", __FUNCTION__); - - Mutex::Locker lock(m_message_mutex); - if (m_message_queue.empty()) - return; - - ProcessMessage &message = m_message_queue.front(); - - // Resolve the thread this message corresponds to and pass it along. - // FIXME: we're really dealing with the pid here. This should get - // fixed when this code is fixed to handle multiple threads. - lldb::tid_t tid = message.GetTID(); - if (log) - log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid); - LinuxThread *thread = static_cast( - GetThreadList().FindThreadByID(tid, false).get()); - - assert(thread); - thread->Notify(message); - - m_message_queue.pop(); -} - -bool -ProcessLinux::IsAlive() -{ - StateType state = GetPrivateState(); - return state != eStateDetached && state != eStateExited && state != eStateInvalid; -} - -size_t -ProcessLinux::DoReadMemory(addr_t vm_addr, - void *buf, size_t size, Error &error) -{ - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t -ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, - Error &error) -{ - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t -ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) -{ - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } - - return allocated_addr; -} - -Error -ProcessLinux::DoDeallocateMemory(lldb::addr_t addr) -{ - Error error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); - - return error; -} - -size_t -ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) -{ - static const uint8_t g_i386_opcode[] = { 0xCC }; - - ArchSpec arch = GetTarget().GetArchitecture(); - const uint8_t *opcode = NULL; - size_t opcode_size = 0; - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_64_x86_64: - opcode = g_i386_opcode; - opcode_size = sizeof(g_i386_opcode); - break; - } - - bp_site->SetTrapOpcode(opcode, opcode_size); - return opcode_size; -} - -Error -ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site) -{ - return EnableSoftwareBreakpoint(bp_site); -} - -Error -ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site) -{ - return DisableSoftwareBreakpoint(bp_site); -} - uint32_t -ProcessLinux::UpdateThreadListIfNeeded() -{ - // Do not allow recursive updates. - return m_thread_list.GetSize(false); -} - -uint32_t ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID()); // Update the process thread list with this new thread. @@ -508,62 +106,16 @@ assert(m_monitor); ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); if (!thread_sp) - thread_sp.reset(new LinuxThread(*this, GetID())); + thread_sp.reset(new POSIXThread(*this, GetID())); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID()); new_thread_list.AddThread(thread_sp); return new_thread_list.GetSize(false); } -ByteOrder -ProcessLinux::GetByteOrder() const -{ - // FIXME: We should be able to extract this value directly. See comment in - // ProcessLinux(). - return m_byte_order; -} -size_t -ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error) -{ - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - error.SetErrorToErrno(); - return 0; - } - return status; -} - -size_t -ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error) -{ - ssize_t bytes_read; - - // The terminal file descriptor is always in non-block mode. - if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - if (errno != EAGAIN) - error.SetErrorToErrno(); - return 0; - } - return bytes_read; -} - -size_t -ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error) -{ - return GetSTDOUT(buf, len, error); -} - -UnixSignals & -ProcessLinux::GetUnixSignals() -{ - return m_linux_signals; -} - //------------------------------------------------------------------------------ // ProcessInterface protocol. @@ -601,39 +153,3 @@ { return NULL; } - -//------------------------------------------------------------------------------ -// Utility functions. - -bool -ProcessLinux::HasExited() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} - -bool -ProcessLinux::IsStopped() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - - return false; -} Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessLinuxLog.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp (working copy) @@ -1,193 +0,0 @@ -//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessLinuxLog.h" - -#include "lldb/Interpreter/Args.h" -#include "lldb/Core/StreamFile.h" - -#include "ProcessLinux.h" - -using namespace lldb; -using namespace lldb_private; - - -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_lob_sp the first time this function is -// called. -static LogSP & -GetLog () -{ - static LogSP g_log_sp; - return g_log_sp; -} - -LogSP -ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - LogSP log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return LogSP(); - } - return log; -} - -void -ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm) -{ - LogSP log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - const size_t argc = args.GetArgumentCount (); - if (argc > 0) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; i < argc; ++i) - { - const char *arg = args.GetArgumentAtIndex (i); - - - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS; - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE; - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - - } - } - - if (flag_bits == 0) - GetLog ().reset(); - else - log->GetMask().Reset (flag_bits); - } - - return; -} - -LogSP -ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - LogSP log(GetLog ()); - if (log) - flag_bits = log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - log = make_shared(log_stream_sp); - GetLog () = log; - } - - if (log) - { - bool got_unknown_category = false; - const size_t argc = args.GetArgumentCount(); - for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = LINUX_LOG_DEFAULT; - log->GetMask().Reset(flag_bits); - log->GetOptions().Reset(log_options); - } - return log; -} - -void -ProcessLinuxLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - " ptrace - log all calls to ptrace\n" -#endif - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic()); -} - - -void -ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } -} - -int ProcessLinuxLog::m_nestinglevel; Index: source/Plugins/Process/Linux/ProcessLinux.h =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinux.h (working copy) @@ -19,11 +19,12 @@ #include "lldb/Target/Process.h" #include "LinuxSignals.h" #include "ProcessMessage.h" +#include "ProcessPOSIX.h" class ProcessMonitor; class ProcessLinux : - public lldb_private::Process + public ProcessPOSIX { public: //------------------------------------------------------------------ @@ -51,97 +52,8 @@ ProcessLinux(lldb_private::Target& target, lldb_private::Listener &listener); - virtual - ~ProcessLinux(); - - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - virtual bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); - - virtual lldb_private::Error - WillLaunch(lldb_private::Module *module); - - virtual lldb_private::Error - DoAttachToProcessWithID(lldb::pid_t pid); - - virtual lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - const lldb_private::ProcessLaunchInfo &launch_info); - - virtual void - DidLaunch(); - - virtual lldb_private::Error - DoResume(); - - virtual lldb_private::Error - DoHalt(bool &caused_stop); - - virtual lldb_private::Error - DoDetach(); - - virtual lldb_private::Error - DoSignal(int signal); - - virtual lldb_private::Error - DoDestroy(); - - virtual void - RefreshStateAfterStop(); - - virtual bool - IsAlive(); - - virtual size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error); - - virtual size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); - - virtual lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error); - - virtual lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr); - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - - virtual lldb_private::Error - EnableBreakpoint(lldb_private::BreakpointSite *bp_site); - - virtual lldb_private::Error - DisableBreakpoint(lldb_private::BreakpointSite *bp_site); - virtual uint32_t - UpdateThreadListIfNeeded(); - - uint32_t - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); - - virtual lldb::ByteOrder - GetByteOrder() const; - - virtual lldb::addr_t - GetImageInfoAddress(); - - virtual size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDERR(char *buf, size_t len, lldb_private::Error &error); - + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -165,59 +77,11 @@ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - //-------------------------------------------------------------------------- - // ProcessLinux internal API. - - /// Registers the given message with this process. - void SendMessage(const ProcessMessage &message); - - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } - - lldb_private::UnixSignals & - GetUnixSignals(); - private: - /// Target byte order. - lldb::ByteOrder m_byte_order; - /// Process monitor; - ProcessMonitor *m_monitor; - - /// The module we are executing. - lldb_private::Module *m_module; - - /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; - std::queue m_message_queue; - - /// True when the process has entered a state of "limbo". - /// - /// This flag qualifies eStateStopped. It lets us know that when we - /// continue from this state the process will exit. Also, when true, - /// Process::m_exit_status is set. - bool m_in_limbo; - - /// Drive any exit events to completion. - bool m_exit_now; - /// Linux-specific signal set. LinuxSignals m_linux_signals; - /// Updates the loaded sections provided by the executable. - /// - /// FIXME: It would probably be better to delegate this task to the - /// DynamicLoader plugin, when we have one. - void UpdateLoadedSections(); - - /// Returns true if the process has exited. - bool HasExited(); - - /// Returns true if the process is stopped. - bool IsStopped(); - - typedef std::map MMapMap; - MMapMap m_addr_to_mmap_size; }; #endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/Linux/ProcessLinuxLog.h =================================================================== --- source/Plugins/Process/Linux/ProcessLinuxLog.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinuxLog.h (working copy) @@ -1,98 +0,0 @@ -//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ -#define liblldb_ProcessLinuxLog_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes - -// Project includes -#include "lldb/Core/Log.h" - -#define LINUX_LOG_VERBOSE (1u << 0) -#define LINUX_LOG_PROCESS (1u << 1) -#define LINUX_LOG_THREAD (1u << 2) -#define LINUX_LOG_PACKETS (1u << 3) -#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define LINUX_LOG_BREAKPOINTS (1u << 7) -#define LINUX_LOG_WATCHPOINTS (1u << 8) -#define LINUX_LOG_STEP (1u << 9) -#define LINUX_LOG_COMM (1u << 10) -#define LINUX_LOG_ASYNC (1u << 11) -#define LINUX_LOG_PTRACE (1u << 12) -#define LINUX_LOG_REGISTERS (1u << 13) -#define LINUX_LOG_ALL (UINT32_MAX) -#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS - -// The size which determines "short memory reads/writes". -#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) - -class ProcessLinuxLog -{ - static int m_nestinglevel; - -public: - static lldb::LogSP - GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void - DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static lldb::LogSP - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, - lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories (lldb_private::Stream *strm); - - static void - LogIf (uint32_t mask, const char *format, ...); - - // The following functions can be used to enable the client to limit - // logging to only the top level function calls. This is useful for - // recursive functions. FIXME: not thread safe! - // Example: - // void NestingFunc() { - // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL)); - // if (log) - // { - // ProcessLinuxLog::IncNestLevel(); - // if (ProcessLinuxLog::AtTopNestLevel()) - // log->Print(msg); - // } - // NestingFunc(); - // if (log) - // ProcessLinuxLog::DecNestLevel(); - // } - - static bool - AtTopNestLevel() - { - return m_nestinglevel == 1; - } - - static void - IncNestLevel() - { - ++m_nestinglevel; - } - - static void - DecNestLevel() - { - --m_nestinglevel; - assert(m_nestinglevel >= 0); - } -}; - -#endif // liblldb_ProcessLinuxLog_h_ Index: source/Plugins/Process/Linux/RegisterContextLinux.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux.h (working copy) @@ -1,40 +0,0 @@ -//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextLinux_H_ -#define liblldb_RegisterContextLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Target/RegisterContext.h" - -//------------------------------------------------------------------------------ -/// @class RegisterContextLinux -/// -/// @brief Extends RegisterClass with a few virtual operations useful on Linux. -class RegisterContextLinux - : public lldb_private::RegisterContext -{ -public: - RegisterContextLinux(lldb_private::Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) { } - - /// Updates the register state of the associated thread after hitting a - /// breakpoint (if that make sense for the architecture). Default - /// implementation simply returns true for architectures which do not - /// require any update. - /// - /// @return - /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() { return true; } -}; - -#endif // #ifndef liblldb_RegisterContextLinux_H_ Index: source/Plugins/Process/Linux/LinuxStopInfo.cpp =================================================================== --- source/Plugins/Process/Linux/LinuxStopInfo.cpp (revision 147560) +++ source/Plugins/Process/Linux/LinuxStopInfo.cpp (working copy) @@ -1,60 +0,0 @@ -//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LinuxStopInfo.h" - -using namespace lldb; -using namespace lldb_private; - - -//===----------------------------------------------------------------------===// -// LinuxLimboStopInfo - -LinuxLimboStopInfo::~LinuxLimboStopInfo() { } - -lldb::StopReason -LinuxLimboStopInfo::GetStopReason() const -{ - return lldb::eStopReasonTrace; -} - -const char * -LinuxLimboStopInfo::GetDescription() -{ - return "thread exiting"; -} - -bool -LinuxLimboStopInfo::ShouldStop(Event *event_ptr) -{ - return true; -} - -bool -LinuxLimboStopInfo::ShouldNotify(Event *event_ptr) -{ - return true; -} - -//===----------------------------------------------------------------------===// -// LinuxCrashStopInfo - -LinuxCrashStopInfo::~LinuxCrashStopInfo() { } - -lldb::StopReason -LinuxCrashStopInfo::GetStopReason() const -{ - return lldb::eStopReasonException; -} - -const char * -LinuxCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason); -} Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (working copy) @@ -1,650 +0,0 @@ -//===-- RegisterContextLinux_i386.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/Core/DataExtractor.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" - -using namespace lldb_private; -using namespace lldb; - -enum -{ - k_first_gpr, - gpr_eax = k_first_gpr, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, - k_last_gpr = gpr_gs, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - k_last_fpr = fpu_xmm7, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum -{ - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags -}; - -enum -{ - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7 -}; - -enum -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fcw = 24, - gdb_fsw = 25, - gdb_ftw = 26, - gdb_fpu_cs = 27, - gdb_ip = 28, - gdb_fpu_ds = 29, - gdb_dp = 30, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, regs) + \ - offsetof(RegisterContextLinux_i386::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, i387) + \ - offsetof(RegisterContextLinux_i386::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), - - // Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), - - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - -}; - -#ifndef NDEBUG -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); -#endif - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not in use. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - - -RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_i386::~RegisterContextLinux_i386() -{ -} - -ProcessMonitor & -RegisterContextLinux_i386::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_i386::Invalidate() -{ -} - -void -RegisterContextLinux_i386::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_i386::GetRegisterCount() -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_i386::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_i386::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_i386::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - return false; -} - -bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data) -{ - return false; -} - -bool -RegisterContextLinux_i386::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case dwarf_eax: return gpr_eax; - case dwarf_edx: return gpr_edx; - case dwarf_ecx: return gpr_ecx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_ebp: return gpr_ebp; - case dwarf_esp: return gpr_esp; - case dwarf_eip: return gpr_eip; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_eax : return gpr_eax; - case gdb_ebx : return gpr_ebx; - case gdb_ecx : return gpr_ecx; - case gdb_edx : return gpr_edx; - case gdb_esi : return gpr_esi; - case gdb_edi : return gpr_edi; - case gdb_ebp : return gpr_ebp; - case gdb_esp : return gpr_esp; - case gdb_eip : return gpr_eip; - case gdb_eflags : return gpr_eflags; - case gdb_cs : return gpr_cs; - case gdb_ss : return gpr_ss; - case gdb_ds : return gpr_ds; - case gdb_es : return gpr_es; - case gdb_fs : return gpr_fs; - case gdb_gs : return gpr_gs; - case gdb_stmm0 : return fpu_stmm0; - case gdb_stmm1 : return fpu_stmm1; - case gdb_stmm2 : return fpu_stmm2; - case gdb_stmm3 : return fpu_stmm3; - case gdb_stmm4 : return fpu_stmm4; - case gdb_stmm5 : return fpu_stmm5; - case gdb_stmm6 : return fpu_stmm6; - case gdb_stmm7 : return fpu_stmm7; - case gdb_fcw : return fpu_fcw; - case gdb_fsw : return fpu_fsw; - case gdb_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_fos; - case gdb_dp : return fpu_foo; - case gdb_fop : return fpu_fop; - case gdb_xmm0 : return fpu_xmm0; - case gdb_xmm1 : return fpu_xmm1; - case gdb_xmm2 : return fpu_xmm2; - case gdb_xmm3 : return fpu_xmm3; - case gdb_xmm4 : return fpu_xmm4; - case gdb_xmm5 : return fpu_xmm5; - case gdb_xmm6 : return fpu_xmm6; - case gdb_xmm7 : return fpu_xmm7; - case gdb_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_i386::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t eflags; - - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (eflags & TRACE_BIT) - return true; - - eflags |= TRACE_BIT; - } - else - { - if (!(eflags & TRACE_BIT)) - return false; - - eflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_eflags, eflags); -} - -void -RegisterContextLinux_i386::LogGPR(const char *title) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); - if (log) - { - if (title) - log->Printf ("%s", title); - for (uint32_t i=0; iPrintf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); - } - } -} - -bool -RegisterContextLinux_i386::ReadGPR() -{ - bool result; - - ProcessMonitor &monitor = GetMonitor(); - result = monitor.ReadGPR(&user.regs); - LogGPR("RegisterContextLinux_i386::ReadGPR()"); - return result; -} - -bool -RegisterContextLinux_i386::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} Index: source/Plugins/Process/Linux/ProcessMessage.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessMessage.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessMessage.cpp (working copy) @@ -1,245 +0,0 @@ -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessMessage.h" - -using namespace lldb_private; - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason) -{ - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - break; - case ePrivilegedAddress: - str = "address access protected"; - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str; -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash rcase easons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash rcase easons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash rcase easons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash rcase easons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintCrashReason() const -{ - return PrintCrashReason(m_crash_reason); -} - -const char * -ProcessMessage::PrintKind(Kind kind) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (kind) - { - default: - assert(false && "invalid Kind"); - break; - - case eInvalidMessage: - str = "eInvalidMessage"; - break; - case eExitMessage: - str = "eExitMessage"; - break; - case eLimboMessage: - str = "eLimboMessage"; - break; - case eSignalMessage: - str = "eSignalMessage"; - break; - case eSignalDeliveredMessage: - str = "eSignalDeliveredMessage"; - break; - case eTraceMessage: - str = "eTraceMessage"; - break; - case eBreakpointMessage: - str = "eBreakpointMessage"; - break; - case eCrashMessage: - str = "eCrashMessage"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintKind() const -{ - return PrintKind(m_kind); -} Index: source/Plugins/Process/Linux/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy) @@ -28,9 +28,9 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" -#include "LinuxThread.h" +#include "POSIXThread.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" @@ -63,8 +63,8 @@ static void PtraceDisplayBytes(__ptrace_request &req, void *data) { StreamString buf; - LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet ( - LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE)); + LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); if (verbose_log) { @@ -120,7 +120,7 @@ { long int result; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); if (log) log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d", @@ -170,10 +170,10 @@ size_t remainder; long data; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -187,7 +187,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -200,10 +200,10 @@ for (unsigned i = 0; i < remainder; ++i) dst[i] = ((data >> i*8) & 0xFF); - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data); @@ -212,7 +212,7 @@ } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -224,10 +224,10 @@ size_t bytes_written = 0; size_t remainder; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -244,10 +244,10 @@ for (unsigned i = 0; i < word_size; ++i) data |= (unsigned long)src[i] << i*8; - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, data); @@ -255,7 +255,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } } @@ -266,7 +266,7 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -276,14 +276,14 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); } @@ -292,7 +292,7 @@ src += word_size; } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -420,7 +420,7 @@ ReadRegOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); // Set errno to zero so that we can detect a failed peek. errno = 0; @@ -434,7 +434,7 @@ } if (log) log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), data); + POSIXThread::GetRegisterNameFromOffset(m_offset), data); } //------------------------------------------------------------------------------ @@ -460,7 +460,7 @@ { void* buf; lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); if (sizeof(void*) == sizeof(uint64_t)) buf = (void*) m_value.GetAsUInt64(); @@ -472,7 +472,7 @@ if (log) log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), buf); + POSIXThread::GetRegisterNameFromOffset(m_offset), buf); if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf)) m_result = false; else @@ -794,7 +794,7 @@ /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, Module *module, const char *argv[], const char *envp[], @@ -802,7 +802,7 @@ const char *stdout_path, const char *stderr_path, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -858,10 +858,10 @@ } } -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -978,7 +978,7 @@ lldb::pid_t pid; lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); // Propagate the environment if one is not supplied. if (envp == NULL || envp[0] == NULL) @@ -1101,11 +1101,10 @@ if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) goto FINISH; - // Update the process thread list with this new thread and mark it as - // current. + // Update the process thread list with this new thread. // FIXME: should we be letting UpdateThreadList handle this? // FIXME: by using pids instead of tids, we can only support one thread. - inferior.reset(new LinuxThread(process, pid)); + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); @@ -1167,9 +1166,8 @@ ProcessMonitor *monitor = args->m_monitor; ProcessLinux &process = monitor->GetProcess(); - lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (pid <= 1) { @@ -1192,13 +1190,11 @@ goto FINISH; } - // Update the process thread list with the attached thread and - // mark it as current. - inferior.reset(new LinuxThread(process, pid)); + // Update the process thread list with the attached thread. + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); - process.GetThreadList().SetSelectedThreadByID(pid); // Let our process instance know the thread has stopped. process.SendMessage(ProcessMessage::Trace(pid)); @@ -1568,7 +1564,7 @@ } bool -ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value) +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) { bool result; ReadRegOperation op(offset, value, result); Index: source/Plugins/Process/Linux/LinuxStopInfo.h =================================================================== --- source/Plugins/Process/Linux/LinuxStopInfo.h (revision 147560) +++ source/Plugins/Process/Linux/LinuxStopInfo.h (working copy) @@ -1,92 +0,0 @@ -//===-- LinuxStopInfo.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_LinuxStopInfo_H_ -#define liblldb_LinuxStopInfo_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/StopInfo.h" - -#include "LinuxThread.h" -#include "ProcessMessage.h" - -//===----------------------------------------------------------------------===// -/// @class LinuxStopInfo -/// @brief Simple base class for all Linux-specific StopInfo objects. -/// -class LinuxStopInfo - : public lldb_private::StopInfo -{ -public: - LinuxStopInfo(lldb_private::Thread &thread, uint32_t status) - : StopInfo(thread, status) - { } -}; - -//===----------------------------------------------------------------------===// -/// @class LinuxLimboStopInfo -/// @brief Represents the stop state of a process ready to exit. -/// -class LinuxLimboStopInfo - : public LinuxStopInfo -{ -public: - LinuxLimboStopInfo(LinuxThread &thread) - : LinuxStopInfo(thread, 0) - { } - - ~LinuxLimboStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - bool - ShouldStop(lldb_private::Event *event_ptr); - - bool - ShouldNotify(lldb_private::Event *event_ptr); -}; - - -//===----------------------------------------------------------------------===// -/// @class LinuxCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class LinuxCrashStopInfo - : public LinuxStopInfo -{ -public: - LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, - ProcessMessage::CrashReason reason) - : LinuxStopInfo(thread, status), - m_crash_reason(reason) - { } - - ~LinuxCrashStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - ProcessMessage::CrashReason - GetCrashReason() const; - -private: - ProcessMessage::CrashReason m_crash_reason; -}; - -#endif Index: source/Plugins/Process/Linux/LinuxThread.cpp =================================================================== --- source/Plugins/Process/Linux/LinuxThread.cpp (revision 147560) +++ source/Plugins/Process/Linux/LinuxThread.cpp (working copy) @@ -1,350 +0,0 @@ -//===-- LinuxThread.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 - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Debugger.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "LinuxStopInfo.h" -#include "LinuxThread.h" -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" -#include "RegisterContextLinux_x86_64.h" -#include "UnwindLLDB.h" - -using namespace lldb_private; - - -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), - m_frame_ap(0) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid); -} - -LinuxThread::~LinuxThread() -{ - DestroyThread(); -} - -ProcessMonitor & -LinuxThread::GetMonitor() -{ - ProcessLinux &process = static_cast(GetProcess()); - return process.GetMonitor(); -} - -void -LinuxThread::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - ProcessLinux &process = static_cast(GetProcess()); - process.GetThreadList().RefreshStateAfterStop(); -} - -const char * -LinuxThread::GetInfo() -{ - return NULL; -} - -lldb::RegisterContextSP -LinuxThread::GetRegisterContext() -{ - if (!m_reg_context_sp) - { - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); - break; - - case ArchSpec::eCore_x86_64_x86_64: - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); - break; - } - } - return m_reg_context_sp; -} - -lldb::RegisterContextSP -LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else - { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -lldb::StopInfoSP -LinuxThread::GetPrivateStopReason() -{ - return m_stop_info; -} - -Unwind * -LinuxThread::GetUnwinder() -{ - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - - return m_unwinder_ap.get(); -} - -bool -LinuxThread::WillResume(lldb::StateType resume_state) -{ - SetResumeState(resume_state); - - ClearStackFrames(); - if (m_unwinder_ap.get()) - m_unwinder_ap->Clear(); - - return Thread::WillResume(resume_state); -} - -bool -LinuxThread::Resume() -{ - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - switch (resume_state) - { - default: - assert(false && "Unexpected state for resume!"); - status = false; - break; - - case lldb::eStateRunning: - SetState(resume_state); - status = monitor.Resume(GetID(), GetResumeSignal()); - break; - - case lldb::eStateStepping: - SetState(resume_state); - status = monitor.SingleStep(GetID(), GetResumeSignal()); - break; - } - - return status; -} - -void -LinuxThread::Notify(const ProcessMessage &message) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected message kind!"); - break; - - case ProcessMessage::eLimboMessage: - LimboNotify(message); - break; - - case ProcessMessage::eSignalMessage: - SignalNotify(message); - break; - - case ProcessMessage::eSignalDeliveredMessage: - SignalDeliveredNotify(message); - break; - - case ProcessMessage::eTraceMessage: - TraceNotify(message); - break; - - case ProcessMessage::eBreakpointMessage: - BreakNotify(message); - break; - - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; - } -} - -void -LinuxThread::BreakNotify(const ProcessMessage &message) -{ - bool status; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - - assert(GetRegisterContextLinux()); - status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); - assert(status && "Breakpoint update failed!"); - - // With our register state restored, resolve the breakpoint object - // corresponding to our current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); - assert(bp_site); - lldb::break_id_t bp_id = bp_site->GetID(); - assert(bp_site && bp_site->ValidForThisThread(this)); - - - m_breakpoint = bp_site; - m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); -} - -void -LinuxThread::TraceNotify(const ProcessMessage &message) -{ - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); -} - -void -LinuxThread::LimboNotify(const ProcessMessage &message) -{ - m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this)); -} - -void -LinuxThread::SignalNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); - SetResumeSignal(signo); -} - -void -LinuxThread::SignalDeliveredNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - // Just treat debugger generated signal events like breakpoints for now. - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); - SetResumeSignal(signo); -} - -void -LinuxThread::CrashNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); - - m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo( - *this, signo, message.GetCrashReason())); - SetResumeSignal(signo); -} - -unsigned -LinuxThread::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset); - break; - - case ArchSpec::eCore_x86_64_x86_64: - reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset); - break; - } - return reg; -} - -const char * -LinuxThread::GetRegisterName(unsigned reg) -{ - const char * name; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - name = RegisterContextLinux_i386::GetRegisterName(reg); - break; - - case ArchSpec::eCore_x86_64_x86_64: - name = RegisterContextLinux_x86_64::GetRegisterName(reg); - break; - } - return name; -} - -const char * -LinuxThread::GetRegisterNameFromOffset(unsigned offset) -{ - return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} - Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_i386.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h (working copy) @@ -1,169 +0,0 @@ -//===-- RegisterContextLinux_i386.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_RegisterContextLinux_i386_h_ -#define liblldb_RegisterContextLinux_i386_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Log.h" -#include "RegisterContextLinux.h" - -class RegisterContextLinux_i386 : public RegisterContextLinux -{ -public: - RegisterContextLinux_i386(lldb_private::Thread &thread, - uint32_t concreate_frame_idx); - - ~RegisterContextLinux_i386(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - -#if 0 - bool - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); - - bool - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); -#endif - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - -#if 0 - bool - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); - - bool - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, - uint32_t data_offset = 0); -#endif - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR - { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - uint32_t orig_ax; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; - }; - - struct MMSReg - { - uint8_t bytes[8]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint32_t ip; - uint32_t cs; - uint32_t foo; - uint32_t fos; - uint32_t mxcsr; - uint32_t reserved; - MMSReg stmm[8]; - XMMReg xmm[8]; - uint32_t pad[56]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - FPU i387; // FPU registers. - uint32_t tsize; // Text segment size. - uint32_t dsize; // Data segment size. - uint32_t ssize; // Stack segment size. - uint32_t start_code; // VM address of text. - uint32_t start_stack; // VM address of stack bottom (top in rsp). - int32_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - uint32_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint32_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). - }; -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - void LogGPR(const char *title); - - bool ReadGPR(); - bool ReadFPR(); -}; - -#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (working copy) @@ -1,759 +0,0 @@ -//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include -#include -#include - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_x86_64.h" - -using namespace lldb_private; -using namespace lldb; - -// Internal codes for all x86_64 registers. -enum -{ - k_first_gpr, - gpr_rax = k_first_gpr, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es, - k_last_gpr = gpr_es, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - k_last_fpr = fpu_xmm15, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum gcc_dwarf_regnums -{ - gcc_dwarf_gpr_rax = 0, - gcc_dwarf_gpr_rdx, - gcc_dwarf_gpr_rcx, - gcc_dwarf_gpr_rbx, - gcc_dwarf_gpr_rsi, - gcc_dwarf_gpr_rdi, - gcc_dwarf_gpr_rbp, - gcc_dwarf_gpr_rsp, - gcc_dwarf_gpr_r8, - gcc_dwarf_gpr_r9, - gcc_dwarf_gpr_r10, - gcc_dwarf_gpr_r11, - gcc_dwarf_gpr_r12, - gcc_dwarf_gpr_r13, - gcc_dwarf_gpr_r14, - gcc_dwarf_gpr_r15, - gcc_dwarf_gpr_rip, - gcc_dwarf_fpu_xmm0, - gcc_dwarf_fpu_xmm1, - gcc_dwarf_fpu_xmm2, - gcc_dwarf_fpu_xmm3, - gcc_dwarf_fpu_xmm4, - gcc_dwarf_fpu_xmm5, - gcc_dwarf_fpu_xmm6, - gcc_dwarf_fpu_xmm7, - gcc_dwarf_fpu_xmm8, - gcc_dwarf_fpu_xmm9, - gcc_dwarf_fpu_xmm10, - gcc_dwarf_fpu_xmm11, - gcc_dwarf_fpu_xmm12, - gcc_dwarf_fpu_xmm13, - gcc_dwarf_fpu_xmm14, - gcc_dwarf_fpu_xmm15, - gcc_dwarf_fpu_stmm0, - gcc_dwarf_fpu_stmm1, - gcc_dwarf_fpu_stmm2, - gcc_dwarf_fpu_stmm3, - gcc_dwarf_fpu_stmm4, - gcc_dwarf_fpu_stmm5, - gcc_dwarf_fpu_stmm6, - gcc_dwarf_fpu_stmm7 -}; - -enum gdb_regnums -{ - gdb_gpr_rax = 0, - gdb_gpr_rbx = 1, - gdb_gpr_rcx = 2, - gdb_gpr_rdx = 3, - gdb_gpr_rsi = 4, - gdb_gpr_rdi = 5, - gdb_gpr_rbp = 6, - gdb_gpr_rsp = 7, - gdb_gpr_r8 = 8, - gdb_gpr_r9 = 9, - gdb_gpr_r10 = 10, - gdb_gpr_r11 = 11, - gdb_gpr_r12 = 12, - gdb_gpr_r13 = 13, - gdb_gpr_r14 = 14, - gdb_gpr_r15 = 15, - gdb_gpr_rip = 16, - gdb_gpr_rflags = 17, - gdb_gpr_cs = 18, - gdb_gpr_ss = 19, - gdb_gpr_ds = 20, - gdb_gpr_es = 21, - gdb_gpr_fs = 22, - gdb_gpr_gs = 23, - gdb_fpu_stmm0 = 24, - gdb_fpu_stmm1 = 25, - gdb_fpu_stmm2 = 26, - gdb_fpu_stmm3 = 27, - gdb_fpu_stmm4 = 28, - gdb_fpu_stmm5 = 29, - gdb_fpu_stmm6 = 30, - gdb_fpu_stmm7 = 31, - gdb_fpu_fcw = 32, - gdb_fpu_fsw = 33, - gdb_fpu_ftw = 34, - gdb_fpu_cs = 35, - gdb_fpu_ip = 36, - gdb_fpu_ds = 37, - gdb_fpu_dp = 38, - gdb_fpu_fop = 39, - gdb_fpu_xmm0 = 40, - gdb_fpu_xmm1 = 41, - gdb_fpu_xmm2 = 42, - gdb_fpu_xmm3 = 43, - gdb_fpu_xmm4 = 44, - gdb_fpu_xmm5 = 45, - gdb_fpu_xmm6 = 46, - gdb_fpu_xmm7 = 47, - gdb_fpu_xmm8 = 48, - gdb_fpu_xmm9 = 49, - gdb_fpu_xmm10 = 50, - gdb_fpu_xmm11 = 51, - gdb_fpu_xmm12 = 52, - gdb_fpu_xmm13 = 53, - gdb_fpu_xmm14 = 54, - gdb_fpu_xmm15 = 55, - gdb_fpu_mxcsr = 56 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \ - offsetof(RegisterContextLinux_x86_64::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \ - offsetof(RegisterContextLinux_x86_64::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU)) - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), - - // i387 Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), - // FIXME: Extract segment from ip. - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), - // FIXME: Extract segment from dp. - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - // FP registers. - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), - DEFINE_XMM(xmm, 15) -}; - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not being used. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() -{ -} - -ProcessMonitor & -RegisterContextLinux_x86_64::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_x86_64::Invalidate() -{ -} - -void -RegisterContextLinux_x86_64::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_x86_64::GetRegisterCount() -{ - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg) -{ - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_x86_64::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_x86_64::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &user.regs, sizeof(user.regs)); - dst += sizeof(user.regs); - - ::memcpy (dst, &user.i387, sizeof(user.i387)); - return true; - } - return false; -} - -bool -RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&user.regs, src, sizeof(user.regs)); - src += sizeof(user.regs); - - ::memcpy (&user.i387, src, sizeof(user.i387)); - return WriteGPR() & WriteFPR(); - } - return false; -} - -bool -RegisterContextLinux_x86_64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case gcc_dwarf_gpr_rax: return gpr_rax; - case gcc_dwarf_gpr_rdx: return gpr_rdx; - case gcc_dwarf_gpr_rcx: return gpr_rcx; - case gcc_dwarf_gpr_rbx: return gpr_rbx; - case gcc_dwarf_gpr_rsi: return gpr_rsi; - case gcc_dwarf_gpr_rdi: return gpr_rdi; - case gcc_dwarf_gpr_rbp: return gpr_rbp; - case gcc_dwarf_gpr_rsp: return gpr_rsp; - case gcc_dwarf_gpr_r8: return gpr_r8; - case gcc_dwarf_gpr_r9: return gpr_r9; - case gcc_dwarf_gpr_r10: return gpr_r10; - case gcc_dwarf_gpr_r11: return gpr_r11; - case gcc_dwarf_gpr_r12: return gpr_r12; - case gcc_dwarf_gpr_r13: return gpr_r13; - case gcc_dwarf_gpr_r14: return gpr_r14; - case gcc_dwarf_gpr_r15: return gpr_r15; - case gcc_dwarf_gpr_rip: return gpr_rip; - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_gpr_rax : return gpr_rax; - case gdb_gpr_rbx : return gpr_rbx; - case gdb_gpr_rcx : return gpr_rcx; - case gdb_gpr_rdx : return gpr_rdx; - case gdb_gpr_rsi : return gpr_rsi; - case gdb_gpr_rdi : return gpr_rdi; - case gdb_gpr_rbp : return gpr_rbp; - case gdb_gpr_rsp : return gpr_rsp; - case gdb_gpr_r8 : return gpr_r8; - case gdb_gpr_r9 : return gpr_r9; - case gdb_gpr_r10 : return gpr_r10; - case gdb_gpr_r11 : return gpr_r11; - case gdb_gpr_r12 : return gpr_r12; - case gdb_gpr_r13 : return gpr_r13; - case gdb_gpr_r14 : return gpr_r14; - case gdb_gpr_r15 : return gpr_r15; - case gdb_gpr_rip : return gpr_rip; - case gdb_gpr_rflags : return gpr_rflags; - case gdb_gpr_cs : return gpr_cs; - case gdb_gpr_ss : return gpr_ss; - case gdb_gpr_ds : return gpr_ds; - case gdb_gpr_es : return gpr_es; - case gdb_gpr_fs : return gpr_fs; - case gdb_gpr_gs : return gpr_gs; - case gdb_fpu_stmm0 : return fpu_stmm0; - case gdb_fpu_stmm1 : return fpu_stmm1; - case gdb_fpu_stmm2 : return fpu_stmm2; - case gdb_fpu_stmm3 : return fpu_stmm3; - case gdb_fpu_stmm4 : return fpu_stmm4; - case gdb_fpu_stmm5 : return fpu_stmm5; - case gdb_fpu_stmm6 : return fpu_stmm6; - case gdb_fpu_stmm7 : return fpu_stmm7; - case gdb_fpu_fcw : return fpu_fcw; - case gdb_fpu_fsw : return fpu_fsw; - case gdb_fpu_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_fpu_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_ds; - case gdb_fpu_dp : return fpu_dp; - case gdb_fpu_fop : return fpu_fop; - case gdb_fpu_xmm0 : return fpu_xmm0; - case gdb_fpu_xmm1 : return fpu_xmm1; - case gdb_fpu_xmm2 : return fpu_xmm2; - case gdb_fpu_xmm3 : return fpu_xmm3; - case gdb_fpu_xmm4 : return fpu_xmm4; - case gdb_fpu_xmm5 : return fpu_xmm5; - case gdb_fpu_xmm6 : return fpu_xmm6; - case gdb_fpu_xmm7 : return fpu_xmm7; - case gdb_fpu_xmm8 : return fpu_xmm8; - case gdb_fpu_xmm9 : return fpu_xmm9; - case gdb_fpu_xmm10 : return fpu_xmm10; - case gdb_fpu_xmm11 : return fpu_xmm11; - case gdb_fpu_xmm12 : return fpu_xmm12; - case gdb_fpu_xmm13 : return fpu_xmm13; - case gdb_fpu_xmm14 : return fpu_xmm14; - case gdb_fpu_xmm15 : return fpu_xmm15; - case gdb_fpu_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_x86_64::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; - - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (rflags & TRACE_BIT) - return true; - - rflags |= TRACE_BIT; - } - else - { - if (!(rflags & TRACE_BIT)) - return false; - - rflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_rflags, rflags); -} - -bool -RegisterContextLinux_x86_64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} - -bool -RegisterContextLinux_x86_64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(&user.i387); -} Index: source/Plugins/Process/Linux/ProcessMessage.h =================================================================== --- source/Plugins/Process/Linux/ProcessMessage.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessMessage.h (working copy) @@ -1,171 +0,0 @@ -//===-- ProcessMessage.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_ProcessMessage_H_ -#define liblldb_ProcessMessage_H_ - -#include - -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -class ProcessMessage -{ -public: - - /// The type of signal this message can correspond to. - enum Kind - { - eInvalidMessage, - eExitMessage, - eLimboMessage, - eSignalMessage, - eSignalDeliveredMessage, - eTraceMessage, - eBreakpointMessage, - eCrashMessage - }; - - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - - ProcessMessage() - : m_tid(LLDB_INVALID_PROCESS_ID), - m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), - m_status(0), - m_addr(0) { } - - Kind GetKind() const { return m_kind; } - - lldb::tid_t GetTID() const { return m_tid; } - - /// Indicates that the thread @p tid is about to exit with status @p status. - static ProcessMessage Limbo(lldb::tid_t tid, int status) { - return ProcessMessage(tid, eLimboMessage, status); - } - - /// Indicates that the thread @p tid had the signal @p signum delivered. - static ProcessMessage Signal(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalMessage, signum); - } - - /// Indicates that a signal @p signum generated by the debugging process was - /// delivered to the thread @p tid. - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalDeliveredMessage, signum); - } - - /// Indicates that the thread @p tid encountered a trace point. - static ProcessMessage Trace(lldb::tid_t tid) { - return ProcessMessage(tid, eTraceMessage); - } - - /// Indicates that the thread @p tid encountered a break point. - static ProcessMessage Break(lldb::tid_t tid) { - return ProcessMessage(tid, eBreakpointMessage); - } - - /// Indicates that the thread @p tid crashed. - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, - int signo, lldb::addr_t fault_addr) { - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); - message.m_crash_reason = reason; - return message; - } - - int GetExitStatus() const { - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); - return m_status; - } - - int GetSignal() const { - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || - GetKind() == eSignalDeliveredMessage); - return m_status; - } - - int GetStopStatus() const { - assert(GetKind() == eSignalMessage); - return m_status; - } - - CrashReason GetCrashReason() const { - assert(GetKind() == eCrashMessage); - return m_crash_reason; - } - - lldb::addr_t GetFaultAddress() const { - assert(GetKind() == eCrashMessage); - return m_addr; - } - - static const char * - GetCrashReasonString(CrashReason reason); - - const char * - PrintCrashReason() const; - - static const char * - PrintCrashReason(CrashReason reason); - - const char * - PrintKind() const; - - static const char * - PrintKind(Kind); - -private: - ProcessMessage(lldb::tid_t tid, Kind kind, - int status = 0, lldb::addr_t addr = 0) - : m_tid(tid), - m_kind(kind), - m_crash_reason(eInvalidCrashReason), - m_status(status), - m_addr(addr) { } - - lldb::tid_t m_tid; - Kind m_kind : 8; - CrashReason m_crash_reason : 8; - int m_status; - lldb::addr_t m_addr; -}; - -#endif // #ifndef liblldb_ProcessMessage_H_ Index: source/Plugins/Process/Linux/ProcessMonitor.h =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy) @@ -24,10 +24,12 @@ class Error; class Module; class Scalar; + } // End lldb_private namespace. class ProcessLinux; class Operation; +class ProcessPOSIX; /// @class ProcessMonitor /// @brief Manages communication with the inferior (debugee) process. @@ -47,7 +49,7 @@ /// Launches an inferior process ready for debugging. Forms the /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb_private::Module *module, char const *argv[], char const *envp[], @@ -56,7 +58,7 @@ const char *stderr_path, lldb_private::Error &error); - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error); @@ -104,7 +106,7 @@ /// /// This method is provided for use by RegisterContextLinux derivatives. bool - ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value); + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); /// Writes the given value to the register identified by the given /// (architecture dependent) offset. Index: source/Plugins/Process/Linux/Makefile =================================================================== --- source/Plugins/Process/Linux/Makefile (revision 147560) +++ source/Plugins/Process/Linux/Makefile (working copy) @@ -12,6 +12,6 @@ BUILD_ARCHIVE = 1 # Extend the include path so we may locate UnwindLLDB.h -CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/Linux/LinuxThread.h =================================================================== --- source/Plugins/Process/Linux/LinuxThread.h (revision 147560) +++ source/Plugins/Process/Linux/LinuxThread.h (working copy) @@ -1,102 +0,0 @@ -//===-- LinuxThread.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_LinuxThread_H_ -#define liblldb_LinuxThread_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/Target/Thread.h" - -class ProcessMessage; -class ProcessMonitor; -class RegisterContextLinux; - -//------------------------------------------------------------------------------ -// @class LinuxThread -// @brief Abstraction of a linux process (thread). -class LinuxThread - : public lldb_private::Thread -{ -public: - LinuxThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~LinuxThread(); - - void - RefreshStateAfterStop(); - - bool - WillResume(lldb::StateType resume_state); - - const char * - GetInfo(); - - virtual lldb::RegisterContextSP - GetRegisterContext(); - - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - - //-------------------------------------------------------------------------- - // These static functions provide a mapping from the register offset - // back to the register index or name for use in debugging or log - // output. - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - static const char * - GetRegisterNameFromOffset(unsigned offset); - - //-------------------------------------------------------------------------- - // These methods form a specialized interface to linux threads. - // - bool Resume(); - - void Notify(const ProcessMessage &message); - -private: - RegisterContextLinux * - GetRegisterContextLinux () - { - if (!m_reg_context_sp) - GetRegisterContext(); - return (RegisterContextLinux *)m_reg_context_sp.get(); - } - - std::auto_ptr m_frame_ap; - - lldb::BreakpointSiteSP m_breakpoint; - lldb::StopInfoSP m_stop_info; - - ProcessMonitor & - GetMonitor(); - - lldb::StopInfoSP - GetPrivateStopReason(); - - void BreakNotify(const ProcessMessage &message); - void TraceNotify(const ProcessMessage &message); - void LimboNotify(const ProcessMessage &message); - void SignalNotify(const ProcessMessage &message); - void SignalDeliveredNotify(const ProcessMessage &message); - void CrashNotify(const ProcessMessage &message); - - lldb_private::Unwind * - GetUnwinder(); -}; - -#endif // #ifndef liblldb_LinuxThread_H_ Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (working copy) @@ -10,67 +10,7 @@ #ifndef liblldb_RegisterContextLinux_x86_64_H_ #define liblldb_RegisterContextLinux_x86_64_H_ -#include "RegisterContextLinux.h" - -class ProcessMonitor; - -class RegisterContextLinux_x86_64 - : public RegisterContextLinux -{ -public: - RegisterContextLinux_x86_64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContextLinux_x86_64(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR + typedef struct _GPR { uint64_t r15; uint64_t r14; @@ -99,67 +39,6 @@ uint64_t es; uint64_t fs; uint64_t gs; - }; + } GPR; - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint64_t ip; - uint64_t dp; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[16]; - uint32_t padding[24]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - int32_t pad0; - FPU i387; // FPU registers. - uint64_t tsize; // Text segment size. - uint64_t dsize; // Data segment size. - uint64_t ssize; // Stack segment size. - uint64_t start_code; // VM address of text. - uint64_t start_stack; // VM address of stack bottom (top in rsp). - int64_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - int32_t pad1; - uint64_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint64_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). - uint64_t error_code; // CPU error code. - uint64_t fault_address; // Control register CR3. - }; - -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - bool ReadGPR(); - bool ReadFPR(); - - bool WriteGPR(); - bool WriteFPR(); -}; - -#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_ +#endif Index: source/Plugins/Process/POSIX/POSIXThread.h =================================================================== --- source/Plugins/Process/POSIX/POSIXThread.h (revision 0) +++ source/Plugins/Process/POSIX/POSIXThread.h (revision 0) @@ -0,0 +1,106 @@ +//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_POSIXThread_H_ +#define liblldb_POSIXThread_H_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIX.h" + +class ProcessMessage; +class ProcessMonitor; +class RegisterContextPOSIX; + +//------------------------------------------------------------------------------ +// @class POSIXThread +// @brief Abstraction of a linux process (thread). +class POSIXThread + : public lldb_private::Thread +{ +public: + POSIXThread(lldb_private::Process &process, lldb::tid_t tid); + + virtual ~POSIXThread(); + + void + RefreshStateAfterStop(); + + bool + WillResume(lldb::StateType resume_state); + + const char * + GetInfo(); + + virtual lldb::RegisterContextSP + GetRegisterContext(); + + virtual lldb::RegisterContextSP + CreateRegisterContextForFrame (lldb_private::StackFrame *frame); + + //-------------------------------------------------------------------------- + // These static functions provide a mapping from the register offset + // back to the register index or name for use in debugging or log + // output. + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + static const char * + GetRegisterNameFromOffset(unsigned offset); + + //-------------------------------------------------------------------------- + // These methods form a specialized interface to linux threads. + // + bool Resume(); + + void Notify(const ProcessMessage &message); + +private: + RegisterContextPOSIX * + GetRegisterContextPOSIX () + { + if (!m_reg_context_sp) + m_reg_context_sp = GetRegisterContext(); +#if 0 + return dynamic_cast(m_reg_context_sp.get()); +#endif + return (RegisterContextPOSIX *)m_reg_context_sp.get(); + } + + std::auto_ptr m_frame_ap; + + lldb::BreakpointSiteSP m_breakpoint; + lldb::StopInfoSP m_stop_info; + + ProcessMonitor & + GetMonitor(); + + lldb::StopInfoSP + GetPrivateStopReason(); + + void BreakNotify(const ProcessMessage &message); + void TraceNotify(const ProcessMessage &message); + void LimboNotify(const ProcessMessage &message); + void SignalNotify(const ProcessMessage &message); + void SignalDeliveredNotify(const ProcessMessage &message); + void CrashNotify(const ProcessMessage &message); + + lldb_private::Unwind * + GetUnwinder(); +}; + +#endif // #ifndef liblldb_POSIXThread_H_ Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) @@ -0,0 +1,594 @@ +//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Target.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "ProcessMonitor.h" +#include "POSIXThread.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------------ +// Static functions. +#if 0 +Process* +ProcessPOSIX::CreateInstance(Target& target, Listener &listener) +{ + return new ProcessPOSIX(target, listener); +} + + +void +ProcessPOSIX::Initialize() +{ + static bool g_initialized = false; + + if (!g_initialized) + { + g_initialized = true; + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + + Log::Callbacks log_callbacks = { + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories + }; + + Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks); + } +} +#endif + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) + : Process(target, listener), + m_monitor(NULL), + m_module(NULL), + m_in_limbo(false), + m_exit_now(false) +{ + // FIXME: Putting this code in the ctor and saving the byte order in a + // member variable is a hack to avoid const qual issues in GetByteOrder. + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); + m_byte_order = obj_file->GetByteOrder(); +} + +ProcessPOSIX::~ProcessPOSIX() +{ + delete m_monitor; +} + +//------------------------------------------------------------------------------ +// Process protocol. + +bool +ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) +{ + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target.GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + return false; +} + +Error +ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid) +{ + Error error; + assert(m_monitor == NULL); + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID()); + + m_monitor = new ProcessMonitor(this, pid, error); + + if (!error.Success()) + return error; + + SetID(pid); + return error; +} + +Error +ProcessPOSIX::WillLaunch(Module* module) +{ + Error error; + return error; +} + +const char * +ProcessPOSIX::GetFilePath( + const lldb_private::ProcessLaunchInfo::FileAction *file_action, + const char *default_path) +{ + const char *pts_name = "/dev/pts/"; + const char *path = NULL; + + if (file_action) + { + if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) + path = file_action->GetPath(); + // By default the stdio paths passed in will be pseudo-terminal + // (/dev/pts). If so, convert to using a different default path + // instead to redirect I/O to the debugger console. This should + // also handle user overrides to /dev/null or a different file. + if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0) + path = default_path; + } + + return path; +} + +Error +ProcessPOSIX::DoLaunch (Module *module, + const ProcessLaunchInfo &launch_info) +{ + Error error; + assert(m_monitor == NULL); + + SetPrivateState(eStateLaunching); + + const lldb_private::ProcessLaunchInfo::FileAction *file_action; + + // Default of NULL will mean to use existing open file descriptors + const char *stdin_path = NULL; + const char *stdout_path = NULL; + const char *stderr_path = NULL; + + file_action = launch_info.GetFileActionForFD (STDIN_FILENO); + stdin_path = GetFilePath(file_action, stdin_path); + + file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); + stdout_path = GetFilePath(file_action, stdout_path); + + file_action = launch_info.GetFileActionForFD (STDERR_FILENO); + stderr_path = GetFilePath(file_action, stderr_path); + + m_monitor = new ProcessMonitor (this, + module, + launch_info.GetArguments().GetConstArgumentVector(), + launch_info.GetEnvironmentEntries().GetConstArgumentVector(), + stdin_path, + stdout_path, + stderr_path, + error); + + m_module = module; + + if (!error.Success()) + return error; + + SetID(m_monitor->GetPID()); + return error; +} + +void +ProcessPOSIX::DidLaunch() +{ +} + +Error +ProcessPOSIX::DoResume() +{ + StateType state = GetPrivateState(); + + assert(state == eStateStopped || state == eStateCrashed); + + // We are about to resume a thread that will cause the process to exit so + // set our exit status now. Do not change our state if the inferior + // crashed. + if (state == eStateStopped) + { + if (m_in_limbo) + SetExitStatus(m_exit_status, NULL); + else + SetPrivateState(eStateRunning); + } + + bool did_resume = false; + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) + { + POSIXThread *thread = static_cast( + m_thread_list.GetThreadAtIndex(i, false).get()); + did_resume = thread->Resume() || did_resume; + } + assert(did_resume && "Process resume failed!"); + + return Error(); +} + +addr_t +ProcessPOSIX::GetImageInfoAddress() +{ + Target *target = &GetTarget(); + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(); + + if (addr.IsValid()) + return addr.GetLoadAddress(target); + else + return LLDB_INVALID_ADDRESS; +} + +Error +ProcessPOSIX::DoHalt(bool &caused_stop) +{ + Error error; + + if (IsStopped()) + { + caused_stop = false; + } + else if (kill(GetID(), SIGSTOP)) + { + caused_stop = false; + error.SetErrorToErrno(); + } + else + { + caused_stop = true; + } + + return error; +} + +Error +ProcessPOSIX::DoDetach() +{ + Error error; + + error = m_monitor->Detach(); + if (error.Success()) + SetPrivateState(eStateDetached); + + return error; +} + +Error +ProcessPOSIX::DoSignal(int signal) +{ + Error error; + + if (kill(GetID(), signal)) + error.SetErrorToErrno(); + + return error; +} + +Error +ProcessPOSIX::DoDestroy() +{ + Error error; + + if (!HasExited()) + { + // Drive the exit event to completion (do not keep the inferior in + // limbo). + m_exit_now = true; + + if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) + { + error.SetErrorToErrno(); + return error; + } + + SetPrivateState(eStateExited); + } + + return error; +} + +void +ProcessPOSIX::SendMessage(const ProcessMessage &message) +{ + Mutex::Locker lock(m_message_mutex); + + switch (message.GetKind()) + { + default: + assert(false && "Unexpected process message!"); + break; + + case ProcessMessage::eInvalidMessage: + return; + + case ProcessMessage::eLimboMessage: + m_in_limbo = true; + m_exit_status = message.GetExitStatus(); + if (m_exit_now) + { + SetPrivateState(eStateExited); + m_monitor->Detach(); + } + else + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eExitMessage: + m_exit_status = message.GetExitStatus(); + SetExitStatus(m_exit_status, NULL); + break; + + case ProcessMessage::eTraceMessage: + case ProcessMessage::eBreakpointMessage: + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eSignalMessage: + case ProcessMessage::eSignalDeliveredMessage: + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eCrashMessage: + SetPrivateState(eStateCrashed); + break; + } + + m_message_queue.push(message); +} + +void +ProcessPOSIX::RefreshStateAfterStop() +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s()", __FUNCTION__); + + Mutex::Locker lock(m_message_mutex); + if (m_message_queue.empty()) + return; + + ProcessMessage &message = m_message_queue.front(); + + // Resolve the thread this message corresponds to and pass it along. + // FIXME: we're really dealing with the pid here. This should get + // fixed when this code is fixed to handle multiple threads. + lldb::tid_t tid = message.GetTID(); + if (log) + log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid); + POSIXThread *thread = static_cast( + GetThreadList().FindThreadByID(tid, false).get()); + + assert(thread); + thread->Notify(message); + + m_message_queue.pop(); +} + +bool +ProcessPOSIX::IsAlive() +{ + StateType state = GetPrivateState(); + return state != eStateDetached && state != eStateExited && state != eStateInvalid; +} + +size_t +ProcessPOSIX::DoReadMemory(addr_t vm_addr, + void *buf, size_t size, Error &error) +{ + assert(m_monitor); + return m_monitor->ReadMemory(vm_addr, buf, size, error); +} + +size_t +ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, + Error &error) +{ + assert(m_monitor); + return m_monitor->WriteMemory(vm_addr, buf, size, error); +} + +addr_t +ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) +{ + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { + m_addr_to_mmap_size[allocated_addr] = size; + error.Clear(); + } else { + allocated_addr = LLDB_INVALID_ADDRESS; + error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); + } + + return allocated_addr; +} + +Error +ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) +{ + Error error; + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); + if (pos != m_addr_to_mmap_size.end() && + InferiorCallMunmap(this, addr, pos->second)) + m_addr_to_mmap_size.erase (pos); + else + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); + + return error; +} + +size_t +ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) +{ + static const uint8_t g_i386_opcode[] = { 0xCC }; + + ArchSpec arch = GetTarget().GetArchitecture(); + const uint8_t *opcode = NULL; + size_t opcode_size = 0; + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_64_x86_64: + opcode = g_i386_opcode; + opcode_size = sizeof(g_i386_opcode); + break; + } + + bp_site->SetTrapOpcode(opcode, opcode_size); + return opcode_size; +} + +Error +ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site) +{ + return EnableSoftwareBreakpoint(bp_site); +} + +Error +ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site) +{ + return DisableSoftwareBreakpoint(bp_site); +} + +uint32_t +ProcessPOSIX::UpdateThreadListIfNeeded() +{ + // Do not allow recursive updates. + return m_thread_list.GetSize(false); +} + +uint32_t +ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID()); + + // Update the process thread list with this new thread. + // FIXME: We should be using tid, not pid. + assert(m_monitor); + ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); + if (!thread_sp) + thread_sp.reset(new POSIXThread(*this, GetID())); + + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID()); + new_thread_list.AddThread(thread_sp); + + return new_thread_list.GetSize(false); +} + +ByteOrder +ProcessPOSIX::GetByteOrder() const +{ + // FIXME: We should be able to extract this value directly. See comment in + // ProcessPOSIX(). + return m_byte_order; +} + +size_t +ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) +{ + ssize_t status; + if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) + { + error.SetErrorToErrno(); + return 0; + } + return status; +} + +size_t +ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error) +{ + ssize_t bytes_read; + + // The terminal file descriptor is always in non-block mode. + if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) + { + if (errno != EAGAIN) + error.SetErrorToErrno(); + return 0; + } + return bytes_read; +} + +size_t +ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error) +{ + return GetSTDOUT(buf, len, error); +} + +UnixSignals & +ProcessPOSIX::GetUnixSignals() +{ + return m_signals; +} + +//------------------------------------------------------------------------------ +// Utility functions. + +bool +ProcessPOSIX::HasExited() +{ + switch (GetPrivateState()) + { + default: + break; + + case eStateDetached: + case eStateExited: + return true; + } + + return false; +} + +bool +ProcessPOSIX::IsStopped() +{ + switch (GetPrivateState()) + { + default: + break; + + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + return true; + } + + return false; +} Index: source/Plugins/Process/POSIX/RegisterContext_i386.cpp =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) @@ -0,0 +1,643 @@ +//===-- RegisterContextPOSIX_i386.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/Core/DataExtractor.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContext_i386.h" + +using namespace lldb_private; +using namespace lldb; + +enum +{ + k_first_gpr, + gpr_eax = k_first_gpr, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_ss, + gpr_eflags, +#ifdef __FreeBSD__ + gpr_orig_ax, +#endif + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, + k_last_gpr = gpr_gs, + + k_first_fpr, + fpu_fcw = k_first_fpr, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_foo, + fpu_fos, + fpu_mxcsr, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + k_last_fpr = fpu_xmm7, + + k_num_registers, + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +enum +{ + gcc_eax = 0, + gcc_ecx, + gcc_edx, + gcc_ebx, + gcc_ebp, + gcc_esp, + gcc_esi, + gcc_edi, + gcc_eip, + gcc_eflags +}; + +enum +{ + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + dwarf_stmm0 = 11, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7 +}; + +enum +{ + gdb_eax = 0, + gdb_ecx = 1, + gdb_edx = 2, + gdb_ebx = 3, + gdb_esp = 4, + gdb_ebp = 5, + gdb_esi = 6, + gdb_edi = 7, + gdb_eip = 8, + gdb_eflags = 9, + gdb_cs = 10, + gdb_ss = 11, + gdb_ds = 12, + gdb_es = 13, + gdb_fs = 14, + gdb_gs = 15, + gdb_stmm0 = 16, + gdb_stmm1 = 17, + gdb_stmm2 = 18, + gdb_stmm3 = 19, + gdb_stmm4 = 20, + gdb_stmm5 = 21, + gdb_stmm6 = 22, + gdb_stmm7 = 23, + gdb_fcw = 24, + gdb_fsw = 25, + gdb_ftw = 26, + gdb_fpu_cs = 27, + gdb_ip = 28, + gdb_fpu_ds = 29, + gdb_dp = 30, + gdb_fop = 31, + gdb_xmm0 = 32, + gdb_xmm1 = 33, + gdb_xmm2 = 34, + gdb_xmm3 = 35, + gdb_xmm4 = 36, + gdb_xmm5 = 37, + gdb_xmm6 = 38, + gdb_xmm7 = 39, + gdb_mxcsr = 40, + gdb_mm0 = 41, + gdb_mm1 = 42, + gdb_mm2 = 43, + gdb_mm3 = 44, + gdb_mm4 = 45, + gdb_mm5 = 46, + gdb_mm6 = 47, + gdb_mm7 = 48 +}; + +static const +uint32_t g_gpr_regnums[k_num_gpr_registers] = +{ + gpr_eax, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_ss, + gpr_eflags, +#ifdef __FreeBSD__ + gpr_orig_ax, +#endif + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, +}; + +static const uint32_t +g_fpu_regnums[k_num_fpu_registers] = +{ + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_foo, + fpu_fos, + fpu_mxcsr, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, +}; + +static const RegisterSet +g_reg_sets[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } +}; + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (offsetof(RegisterContext_i386::UserArea, regs) + \ + offsetof(RegisterContext_i386::GPR, regname)) + +// Computes the offset of the given FPR in the user data area. +#define FPR_OFFSET(regname) \ + (offsetof(RegisterContext_i386::UserArea, i387) + \ + offsetof(RegisterContext_i386::FPU, regname)) + +// Number of bytes needed to represent a GPR. +#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } + +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } + +#define DEFINE_FP(reg, i) \ + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { dwarf_##reg##i, dwarf_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { dwarf_##reg##i, dwarf_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } + +static RegisterInfo +g_register_infos[k_num_registers] = +{ + // General purpose registers. + DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), + DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), + DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), + DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), + DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), + DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), + DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), + DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), + DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), + DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), + + // Floating point registers. + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), + DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), + DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), + DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), + + DEFINE_FP(stmm, 0), + DEFINE_FP(stmm, 1), + DEFINE_FP(stmm, 2), + DEFINE_FP(stmm, 3), + DEFINE_FP(stmm, 4), + DEFINE_FP(stmm, 5), + DEFINE_FP(stmm, 6), + DEFINE_FP(stmm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + +}; + +#ifndef NDEBUG +static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); +#endif + +static unsigned GetRegOffset(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_offset; +} + +static unsigned GetRegSize(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_size; +} + +RegisterContext_i386::RegisterContext_i386(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextPOSIX(thread, concrete_frame_idx) +{ +} + +RegisterContext_i386::~RegisterContext_i386() +{ +} + +ProcessMonitor & +RegisterContext_i386::GetMonitor() +{ + ProcessPOSIX *process = static_cast(CalculateProcess()); + return process->GetMonitor(); +} + +void +RegisterContext_i386::Invalidate() +{ +} + +void +RegisterContext_i386::InvalidateAllRegisters() +{ +} + +size_t +RegisterContext_i386::GetRegisterCount() +{ + assert(k_num_register_infos == k_num_registers); + return k_num_registers; +} + +const RegisterInfo * +RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg) +{ + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos[reg]; + else + return NULL; +} + +size_t +RegisterContext_i386::GetRegisterSetCount() +{ + return k_num_register_sets; +} + +const RegisterSet * +RegisterContext_i386::GetRegisterSet(uint32_t set) +{ + if (set < k_num_register_sets) + return &g_reg_sets[set]; + else + return NULL; +} + +unsigned +RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < k_num_registers; reg++) + { + if (g_register_infos[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers && "Invalid register offset."); + return reg; +} + +const char * +RegisterContext_i386::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register offset."); + return g_register_infos[reg].name; +} + +bool +RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); +} + +bool +RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + return false; +} + +bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(GetRegOffset(reg), value); +} + +bool +RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data) +{ + return false; +} + +bool +RegisterContext_i386::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +uint32_t +RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + if (kind == eRegisterKindGeneric) + { + switch (num) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_eip; + case LLDB_REGNUM_GENERIC_SP: return gpr_esp; + case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; + case LLDB_REGNUM_GENERIC_RA: + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) + { + switch (num) + { + case dwarf_eax: return gpr_eax; + case dwarf_edx: return gpr_edx; + case dwarf_ecx: return gpr_ecx; + case dwarf_ebx: return gpr_ebx; + case dwarf_esi: return gpr_esi; + case dwarf_edi: return gpr_edi; + case dwarf_ebp: return gpr_ebp; + case dwarf_esp: return gpr_esp; + case dwarf_eip: return gpr_eip; + case dwarf_xmm0: return fpu_xmm0; + case dwarf_xmm1: return fpu_xmm1; + case dwarf_xmm2: return fpu_xmm2; + case dwarf_xmm3: return fpu_xmm3; + case dwarf_xmm4: return fpu_xmm4; + case dwarf_xmm5: return fpu_xmm5; + case dwarf_xmm6: return fpu_xmm6; + case dwarf_xmm7: return fpu_xmm7; + case dwarf_stmm0: return fpu_stmm0; + case dwarf_stmm1: return fpu_stmm1; + case dwarf_stmm2: return fpu_stmm2; + case dwarf_stmm3: return fpu_stmm3; + case dwarf_stmm4: return fpu_stmm4; + case dwarf_stmm5: return fpu_stmm5; + case dwarf_stmm6: return fpu_stmm6; + case dwarf_stmm7: return fpu_stmm7; + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGDB) + { + switch (num) + { + case gdb_eax : return gpr_eax; + case gdb_ebx : return gpr_ebx; + case gdb_ecx : return gpr_ecx; + case gdb_edx : return gpr_edx; + case gdb_esi : return gpr_esi; + case gdb_edi : return gpr_edi; + case gdb_ebp : return gpr_ebp; + case gdb_esp : return gpr_esp; + case gdb_eip : return gpr_eip; + case gdb_eflags : return gpr_eflags; + case gdb_cs : return gpr_cs; + case gdb_ss : return gpr_ss; + case gdb_ds : return gpr_ds; + case gdb_es : return gpr_es; + case gdb_fs : return gpr_fs; + case gdb_gs : return gpr_gs; + case gdb_stmm0 : return fpu_stmm0; + case gdb_stmm1 : return fpu_stmm1; + case gdb_stmm2 : return fpu_stmm2; + case gdb_stmm3 : return fpu_stmm3; + case gdb_stmm4 : return fpu_stmm4; + case gdb_stmm5 : return fpu_stmm5; + case gdb_stmm6 : return fpu_stmm6; + case gdb_stmm7 : return fpu_stmm7; + case gdb_fcw : return fpu_fcw; + case gdb_fsw : return fpu_fsw; + case gdb_ftw : return fpu_ftw; + case gdb_fpu_cs : return fpu_cs; + case gdb_ip : return fpu_ip; + case gdb_fpu_ds : return fpu_fos; + case gdb_dp : return fpu_foo; + case gdb_fop : return fpu_fop; + case gdb_xmm0 : return fpu_xmm0; + case gdb_xmm1 : return fpu_xmm1; + case gdb_xmm2 : return fpu_xmm2; + case gdb_xmm3 : return fpu_xmm3; + case gdb_xmm4 : return fpu_xmm4; + case gdb_xmm5 : return fpu_xmm5; + case gdb_xmm6 : return fpu_xmm6; + case gdb_xmm7 : return fpu_xmm7; + case gdb_mxcsr : return fpu_mxcsr; + default: + return LLDB_INVALID_REGNUM; + } + } + else if (kind == eRegisterKindLLDB) + { + return num; + } + + return LLDB_INVALID_REGNUM; +} + +bool +RegisterContext_i386::HardwareSingleStep(bool enable) +{ + enum { TRACE_BIT = 0x100 }; + uint64_t eflags; + + if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) + return false; + + if (enable) + { + if (eflags & TRACE_BIT) + return true; + + eflags |= TRACE_BIT; + } + else + { + if (!(eflags & TRACE_BIT)) + return false; + + eflags &= ~TRACE_BIT; + } + + return WriteRegisterFromUnsigned(gpr_eflags, eflags); +} + +void +RegisterContext_i386::LogGPR(const char *title) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); + if (log) + { + if (title) + log->Printf ("%s", title); + for (uint32_t i=0; iPrintf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); + } + } +} + +bool +RegisterContext_i386::ReadGPR() +{ + bool result; + + ProcessMonitor &monitor = GetMonitor(); + result = monitor.ReadGPR(&user.regs); + LogGPR("RegisterContext_i386::ReadGPR()"); + return result; +} + +bool +RegisterContext_i386::ReadFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(&user.i387); +} Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) @@ -0,0 +1,195 @@ +//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessPOSIXLog.h" + +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/StreamFile.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" + +using namespace lldb; +using namespace lldb_private; + + +// We want to avoid global constructors where code needs to be run so here we +// control access to our static g_log_sp by hiding it in a singleton function +// that will construct the static g_lob_sp the first time this function is +// called. +static LogSP & +GetLog () +{ + static LogSP g_log_sp; + return g_log_sp; +} + +LogSP +ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) +{ + LogSP log(GetLog ()); + if (log && mask) + { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return LogSP(); + } + return log; +} + +void +ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm) +{ + LogSP log (GetLog ()); + if (log) + { + uint32_t flag_bits = 0; + + const size_t argc = args.GetArgumentCount (); + if (argc > 0) + { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; i < argc; ++i) + { + const char *arg = args.GetArgumentAtIndex (i); + + + if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; + else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; + else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; + else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; + else + { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories (feedback_strm); + } + + } + } + + if (flag_bits == 0) + GetLog ().reset(); + else + log->GetMask().Reset (flag_bits); + } + + return; +} + +LogSP +ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) +{ + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the same. + uint32_t flag_bits = 0; + LogSP log(GetLog ()); + if (log) + flag_bits = log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) + { + log = make_shared(log_stream_sp); + GetLog () = log; + } + + if (log) + { + bool got_unknown_category = false; + const size_t argc = args.GetArgumentCount(); + for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) + { + got_unknown_category = true; + ListLogCategories (feedback_strm); + } + } + } + if (flag_bits == 0) + flag_bits = POSIX_LOG_DEFAULT; + log->GetMask().Reset(flag_bits); + log->GetOptions().Reset(log_options); + } + return log; +} + +void +ProcessPOSIXLog::ListLogCategories (Stream *strm) +{ + strm->Printf ("Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " async - log asynchronous activity\n" + " break - log breakpoints\n" + " communication - log communication activity\n" + " default - enable the default set of logging categories for liblldb\n" + " packets - log gdb remote packets\n" + " memory - log memory reads and writes\n" + " data-short - log memory bytes for memory reads and writes for short transactions only\n" + " data-long - log memory bytes for memory reads and writes for all transactions\n" + " process - log process events and activities\n" +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION + " ptrace - log all calls to ptrace\n" +#endif + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); +} + + +void +ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); + if (log) + { + va_list args; + va_start (args, format); + log->VAPrintf (format, args); + va_end (args); + } +} + +int ProcessPOSIXLog::m_nestinglevel; +const char *ProcessPOSIXLog::m_pluginname = ""; Index: source/Plugins/Process/POSIX/ProcessPOSIX.h =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) @@ -0,0 +1,180 @@ +//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessPOSIX_H_ +#define liblldb_ProcessPOSIX_H_ + +// C Includes + +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Process.h" +#include "lldb/Target/UnixSignals.h" +#include "ProcessMessage.h" + +class ProcessMonitor; + +class ProcessPOSIX : + public lldb_private::Process +{ +public: + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessPOSIX(lldb_private::Target& target, + lldb_private::Listener &listener); + + virtual + ~ProcessPOSIX(); + + //------------------------------------------------------------------ + // Process protocol. + //------------------------------------------------------------------ + virtual bool + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); + + virtual lldb_private::Error + WillLaunch(lldb_private::Module *module); + + virtual lldb_private::Error + DoAttachToProcessWithID(lldb::pid_t pid); + + virtual lldb_private::Error + DoLaunch (lldb_private::Module *exe_module, + const lldb_private::ProcessLaunchInfo &launch_info); + + virtual void + DidLaunch(); + + virtual lldb_private::Error + DoResume(); + + virtual lldb_private::Error + DoHalt(bool &caused_stop); + + virtual lldb_private::Error + DoDetach(); + + virtual lldb_private::Error + DoSignal(int signal); + + virtual lldb_private::Error + DoDestroy(); + + virtual void + RefreshStateAfterStop(); + + virtual bool + IsAlive(); + + virtual size_t + DoReadMemory(lldb::addr_t vm_addr, + void *buf, + size_t size, + lldb_private::Error &error); + + virtual size_t + DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error); + + virtual lldb::addr_t + DoAllocateMemory(size_t size, uint32_t permissions, + lldb_private::Error &error); + + virtual lldb_private::Error + DoDeallocateMemory(lldb::addr_t ptr); + + virtual size_t + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); + + virtual lldb_private::Error + EnableBreakpoint(lldb_private::BreakpointSite *bp_site); + + virtual lldb_private::Error + DisableBreakpoint(lldb_private::BreakpointSite *bp_site); + + virtual uint32_t + UpdateThreadListIfNeeded(); + + virtual uint32_t + UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) = 0; + + virtual lldb::ByteOrder + GetByteOrder() const; + + virtual lldb::addr_t + GetImageInfoAddress(); + + virtual size_t + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); + + virtual size_t + GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); + + virtual size_t + GetSTDERR(char *buf, size_t len, lldb_private::Error &error); + + //-------------------------------------------------------------------------- + // ProcessPOSIX internal API. + + /// Registers the given message with this process. + void SendMessage(const ProcessMessage &message); + + ProcessMonitor & + GetMonitor() { assert(m_monitor); return *m_monitor; } + + lldb_private::UnixSignals & + GetUnixSignals(); + + const char * + GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action, + const char *default_path); + +protected: + /// Target byte order. + lldb::ByteOrder m_byte_order; + + /// Process monitor; + ProcessMonitor *m_monitor; + + /// The module we are executing. + lldb_private::Module *m_module; + + /// Message queue notifying this instance of inferior process state changes. + lldb_private::Mutex m_message_mutex; + std::queue m_message_queue; + + /// True when the process has entered a state of "limbo". + /// + /// This flag qualifies eStateStopped. It lets us know that when we + /// continue from this state the process will exit. Also, when true, + /// Process::m_exit_status is set. + bool m_in_limbo; + + /// Drive any exit events to completion. + bool m_exit_now; + + /// OS-specific signal set. + lldb_private::UnixSignals m_signals; + + /// Returns true if the process has exited. + bool HasExited(); + + /// Returns true if the process is stopped. + bool IsStopped(); + + typedef std::map MMapMap; + MMapMap m_addr_to_mmap_size; +}; + +#endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/POSIX/RegisterContext_i386.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) @@ -0,0 +1,169 @@ +//===-- RegisterContext_i386.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_RegisterContext_i386_h_ +#define liblldb_RegisterContext_i386_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" + +class RegisterContext_i386 : public RegisterContextPOSIX +{ +public: + RegisterContext_i386(lldb_private::Thread &thread, + uint32_t concreate_frame_idx); + + ~RegisterContext_i386(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(uint32_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(uint32_t set); + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + bool + ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); + + bool + ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); + + bool + WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, + uint32_t data_offset = 0); + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + + bool + HardwareSingleStep(bool enable); + + bool + UpdateAfterBreakpoint(); + + struct GPR + { + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t orig_ax; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; + }; + + struct MMSReg + { + uint8_t bytes[8]; + }; + + struct XMMReg + { + uint8_t bytes[16]; + }; + + struct FPU + { + uint16_t fcw; + uint16_t fsw; + uint16_t ftw; + uint16_t fop; + uint32_t ip; + uint32_t cs; + uint32_t foo; + uint32_t fos; + uint32_t mxcsr; + uint32_t reserved; + MMSReg stmm[8]; + XMMReg xmm[8]; + uint32_t pad[56]; + }; + + // A user area like this no longer exists on FreeBSD + // making this a Linux artifact. Nonetheless, it is safe + // leaving it here while the code is being cleaned up and generalized. + + struct UserArea + { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + FPU i387; // FPU registers. + uint32_t tsize; // Text segment size. + uint32_t dsize; // Data segment size. + uint32_t ssize; // Stack segment size. + uint32_t start_code; // VM address of text. + uint32_t start_stack; // VM address of stack bottom (top in rsp). + int32_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + uint32_t ar0; // Location of GPR's. + FPU* fpstate; // Location of FPR's. + uint32_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). + }; +private: + UserArea user; + + ProcessMonitor &GetMonitor(); + + void LogGPR(const char *title); + + bool ReadGPR(); + bool ReadFPR(); +}; + +#endif // #ifndef liblldb_RegisterContext_i386_h_ Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) @@ -0,0 +1,757 @@ +//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" + +#include "ProcessPOSIX.h" +#include "ProcessMonitor.h" +#include "RegisterContext_x86_64.h" + +using namespace lldb_private; +using namespace lldb; + +// Internal codes for all x86_64 registers. +enum +{ + k_first_gpr, + gpr_rax = k_first_gpr, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + gpr_ss, + gpr_ds, + gpr_es, + k_last_gpr = gpr_es, + + k_first_fpr, + fpu_fcw = k_first_fpr, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15, + k_last_fpr = fpu_xmm15, + + k_num_registers, + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +enum gcc_dwarf_regnums +{ + gcc_dwarf_gpr_rax = 0, + gcc_dwarf_gpr_rdx, + gcc_dwarf_gpr_rcx, + gcc_dwarf_gpr_rbx, + gcc_dwarf_gpr_rsi, + gcc_dwarf_gpr_rdi, + gcc_dwarf_gpr_rbp, + gcc_dwarf_gpr_rsp, + gcc_dwarf_gpr_r8, + gcc_dwarf_gpr_r9, + gcc_dwarf_gpr_r10, + gcc_dwarf_gpr_r11, + gcc_dwarf_gpr_r12, + gcc_dwarf_gpr_r13, + gcc_dwarf_gpr_r14, + gcc_dwarf_gpr_r15, + gcc_dwarf_gpr_rip, + gcc_dwarf_fpu_xmm0, + gcc_dwarf_fpu_xmm1, + gcc_dwarf_fpu_xmm2, + gcc_dwarf_fpu_xmm3, + gcc_dwarf_fpu_xmm4, + gcc_dwarf_fpu_xmm5, + gcc_dwarf_fpu_xmm6, + gcc_dwarf_fpu_xmm7, + gcc_dwarf_fpu_xmm8, + gcc_dwarf_fpu_xmm9, + gcc_dwarf_fpu_xmm10, + gcc_dwarf_fpu_xmm11, + gcc_dwarf_fpu_xmm12, + gcc_dwarf_fpu_xmm13, + gcc_dwarf_fpu_xmm14, + gcc_dwarf_fpu_xmm15, + gcc_dwarf_fpu_stmm0, + gcc_dwarf_fpu_stmm1, + gcc_dwarf_fpu_stmm2, + gcc_dwarf_fpu_stmm3, + gcc_dwarf_fpu_stmm4, + gcc_dwarf_fpu_stmm5, + gcc_dwarf_fpu_stmm6, + gcc_dwarf_fpu_stmm7 +}; + +enum gdb_regnums +{ + gdb_gpr_rax = 0, + gdb_gpr_rbx = 1, + gdb_gpr_rcx = 2, + gdb_gpr_rdx = 3, + gdb_gpr_rsi = 4, + gdb_gpr_rdi = 5, + gdb_gpr_rbp = 6, + gdb_gpr_rsp = 7, + gdb_gpr_r8 = 8, + gdb_gpr_r9 = 9, + gdb_gpr_r10 = 10, + gdb_gpr_r11 = 11, + gdb_gpr_r12 = 12, + gdb_gpr_r13 = 13, + gdb_gpr_r14 = 14, + gdb_gpr_r15 = 15, + gdb_gpr_rip = 16, + gdb_gpr_rflags = 17, + gdb_gpr_cs = 18, + gdb_gpr_ss = 19, + gdb_gpr_ds = 20, + gdb_gpr_es = 21, + gdb_gpr_fs = 22, + gdb_gpr_gs = 23, + gdb_fpu_stmm0 = 24, + gdb_fpu_stmm1 = 25, + gdb_fpu_stmm2 = 26, + gdb_fpu_stmm3 = 27, + gdb_fpu_stmm4 = 28, + gdb_fpu_stmm5 = 29, + gdb_fpu_stmm6 = 30, + gdb_fpu_stmm7 = 31, + gdb_fpu_fcw = 32, + gdb_fpu_fsw = 33, + gdb_fpu_ftw = 34, + gdb_fpu_cs = 35, + gdb_fpu_ip = 36, + gdb_fpu_ds = 37, + gdb_fpu_dp = 38, + gdb_fpu_fop = 39, + gdb_fpu_xmm0 = 40, + gdb_fpu_xmm1 = 41, + gdb_fpu_xmm2 = 42, + gdb_fpu_xmm3 = 43, + gdb_fpu_xmm4 = 44, + gdb_fpu_xmm5 = 45, + gdb_fpu_xmm6 = 46, + gdb_fpu_xmm7 = 47, + gdb_fpu_xmm8 = 48, + gdb_fpu_xmm9 = 49, + gdb_fpu_xmm10 = 50, + gdb_fpu_xmm11 = 51, + gdb_fpu_xmm12 = 52, + gdb_fpu_xmm13 = 53, + gdb_fpu_xmm14 = 54, + gdb_fpu_xmm15 = 55, + gdb_fpu_mxcsr = 56 +}; + +static const +uint32_t g_gpr_regnums[k_num_gpr_registers] = +{ + gpr_rax, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + gpr_ss, + gpr_ds, + gpr_es +}; + +static const uint32_t +g_fpu_regnums[k_num_fpu_registers] = +{ + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15 +}; + +static const RegisterSet +g_reg_sets[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } +}; + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (offsetof(RegisterContext_x86_64::UserArea, regs) + \ + offsetof(GPR, regname)) + +// Computes the offset of the given FPR in the user data area. +#define FPR_OFFSET(regname) \ + (offsetof(RegisterContext_x86_64::UserArea, i387) + \ + offsetof(RegisterContext_x86_64::FPU, regname)) + +// Number of bytes needed to represent a GPR. +#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } + +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } + +#define DEFINE_FP(reg, i) \ + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } + +#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU)) + +static RegisterInfo +g_register_infos[k_num_registers] = +{ + // General purpose registers. + DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), + DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), + DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), + DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), + DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), + DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), + DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), + DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), + DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), + DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), + DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), + DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), + DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), + DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), + DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), + DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), + DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), + DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), + + // i387 Floating point registers. + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), + // FIXME: Extract segment from ip. + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), + // FIXME: Extract segment from dp. + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), + DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + // FP registers. + DEFINE_FP(stmm, 0), + DEFINE_FP(stmm, 1), + DEFINE_FP(stmm, 2), + DEFINE_FP(stmm, 3), + DEFINE_FP(stmm, 4), + DEFINE_FP(stmm, 5), + DEFINE_FP(stmm, 6), + DEFINE_FP(stmm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), + DEFINE_XMM(xmm, 10), + DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), + DEFINE_XMM(xmm, 13), + DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 15) +}; + +static unsigned GetRegOffset(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_offset; +} + +static unsigned GetRegSize(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_size; +} + +static bool IsGPR(unsigned reg) +{ + return reg <= k_last_gpr; // GPR's come first. +} + +static bool IsFPR(unsigned reg) +{ + return (k_first_fpr <= reg && reg <= k_last_fpr); +} + +RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextPOSIX(thread, concrete_frame_idx) +{ +} + +RegisterContext_x86_64::~RegisterContext_x86_64() +{ +} + +ProcessMonitor & +RegisterContext_x86_64::GetMonitor() +{ + ProcessPOSIX *process = static_cast(CalculateProcess()); + return process->GetMonitor(); +} + +void +RegisterContext_x86_64::Invalidate() +{ +} + +void +RegisterContext_x86_64::InvalidateAllRegisters() +{ +} + +size_t +RegisterContext_x86_64::GetRegisterCount() +{ + return k_num_registers; +} + +const RegisterInfo * +RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg) +{ + if (reg < k_num_registers) + return &g_register_infos[reg]; + else + return NULL; +} + +size_t +RegisterContext_x86_64::GetRegisterSetCount() +{ + return k_num_register_sets; +} + +const RegisterSet * +RegisterContext_x86_64::GetRegisterSet(uint32_t set) +{ + if (set < k_num_register_sets) + return &g_reg_sets[set]; + else + return NULL; +} + +unsigned +RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < k_num_registers; reg++) + { + if (g_register_infos[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers && "Invalid register offset."); + return reg; +} + +const char * +RegisterContext_x86_64::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register offset."); + return g_register_infos[reg].name; +} + +bool +RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); +} + +bool +RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR () && ReadFPR ()) + { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy (dst, &user.regs, sizeof(user.regs)); + dst += sizeof(user.regs); + + ::memcpy (dst, &user.i387, sizeof(user.i387)); + return true; + } + return false; +} + +bool +RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(GetRegOffset(reg), value); +} + +bool +RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) +{ + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) + { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy (&user.regs, src, sizeof(user.regs)); + src += sizeof(user.regs); + + ::memcpy (&user.i387, src, sizeof(user.i387)); + return WriteGPR() & WriteFPR(); + } + return false; +} + +bool +RegisterContext_x86_64::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +uint32_t +RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + if (kind == eRegisterKindGeneric) + { + switch (num) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_rip; + case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; + case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; + case LLDB_REGNUM_GENERIC_RA: + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) + { + switch (num) + { + case gcc_dwarf_gpr_rax: return gpr_rax; + case gcc_dwarf_gpr_rdx: return gpr_rdx; + case gcc_dwarf_gpr_rcx: return gpr_rcx; + case gcc_dwarf_gpr_rbx: return gpr_rbx; + case gcc_dwarf_gpr_rsi: return gpr_rsi; + case gcc_dwarf_gpr_rdi: return gpr_rdi; + case gcc_dwarf_gpr_rbp: return gpr_rbp; + case gcc_dwarf_gpr_rsp: return gpr_rsp; + case gcc_dwarf_gpr_r8: return gpr_r8; + case gcc_dwarf_gpr_r9: return gpr_r9; + case gcc_dwarf_gpr_r10: return gpr_r10; + case gcc_dwarf_gpr_r11: return gpr_r11; + case gcc_dwarf_gpr_r12: return gpr_r12; + case gcc_dwarf_gpr_r13: return gpr_r13; + case gcc_dwarf_gpr_r14: return gpr_r14; + case gcc_dwarf_gpr_r15: return gpr_r15; + case gcc_dwarf_gpr_rip: return gpr_rip; + case gcc_dwarf_fpu_xmm0: return fpu_xmm0; + case gcc_dwarf_fpu_xmm1: return fpu_xmm1; + case gcc_dwarf_fpu_xmm2: return fpu_xmm2; + case gcc_dwarf_fpu_xmm3: return fpu_xmm3; + case gcc_dwarf_fpu_xmm4: return fpu_xmm4; + case gcc_dwarf_fpu_xmm5: return fpu_xmm5; + case gcc_dwarf_fpu_xmm6: return fpu_xmm6; + case gcc_dwarf_fpu_xmm7: return fpu_xmm7; + case gcc_dwarf_fpu_xmm8: return fpu_xmm8; + case gcc_dwarf_fpu_xmm9: return fpu_xmm9; + case gcc_dwarf_fpu_xmm10: return fpu_xmm10; + case gcc_dwarf_fpu_xmm11: return fpu_xmm11; + case gcc_dwarf_fpu_xmm12: return fpu_xmm12; + case gcc_dwarf_fpu_xmm13: return fpu_xmm13; + case gcc_dwarf_fpu_xmm14: return fpu_xmm14; + case gcc_dwarf_fpu_xmm15: return fpu_xmm15; + case gcc_dwarf_fpu_stmm0: return fpu_stmm0; + case gcc_dwarf_fpu_stmm1: return fpu_stmm1; + case gcc_dwarf_fpu_stmm2: return fpu_stmm2; + case gcc_dwarf_fpu_stmm3: return fpu_stmm3; + case gcc_dwarf_fpu_stmm4: return fpu_stmm4; + case gcc_dwarf_fpu_stmm5: return fpu_stmm5; + case gcc_dwarf_fpu_stmm6: return fpu_stmm6; + case gcc_dwarf_fpu_stmm7: return fpu_stmm7; + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGDB) + { + switch (num) + { + case gdb_gpr_rax : return gpr_rax; + case gdb_gpr_rbx : return gpr_rbx; + case gdb_gpr_rcx : return gpr_rcx; + case gdb_gpr_rdx : return gpr_rdx; + case gdb_gpr_rsi : return gpr_rsi; + case gdb_gpr_rdi : return gpr_rdi; + case gdb_gpr_rbp : return gpr_rbp; + case gdb_gpr_rsp : return gpr_rsp; + case gdb_gpr_r8 : return gpr_r8; + case gdb_gpr_r9 : return gpr_r9; + case gdb_gpr_r10 : return gpr_r10; + case gdb_gpr_r11 : return gpr_r11; + case gdb_gpr_r12 : return gpr_r12; + case gdb_gpr_r13 : return gpr_r13; + case gdb_gpr_r14 : return gpr_r14; + case gdb_gpr_r15 : return gpr_r15; + case gdb_gpr_rip : return gpr_rip; + case gdb_gpr_rflags : return gpr_rflags; + case gdb_gpr_cs : return gpr_cs; + case gdb_gpr_ss : return gpr_ss; + case gdb_gpr_ds : return gpr_ds; + case gdb_gpr_es : return gpr_es; + case gdb_gpr_fs : return gpr_fs; + case gdb_gpr_gs : return gpr_gs; + case gdb_fpu_stmm0 : return fpu_stmm0; + case gdb_fpu_stmm1 : return fpu_stmm1; + case gdb_fpu_stmm2 : return fpu_stmm2; + case gdb_fpu_stmm3 : return fpu_stmm3; + case gdb_fpu_stmm4 : return fpu_stmm4; + case gdb_fpu_stmm5 : return fpu_stmm5; + case gdb_fpu_stmm6 : return fpu_stmm6; + case gdb_fpu_stmm7 : return fpu_stmm7; + case gdb_fpu_fcw : return fpu_fcw; + case gdb_fpu_fsw : return fpu_fsw; + case gdb_fpu_ftw : return fpu_ftw; + case gdb_fpu_cs : return fpu_cs; + case gdb_fpu_ip : return fpu_ip; + case gdb_fpu_ds : return fpu_ds; + case gdb_fpu_dp : return fpu_dp; + case gdb_fpu_fop : return fpu_fop; + case gdb_fpu_xmm0 : return fpu_xmm0; + case gdb_fpu_xmm1 : return fpu_xmm1; + case gdb_fpu_xmm2 : return fpu_xmm2; + case gdb_fpu_xmm3 : return fpu_xmm3; + case gdb_fpu_xmm4 : return fpu_xmm4; + case gdb_fpu_xmm5 : return fpu_xmm5; + case gdb_fpu_xmm6 : return fpu_xmm6; + case gdb_fpu_xmm7 : return fpu_xmm7; + case gdb_fpu_xmm8 : return fpu_xmm8; + case gdb_fpu_xmm9 : return fpu_xmm9; + case gdb_fpu_xmm10 : return fpu_xmm10; + case gdb_fpu_xmm11 : return fpu_xmm11; + case gdb_fpu_xmm12 : return fpu_xmm12; + case gdb_fpu_xmm13 : return fpu_xmm13; + case gdb_fpu_xmm14 : return fpu_xmm14; + case gdb_fpu_xmm15 : return fpu_xmm15; + case gdb_fpu_mxcsr : return fpu_mxcsr; + default: + return LLDB_INVALID_REGNUM; + } + } + else if (kind == eRegisterKindLLDB) + { + return num; + } + + return LLDB_INVALID_REGNUM; +} + +bool +RegisterContext_x86_64::HardwareSingleStep(bool enable) +{ + enum { TRACE_BIT = 0x100 }; + uint64_t rflags; + + if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) + return false; + + if (enable) + { + if (rflags & TRACE_BIT) + return true; + + rflags |= TRACE_BIT; + } + else + { + if (!(rflags & TRACE_BIT)) + return false; + + rflags &= ~TRACE_BIT; + } + + return WriteRegisterFromUnsigned(gpr_rflags, rflags); +} + +bool +RegisterContext_x86_64::ReadGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(&user.regs); +} + +bool +RegisterContext_x86_64::ReadFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(&user.i387); +} + +bool +RegisterContext_x86_64::WriteGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(&user.regs); +} + +bool +RegisterContext_x86_64::WriteFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(&user.i387); +} Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.h =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) @@ -0,0 +1,106 @@ +//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ +#define liblldb_ProcessLinuxLog_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes + +// Project includes +#include "lldb/Core/Log.h" + +#define POSIX_LOG_VERBOSE (1u << 0) +#define POSIX_LOG_PROCESS (1u << 1) +#define POSIX_LOG_THREAD (1u << 2) +#define POSIX_LOG_PACKETS (1u << 3) +#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes +#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes +#define POSIX_LOG_BREAKPOINTS (1u << 7) +#define POSIX_LOG_WATCHPOINTS (1u << 8) +#define POSIX_LOG_STEP (1u << 9) +#define POSIX_LOG_COMM (1u << 10) +#define POSIX_LOG_ASYNC (1u << 11) +#define POSIX_LOG_PTRACE (1u << 12) +#define POSIX_LOG_REGISTERS (1u << 13) +#define POSIX_LOG_ALL (UINT32_MAX) +#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS + +// The size which determines "short memory reads/writes". +#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) + +class ProcessPOSIXLog +{ + static int m_nestinglevel; + static const char *m_pluginname; + +public: + static void + RegisterPluginName(const char *pluginName) + { + m_pluginname = pluginName; + } + + + static lldb::LogSP + GetLogIfAllCategoriesSet(uint32_t mask = 0); + + static void + DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static lldb::LogSP + EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, + lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static void + ListLogCategories (lldb_private::Stream *strm); + + static void + LogIf (uint32_t mask, const char *format, ...); + + // The following functions can be used to enable the client to limit + // logging to only the top level function calls. This is useful for + // recursive functions. FIXME: not thread safe! + // Example: + // void NestingFunc() { + // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); + // if (log) + // { + // ProcessLinuxLog::IncNestLevel(); + // if (ProcessLinuxLog::AtTopNestLevel()) + // log->Print(msg); + // } + // NestingFunc(); + // if (log) + // ProcessLinuxLog::DecNestLevel(); + // } + + static bool + AtTopNestLevel() + { + return m_nestinglevel == 1; + } + + static void + IncNestLevel() + { + ++m_nestinglevel; + } + + static void + DecNestLevel() + { + --m_nestinglevel; + assert(m_nestinglevel >= 0); + } +}; + +#endif // liblldb_ProcessLinuxLog_h_ Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) @@ -0,0 +1,143 @@ +//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContext_x86_64_H_ +#define liblldb_RegisterContext_x86_64_H_ + +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" + +#ifdef __FreeBSD__ +#include "RegisterContextFreeBSD_x86_64.h" +#endif + +#ifdef __linux__ +#include "RegisterContextLinux_x86_64.h" +#endif + +class ProcessMonitor; + +class RegisterContext_x86_64 + : public RegisterContextPOSIX +{ +public: + RegisterContext_x86_64 (lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + ~RegisterContext_x86_64(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(uint32_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(uint32_t set); + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + + bool + HardwareSingleStep(bool enable); + + bool + UpdateAfterBreakpoint(); + + struct MMSReg + { + uint8_t bytes[10]; + uint8_t pad[6]; + }; + + struct XMMReg + { + uint8_t bytes[16]; + }; + + struct FPU + { + uint16_t fcw; + uint16_t fsw; + uint16_t ftw; + uint16_t fop; + uint64_t ip; + uint64_t dp; + uint32_t mxcsr; + uint32_t mxcsrmask; + MMSReg stmm[8]; + XMMReg xmm[16]; + uint32_t padding[24]; + }; + + struct UserArea + { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + int32_t pad0; + FPU i387; // FPU registers. + uint64_t tsize; // Text segment size. + uint64_t dsize; // Data segment size. + uint64_t ssize; // Stack segment size. + uint64_t start_code; // VM address of text. + uint64_t start_stack; // VM address of stack bottom (top in rsp). + int64_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + int32_t pad1; + uint64_t ar0; // Location of GPR's. + FPU* fpstate; // Location of FPR's. + uint64_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). + uint64_t error_code; // CPU error code. + uint64_t fault_address; // Control register CR3. + }; + +private: + UserArea user; + + ProcessMonitor &GetMonitor(); + + bool ReadGPR(); + bool ReadFPR(); + + bool WriteGPR(); + bool WriteFPR(); +}; + +#endif // #ifndef liblldb_RegisterContext_x86_64_H_ Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) @@ -0,0 +1,40 @@ +//===-- RegisterContextPOSIX.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_RegisterContextPOSIX_H_ +#define liblldb_RegisterContextPOSIX_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Target/RegisterContext.h" + +//------------------------------------------------------------------------------ +/// @class RegisterContextPOSIX +/// +/// @brief Extends RegisterClass with a few virtual operations useful on POSIX. +class RegisterContextPOSIX + : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX(lldb_private::Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx) { } + + /// Updates the register state of the associated thread after hitting a + /// breakpoint (if that make sense for the architecture). Default + /// implementation simply returns true for architectures which do not + /// require any update. + /// + /// @return + /// True if the operation succeeded and false otherwise. + virtual bool UpdateAfterBreakpoint() { return true; } +}; + +#endif // #ifndef liblldb_RegisterContextPOSIX_H_ Index: source/Plugins/Process/POSIX/ProcessMessage.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) @@ -0,0 +1,245 @@ +//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessMessage.h" + +using namespace lldb_private; + +const char * +ProcessMessage::GetCrashReasonString(CrashReason reason) +{ + const char *str = NULL; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case eInvalidAddress: + str = "invalid address"; + break; + case ePrivilegedAddress: + str = "address access protected"; + break; + case eIllegalOpcode: + str = "illegal instruction"; + break; + case eIllegalOperand: + str = "illegal instruction operand"; + break; + case eIllegalAddressingMode: + str = "illegal addressing mode"; + break; + case eIllegalTrap: + str = "illegal trap"; + break; + case ePrivilegedOpcode: + str = "privileged instruction"; + break; + case ePrivilegedRegister: + str = "privileged register"; + break; + case eCoprocessorError: + str = "coprocessor error"; + break; + case eInternalStackError: + str = "internal stack error"; + break; + case eIllegalAlignment: + str = "illegal alignment"; + break; + case eIllegalAddress: + str = "illegal address"; + break; + case eHardwareError: + str = "hardware error"; + break; + case eIntegerDivideByZero: + str = "integer divide by zero"; + break; + case eIntegerOverflow: + str = "integer overflow"; + break; + case eFloatDivideByZero: + str = "floating point divide by zero"; + break; + case eFloatOverflow: + str = "floating point overflow"; + break; + case eFloatUnderflow: + str = "floating point underflow"; + break; + case eFloatInexactResult: + str = "inexact floating point result"; + break; + case eFloatInvalidOperation: + str = "invalid floating point operation"; + break; + case eFloatSubscriptRange: + str = "invalid floating point subscript range"; + break; + } + + return str; +} + +const char * +ProcessMessage::PrintCrashReason(CrashReason reason) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in asci for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = NULL; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; + + // SIGSEGV crash reasons. + case eInvalidAddress: + str = "eInvalidAddress"; + break; + case ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; + + // SIGILL crash reasons. + case eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case eIllegalOperand: + str = "eIllegalOperand"; + break; + case eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case eIllegalTrap: + str = "eIllegalTrap"; + break; + case ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case eCoprocessorError: + str = "eCoprocessorError"; + break; + case eInternalStackError: + str = "eInternalStackError"; + break; + + // SIGBUS crash reasons: + case eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case eIllegalAddress: + str = "eIllegalAddress"; + break; + case eHardwareError: + str = "eHardwareError"; + break; + + // SIGFPE crash reasons: + case eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case eFloatOverflow: + str = "eFloatOverflow"; + break; + case eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } +#endif + + return str; +} + +const char * +ProcessMessage::PrintCrashReason() const +{ + return PrintCrashReason(m_crash_reason); +} + +const char * +ProcessMessage::PrintKind(Kind kind) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in asci for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = NULL; + + switch (kind) + { + default: + assert(false && "invalid Kind"); + break; + + case eInvalidMessage: + str = "eInvalidMessage"; + break; + case eExitMessage: + str = "eExitMessage"; + break; + case eLimboMessage: + str = "eLimboMessage"; + break; + case eSignalMessage: + str = "eSignalMessage"; + break; + case eSignalDeliveredMessage: + str = "eSignalDeliveredMessage"; + break; + case eTraceMessage: + str = "eTraceMessage"; + break; + case eBreakpointMessage: + str = "eBreakpointMessage"; + break; + case eCrashMessage: + str = "eCrashMessage"; + break; + } +#endif + + return str; +} + +const char * +ProcessMessage::PrintKind() const +{ + return PrintKind(m_kind); +} Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp =================================================================== --- source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) +++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) @@ -0,0 +1,60 @@ +//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "POSIXStopInfo.h" + +using namespace lldb; +using namespace lldb_private; + + +//===----------------------------------------------------------------------===// +// POSIXLimboStopInfo + +POSIXLimboStopInfo::~POSIXLimboStopInfo() { } + +lldb::StopReason +POSIXLimboStopInfo::GetStopReason() const +{ + return lldb::eStopReasonTrace; +} + +const char * +POSIXLimboStopInfo::GetDescription() +{ + return "thread exiting"; +} + +bool +POSIXLimboStopInfo::ShouldStop(Event *event_ptr) +{ + return true; +} + +bool +POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) +{ + return true; +} + +//===----------------------------------------------------------------------===// +// POSIXCrashStopInfo + +POSIXCrashStopInfo::~POSIXCrashStopInfo() { } + +lldb::StopReason +POSIXCrashStopInfo::GetStopReason() const +{ + return lldb::eStopReasonException; +} + +const char * +POSIXCrashStopInfo::GetDescription() +{ + return ProcessMessage::GetCrashReasonString(m_crash_reason); +} Index: source/Plugins/Process/POSIX/ProcessMessage.h =================================================================== --- source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) @@ -0,0 +1,171 @@ +//===-- ProcessMessage.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_ProcessMessage_H_ +#define liblldb_ProcessMessage_H_ + +#include + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +class ProcessMessage +{ +public: + + /// The type of signal this message can correspond to. + enum Kind + { + eInvalidMessage, + eExitMessage, + eLimboMessage, + eSignalMessage, + eSignalDeliveredMessage, + eTraceMessage, + eBreakpointMessage, + eCrashMessage + }; + + enum CrashReason + { + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange + }; + + ProcessMessage() + : m_tid(LLDB_INVALID_PROCESS_ID), + m_kind(eInvalidMessage), + m_crash_reason(eInvalidCrashReason), + m_status(0), + m_addr(0) { } + + Kind GetKind() const { return m_kind; } + + lldb::tid_t GetTID() const { return m_tid; } + + /// Indicates that the thread @p tid is about to exit with status @p status. + static ProcessMessage Limbo(lldb::tid_t tid, int status) { + return ProcessMessage(tid, eLimboMessage, status); + } + + /// Indicates that the thread @p tid had the signal @p signum delivered. + static ProcessMessage Signal(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalMessage, signum); + } + + /// Indicates that a signal @p signum generated by the debugging process was + /// delivered to the thread @p tid. + static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalDeliveredMessage, signum); + } + + /// Indicates that the thread @p tid encountered a trace point. + static ProcessMessage Trace(lldb::tid_t tid) { + return ProcessMessage(tid, eTraceMessage); + } + + /// Indicates that the thread @p tid encountered a break point. + static ProcessMessage Break(lldb::tid_t tid) { + return ProcessMessage(tid, eBreakpointMessage); + } + + /// Indicates that the thread @p tid crashed. + static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, + int signo, lldb::addr_t fault_addr) { + ProcessMessage message(pid, eCrashMessage, signo, fault_addr); + message.m_crash_reason = reason; + return message; + } + + int GetExitStatus() const { + assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); + return m_status; + } + + int GetSignal() const { + assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || + GetKind() == eSignalDeliveredMessage); + return m_status; + } + + int GetStopStatus() const { + assert(GetKind() == eSignalMessage); + return m_status; + } + + CrashReason GetCrashReason() const { + assert(GetKind() == eCrashMessage); + return m_crash_reason; + } + + lldb::addr_t GetFaultAddress() const { + assert(GetKind() == eCrashMessage); + return m_addr; + } + + static const char * + GetCrashReasonString(CrashReason reason); + + const char * + PrintCrashReason() const; + + static const char * + PrintCrashReason(CrashReason reason); + + const char * + PrintKind() const; + + static const char * + PrintKind(Kind); + +private: + ProcessMessage(lldb::tid_t tid, Kind kind, + int status = 0, lldb::addr_t addr = 0) + : m_tid(tid), + m_kind(kind), + m_crash_reason(eInvalidCrashReason), + m_status(status), + m_addr(addr) { } + + lldb::tid_t m_tid; + Kind m_kind : 8; + CrashReason m_crash_reason : 8; + int m_status; + lldb::addr_t m_addr; +}; + +#endif // #ifndef liblldb_ProcessMessage_H_ Index: source/Plugins/Process/POSIX/POSIXStopInfo.h =================================================================== --- source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) +++ source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) @@ -0,0 +1,92 @@ +//===-- POSIXStopInfo.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_POSIXStopInfo_H_ +#define liblldb_POSIXStopInfo_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/StopInfo.h" + +#include "POSIXThread.h" +#include "ProcessMessage.h" + +//===----------------------------------------------------------------------===// +/// @class POSIXStopInfo +/// @brief Simple base class for all POSIX-specific StopInfo objects. +/// +class POSIXStopInfo + : public lldb_private::StopInfo +{ +public: + POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) + : StopInfo(thread, status) + { } +}; + +//===----------------------------------------------------------------------===// +/// @class POSIXLimboStopInfo +/// @brief Represents the stop state of a process ready to exit. +/// +class POSIXLimboStopInfo + : public POSIXStopInfo +{ +public: + POSIXLimboStopInfo(POSIXThread &thread) + : POSIXStopInfo(thread, 0) + { } + + ~POSIXLimboStopInfo(); + + lldb::StopReason + GetStopReason() const; + + const char * + GetDescription(); + + bool + ShouldStop(lldb_private::Event *event_ptr); + + bool + ShouldNotify(lldb_private::Event *event_ptr); +}; + + +//===----------------------------------------------------------------------===// +/// @class POSIXCrashStopInfo +/// @brief Represents the stop state of process that is ready to crash. +/// +class POSIXCrashStopInfo + : public POSIXStopInfo +{ +public: + POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, + ProcessMessage::CrashReason reason) + : POSIXStopInfo(thread, status), + m_crash_reason(reason) + { } + + ~POSIXCrashStopInfo(); + + lldb::StopReason + GetStopReason() const; + + const char * + GetDescription(); + + ProcessMessage::CrashReason + GetCrashReason() const; + +private: + ProcessMessage::CrashReason m_crash_reason; +}; + +#endif Index: source/Plugins/Process/POSIX/POSIXThread.cpp =================================================================== --- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) +++ source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) @@ -0,0 +1,352 @@ +//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "POSIXStopInfo.h" +#include "POSIXThread.h" +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContext_i386.h" +#include "RegisterContext_x86_64.h" +#include "RegisterContextPOSIX.h" + +#include "UnwindLLDB.h" + +using namespace lldb_private; + + +POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) + : Thread(process, tid), + m_frame_ap(0) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid); +} + +POSIXThread::~POSIXThread() +{ + DestroyThread(); +} + +ProcessMonitor & +POSIXThread::GetMonitor() +{ + ProcessPOSIX &process = static_cast(GetProcess()); + return process.GetMonitor(); +} + +void +POSIXThread::RefreshStateAfterStop() +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + ProcessPOSIX &process = static_cast(GetProcess()); + process.GetThreadList().RefreshStateAfterStop(); +} + +const char * +POSIXThread::GetInfo() +{ + return NULL; +} + +lldb::RegisterContextSP +POSIXThread::GetRegisterContext() +{ + if (!m_reg_context_sp) + { + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); + break; + + case ArchSpec::eCore_x86_64_x86_64: + m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0)); + break; + } + } + return m_reg_context_sp; +} + +lldb::RegisterContextSP +POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) +{ + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) + reg_ctx_sp = GetRegisterContext(); + else + { + assert(GetUnwinder()); + reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); + } + + return reg_ctx_sp; +} + +lldb::StopInfoSP +POSIXThread::GetPrivateStopReason() +{ + return m_stop_info; +} + +Unwind * +POSIXThread::GetUnwinder() +{ + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + + return m_unwinder_ap.get(); +} + +bool +POSIXThread::WillResume(lldb::StateType resume_state) +{ + SetResumeState(resume_state); + + ClearStackFrames(); + if (m_unwinder_ap.get()) + m_unwinder_ap->Clear(); + + return Thread::WillResume(resume_state); +} + +bool +POSIXThread::Resume() +{ + lldb::StateType resume_state = GetResumeState(); + ProcessMonitor &monitor = GetMonitor(); + bool status; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + switch (resume_state) + { + default: + assert(false && "Unexpected state for resume!"); + status = false; + break; + + case lldb::eStateRunning: + SetState(resume_state); + status = monitor.Resume(GetID(), GetResumeSignal()); + break; + + case lldb::eStateStepping: + SetState(resume_state); + status = monitor.SingleStep(GetID(), GetResumeSignal()); + break; + } + + return status; +} + +void +POSIXThread::Notify(const ProcessMessage &message) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); + + switch (message.GetKind()) + { + default: + assert(false && "Unexpected message kind!"); + break; + + case ProcessMessage::eLimboMessage: + LimboNotify(message); + break; + + case ProcessMessage::eSignalMessage: + SignalNotify(message); + break; + + case ProcessMessage::eSignalDeliveredMessage: + SignalDeliveredNotify(message); + break; + + case ProcessMessage::eTraceMessage: + TraceNotify(message); + break; + + case ProcessMessage::eBreakpointMessage: + BreakNotify(message); + break; + + case ProcessMessage::eCrashMessage: + CrashNotify(message); + break; + } +} + +void +POSIXThread::BreakNotify(const ProcessMessage &message) +{ + bool status; + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + + assert(GetRegisterContext()); + status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); + assert(status && "Breakpoint update failed!"); + + // With our register state restored, resolve the breakpoint object + // corresponding to our current PC. + assert(GetRegisterContext()); + lldb::addr_t pc = GetRegisterContext()->GetPC(); + if (log) + log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); + lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); + assert(bp_site); + lldb::break_id_t bp_id = bp_site->GetID(); + assert(bp_site && bp_site->ValidForThisThread(this)); + + + m_breakpoint = bp_site; + m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); +} + +void +POSIXThread::TraceNotify(const ProcessMessage &message) +{ + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); +} + +void +POSIXThread::LimboNotify(const ProcessMessage &message) +{ + m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this)); +} + +void +POSIXThread::SignalNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); + SetResumeSignal(signo); +} + +void +POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + // Just treat debugger generated signal events like breakpoints for now. + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); + SetResumeSignal(signo); +} + +void +POSIXThread::CrashNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + assert(message.GetKind() == ProcessMessage::eCrashMessage); + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); + + m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo( + *this, signo, message.GetCrashReason())); + SetResumeSignal(signo); +} + +unsigned +POSIXThread::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset); + break; + + case ArchSpec::eCore_x86_64_x86_64: + reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset); + break; + } + return reg; +} + +const char * +POSIXThread::GetRegisterName(unsigned reg) +{ + const char * name; + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + name = RegisterContext_i386::GetRegisterName(reg); + break; + + case ArchSpec::eCore_x86_64_x86_64: + name = RegisterContext_x86_64::GetRegisterName(reg); + break; + } + return name; +} + +const char * +POSIXThread::GetRegisterNameFromOffset(unsigned offset) +{ + return GetRegisterName(GetRegisterIndexFromOffset(offset)); +} + Index: source/Plugins/Process/POSIX/Makefile =================================================================== --- source/Plugins/Process/POSIX/Makefile (revision 0) +++ source/Plugins/Process/POSIX/Makefile (revision 0) @@ -0,0 +1,28 @@ +##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginProcessPOSIX +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/../../Makefile.config + +# Extend the include path so we may locate UnwindLLDB.h +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility + +ifeq ($(HOST_OS),Linux) +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux +endif + +ifeq ($(HOST_OS),FreeBSD) +# Extend the include path so we may locate ProcessMonitor +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD +endif + +include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) @@ -0,0 +1,84 @@ +//===-- ProcessFreeBSD.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_ProcessFreeBSD_H_ +#define liblldb_ProcessFreeBSD_H_ + +// C Includes + +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Process.h" +#include "lldb/Target/ThreadList.h" +#include "ProcessMessage.h" +#include "ProcessPOSIX.h" + +class ProcessMonitor; + +class ProcessFreeBSD : + public ProcessPOSIX +{ + +public: + //------------------------------------------------------------------ + // Static functions. + //------------------------------------------------------------------ + static Process* + CreateInstance(lldb_private::Target& target, + lldb_private::Listener &listener); + + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessFreeBSD(lldb_private::Target& target, + lldb_private::Listener &listener); + + virtual uint32_t + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + + virtual void + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + + virtual lldb_private::Error + ExecutePluginCommand(lldb_private::Args &command, + lldb_private::Stream *strm); + + virtual lldb_private::Log * + EnablePluginLogging(lldb_private::Stream *strm, + lldb_private::Args &command); + +}; + +#endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) @@ -0,0 +1,1558 @@ +//===-- ProcessMonitor.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 +#include +#include +#include +#include +#include +#include +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/Error.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/PseudoTerminal.h" + + +#include "POSIXThread.h" +#include "ProcessFreeBSD.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" + +extern "C" { + extern char ** environ; + } + +using namespace lldb; +using namespace lldb_private; + +// We disable the tracing of ptrace calls for integration builds to +// avoid the additional indirection and checks. +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION +// Wrapper for ptrace to catch errors and log calls. + +const char * +Get_PT_IO_OP(int op) +{ + switch (op) { + case PIOD_READ_D: return "READ_D"; + case PIOD_WRITE_D: return "WRITE_D"; + case PIOD_READ_I: return "READ_I"; + case PIOD_WRITE_I: return "WRITE_I"; + default: return "Unknown op"; + } +} + +extern long +PtraceWrapper(int req, ::pid_t pid, void *addr, int data, + const char* reqName, const char* file, int line) +{ + long int result; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + + if (log) { + log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d", + reqName, pid, addr, data, file, line); + if (req == PT_IO) { + struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; + + log->Printf("PT_IO: op=%s offs=%zx size=%ld", + Get_PT_IO_OP(pi->piod_op), pi->piod_offs, pi->piod_len); + } + } + + //PtraceDisplayBytes(req, data); + + errno = 0; + result = ptrace(req, pid, (caddr_t) addr, data); + + //PtraceDisplayBytes(req, data); + + if (log && (result == -1 || errno != 0)) + { + const char* str; + switch (errno) + { + case ESRCH: str = "ESRCH"; break; + case EINVAL: str = "EINVAL"; break; + case EBUSY: str = "EBUSY"; break; + case EPERM: str = "EPERM"; break; + default: str = ""; + } + log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + } + + if (log) { + if (req == PT_GETREGS) { + struct reg *r = (struct reg *) addr; + + log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip); + log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp); + log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); + log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); + } + } + + return result; +} + +#define PTRACE(req, pid, addr, data) \ + PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) +#else +#define PTRACE ptrace +#endif + +//------------------------------------------------------------------------------ +// Static implementations of ProcessMonitor::ReadMemory and +// ProcessMonitor::WriteMemory. This enables mutual recursion between these +// functions without needed to go thru the thread funnel. + +static size_t +DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, + Error &error) +{ + struct ptrace_io_desc pi_desc; + + pi_desc.piod_op = PIOD_READ_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = buf; + pi_desc.piod_len = size; + + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; +} + +static size_t +DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, + size_t size, Error &error) +{ + struct ptrace_io_desc pi_desc; + + pi_desc.piod_op = PIOD_WRITE_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = (void *)buf; + pi_desc.piod_len = size; + + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; +} + +// Simple helper function to ensure flags are enabled on the given file +// descriptor. +static bool +EnsureFDFlags(int fd, int flags, Error &error) +{ + int status; + + if ((status = fcntl(fd, F_GETFL)) == -1) + { + error.SetErrorToErrno(); + return false; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) + { + error.SetErrorToErrno(); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------ +/// @class Operation +/// @brief Represents a ProcessMonitor operation. +/// +/// Under FreeBSD, it is not possible to ptrace() from any other thread but the +/// one that spawned or attached to the process from the start. Therefore, when +/// a ProcessMonitor is asked to deliver or change the state of an inferior +/// process the operation must be "funneled" to a specific thread to perform the +/// task. The Operation class provides an abstract base for all services the +/// ProcessMonitor must perform via the single virtual function Execute, thus +/// encapsulating the code that needs to run in the privileged context. +class Operation +{ +public: + virtual void Execute(ProcessMonitor *monitor) = 0; +}; + +//------------------------------------------------------------------------------ +/// @class ReadOperation +/// @brief Implements ProcessMonitor::ReadMemory. +class ReadOperation : public Operation +{ +public: + ReadOperation(lldb::addr_t addr, void *buff, size_t size, + Error &error, size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), + m_error(error), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::addr_t m_addr; + void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; +}; + +void +ReadOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); +} + +//------------------------------------------------------------------------------ +/// @class ReadOperation +/// @brief Implements ProcessMonitor::WriteMemory. +class WriteOperation : public Operation +{ +public: + WriteOperation(lldb::addr_t addr, const void *buff, size_t size, + Error &error, size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), + m_error(error), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::addr_t m_addr; + const void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; +}; + +void +WriteOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); +} + +//------------------------------------------------------------------------------ +/// @class ReadRegOperation +/// @brief Implements ProcessMonitor::ReadRegisterValue. +class ReadRegOperation : public Operation +{ +public: + ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result) + : m_offset(offset), m_size(size), m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + unsigned m_offset; + unsigned m_size; + RegisterValue &m_value; + bool &m_result; +}; + +void +ReadRegOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + struct reg regs; + int rc; + + if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0)) < 0) { + m_result = false; + } else { + if (m_size == sizeof(uintptr_t)) + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); + else + memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); + m_result = true; + } +} + +//------------------------------------------------------------------------------ +/// @class WriteRegOperation +/// @brief Implements ProcessMonitor::WriteRegisterValue. +class WriteRegOperation : public Operation +{ +public: + WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result) + : m_offset(offset), m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + unsigned m_offset; + const RegisterValue &m_value; + bool &m_result; +}; + +void +WriteRegOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + struct reg regs; + + if (PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0) < 0) { + m_result = false; + return; + } + *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); + if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ReadGPROperation +/// @brief Implements ProcessMonitor::ReadGPR. +class ReadGPROperation : public Operation +{ +public: + ReadGPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +ReadGPROperation::Execute(ProcessMonitor *monitor) +{ + int rc; + + errno = 0; + rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0); + if (errno != 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ReadFPROperation +/// @brief Implements ProcessMonitor::ReadFPR. +class ReadFPROperation : public Operation +{ +public: + ReadFPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +ReadFPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class WriteGPROperation +/// @brief Implements ProcessMonitor::WriteGPR. +class WriteGPROperation : public Operation +{ +public: + WriteGPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +WriteGPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class WriteFPROperation +/// @brief Implements ProcessMonitor::WriteFPR. +class WriteFPROperation : public Operation +{ +public: + WriteFPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +WriteFPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ResumeOperation +/// @brief Implements ProcessMonitor::Resume. +class ResumeOperation : public Operation +{ +public: + ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : + m_tid(tid), m_signo(signo), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + uint32_t m_signo; + bool &m_result; +}; + +void +ResumeOperation::Execute(ProcessMonitor *monitor) +{ + int data = 0; + + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; + + if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ResumeOperation +/// @brief Implements ProcessMonitor::SingleStep. +class SingleStepOperation : public Operation +{ +public: + SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) + : m_tid(tid), m_signo(signo), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + uint32_t m_signo; + bool &m_result; +}; + +void +SingleStepOperation::Execute(ProcessMonitor *monitor) +{ + int data = 0; + + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; + + if (PTRACE(PT_STEP, m_tid, NULL, data)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class SiginfoOperation +/// @brief Implements ProcessMonitor::GetSignalInfo. +class SiginfoOperation : public Operation +{ +public: + SiginfoOperation(lldb::tid_t tid, void *info, bool &result) + : m_tid(tid), m_info(info), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + void *m_info; + bool &m_result; +}; + +void +SiginfoOperation::Execute(ProcessMonitor *monitor) +{ + struct ptrace_lwpinfo plwp; + + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) + m_result = false; + else { + memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t)); + m_result = true; + } +} + +//------------------------------------------------------------------------------ +/// @class EventMessageOperation +/// @brief Implements ProcessMonitor::GetEventMessage. +class EventMessageOperation : public Operation +{ +public: + EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) + : m_tid(tid), m_message(message), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + unsigned long *m_message; + bool &m_result; +}; + +void +EventMessageOperation::Execute(ProcessMonitor *monitor) +{ + struct ptrace_lwpinfo plwp; + + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) + m_result = false; + else { + if (plwp.pl_flags & PL_FLAG_FORKED) { + m_message = (unsigned long *)plwp.pl_child_pid; + m_result = true; + } else + m_result = false; + } +} + +//------------------------------------------------------------------------------ +/// @class KillOperation +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. +class KillOperation : public Operation +{ +public: + KillOperation(bool &result) : m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + bool &m_result; +}; + +void +KillOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + if (PTRACE(PT_KILL, pid, NULL, 0)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class KillOperation +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. +class DetachOperation : public Operation +{ +public: + DetachOperation(Error &result) : m_error(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + Error &m_error; +}; + +void +DetachOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) + m_error.SetErrorToErrno(); + +} + +ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) + : m_monitor(monitor) +{ + sem_init(&m_semaphore, 0, 0); +} + +ProcessMonitor::OperationArgs::~OperationArgs() +{ + sem_destroy(&m_semaphore); +} + +ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, + lldb_private::Module *module, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path) + : OperationArgs(monitor), + m_module(module), + m_argv(argv), + m_envp(envp), + m_stdin_path(stdin_path), + m_stdout_path(stdout_path), + m_stderr_path(stderr_path) { } + +ProcessMonitor::LaunchArgs::~LaunchArgs() +{ } + +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, + lldb::pid_t pid) + : OperationArgs(monitor), m_pid(pid) { } + +ProcessMonitor::AttachArgs::~AttachArgs() +{ } + +//------------------------------------------------------------------------------ +/// The basic design of the ProcessMonitor is built around two threads. +/// +/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking +/// for changes in the debugee state. When a change is detected a +/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread +/// "drives" state changes in the debugger. +/// +/// The second thread (@see OperationThread) is responsible for two things 1) +/// launching or attaching to the inferior process, and then 2) servicing +/// operations such as register reads/writes, stepping, etc. See the comments +/// on the Operation class for more info as to why this is needed. +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, + Module *module, + const char *argv[], + const char *envp[], + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + lldb_private::Error &error) + : m_process(static_cast(process)), + m_operation_thread(LLDB_INVALID_HOST_THREAD), + m_monitor_thread(LLDB_INVALID_HOST_THREAD), + m_pid(LLDB_INVALID_PROCESS_ID), + m_server_mutex(Mutex::eMutexTypeRecursive), + m_terminal_fd(-1), + m_client_fd(-1), + m_server_fd(-1) +{ + std::auto_ptr args; + + args.reset(new LaunchArgs(this, module, argv, envp, + stdin_path, stdout_path, stderr_path)); + + + // Server/client descriptors. + if (!EnableIPC()) + { + error.SetErrorToGenericError(); + error.SetErrorString("Monitor failed to initialize."); + } + + StartLaunchOpThread(args.get(), error); + if (!error.Success()) + return; + +WAIT_AGAIN: + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) + { + if (errno == EINTR) + goto WAIT_AGAIN; + else + { + error.SetErrorToErrno(); + return; + } + } + + // Check that the launch was a success. + if (!args->m_error.Success()) + { + StopLaunchOpThread(); + error = args->m_error; + return; + } + + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + ProcessMonitor::MonitorCallback, this, GetPID(), true); + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + error.SetErrorToGenericError(); + error.SetErrorString("Process launch failed."); + return; + } +} + +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, + lldb::pid_t pid, + lldb_private::Error &error) + : m_process(static_cast(process)), + m_operation_thread(LLDB_INVALID_HOST_THREAD), + m_monitor_thread(LLDB_INVALID_HOST_THREAD), + m_pid(pid), + m_server_mutex(Mutex::eMutexTypeRecursive), + m_terminal_fd(-1), + m_client_fd(-1), + m_server_fd(-1) +{ + std::auto_ptr args; + + args.reset(new AttachArgs(this, pid)); + + // Server/client descriptors. + if (!EnableIPC()) + { + error.SetErrorToGenericError(); + error.SetErrorString("Monitor failed to initialize."); + } + + StartAttachOpThread(args.get(), error); + if (!error.Success()) + return; + +WAIT_AGAIN: + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) + { + if (errno == EINTR) + goto WAIT_AGAIN; + else + { + error.SetErrorToErrno(); + return; + } + } + + // Check that the launch was a success. + if (!args->m_error.Success()) + { + StopAttachOpThread(); + error = args->m_error; + return; + } + + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + ProcessMonitor::MonitorCallback, this, GetPID(), true); + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + error.SetErrorToGenericError(); + error.SetErrorString("Process attach failed."); + return; + } +} + +ProcessMonitor::~ProcessMonitor() +{ + StopMonitor(); +} + +//------------------------------------------------------------------------------ +// Thread setup and tear down. +void +ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) +{ + static const char *g_thread_name = "lldb.process.freebsd.operation"; + + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + m_operation_thread = + Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error); +} + +void +ProcessMonitor::StopLaunchOpThread() +{ + lldb::thread_result_t result; + + if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + Host::ThreadCancel(m_operation_thread, NULL); + Host::ThreadJoin(m_operation_thread, &result, NULL); +} + +void * +ProcessMonitor::LaunchOpThread(void *arg) +{ + LaunchArgs *args = static_cast(arg); + + if (!Launch(args)) { + sem_post(&args->m_semaphore); + return NULL; + } + + ServeOperation(args); + return NULL; +} + +bool +ProcessMonitor::Launch(LaunchArgs *args) +{ + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); + const char **argv = args->m_argv; + const char **envp = args->m_envp; + const char *stdin_path = args->m_stdin_path; + const char *stdout_path = args->m_stdout_path; + const char *stderr_path = args->m_stderr_path; + lldb::pid_t pid; + + lldb::ThreadSP inferior; + + // Propagate the environment if one is not supplied. + if (envp == NULL || envp[0] == NULL) + envp = const_cast(environ); + + // Recognized child exit status codes. + enum { + ePtraceFailed = 1, + eDupStdinFailed, + eDupStdoutFailed, + eDupStderrFailed, + eExecFailed + }; + + pid = fork(); + + // Child process. + if (pid == 0) + { + // Trace this process. + if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) + exit(ePtraceFailed); + + // Do not inherit setgid powers. + setgid(getgid()); + + // Let us have our own process group. + setpgid(0, 0); + + // Dup file descriptors if needed. + // + // FIXME: If two or more of the paths are the same we needlessly open + // the same file multiple times. + if (stdin_path != NULL && stdin_path[0]) + if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY)) + exit(eDupStdinFailed); + + if (stdout_path != NULL && stdout_path[0]) + if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStdoutFailed); + + if (stderr_path != NULL && stderr_path[0]) + if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStderrFailed); + + // Execute. We should never return. + execve(argv[0], + const_cast(argv), + const_cast(envp)); + exit(eExecFailed); + } + + // Wait for the child process to to trap on its call to execve. + ::pid_t wpid; + int status; + if ((wpid = waitpid(pid, &status, 0)) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + else if (WIFEXITED(status)) + { + // open, dup or execve likely failed for some reason. + args->m_error.SetErrorToGenericError(); + switch (WEXITSTATUS(status)) + { + case ePtraceFailed: + args->m_error.SetErrorString("Child ptrace failed."); + break; + case eDupStdinFailed: + args->m_error.SetErrorString("Child open stdin failed."); + break; + case eDupStdoutFailed: + args->m_error.SetErrorString("Child open stdout failed."); + break; + case eDupStderrFailed: + args->m_error.SetErrorString("Child open stderr failed."); + break; + case eExecFailed: + args->m_error.SetErrorString("Child exec failed."); + break; + default: + args->m_error.SetErrorString("Child returned unknown exit status."); + break; + } + goto FINISH; + } + assert(WIFSTOPPED(status) && wpid == pid && + "Could not sync with inferior process."); + +#ifdef notyet + // Have the child raise an event on exit. This is used to keep the child in + // limbo until it is destroyed. + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } +#endif + // XXX - Release the master terminal descriptor and pass it off to the + // XXX - ProcessMonitor instance. Similarly stash the inferior pid. + // For now just use stdin fd + monitor->m_terminal_fd = STDIN_FILENO; + monitor->m_pid = pid; + + // Set the terminal fd to be in non blocking mode (it simplifies the + // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking + // descriptor to read from). + if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) + goto FINISH; + + // Update the process thread list with this new thread. + inferior.reset(new POSIXThread(process, pid)); + process.GetThreadList().AddThread(inferior); + + // Let our process instance know the thread has stopped. + process.SendMessage(ProcessMessage::Trace(pid)); + +FINISH: + return args->m_error.Success(); +} + +bool +ProcessMonitor::EnableIPC() +{ + int fd[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) + return false; + + m_client_fd = fd[0]; + m_server_fd = fd[1]; + return true; +} + +void +ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) +{ + static const char *g_thread_name = "lldb.process.freebsd.operation"; + + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + m_operation_thread = + Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error); +} + +void +ProcessMonitor::StopAttachOpThread() +{ + assert(!"Not implemented yet!!!"); +} + +void * +ProcessMonitor::AttachOpThread(void *arg) +{ + AttachArgs *args = static_cast(arg); + + if (!Attach(args)) + return NULL; + + ServeOperation(args); + return NULL; +} + +bool +ProcessMonitor::Attach(AttachArgs *args) +{ + lldb::pid_t pid = args->m_pid; + + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); + ThreadList &tl = process.GetThreadList(); + lldb::ThreadSP inferior; + + if (pid <= 1) + { + args->m_error.SetErrorToGenericError(); + args->m_error.SetErrorString("Attaching to process 1 is not allowed."); + goto FINISH; + } + + // Attach to the requested process. + if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + + int status; + if ((status = waitpid(pid, NULL, 0)) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + + // Update the process thread list with the attached thread. + inferior.reset(new POSIXThread(process, pid)); + tl.AddThread(inferior); + + // Let our process instance know the thread has stopped. + process.SendMessage(ProcessMessage::Trace(pid)); + + FINISH: + return args->m_error.Success(); +} + +bool +ProcessMonitor::MonitorCallback(void *callback_baton, + lldb::pid_t pid, + bool exited, + int signal, + int status) +{ + ProcessMessage message; + ProcessMonitor *monitor = static_cast(callback_baton); + ProcessFreeBSD *process = monitor->m_process; + bool stop_monitoring; + siginfo_t info; + + if (!monitor->GetSignalInfo(pid, &info)) + stop_monitoring = true; // pid is gone. Bail. + else { + switch (info.si_signo) + { + case SIGTRAP: + message = MonitorSIGTRAP(monitor, &info, pid); + break; + + default: + message = MonitorSignal(monitor, &info, pid); + break; + } + + process->SendMessage(message); + stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; + } + + return stop_monitoring; +} + +ProcessMessage +ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid) +{ + ProcessMessage message; + + assert(info->si_signo == SIGTRAP && "Unexpected child signal!"); + + switch (info->si_code) + { + default: + assert(false && "Unexpected SIGTRAP code!"); + break; + + case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): + { + // The inferior process is about to exit. Maintain the process in a + // state of "limbo" until we are explicitly commanded to detach, + // destroy, resume, etc. + unsigned long data = 0; + if (!monitor->GetEventMessage(pid, &data)) + data = -1; + message = ProcessMessage::Limbo(pid, (data >> 8)); + break; + } + + case 0: + case TRAP_TRACE: + message = ProcessMessage::Trace(pid); + break; + + case SI_KERNEL: + case TRAP_BRKPT: + message = ProcessMessage::Break(pid); + break; + } + + return message; +} + +ProcessMessage +ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid) +{ + ProcessMessage message; + int signo = info->si_signo; + + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a + // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. + // + // IOW, user generated signals never generate what we consider to be a + // "crash". + // + // Similarly, ACK signals generated by this monitor. + if (info->si_code == SI_USER) + { + if (info->si_pid == getpid()) + return ProcessMessage::SignalDelivered(pid, signo); + else + return ProcessMessage::Signal(pid, signo); + } + + if (signo == SIGSEGV) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGILL) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGFPE) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGBUS) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + // Everything else is "normal" and does not require any special action on + // our part. + return ProcessMessage::Signal(pid, signo); +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGSEGV); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGSEGV"); + break; + case SEGV_MAPERR: + reason = ProcessMessage::eInvalidAddress; + break; + case SEGV_ACCERR: + reason = ProcessMessage::ePrivilegedAddress; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGILL); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGILL"); + break; + case ILL_ILLOPC: + reason = ProcessMessage::eIllegalOpcode; + break; + case ILL_ILLOPN: + reason = ProcessMessage::eIllegalOperand; + break; + case ILL_ILLADR: + reason = ProcessMessage::eIllegalAddressingMode; + break; + case ILL_ILLTRP: + reason = ProcessMessage::eIllegalTrap; + break; + case ILL_PRVOPC: + reason = ProcessMessage::ePrivilegedOpcode; + break; + case ILL_PRVREG: + reason = ProcessMessage::ePrivilegedRegister; + break; + case ILL_COPROC: + reason = ProcessMessage::eCoprocessorError; + break; + case ILL_BADSTK: + reason = ProcessMessage::eInternalStackError; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGFPE); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGFPE"); + break; + case FPE_INTDIV: + reason = ProcessMessage::eIntegerDivideByZero; + break; + case FPE_INTOVF: + reason = ProcessMessage::eIntegerOverflow; + break; + case FPE_FLTDIV: + reason = ProcessMessage::eFloatDivideByZero; + break; + case FPE_FLTOVF: + reason = ProcessMessage::eFloatOverflow; + break; + case FPE_FLTUND: + reason = ProcessMessage::eFloatUnderflow; + break; + case FPE_FLTRES: + reason = ProcessMessage::eFloatInexactResult; + break; + case FPE_FLTINV: + reason = ProcessMessage::eFloatInvalidOperation; + break; + case FPE_FLTSUB: + reason = ProcessMessage::eFloatSubscriptRange; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGBUS); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGBUS"); + break; + case BUS_ADRALN: + reason = ProcessMessage::eIllegalAlignment; + break; + case BUS_ADRERR: + reason = ProcessMessage::eIllegalAddress; + break; + case BUS_OBJERR: + reason = ProcessMessage::eHardwareError; + break; + } + + return reason; +} + +void +ProcessMonitor::ServeOperation(OperationArgs *args) +{ + int status; + pollfd fdset; + + ProcessMonitor *monitor = args->m_monitor; + + fdset.fd = monitor->m_server_fd; + fdset.events = POLLIN | POLLPRI; + fdset.revents = 0; + + // We are finised with the arguments and are ready to go. Sync with the + // parent thread and start serving operations on the inferior. + sem_post(&args->m_semaphore); + + for (;;) + { + if ((status = poll(&fdset, 1, -1)) < 0) + { + switch (errno) + { + default: + assert(false && "Unexpected poll() failure!"); + continue; + + case EINTR: continue; // Just poll again. + case EBADF: return; // Connection terminated. + } + } + + assert(status == 1 && "Too many descriptors!"); + + if (fdset.revents & POLLIN) + { + Operation *op = NULL; + + READ_AGAIN: + if ((status = read(fdset.fd, &op, sizeof(op))) < 0) + { + // There is only one acceptable failure. + assert(errno == EINTR); + goto READ_AGAIN; + } + + assert(status == sizeof(op)); + op->Execute(monitor); + write(fdset.fd, &op, sizeof(op)); + } + } +} + +void +ProcessMonitor::DoOperation(Operation *op) +{ + int status; + Operation *ack = NULL; + Mutex::Locker lock(m_server_mutex); + + // FIXME: Do proper error checking here. + write(m_client_fd, &op, sizeof(op)); + +READ_AGAIN: + if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0) + { + // If interrupted by a signal handler try again. Otherwise the monitor + // thread probably died and we have a stale file descriptor -- abort the + // operation. + if (errno == EINTR) + goto READ_AGAIN; + return; + } + + assert(status == sizeof(ack)); + assert(ack == op && "Invalid monitor thread response!"); +} + +size_t +ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + Error &error) +{ + size_t result; + ReadOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; +} + +size_t +ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) +{ + size_t result; + WriteOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) +{ + bool result; + ReadRegOperation op(offset, size, value, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value) +{ + bool result; + WriteRegOperation op(offset, value, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadGPR(void *buf) +{ + bool result; + ReadGPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadFPR(void *buf) +{ + bool result; + ReadFPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteGPR(void *buf) +{ + bool result; + WriteGPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteFPR(void *buf) +{ + bool result; + WriteFPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) +{ + bool result; + ResumeOperation op(tid, signo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo) +{ + bool result; + SingleStepOperation op(tid, signo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::BringProcessIntoLimbo() +{ + bool result; + KillOperation op(result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo) +{ + bool result; + SiginfoOperation op(tid, siginfo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) +{ + bool result; + EventMessageOperation op(tid, message, result); + DoOperation(&op); + return result; +} + +Error +ProcessMonitor::Detach() +{ + Error result; + DetachOperation op(result); + DoOperation(&op); + StopMonitor(); + return result; +} + +bool +ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) +{ + int target_fd = open(path, flags, 0666); + + if (target_fd == -1) + return false; + + return (dup2(target_fd, fd) == -1) ? false : true; +} + +void +ProcessMonitor::StopMonitoringChildProcess() +{ + lldb::thread_result_t thread_result; + + if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + Host::ThreadCancel(m_monitor_thread, NULL); + Host::ThreadJoin(m_monitor_thread, &thread_result, NULL); + m_monitor_thread = LLDB_INVALID_HOST_THREAD; + } +} + +void +ProcessMonitor::StopMonitor() +{ + StopMonitoringChildProcess(); + StopLaunchOpThread(); + CloseFD(m_terminal_fd); + CloseFD(m_client_fd); + CloseFD(m_server_fd); +} + +void +ProcessMonitor::CloseFD(int &fd) +{ + if (fd != -1) + { + close(fd); + fd = -1; + } +} Index: source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h =================================================================== --- source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) +++ source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) @@ -0,0 +1,43 @@ +//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ +#define liblldb_RegisterContextFreeBSD_x86_64_H_ + + typedef struct _GPR + { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rbx; + uint64_t rdx; + uint64_t rcx; + uint64_t rax; + uint32_t trapno; + uint16_t fs; + uint16_t gs; + uint32_t err; + uint16_t es; + uint16_t ds; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; + } GPR; + +#endif Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) @@ -0,0 +1,136 @@ +//===-- ProcessFreeBSD.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 + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Target.h" + +#include "ProcessFreeBSD.h" +#include "ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "ProcessMonitor.h" +#include "POSIXThread.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------------ +// Static functions. + +Process* +ProcessFreeBSD::CreateInstance(Target& target, Listener &listener) +{ + return new ProcessFreeBSD(target, listener); +} + +void +ProcessFreeBSD::Initialize() +{ + static bool g_initialized = false; + + if (!g_initialized) + { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + Log::Callbacks log_callbacks = { + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories + }; + + Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks); + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); + g_initialized = true; + } +} + +const char * +ProcessFreeBSD::GetPluginNameStatic() +{ + return "freebsd"; +} + +const char * +ProcessFreeBSD::GetPluginDescriptionStatic() +{ + return "Process plugin for FreeBSD"; +} + +//------------------------------------------------------------------------------ +// ProcessInterface protocol. + +const char * +ProcessFreeBSD::GetPluginName() +{ + return "process.freebsd"; +} + +const char * +ProcessFreeBSD::GetShortPluginName() +{ + return "process.freebsd"; +} + +uint32_t +ProcessFreeBSD::GetPluginVersion() +{ + return 1; +} + +void +ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) +{ +} + +Error +ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) +{ + return Error(1, eErrorTypeGeneric); +} + +Log * +ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) + : ProcessPOSIX(target, listener) +{ + // FIXME: Putting this code in the ctor and saving the byte order in a + // member variable is a hack to avoid const qual issues in GetByteOrder. + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); + m_byte_order = obj_file->GetByteOrder(); +} + +void +ProcessFreeBSD::Terminate() +{ +} + +uint32_t +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + // XXX haxx + new_thread_list = old_thread_list; + + return 0; +} Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) @@ -0,0 +1,292 @@ +//===-- ProcessMonitor.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_ProcessMonitor_H_ +#define liblldb_ProcessMonitor_H_ + +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/lldb-types.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private +{ +class Error; +class Module; +class Scalar; +} // End lldb_private namespace. + +class ProcessFreeBSD; +class Operation; + +/// @class ProcessMonitor +/// @brief Manages communication with the inferior (debugee) process. +/// +/// Upon construction, this class prepares and launches an inferior process for +/// debugging. +/// +/// Changes in the inferior process state are propagated to the associated +/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the +/// appropriate ProcessMessage events. +/// +/// A purposely minimal set of operations are provided to interrogate and change +/// the inferior process state. +class ProcessMonitor +{ +public: + + /// Launches an inferior process ready for debugging. Forms the + /// implementation of Process::DoLaunch. + ProcessMonitor(ProcessPOSIX *process, + lldb_private::Module *module, + char const *argv[], + char const *envp[], + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + lldb_private::Error &error); + + ProcessMonitor(ProcessPOSIX *process, + lldb::pid_t pid, + lldb_private::Error &error); + + ~ProcessMonitor(); + + /// Provides the process number of debugee. + lldb::pid_t + GetPID() const { return m_pid; } + + /// Returns the process associated with this ProcessMonitor. + ProcessFreeBSD & + GetProcess() { return *m_process; } + + /// Returns a file descriptor to the controlling terminal of the inferior + /// process. + /// + /// Reads from this file descriptor yield both the standard output and + /// standard error of this debugee. Even if stderr and stdout were + /// redirected on launch it may still happen that data is available on this + /// descriptor (if the inferior process opens /dev/tty, for example). + /// + /// If this monitor was attached to an existing process this method returns + /// -1. + int + GetTerminalFD() const { return m_terminal_fd; } + + /// Reads @p size bytes from address @vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoReadMemory. + size_t + ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error); + + /// Writes @p size bytes from address @p vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoWriteMemory. + size_t + WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error); + + /// Reads the contents from the register identified by the given (architecture + /// dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); + + /// Writes the given value to the register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value); + + /// Reads all general purpose registers into the specified buffer. + bool + ReadGPR(void *buf); + + /// Reads all floating point registers into the specified buffer. + bool + ReadFPR(void *buf); + + /// Writes all general purpose registers into the specified buffer. + bool + WriteGPR(void *buf); + + /// Writes all floating point registers into the specified buffer. + bool + WriteFPR(void *buf); + + /// Writes a siginfo_t structure corresponding to the given thread ID to the + /// memory region pointed to by @p siginfo. + bool + GetSignalInfo(lldb::tid_t tid, void *siginfo); + + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) + /// corresponding to the given thread IDto the memory pointed to by @p + /// message. + bool + GetEventMessage(lldb::tid_t tid, unsigned long *message); + + /// Resumes the given thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + bool + Resume(lldb::tid_t tid, uint32_t signo); + + /// Single steps the given thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + bool + SingleStep(lldb::tid_t tid, uint32_t signo); + + /// Sends the inferior process a PTRACE_KILL signal. The inferior will + /// still exists and can be interrogated. Once resumed it will exit as + /// though it received a SIGKILL. + bool + BringProcessIntoLimbo(); + + lldb_private::Error + Detach(); + + +private: + ProcessFreeBSD *m_process; + + lldb::thread_t m_operation_thread; + lldb::thread_t m_monitor_thread; + lldb::pid_t m_pid; + + + lldb_private::Mutex m_server_mutex; + int m_terminal_fd; + int m_client_fd; + int m_server_fd; + + struct OperationArgs + { + OperationArgs(ProcessMonitor *monitor); + + ~OperationArgs(); + + ProcessMonitor *m_monitor; // The monitor performing the attach. + sem_t m_semaphore; // Posted to once operation complete. + lldb_private::Error m_error; // Set if process operation failed. + }; + + /// @class LauchArgs + /// + /// @brief Simple structure to pass data to the thread responsible for + /// launching a child process. + struct LaunchArgs : OperationArgs + { + LaunchArgs(ProcessMonitor *monitor, + lldb_private::Module *module, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path); + + ~LaunchArgs(); + + lldb_private::Module *m_module; // The executable image to launch. + char const **m_argv; // Process arguments. + char const **m_envp; // Process environment. + const char *m_stdin_path; // Redirect stdin or NULL. + const char *m_stdout_path; // Redirect stdout or NULL. + const char *m_stderr_path; // Redirect stderr or NULL. + }; + + void + StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); + + void + StopLaunchOpThread(); + + static void * + LaunchOpThread(void *arg); + + static bool + Launch(LaunchArgs *args); + + bool + EnableIPC(); + + struct AttachArgs : OperationArgs + { + AttachArgs(ProcessMonitor *monitor, + lldb::pid_t pid); + + ~AttachArgs(); + + lldb::pid_t m_pid; // pid of the process to be attached. + }; + + void + StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); + + void + StopAttachOpThread(); + + static void * + AttachOpThread(void *args); + + static bool + Attach(AttachArgs *args); + + static void + ServeOperation(OperationArgs *args); + + static bool + DupDescriptor(const char *path, int fd, int flags); + + static bool + MonitorCallback(void *callback_baton, + lldb::pid_t pid, bool exited, int signal, int status); + + static ProcessMessage + MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); + + static ProcessMessage + MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGSEGV(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGILL(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGFPE(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGBUS(const siginfo_t *info); + + void + DoOperation(Operation *op); + + /// Stops the child monitor thread. + void + StopMonitoringChildProcess(); + + void + StopMonitor(); + + void + CloseFD(int &fd); +}; + +#endif // #ifndef liblldb_ProcessMonitor_H_ Index: source/Plugins/Process/FreeBSD/Makefile =================================================================== --- source/Plugins/Process/FreeBSD/Makefile (revision 0) +++ source/Plugins/Process/FreeBSD/Makefile (revision 0) @@ -0,0 +1,17 @@ +##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginProcessFreeBSD +BUILD_ARCHIVE = 1 + +# Extend the include path so we may locate UnwindLLDB.h +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility + +include $(LLDB_LEVEL)/Makefile Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp (revision 147560) +++ source/Target/Platform.cpp (working copy) @@ -572,6 +572,16 @@ Error &error) { ProcessSP process_sp; + + launch_info.GetFlags ().Set (eLaunchFlagDebug); + const char *plugin_name = launch_info.GetProcessPluginName(); + process_sp = target->CreateProcess (listener, plugin_name).get(); + error = process_sp->Launch (launch_info); + return process_sp; + + +#if 0 + ProcessSP process_sp; // Make sure we stop at the entry point launch_info.GetFlags ().Set (eLaunchFlagDebug); error = LaunchProcess (launch_info); @@ -602,4 +612,5 @@ } } return process_sp; +#endif } Index: source/Target/TargetList.cpp =================================================================== --- source/Target/TargetList.cpp (revision 147560) +++ source/Target/TargetList.cpp (working copy) @@ -72,7 +72,8 @@ if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); - ArchSpec arch; + // Unclear why I need to init this and others don't + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); if (triple_cstr) { @@ -83,6 +84,7 @@ return error; } } + error = TargetList::CreateTarget (debugger, file, arch, Index: source/Host/linux/Host.cpp =================================================================== --- source/Host/linux/Host.cpp (revision 147560) +++ source/Host/linux/Host.cpp (working copy) @@ -10,12 +10,20 @@ // C Includes #include #include +#include +#include +#include + // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Error.h" +#include "lldb/Target/Process.h" + #include "lldb/Host/Host.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" using namespace lldb; using namespace lldb_private; @@ -43,3 +51,48 @@ return error; } +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + static const size_t path_size = 128; + static char path[path_size]; + lldb::DataBufferSP buf_sp; + + int fd; + + // Ideally, we would simply create a FileSpec and call ReadFileContents. + // However, files in procfs have zero size (since they are, in general, + // dynamically generated by the kernel) which is incompatible with the + // current ReadFileContents implementation. Therefore we simply stream the + // data into a DataBuffer ourselves. + if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0) + return buf_sp; + + if ((fd = open(path, O_RDONLY, 0)) < 0) + return buf_sp; + + size_t bytes_read = 0; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + for (;;) + { + size_t avail = buf_ap->GetByteSize() - bytes_read; + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); + + if (status < 0) + break; + + bytes_read += status; + + if (status == 0) + { + buf_ap->SetByteSize(bytes_read); + buf_sp.reset(buf_ap.release()); + break; + } + + if (avail - status == 0) + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); + } + + return buf_sp; +} Index: source/Host/freebsd/Host.cpp =================================================================== --- source/Host/freebsd/Host.cpp (revision 147560) +++ source/Host/freebsd/Host.cpp (working copy) @@ -9,12 +9,18 @@ // C Includes #include +#include #include #include #include #include #include +#include +#include +#include + + // C++ Includes // Other libraries and framework includes // Project includes @@ -26,15 +32,19 @@ #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "llvm/Support/Host.h" + extern "C" { - char **environ; + extern char **environ; } using namespace lldb; using namespace lldb_private; + class FreeBSDThread { public: @@ -77,7 +87,7 @@ std::vector frame_buffer (max_frames, NULL); int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); - + const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) @@ -101,7 +111,7 @@ { char *v; char **var = environ; - for (var = environ; var != NULL; ++var) { + for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; @@ -168,49 +178,47 @@ ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; char arg_data[8192]; size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) { DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); uint32_t offset = 0; - uint32_t start_offset; - uint32_t argc = data.GetU32 (&offset); const char *cstr; - + cstr = data.GetCStr (&offset); if (cstr) { process_info.GetExecutableFile().SetFile(cstr, false); - if (match_info_ptr == NULL || + if (!(match_info_ptr == NULL || NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName())) + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) { - // Skip NULLs - while (1) + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - const uint8_t *p = data.PeekData(offset, 1); - if ((p == NULL) || (*p != '\0')) - break; ++offset; + p = data.PeekData(offset, 1); } - // Now extract all arguments - Args &proc_args = process_info.GetArguments(); - for (int i=0; i= arg_data_size) + return true; + + cstr = data.GetCStr(&offset); + if (cstr) + proc_args.AppendArgument(cstr); + else + return true; } } - } + } } return false; } @@ -219,8 +227,8 @@ GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - // TODO: This - // return true; + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); + return true; } process_info.GetArchitecture().Clear(); return false; @@ -249,7 +257,7 @@ if (proc_kinfo.ki_ngroups > 0) process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); else - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return true; } } @@ -258,7 +266,7 @@ process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return false; } @@ -275,3 +283,46 @@ process_info.Clear(); return false; } + +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; + void *ps_strings_addr, *auxv_addr; + size_t ps_strings_size = sizeof(void *); + Elf_Auxinfo aux_info[AT_COUNT]; + struct ps_strings ps_strings; + struct ptrace_io_desc pid; + DataBufferSP buf_sp; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { + pid.piod_op = PIOD_READ_D; + pid.piod_addr = &ps_strings; + pid.piod_offs = ps_strings_addr; + pid.piod_len = sizeof(ps_strings); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch ps_strings"); + buf_ap.release(); + goto done; + } + + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; + + pid.piod_addr = aux_info; + pid.piod_offs = auxv_addr; + pid.piod_len = sizeof(aux_info); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch aux_info"); + buf_ap.release(); + goto done; + } + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); + buf_sp.reset(buf_ap.release()); + } else { + perror("sysctl failed on ps_strings"); + } + + done: + return buf_sp; +} Index: source/lldb.cpp =================================================================== --- source/lldb.cpp (revision 147560) +++ source/lldb.cpp (working copy) @@ -52,13 +52,16 @@ #endif #if defined (__linux__) -#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h" +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/Linux/PlatformLinux.h" #include "Plugins/Process/Linux/ProcessLinux.h" #endif #if defined (__FreeBSD__) +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" +#include "Plugins/Process/POSIX/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #endif #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" @@ -120,10 +123,12 @@ //---------------------------------------------------------------------- PlatformLinux::Initialize(); ProcessLinux::Initialize(); - DynamicLoaderLinuxDYLD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Initialize(); + PlatformFreeBSD::Initialize(); + ProcessFreeBSD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif //---------------------------------------------------------------------- // Platform agnostic plugins @@ -190,11 +195,13 @@ #if defined (__linux__) PlatformLinux::Terminate(); ProcessLinux::Terminate(); - DynamicLoaderLinuxDYLD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Terminate(); + PlatformFreeBSD::Terminate(); + ProcessFreeBSD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif DynamicLoaderStatic::Terminate(); Index: tools/driver/Makefile =================================================================== --- tools/driver/Makefile (revision 147560) +++ tools/driver/Makefile (working copy) @@ -25,7 +25,6 @@ ifeq ($(HOST_OS),FreeBSD) CPP.Flags += -I/usr/include/edit #-v - LD.Flags += -lEnhancedDisassembly LD.Flags += -Wl,-rpath,$(LibDir) endif Index: lib/Makefile =================================================================== --- lib/Makefile (revision 147560) +++ lib/Makefile (working copy) @@ -81,15 +81,19 @@ endif ifeq ($(HOST_OS),Linux) - USEDLIBS += lldbPluginProcessLinux.a \ - lldbPluginDynamicLoaderLinux.a \ + USEDLIBS += lldbPluginProcessPOSIX.a \ + lldbPluginProcessLinux.a \ + lldbPluginDynamicLoaderPOSIX.a \ lldbPluginPlatformLinux.a \ lldbHostLinux.a endif ifeq ($(HOST_OS),FreeBSD) USEDLIBS += lldbHostFreeBSD.a \ - lldbPluginPlatformFreeBSD.a + lldbPluginDynamicLoaderPOSIX.a \ + lldbPluginProcessPOSIX.a \ + lldbPluginProcessFreeBSD.a \ + lldbPluginPlatformFreeBSD.a endif include $(LEVEL)/Makefile.common @@ -130,8 +134,8 @@ # Include everything from the .a's into the shared library. ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \ -Wl,--no-whole-archive - # Don't allow unresolved symbols. - LLVMLibsOptions += -Wl,--no-undefined + # Allow unresolved symbols. + LLVMLibsOptions += -Wl,--allow-shlib-undefined # Link in python LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo endif Index: Makefile =================================================================== --- Makefile (revision 147560) +++ Makefile (working copy) @@ -39,6 +39,7 @@ CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX ifeq ($(HOST_OS),Darwin) CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks endif From johnny.chen at apple.com Wed Jan 4 18:41:08 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 04 Jan 2012 16:41:08 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120104232604.GA29483@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> Message-ID: <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> Hi Dawn, The patch looks good. I have a couple of questions on source/Target/Platform.cpp and source/Target/TargetList.cpp, though. Please commit the patch except the two files. Here are my questions: The Platform.cpp patch looks wrong? Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp (revision 147560) +++ source/Target/Platform.cpp (working copy) @@ -572,6 +572,16 @@ Error &error) { ProcessSP process_sp; + + launch_info.GetFlags ().Set (eLaunchFlagDebug); + const char *plugin_name = launch_info.GetProcessPluginName(); + process_sp = target->CreateProcess (listener, plugin_name).get(); + error = process_sp->Launch (launch_info); + return process_sp; + + +#if 0 + ProcessSP process_sp; // Make sure we stop at the entry point launch_info.GetFlags ().Set (eLaunchFlagDebug); error = LaunchProcess (launch_info); @@ -602,4 +612,5 @@ } } return process_sp; +#endif } Also, I'll ask Greg to review the TargetList.cpp question you have. Please don't commit it for the time being. Index: source/Target/TargetList.cpp =================================================================== --- source/Target/TargetList.cpp (revision 147560) +++ source/Target/TargetList.cpp (working copy) @@ -72,7 +72,8 @@ if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); - ArchSpec arch; + // Unclear why I need to init this and others don't + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); if (triple_cstr) { @@ -83,6 +84,7 @@ return error; } } + error = TargetList::CreateTarget (debugger, file, arch, On Jan 4, 2012, at 3:26 PM, dawn at burble.org wrote: > > This patch combines common code from Linux and FreeBSD into > a new POSIX platform. It also contains fixes for 64bit FreeBSD. > > The patch is based on changes by Mark Peek and > "K. Macy" in their > github repo located at https://github.com/fbsd/lldb. > > Ok to commit? > Thanks! > -Dawn > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits From dawn at burble.org Wed Jan 4 19:11:13 2012 From: dawn at burble.org (dawn at burble.org) Date: Wed, 4 Jan 2012 17:11:13 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD In-Reply-To: <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> Message-ID: <20120105011113.GA30805@bloodbath.burble.org> On Wed, Jan 04, 2012 at 04:41:08PM -0800, Johnny Chen wrote: > Hi Dawn, > > The patch looks good. I have a couple of questions on source/Target/Platform.cpp and source/Target/TargetList.cpp, though. > Please commit the patch except the two files. > > Here are my questions: > > The Platform.cpp patch looks wrong? Sorry - you're right. That was a left over from a mis-applied git patch that I thought I had reverted. I will fix ASAP and resubmit. Thanks for catching this!!! ...stay tuned... > Index: source/Target/Platform.cpp > =================================================================== > --- source/Target/Platform.cpp (revision 147560) > +++ source/Target/Platform.cpp (working copy) > @@ -572,6 +572,16 @@ > Error &error) > { > ProcessSP process_sp; > + > + launch_info.GetFlags ().Set (eLaunchFlagDebug); > + const char *plugin_name = launch_info.GetProcessPluginName(); > + process_sp = target->CreateProcess (listener, plugin_name).get(); > + error = process_sp->Launch (launch_info); > + return process_sp; > + > + > +#if 0 > + ProcessSP process_sp; > // Make sure we stop at the entry point > launch_info.GetFlags ().Set (eLaunchFlagDebug); > error = LaunchProcess (launch_info); > @@ -602,4 +612,5 @@ > } > } > return process_sp; > +#endif > } > > Also, I'll ask Greg to review the TargetList.cpp question you have. > Please don't commit it for the time being. > > Index: source/Target/TargetList.cpp > =================================================================== > --- source/Target/TargetList.cpp (revision 147560) > +++ source/Target/TargetList.cpp (working copy) > @@ -72,7 +72,8 @@ > if (!platform_sp) > platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); > > - ArchSpec arch; > + // Unclear why I need to init this and others don't > + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); > > if (triple_cstr) > { > @@ -83,6 +84,7 @@ > return error; > } > } > + > error = TargetList::CreateTarget (debugger, > file, > arch, > > On Jan 4, 2012, at 3:26 PM, dawn at burble.org wrote: > > > > > This patch combines common code from Linux and FreeBSD into > > a new POSIX platform. It also contains fixes for 64bit FreeBSD. > > > > The patch is based on changes by Mark Peek and > > "K. Macy" in their > > github repo located at https://github.com/fbsd/lldb. > > > > Ok to commit? > > Thanks! > > -Dawn > > _______________________________________________ > > lldb-commits mailing list > > lldb-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits From scallanan at apple.com Wed Jan 4 19:11:10 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 05 Jan 2012 01:11:10 -0000 Subject: [Lldb-commits] [lldb] r147587 - in /lldb/trunk/source: Core/ValueObjectConstResult.cpp Target/ABI.cpp Message-ID: <20120105011110.0E02E2A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 19:11:09 2012 New Revision: 147587 URL: http://llvm.org/viewvc/llvm-project?rev=147587&view=rev Log: Fixed a dangling pointer bug associated with the result variable on a "finish" statement. The ownership of the result value was not being properly assigned to the newly-created persistent result variable; now it is. Modified: lldb/trunk/source/Core/ValueObjectConstResult.cpp lldb/trunk/source/Target/ABI.cpp Modified: lldb/trunk/source/Core/ValueObjectConstResult.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectConstResult.cpp?rev=147587&r1=147586&r2=147587&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectConstResult.cpp (original) +++ lldb/trunk/source/Core/ValueObjectConstResult.cpp Wed Jan 4 19:11:09 2012 @@ -98,6 +98,13 @@ m_impl(this, address) { m_data = data; + + if (!m_data.GetSharedDataBuffer()) + { + DataBufferSP shared_data_buffer(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); + m_data.SetData(shared_data_buffer); + } + m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); m_value.SetValueType(Value::eValueTypeHostAddress); m_value.SetContext(Value::eContextTypeClangType, clang_type); Modified: lldb/trunk/source/Target/ABI.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ABI.cpp?rev=147587&r1=147586&r2=147587&view=diff ============================================================================== --- lldb/trunk/source/Target/ABI.cpp (original) +++ lldb/trunk/source/Target/ABI.cpp Wed Jan 4 19:11:09 2012 @@ -156,6 +156,7 @@ // we don't do anything with these for now break; case Value::eValueTypeScalar: + clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried; clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; break; @@ -164,8 +165,8 @@ clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference; break; } + return_valobj_sp = clang_expr_variable_sp->GetValueObject(); - } return return_valobj_sp; } From johnny.chen at apple.com Wed Jan 4 19:26:01 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 05 Jan 2012 01:26:01 -0000 Subject: [Lldb-commits] [lldb] r147590 - /lldb/trunk/source/Target/TargetList.cpp Message-ID: <20120105012601.DD69C2A6C12C@llvm.org> Author: johnny Date: Wed Jan 4 19:26:01 2012 New Revision: 147590 URL: http://llvm.org/viewvc/llvm-project?rev=147590&view=rev Log: Add comment explaining the default constructor (ArchSpec) used in CreateTarget(). Modified: lldb/trunk/source/Target/TargetList.cpp Modified: lldb/trunk/source/Target/TargetList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/TargetList.cpp?rev=147590&r1=147589&r2=147590&view=diff ============================================================================== --- lldb/trunk/source/Target/TargetList.cpp (original) +++ lldb/trunk/source/Target/TargetList.cpp Wed Jan 4 19:26:01 2012 @@ -72,6 +72,9 @@ if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); + // This is purposely left empty unless it is specified by triple_cstr. + // If not initialized via triple_cstr, then the currently selected platform + // will set the architecture correctly. ArchSpec arch; if (triple_cstr) From scallanan at apple.com Wed Jan 4 20:00:15 2012 From: scallanan at apple.com (Sean Callanan) Date: Thu, 05 Jan 2012 02:00:15 -0000 Subject: [Lldb-commits] [lldb] r147592 - /lldb/trunk/source/Target/Process.cpp Message-ID: <20120105020015.2B46D2A6C12C@llvm.org> Author: spyffe Date: Wed Jan 4 20:00:14 2012 New Revision: 147592 URL: http://llvm.org/viewvc/llvm-project?rev=147592&view=rev Log: Fixed a potential hang while trying to execute a function in the inferior. Modified: lldb/trunk/source/Target/Process.cpp Modified: lldb/trunk/source/Target/Process.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=147592&r1=147591&r2=147592&view=diff ============================================================================== --- lldb/trunk/source/Target/Process.cpp (original) +++ lldb/trunk/source/Target/Process.cpp Wed Jan 4 20:00:14 2012 @@ -3796,7 +3796,7 @@ real_timeout.OffsetWithMicroSeconds(500000); timeout_ptr = &real_timeout; - got_event = listener.WaitForEvent(NULL, event_sp); + got_event = listener.WaitForEvent(timeout_ptr, event_sp); if (!got_event) { if (log) From dawn at burble.org Wed Jan 4 20:04:17 2012 From: dawn at burble.org (dawn at burble.org) Date: Wed, 4 Jan 2012 18:04:17 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120105011113.GA30805@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> <20120105011113.GA30805@bloodbath.burble.org> Message-ID: <20120105020417.GA31220@bloodbath.burble.org> Looks like only source/Target/Platform.cpp had left-overs from the bad git patch, so we're good now. New patches attached: lldb_svnR147560_POSIX_TargetList.patch - changes to TargetList.cpp separated out. lldb_svnR147560_POSIX.patch - changes sans Platform.cpp and TargetList.cpp The changes to TargetList.cpp are needed by both BSD and Linux in order for Attach() to work. I spent a lot of time debugging this one, and the BSD folks came to the same conclusion. I'll dig through my notes and try to write up my findings - should this be discussed here or on lldb-dev? So I should go ahead and commit the rest of the patch? I've commited to clang but never lldb - I can give it a try... Thanks, -Dawn On Wed, Jan 04, 2012 at 05:11:13PM -0800, dawn at burble.org wrote: > On Wed, Jan 04, 2012 at 04:41:08PM -0800, Johnny Chen wrote: > > Hi Dawn, > > > > The patch looks good. I have a couple of questions on source/Target/Platform.cpp and source/Target/TargetList.cpp, though. > > Please commit the patch except the two files. > > > > Here are my questions: > > > > The Platform.cpp patch looks wrong? > > Sorry - you're right. That was a left over from a mis-applied git patch > that I thought I had reverted. I will fix ASAP and resubmit. > > Thanks for catching this!!! > > ...stay tuned... > > > Index: source/Target/Platform.cpp > > =================================================================== > > --- source/Target/Platform.cpp (revision 147560) > > +++ source/Target/Platform.cpp (working copy) > > @@ -572,6 +572,16 @@ > > Error &error) > > { > > ProcessSP process_sp; > > + > > + launch_info.GetFlags ().Set (eLaunchFlagDebug); > > + const char *plugin_name = launch_info.GetProcessPluginName(); > > + process_sp = target->CreateProcess (listener, plugin_name).get(); > > + error = process_sp->Launch (launch_info); > > + return process_sp; > > + > > + > > +#if 0 > > + ProcessSP process_sp; > > // Make sure we stop at the entry point > > launch_info.GetFlags ().Set (eLaunchFlagDebug); > > error = LaunchProcess (launch_info); > > @@ -602,4 +612,5 @@ > > } > > } > > return process_sp; > > +#endif > > } > > > > Also, I'll ask Greg to review the TargetList.cpp question you have. > > Please don't commit it for the time being. > > > > Index: source/Target/TargetList.cpp > > =================================================================== > > --- source/Target/TargetList.cpp (revision 147560) > > +++ source/Target/TargetList.cpp (working copy) > > @@ -72,7 +72,8 @@ > > if (!platform_sp) > > platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); > > > > - ArchSpec arch; > > + // Unclear why I need to init this and others don't > > + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); > > > > if (triple_cstr) > > { > > @@ -83,6 +84,7 @@ > > return error; > > } > > } > > + > > error = TargetList::CreateTarget (debugger, > > file, > > arch, > > > > On Jan 4, 2012, at 3:26 PM, dawn at burble.org wrote: > > > > > > > > This patch combines common code from Linux and FreeBSD into > > > a new POSIX platform. It also contains fixes for 64bit FreeBSD. > > > > > > The patch is based on changes by Mark Peek and > > > "K. Macy" in their > > > github repo located at https://github.com/fbsd/lldb. > > > > > > Ok to commit? > > > Thanks! > > > -Dawn > > > _______________________________________________ > > > lldb-commits mailing list > > > lldb-commits at cs.uiuc.edu > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits -------------- next part -------------- Index: source/Target/TargetList.cpp =================================================================== --- source/Target/TargetList.cpp (revision 147560) +++ source/Target/TargetList.cpp (working copy) @@ -72,7 +72,8 @@ if (!platform_sp) platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); - ArchSpec arch; + // Unclear why I need to init this and others don't + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); if (triple_cstr) { @@ -83,6 +84,7 @@ return error; } } + error = TargetList::CreateTarget (debugger, file, arch, -------------- next part -------------- Index: include/lldb/Host/Host.h =================================================================== --- include/lldb/Host/Host.h (revision 147560) +++ include/lldb/Host/Host.h (working copy) @@ -355,7 +355,10 @@ static Error LaunchProcess (ProcessLaunchInfo &launch_info); - + + static lldb::DataBufferSP + GetAuxvData (lldb_private::Process *process); + static lldb::TargetSP GetDummyTarget (Debugger &debugger); Index: source/Plugins/Platform/Linux/PlatformLinux.h =================================================================== --- source/Plugins/Platform/Linux/PlatformLinux.h (revision 147560) +++ source/Plugins/Platform/Linux/PlatformLinux.h (working copy) @@ -104,6 +104,7 @@ Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Listener &listener, Error &error); + // Linux processes can not be launched by spawning and attaching. virtual bool CanDebugProcess () { Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (revision 147560) +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (working copy) @@ -27,16 +27,13 @@ Platform * PlatformFreeBSD::CreateInstance () { - // The only time we create an instance is when we are creating a remote - // freebsd platform - const bool is_host = false; - return new PlatformFreeBSD (is_host); + return new PlatformFreeBSD (true); } const char * PlatformFreeBSD::GetPluginNameStatic() { - return "PlatformFreeBSD"; + return "plugin.platform.freebsd"; } const char * @@ -66,7 +63,7 @@ { #if defined (__FreeBSD__) PlatformSP default_platform_sp (CreateInstance()); - //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); Platform::SetDefaultPlatform (default_platform_sp); #endif PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false), @@ -79,7 +76,7 @@ void PlatformFreeBSD::Terminate () { - PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); + PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); } //------------------------------------------------------------------ @@ -385,17 +382,16 @@ bool PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) { - bool sucess = false; + bool success = false; if (IsHost()) { - sucess = Platform::GetProcessInfo (pid, process_info); + success = Platform::GetProcessInfo (pid, process_info); } - else + else if (m_remote_platform_sp) { - if (m_remote_platform_sp) - sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); + success = m_remote_platform_sp->GetProcessInfo (pid, process_info); } - return sucess; + return success; } @@ -438,11 +434,11 @@ } lldb::ProcessSP -PlatformFreeBSD::Attach(lldb::pid_t pid, - Debugger &debugger, - Target *target, - Listener &listener, - Error &error) +PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, + Debugger &debugger, + Target *target, + Listener &listener, + Error &error) { lldb::ProcessSP process_sp; if (IsHost()) @@ -457,6 +453,7 @@ emptyFileSpec, emptyArchSpec, false, + m_remote_platform_sp, new_target_sp); target = new_target_sp.get(); } @@ -472,13 +469,13 @@ process_sp = target->CreateProcess (listener, "gdb-remote"); if (process_sp) - error = process_sp->Attach (pid); + error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); else error.SetErrorString ("the platform is not currently connected"); } Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h =================================================================== --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (revision 147560) +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (working copy) @@ -132,12 +132,16 @@ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); virtual lldb::ProcessSP - Attach(lldb::pid_t pid, + Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Listener &listener, lldb_private::Error &error); + // FreeBSD processes can not be launched by spawning and attaching. + virtual bool + CanDebugProcess () { return false; } + // Only on PlatformMacOSX: virtual lldb_private::Error GetFile (const lldb_private::FileSpec &platform_file, Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (working copy) @@ -1,191 +0,0 @@ -//===-- AuxVector.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 -#include -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" - -#include "AuxVector.h" - -using namespace lldb; -using namespace lldb_private; - -static bool -GetMaxU64(DataExtractor &data, - uint32_t *offset, uint64_t *value, unsigned int byte_size) -{ - uint32_t saved_offset = *offset; - *value = data.GetMaxU64(offset, byte_size); - return *offset != saved_offset; -} - -static bool -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, - uint32_t *offset, unsigned int byte_size) -{ - if (!GetMaxU64(data, offset, &entry.type, byte_size)) - return false; - - if (!GetMaxU64(data, offset, &entry.value, byte_size)) - return false; - - return true; -} - -DataBufferSP -AuxVector::GetAuxvData() -{ - static const size_t path_size = 128; - static char path[path_size]; - DataBufferSP buf_sp; - int fd; - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) - return buf_sp; - - if ((fd = open(path, O_RDONLY, 0)) < 0) - return buf_sp; - - size_t bytes_read = 0; - std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); - for (;;) - { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - bytes_read += status; - - if (status == 0) - { - buf_ap->SetByteSize(bytes_read); - buf_sp.reset(buf_ap.release()); - break; - } - - if (avail - status == 0) - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); - } - - return buf_sp; -} - -void -AuxVector::ParseAuxv(DataExtractor &data) -{ - const unsigned int byte_size = m_process->GetAddressByteSize(); - uint32_t offset = 0; - - for (;;) - { - Entry entry; - - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) - break; - - if (entry.type == AT_NULL) - break; - - if (entry.type == AT_IGNORE) - continue; - - m_auxv.push_back(entry); - } -} - -AuxVector::AuxVector(Process *process) - : m_process(process) -{ - DataExtractor data; - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - data.SetData(GetAuxvData()); - data.SetByteOrder(m_process->GetByteOrder()); - data.SetAddressByteSize(m_process->GetAddressByteSize()); - - ParseAuxv(data); - - if (log) - DumpToLog(log); -} - -AuxVector::iterator -AuxVector::FindEntry(EntryType type) const -{ - for (iterator I = begin(); I != end(); ++I) - { - if (I->type == static_cast(type)) - return I; - } - - return end(); -} - -void -AuxVector::DumpToLog(LogSP log) const -{ - if (!log) - return; - - log->PutCString("AuxVector: "); - for (iterator I = begin(); I != end(); ++I) - { - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); - } -} - -const char * -AuxVector::GetEntryName(EntryType type) -{ - const char *name; - -#define ENTRY_NAME(_type) _type: name = #_type - switch (type) - { - default: - name = "unkown"; - break; - - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - } -#undef ENTRY_NAME - - return name; -} - Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (working copy) @@ -1,322 +0,0 @@ -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "DYLDRendezvous.h" - -using namespace lldb; -using namespace lldb_private; - -/// Locates the address of the rendezvous structure. Returns the address on -/// success and LLDB_INVALID_ADDRESS on failure. -static addr_t -ResolveRendezvousAddress(Process *process) -{ - addr_t info_location; - addr_t info_addr; - Error error; - size_t size; - - info_location = process->GetImageInfoAddress(); - - if (info_location == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - info_addr = 0; - size = process->DoReadMemory(info_location, &info_addr, - process->GetAddressByteSize(), error); - if (size != process->GetAddressByteSize() || error.Fail()) - return LLDB_INVALID_ADDRESS; - - if (info_addr == 0) - return LLDB_INVALID_ADDRESS; - - return info_addr; -} - -DYLDRendezvous::DYLDRendezvous(Process *process) - : m_process(process), - m_rendezvous_addr(LLDB_INVALID_ADDRESS), - m_current(), - m_previous(), - m_soentries(), - m_added_soentries(), - m_removed_soentries() -{ -} - -bool -DYLDRendezvous::Resolve() -{ - const size_t word_size = 4; - Rendezvous info; - size_t address_size; - size_t padding; - addr_t info_addr; - addr_t cursor; - - address_size = m_process->GetAddressByteSize(); - padding = address_size - word_size; - - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) - cursor = info_addr = ResolveRendezvousAddress(m_process); - else - cursor = info_addr = m_rendezvous_addr; - - if (cursor == LLDB_INVALID_ADDRESS) - return false; - - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) - return false; - - // The rendezvous was successfully read. Update our internal state. - m_rendezvous_addr = info_addr; - m_previous = m_current; - m_current = info; - - return UpdateSOEntries(); -} - -bool -DYLDRendezvous::IsValid() -{ - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; -} - -bool -DYLDRendezvous::UpdateSOEntries() -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - // When the previous and current states are consistent this is the first - // time we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return TakeSnapshot(m_soentries); - - // If we are about to add or remove a shared object clear out the current - // state and take a snapshot of the currently loaded images. - if (m_current.state == eAdd || m_current.state == eDelete) - { - assert(m_previous.state == eConsistent); - m_soentries.clear(); - m_added_soentries.clear(); - m_removed_soentries.clear(); - return TakeSnapshot(m_soentries); - } - assert(m_current.state == eConsistent); - - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return UpdateSOEntriesForAddition(); - else if (m_previous.state == eDelete) - return UpdateSOEntriesForDeletion(); - - return false; -} - -bool -DYLDRendezvous::UpdateSOEntriesForAddition() -{ - SOEntry entry; - iterator pos; - - assert(m_previous.state == eAdd); - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) - { - m_soentries.push_back(entry); - m_added_soentries.push_back(entry); - } - } - - return true; -} - -bool -DYLDRendezvous::UpdateSOEntriesForDeletion() -{ - SOEntryList entry_list; - iterator pos; - - assert(m_previous.state == eDelete); - - if (!TakeSnapshot(entry_list)) - return false; - - for (iterator I = begin(); I != end(); ++I) - { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) - m_removed_soentries.push_back(*I); - } - - m_soentries = entry_list; - return true; -} - -bool -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - entry_list.push_back(entry); - } - - return true; -} - -addr_t -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) -{ - size_t bytes_read; - Error error; - - bytes_read = m_process->DoReadMemory(addr, dst, size, error); - if (bytes_read != size || error.Fail()) - return 0; - - return addr + bytes_read; -} - -std::string -DYLDRendezvous::ReadStringFromMemory(addr_t addr) -{ - std::string str; - Error error; - size_t size; - char c; - - if (addr == LLDB_INVALID_ADDRESS) - return std::string(); - - for (;;) { - size = m_process->DoReadMemory(addr, &c, 1, error); - if (size != 1 || error.Fail()) - return std::string(); - if (c == 0) - break; - else { - str.push_back(c); - addr++; - } - } - - return str; -} - -bool -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) -{ - size_t address_size = m_process->GetAddressByteSize(); - - entry.clear(); - - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.next, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) - return false; - - entry.path = ReadStringFromMemory(entry.path_addr); - - return true; -} - -void -DYLDRendezvous::DumpToLog(LogSP log) const -{ - int state = GetState(); - - if (!log) - return; - - log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %lx", GetRendezvousAddress()); - log->Printf(" Version: %d", GetVersion()); - log->Printf(" Link : %lx", GetLinkMapAddress()); - log->Printf(" Break : %lx", GetBreakAddress()); - log->Printf(" LDBase : %lx", GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) ? "consistent" : - (state == eAdd) ? "add" : - (state == eDelete) ? "delete" : "unknown"); - - iterator I = begin(); - iterator E = end(); - - if (I != E) - log->PutCString("DYLDRendezvous SOEntries:"); - - for (int i = 1; I != E; ++I, ++i) - { - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); - log->Printf(" Base : %lx", I->base_addr); - log->Printf(" Path : %lx", I->path_addr); - log->Printf(" Dyn : %lx", I->dyn_addr); - log->Printf(" Next : %lx", I->next); - log->Printf(" Prev : %lx", I->prev); - } -} Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (working copy) @@ -1,97 +0,0 @@ -//===-- AuxVector.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_AuxVector_H_ -#define liblldb_AuxVector_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/lldb-forward-rtti.h" - -namespace lldb_private { -class DataExtractor; -} - -/// @class AuxVector -/// @brief Represents a processes auxiliary vector. -/// -/// When a process is loaded on Linux a vector of values is placed onto the -/// stack communicating operating system specific information. On construction -/// this class locates and parses this information and provides a simple -/// read-only interface to the entries found. -class AuxVector { - -public: - AuxVector(lldb_private::Process *process); - - struct Entry { - uint64_t type; - uint64_t value; - - Entry() : type(0), value(0) { } - }; - - /// Constants describing the type of entry. - enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). - }; - -private: - typedef std::vector EntryVector; - -public: - typedef EntryVector::const_iterator iterator; - - iterator begin() const { return m_auxv.begin(); } - iterator end() const { return m_auxv.end(); } - - iterator - FindEntry(EntryType type) const; - - static const char * - GetEntryName(const Entry &entry) { - return GetEntryName(static_cast(entry.type)); - } - - static const char * - GetEntryName(EntryType type); - - void - DumpToLog(lldb::LogSP log) const; - -private: - lldb_private::Process *m_process; - EntryVector m_auxv; - - lldb::DataBufferSP - GetAuxvData(); - - void - ParseAuxv(lldb_private::DataExtractor &data); -}; - -#endif Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (working copy) @@ -1,227 +0,0 @@ -//===-- DYLDRendezvous.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_Rendezvous_H_ -#define liblldb_Rendezvous_H_ - -// C Includes -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -class Process; -} - -/// @class DYLDRendezvous -/// @brief Interface to the runtime linker. -/// -/// A structure is present in a processes memory space which is updated by the -/// runtime liker each time a module is loaded or unloaded. This class provides -/// an interface to this structure and maintains a consistent snapshot of the -/// currently loaded modules. -class DYLDRendezvous { - - // This structure is used to hold the contents of the debug rendezvous - // information (struct r_debug) as found in the inferiors memory. Note that - // the layout of this struct is not binary compatible, it is simply large - // enough to hold the information on both 32 and 64 bit platforms. - struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; - - Rendezvous() - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } - }; - -public: - DYLDRendezvous(lldb_private::Process *process); - - /// Update the internal snapshot of runtime linker rendezvous and recompute - /// the currently loaded modules. - /// - /// This method should be called once one start up, then once each time the - /// runtime linker enters the function given by GetBreakAddress(). - /// - /// @returns true on success and false on failure. - /// - /// @see GetBreakAddress(). - bool - Resolve(); - - /// @returns true if this rendezvous has been located in the inferiors - /// address space and false otherwise. - bool - IsValid(); - - /// @returns the address of the rendezvous structure in the inferiors - /// address space. - lldb::addr_t - GetRendezvousAddress() const { return m_rendezvous_addr; } - - /// @returns the version of the rendezvous protocol being used. - int - GetVersion() const { return m_current.version; } - - /// @returns address in the inferiors address space containing the linked - /// list of shared object descriptors. - lldb::addr_t - GetLinkMapAddress() const { return m_current.map_addr; } - - /// A breakpoint should be set at this address and Resolve called on each - /// hit. - /// - /// @returns the address of a function called by the runtime linker each - /// time a module is loaded/unloaded, or about to be loaded/unloaded. - /// - /// @see Resolve() - lldb::addr_t - GetBreakAddress() const { return m_current.brk; } - - /// Returns the current state of the rendezvous structure. - int - GetState() const { return m_current.state; } - - /// @returns the base address of the runtime linker in the inferiors address - /// space. - lldb::addr_t - GetLDBase() const { return m_current.ldbase; } - - /// @returns true if modules have been loaded into the inferior since the - /// last call to Resolve(). - bool - ModulesDidLoad() const { return !m_added_soentries.empty(); } - - /// @returns true if modules have been unloaded from the inferior since the - /// last call to Resolve(). - bool - ModulesDidUnload() const { return !m_removed_soentries.empty(); } - - void - DumpToLog(lldb::LogSP log) const; - - /// @brief Constants describing the state of the rendezvous. - /// - /// @see GetState(). - enum RendezvousState { - eConsistent, - eAdd, - eDelete - }; - - /// @brief Structure representing the shared objects currently loaded into - /// the inferior process. - /// - /// This object is a rough analogue to the struct link_map object which - /// actually lives in the inferiors memory. - struct SOEntry { - lldb::addr_t base_addr; ///< Base address of the loaded object. - lldb::addr_t path_addr; ///< String naming the shared object. - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. - lldb::addr_t next; ///< Address of next so_entry. - lldb::addr_t prev; ///< Address of previous so_entry. - std::string path; ///< File name of shared object. - - SOEntry() { clear(); } - - bool operator ==(const SOEntry &entry) { - return this->path == entry.path; - } - - void clear() { - base_addr = 0; - path_addr = 0; - dyn_addr = 0; - next = 0; - prev = 0; - path.clear(); - } - }; - -protected: - typedef std::list SOEntryList; - -public: - typedef SOEntryList::const_iterator iterator; - - /// Iterators over all currently loaded modules. - iterator begin() const { return m_soentries.begin(); } - iterator end() const { return m_soentries.end(); } - - /// Iterators over all modules loaded into the inferior since the last call - /// to Resolve(). - iterator loaded_begin() const { return m_added_soentries.begin(); } - iterator loaded_end() const { return m_added_soentries.end(); } - - /// Iterators over all modules unloaded from the inferior since the last - /// call to Resolve(). - iterator unloaded_begin() const { return m_removed_soentries.begin(); } - iterator unloaded_end() const { return m_removed_soentries.end(); } - -protected: - lldb_private::Process *m_process; - - /// Location of the r_debug structure in the inferiors address space. - lldb::addr_t m_rendezvous_addr; - - /// Current and previous snapshots of the rendezvous structure. - Rendezvous m_current; - Rendezvous m_previous; - - /// List of SOEntry objects corresponding to the current link map state. - SOEntryList m_soentries; - - /// List of SOEntry's added to the link map since the last call to Resolve(). - SOEntryList m_added_soentries; - - /// List of SOEntry's removed from the link map since the last call to - /// Resolve(). - SOEntryList m_removed_soentries; - - /// Reads @p size bytes from the inferiors address space starting at @p - /// addr. - /// - /// @returns addr + size if the read was successful and false otherwise. - lldb::addr_t - ReadMemory(lldb::addr_t addr, void *dst, size_t size); - - /// Reads a null-terminated C string from the memory location starting at @p - /// addr. - std::string - ReadStringFromMemory(lldb::addr_t addr); - - /// Reads an SOEntry starting at @p addr. - bool - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); - - /// Updates the current set of SOEntries, the set of added entries, and the - /// set of removed entries. - bool - UpdateSOEntries(); - - bool - UpdateSOEntriesForAddition(); - - bool - UpdateSOEntriesForDeletion(); - - /// Reads the current list of shared objects according to the link map - /// supplied by the runtime linker. - bool - TakeSnapshot(SOEntryList &entry_list); -}; - -#endif Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (working copy) @@ -1,423 +0,0 @@ -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" - -#include "AuxVector.h" -#include "DynamicLoaderLinuxDYLD.h" - -using namespace lldb; -using namespace lldb_private; - -void -DynamicLoaderLinuxDYLD::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); -} - -void -DynamicLoaderLinuxDYLD::Terminate() -{ -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginName() -{ - return "DynamicLoaderLinuxDYLD"; -} - -const char * -DynamicLoaderLinuxDYLD::GetShortPluginName() -{ - return "linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginNameStatic() -{ - return "dynamic-loader.linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() -{ - return "Dynamic loader plug-in that watches for shared library " - "loads/unloads in Linux processes."; -} - -void -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - -uint32_t -DynamicLoaderLinuxDYLD::GetPluginVersion() -{ - return 1; -} - -DynamicLoader * -DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force) -{ - bool create = force; - if (!create) - { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Linux) - create = true; - } - - if (create) - return new DynamicLoaderLinuxDYLD (process); - return NULL; -} - -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) - : DynamicLoader(process), - m_rendezvous(process), - m_load_offset(LLDB_INVALID_ADDRESS), - m_entry_point(LLDB_INVALID_ADDRESS), - m_auxv(NULL) -{ -} - -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() -{ -} - -void -DynamicLoaderLinuxDYLD::DidAttach() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -void -DynamicLoaderLinuxDYLD::DidLaunch() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - ProbeEntry(); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -Error -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - -Error -DynamicLoaderLinuxDYLD::CanLoadImage() -{ - return Error(); -} - -void -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) -{ - ObjectFile *obj_file = module->GetObjectFile(); - SectionList *sections = obj_file->GetSectionList(); - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); - const size_t num_sections = sections->GetSize(); - - for (unsigned i = 0; i < num_sections; ++i) - { - Section *section = sections->GetSectionAtIndex(i).get(); - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); - - // If the file address of the section is zero then this is not an - // allocatable/loadable section (property of ELF sh_addr). Skip it. - if (new_load_addr == base_addr) - continue; - - if (old_load_addr == LLDB_INVALID_ADDRESS || - old_load_addr != new_load_addr) - load_list.SetSectionLoadAddress(section, new_load_addr); - } -} - -void -DynamicLoaderLinuxDYLD::ProbeEntry() -{ - Breakpoint *entry_break; - addr_t entry; - - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return; - - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); -} - -// The runtime linker has run and initialized the rendezvous structure once the -// process has hit its entry point. When we hit the corresponding breakpoint we -// interrogate the rendezvous structure to get the load addresses of all -// dependent modules for the process. Similarly, we can discover the runtime -// linker function and setup a breakpoint to notify us of any dynamically loaded -// modules (via dlopen). -bool -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->LoadAllCurrentModules(); - dyld_instance->SetRendezvousBreakpoint(); - return false; // Continue running. -} - -void -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() -{ - Breakpoint *dyld_break; - addr_t break_addr; - - break_addr = m_rendezvous.GetBreakAddress(); - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); -} - -bool -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->RefreshModules(); - - // Return true to stop the target, false to just let the target run. - return dyld_instance->GetStopWhenImagesChange(); -} - -void -DynamicLoaderLinuxDYLD::RefreshModules() -{ - if (!m_rendezvous.Resolve()) - return; - - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); - - if (m_rendezvous.ModulesDidLoad()) - { - ModuleList new_modules; - - E = m_rendezvous.loaded_end(); - for (I = m_rendezvous.loaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - new_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidLoad(new_modules); - } - - if (m_rendezvous.ModulesDidUnload()) - { - ModuleList old_modules; - - E = m_rendezvous.unloaded_end(); - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); - if (module_sp.get()) - old_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidUnload(old_modules); - } -} - -ThreadPlanSP -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) -{ - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ThreadPlanSP thread_plan_sp; - - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *sym = context.symbol; - - if (sym == NULL || !sym->IsTrampoline()) - return thread_plan_sp; - - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); - if (!sym_name) - return thread_plan_sp; - - SymbolContextList target_symbols; - Target &target = thread.GetProcess().GetTarget(); - ModuleList &images = target.GetImages(); - - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); - size_t num_targets = target_symbols.GetSize(); - if (!num_targets) - return thread_plan_sp; - - typedef std::vector AddressVector; - AddressVector addrs; - for (size_t i = 0; i < num_targets; ++i) - { - SymbolContext context; - AddressRange range; - if (target_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange(eSymbolContextEverything, 0, false, range); - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); - if (addr != LLDB_INVALID_ADDRESS) - addrs.push_back(addr); - } - } - - if (addrs.size() > 0) - { - AddressVector::iterator start = addrs.begin(); - AddressVector::iterator end = addrs.end(); - - std::sort(start, end); - addrs.erase(std::unique(start, end), end); - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); - } - - return thread_plan_sp; -} - -void -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() -{ - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - ModuleList module_list; - - if (!m_rendezvous.Resolve()) - return; - - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) - { - FileSpec file(I->path.c_str(), false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - module_list.Append(module_sp); - } - - m_process->GetTarget().ModulesDidLoad(module_list); -} - -ModuleSP -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) - { - UpdateLoadedSections(module_sp, base_addr); - } - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) - { - UpdateLoadedSections(module_sp, base_addr); - modules.Append(module_sp); - } - - return module_sp; -} - -addr_t -DynamicLoaderLinuxDYLD::ComputeLoadOffset() -{ - addr_t virt_entry; - - if (m_load_offset != LLDB_INVALID_ADDRESS) - return m_load_offset; - - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - ModuleSP module = m_process->GetTarget().GetExecutableModule(); - ObjectFile *exe = module->GetObjectFile(); - Address file_entry = exe->GetEntryPointAddress(); - - if (!file_entry.IsValid()) - return LLDB_INVALID_ADDRESS; - - m_load_offset = virt_entry - file_entry.GetFileAddress(); - return m_load_offset; -} - -addr_t -DynamicLoaderLinuxDYLD::GetEntryPoint() -{ - if (m_entry_point != LLDB_INVALID_ADDRESS) - return m_entry_point; - - if (m_auxv.get() == NULL) - return LLDB_INVALID_ADDRESS; - - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); - - if (I == m_auxv->end()) - return LLDB_INVALID_ADDRESS; - - m_entry_point = static_cast(I->value); - return m_entry_point; -} Index: source/Plugins/DynamicLoader/Linux-DYLD/Makefile =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/Makefile (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/Makefile (working copy) @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderLinux -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h =================================================================== --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (revision 147560) +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (working copy) @@ -1,165 +0,0 @@ -//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_ -#define liblldb_DynamicLoaderLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Target/DynamicLoader.h" - -#include "DYLDRendezvous.h" - -class AuxVector; - -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader -{ -public: - - static void - Initialize(); - - static void - Terminate(); - - static const char * - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - DynamicLoaderLinuxDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderLinuxDYLD(); - - //------------------------------------------------------------------ - // DynamicLoader protocol - //------------------------------------------------------------------ - - virtual void - DidAttach(); - - virtual void - DidLaunch(); - - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); - - virtual lldb_private::Error - CanLoadImage(); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual const char * - GetPluginName(); - - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - -protected: - /// Runtime linker rendezvous structure. - DYLDRendezvous m_rendezvous; - - /// Virtual load address of the inferior process. - lldb::addr_t m_load_offset; - - /// Virtual entry address of the inferior process. - lldb::addr_t m_entry_point; - - /// Auxiliary vector of the inferior process. - std::auto_ptr m_auxv; - - /// Enables a breakpoint on a function called by the runtime - /// linker each time a module is loaded or unloaded. - void - SetRendezvousBreakpoint(); - - /// Callback routine which updates the current list of loaded modules based - /// on the information supplied by the runtime linker. - static bool - RendezvousBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set - /// of loaded modules. - void - RefreshModules(); - - /// Updates the load address of every allocatable section in @p module. - /// - /// @param module The module to traverse. - /// - /// @param base_addr The virtual base address @p module is loaded at. - void - UpdateLoadedSections(lldb::ModuleSP module, - lldb::addr_t base_addr = 0); - - /// Locates or creates a module given by @p file and updates/loads the - /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); - - /// Resolves the entry point for the current inferior process and sets a - /// breakpoint at that address. - void - ProbeEntry(); - - /// Callback routine invoked when we hit the breakpoint on process entry. - /// - /// This routine is responsible for resolving the load addresses of all - /// dependent modules required by the inferior and setting up the rendezvous - /// breakpoint. - static bool - EntryBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper for the entry breakpoint callback. Resolves the load addresses - /// of all dependent modules. - void - LoadAllCurrentModules(); - - /// Computes a value for m_load_offset returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - ComputeLoadOffset(); - - /// Computes a value for m_entry_point returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - GetEntryPoint(); - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); -}; - -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) @@ -0,0 +1,165 @@ +//===-- DynamicLoaderPOSIX.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_DynamicLoaderPOSIX_H_ +#define liblldb_DynamicLoaderPOSIX_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Target/DynamicLoader.h" + +#include "DYLDRendezvous.h" + +class AuxVector; + +class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader +{ +public: + + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance(lldb_private::Process *process, bool force); + + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + + virtual + ~DynamicLoaderPOSIXDYLD(); + + //------------------------------------------------------------------ + // DynamicLoader protocol + //------------------------------------------------------------------ + + virtual void + DidAttach(); + + virtual void + DidLaunch(); + + virtual lldb::ThreadPlanSP + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others); + + virtual lldb_private::Error + CanLoadImage(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + + virtual void + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + + virtual lldb_private::Error + ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); + + virtual lldb_private::Log * + EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + +protected: + /// Runtime linker rendezvous structure. + DYLDRendezvous m_rendezvous; + + /// Virtual load address of the inferior process. + lldb::addr_t m_load_offset; + + /// Virtual entry address of the inferior process. + lldb::addr_t m_entry_point; + + /// Auxiliary vector of the inferior process. + std::auto_ptr m_auxv; + + /// Enables a breakpoint on a function called by the runtime + /// linker each time a module is loaded or unloaded. + void + SetRendezvousBreakpoint(); + + /// Callback routine which updates the current list of loaded modules based + /// on the information supplied by the runtime linker. + static bool + RendezvousBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set + /// of loaded modules. + void + RefreshModules(); + + /// Updates the load address of every allocatable section in @p module. + /// + /// @param module The module to traverse. + /// + /// @param base_addr The virtual base address @p module is loaded at. + void + UpdateLoadedSections(lldb::ModuleSP module, + lldb::addr_t base_addr = 0); + + /// Locates or creates a module given by @p file and updates/loads the + /// resulting module at the virtual base address @p base_addr. + lldb::ModuleSP + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); + + /// Resolves the entry point for the current inferior process and sets a + /// breakpoint at that address. + void + ProbeEntry(); + + /// Callback routine invoked when we hit the breakpoint on process entry. + /// + /// This routine is responsible for resolving the load addresses of all + /// dependent modules required by the inferior and setting up the rendezvous + /// breakpoint. + static bool + EntryBreakpointHit(void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + /// Helper for the entry breakpoint callback. Resolves the load addresses + /// of all dependent modules. + void + LoadAllCurrentModules(); + + /// Computes a value for m_load_offset returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t + ComputeLoadOffset(); + + /// Computes a value for m_entry_point returning the computed address on + /// success and LLDB_INVALID_ADDRESS on failure. + lldb::addr_t + GetEntryPoint(); + +private: + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); +}; + +#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) @@ -0,0 +1,153 @@ +//===-- AuxVector.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 +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" + +#include "AuxVector.h" + +using namespace lldb; +using namespace lldb_private; + +static bool +GetMaxU64(DataExtractor &data, + uint32_t *offset, uint64_t *value, unsigned int byte_size) +{ + uint32_t saved_offset = *offset; + *value = data.GetMaxU64(offset, byte_size); + return *offset != saved_offset; +} + +static bool +ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, + uint32_t *offset, unsigned int byte_size) +{ + if (!GetMaxU64(data, offset, &entry.type, byte_size)) + return false; + + if (!GetMaxU64(data, offset, &entry.value, byte_size)) + return false; + + return true; +} + +DataBufferSP +AuxVector::GetAuxvData() +{ + + return lldb_private::Host::GetAuxvData(m_process); +} + +void +AuxVector::ParseAuxv(DataExtractor &data) +{ + const unsigned int byte_size = m_process->GetAddressByteSize(); + uint32_t offset = 0; + + for (;;) + { + Entry entry; + + if (!ParseAuxvEntry(data, entry, &offset, byte_size)) + break; + + if (entry.type == AT_NULL) + break; + + if (entry.type == AT_IGNORE) + continue; + + m_auxv.push_back(entry); + } +} + +AuxVector::AuxVector(Process *process) + : m_process(process) +{ + DataExtractor data; + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + + data.SetData(GetAuxvData()); + data.SetByteOrder(m_process->GetByteOrder()); + data.SetAddressByteSize(m_process->GetAddressByteSize()); + + ParseAuxv(data); + + if (log) + DumpToLog(log); +} + +AuxVector::iterator +AuxVector::FindEntry(EntryType type) const +{ + for (iterator I = begin(); I != end(); ++I) + { + if (I->type == static_cast(type)) + return I; + } + + return end(); +} + +void +AuxVector::DumpToLog(LogSP log) const +{ + if (!log) + return; + + log->PutCString("AuxVector: "); + for (iterator I = begin(); I != end(); ++I) + { + log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); + } +} + +const char * +AuxVector::GetEntryName(EntryType type) +{ + const char *name; + +#define ENTRY_NAME(_type) _type: name = #_type + switch (type) + { + default: + name = "unkown"; + break; + + case ENTRY_NAME(AT_NULL); break; + case ENTRY_NAME(AT_IGNORE); break; + case ENTRY_NAME(AT_EXECFD); break; + case ENTRY_NAME(AT_PHDR); break; + case ENTRY_NAME(AT_PHENT); break; + case ENTRY_NAME(AT_PHNUM); break; + case ENTRY_NAME(AT_PAGESZ); break; + case ENTRY_NAME(AT_BASE); break; + case ENTRY_NAME(AT_FLAGS); break; + case ENTRY_NAME(AT_ENTRY); break; + case ENTRY_NAME(AT_NOTELF); break; + case ENTRY_NAME(AT_UID); break; + case ENTRY_NAME(AT_EUID); break; + case ENTRY_NAME(AT_GID); break; + case ENTRY_NAME(AT_EGID); break; + case ENTRY_NAME(AT_CLKTCK); break; + } +#undef ENTRY_NAME + + return name; +} + Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) @@ -0,0 +1,330 @@ +//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +#include "DYLDRendezvous.h" + +using namespace lldb; +using namespace lldb_private; + +/// Locates the address of the rendezvous structure. Returns the address on +/// success and LLDB_INVALID_ADDRESS on failure. +static addr_t +ResolveRendezvousAddress(Process *process) +{ + addr_t info_location; + addr_t info_addr; + Error error; + size_t size; + + info_location = process->GetImageInfoAddress(); + + if (info_location == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + info_addr = 0; + size = process->DoReadMemory(info_location, &info_addr, + process->GetAddressByteSize(), error); + if (size != process->GetAddressByteSize() || error.Fail()) + return LLDB_INVALID_ADDRESS; + + if (info_addr == 0) + return LLDB_INVALID_ADDRESS; + + return info_addr; +} + +DYLDRendezvous::DYLDRendezvous(Process *process) + : m_process(process), + m_rendezvous_addr(LLDB_INVALID_ADDRESS), + m_current(), + m_previous(), + m_soentries(), + m_added_soentries(), + m_removed_soentries() +{ + // Cache a copy of the executable path + m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX); +} + +bool +DYLDRendezvous::Resolve() +{ + const size_t word_size = 4; + Rendezvous info; + size_t address_size; + size_t padding; + addr_t info_addr; + addr_t cursor; + + address_size = m_process->GetAddressByteSize(); + padding = address_size - word_size; + + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) + cursor = info_addr = ResolveRendezvousAddress(m_process); + else + cursor = info_addr = m_rendezvous_addr; + + if (cursor == LLDB_INVALID_ADDRESS) + return false; + + if (!(cursor = ReadMemory(cursor, &info.version, word_size))) + return false; + + if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) + return false; + + if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) + return false; + + if (!(cursor = ReadMemory(cursor, &info.state, word_size))) + return false; + + if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) + return false; + + // The rendezvous was successfully read. Update our internal state. + m_rendezvous_addr = info_addr; + m_previous = m_current; + m_current = info; + + return UpdateSOEntries(); +} + +bool +DYLDRendezvous::IsValid() +{ + return m_rendezvous_addr != LLDB_INVALID_ADDRESS; +} + +bool +DYLDRendezvous::UpdateSOEntries() +{ + SOEntry entry; + + if (m_current.map_addr == 0) + return false; + + // When the previous and current states are consistent this is the first + // time we have been asked to update. Just take a snapshot of the currently + // loaded modules. + if (m_previous.state == eConsistent && m_current.state == eConsistent) + return TakeSnapshot(m_soentries); + + // If we are about to add or remove a shared object clear out the current + // state and take a snapshot of the currently loaded images. + if (m_current.state == eAdd || m_current.state == eDelete) + { + assert(m_previous.state == eConsistent); + m_soentries.clear(); + m_added_soentries.clear(); + m_removed_soentries.clear(); + return TakeSnapshot(m_soentries); + } + assert(m_current.state == eConsistent); + + // Otherwise check the previous state to determine what to expect and update + // accordingly. + if (m_previous.state == eAdd) + return UpdateSOEntriesForAddition(); + else if (m_previous.state == eDelete) + return UpdateSOEntriesForDeletion(); + + return false; +} + +bool +DYLDRendezvous::UpdateSOEntriesForAddition() +{ + SOEntry entry; + iterator pos; + + assert(m_previous.state == eAdd); + + if (m_current.map_addr == 0) + return false; + + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) + { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; + + // Only add shared libraries and not the executable. + // On Linux this is indicated by an empty path in the entry. + // On FreeBSD it is the name of the executable. + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + continue; + + pos = std::find(m_soentries.begin(), m_soentries.end(), entry); + if (pos == m_soentries.end()) + { + m_soentries.push_back(entry); + m_added_soentries.push_back(entry); + } + } + + return true; +} + +bool +DYLDRendezvous::UpdateSOEntriesForDeletion() +{ + SOEntryList entry_list; + iterator pos; + + assert(m_previous.state == eDelete); + + if (!TakeSnapshot(entry_list)) + return false; + + for (iterator I = begin(); I != end(); ++I) + { + pos = std::find(entry_list.begin(), entry_list.end(), *I); + if (pos == entry_list.end()) + m_removed_soentries.push_back(*I); + } + + m_soentries = entry_list; + return true; +} + +bool +DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) +{ + SOEntry entry; + + if (m_current.map_addr == 0) + return false; + + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) + { + if (!ReadSOEntryFromMemory(cursor, entry)) + return false; + + // Only add shared libraries and not the executable. + // On Linux this is indicated by an empty path in the entry. + // On FreeBSD it is the name of the executable. + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) + continue; + + entry_list.push_back(entry); + } + + return true; +} + +addr_t +DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) +{ + size_t bytes_read; + Error error; + + bytes_read = m_process->DoReadMemory(addr, dst, size, error); + if (bytes_read != size || error.Fail()) + return 0; + + return addr + bytes_read; +} + +std::string +DYLDRendezvous::ReadStringFromMemory(addr_t addr) +{ + std::string str; + Error error; + size_t size; + char c; + + if (addr == LLDB_INVALID_ADDRESS) + return std::string(); + + for (;;) { + size = m_process->DoReadMemory(addr, &c, 1, error); + if (size != 1 || error.Fail()) + return std::string(); + if (c == 0) + break; + else { + str.push_back(c); + addr++; + } + } + + return str; +} + +bool +DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) +{ + size_t address_size = m_process->GetAddressByteSize(); + + entry.clear(); + + if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.next, address_size))) + return false; + + if (!(addr = ReadMemory(addr, &entry.prev, address_size))) + return false; + + entry.path = ReadStringFromMemory(entry.path_addr); + + return true; +} + +void +DYLDRendezvous::DumpToLog(LogSP log) const +{ + int state = GetState(); + + if (!log) + return; + + log->PutCString("DYLDRendezvous:"); + log->Printf(" Address: %lx", GetRendezvousAddress()); + log->Printf(" Version: %d", GetVersion()); + log->Printf(" Link : %lx", GetLinkMapAddress()); + log->Printf(" Break : %lx", GetBreakAddress()); + log->Printf(" LDBase : %lx", GetLDBase()); + log->Printf(" State : %s", + (state == eConsistent) ? "consistent" : + (state == eAdd) ? "add" : + (state == eDelete) ? "delete" : "unknown"); + + iterator I = begin(); + iterator E = end(); + + if (I != E) + log->PutCString("DYLDRendezvous SOEntries:"); + + for (int i = 1; I != E; ++I, ++i) + { + log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); + log->Printf(" Base : %lx", I->base_addr); + log->Printf(" Path : %lx", I->path_addr); + log->Printf(" Dyn : %lx", I->dyn_addr); + log->Printf(" Next : %lx", I->next); + log->Printf(" Prev : %lx", I->prev); + } +} Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) @@ -0,0 +1,97 @@ +//===-- AuxVector.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_AuxVector_H_ +#define liblldb_AuxVector_H_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/lldb-forward-rtti.h" + +namespace lldb_private { +class DataExtractor; +} + +/// @class AuxVector +/// @brief Represents a processes auxiliary vector. +/// +/// When a process is loaded on Linux a vector of values is placed onto the +/// stack communicating operating system specific information. On construction +/// this class locates and parses this information and provides a simple +/// read-only interface to the entries found. +class AuxVector { + +public: + AuxVector(lldb_private::Process *process); + + struct Entry { + uint64_t type; + uint64_t value; + + Entry() : type(0), value(0) { } + }; + + /// Constants describing the type of entry. + enum EntryType { + AT_NULL = 0, ///< End of auxv. + AT_IGNORE = 1, ///< Ignore entry. + AT_EXECFD = 2, ///< File descriptor of program. + AT_PHDR = 3, ///< Program headers. + AT_PHENT = 4, ///< Size of program header. + AT_PHNUM = 5, ///< Number of program headers. + AT_PAGESZ = 6, ///< Page size. + AT_BASE = 7, ///< Interpreter base address. + AT_FLAGS = 8, ///< Flags. + AT_ENTRY = 9, ///< Program entry point. + AT_NOTELF = 10, ///< Set if program is not an ELF. + AT_UID = 11, ///< UID. + AT_EUID = 12, ///< Effective UID. + AT_GID = 13, ///< GID. + AT_EGID = 14, ///< Effective GID. + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). + }; + +private: + typedef std::vector EntryVector; + +public: + typedef EntryVector::const_iterator iterator; + + iterator begin() const { return m_auxv.begin(); } + iterator end() const { return m_auxv.end(); } + + iterator + FindEntry(EntryType type) const; + + static const char * + GetEntryName(const Entry &entry) { + return GetEntryName(static_cast(entry.type)); + } + + static const char * + GetEntryName(EntryType type); + + void + DumpToLog(lldb::LogSP log) const; + +private: + lldb_private::Process *m_process; + EntryVector m_auxv; + + lldb::DataBufferSP + GetAuxvData(); + + void + ParseAuxv(lldb_private::DataExtractor &data); +}; + +#endif Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) @@ -0,0 +1,230 @@ +//===-- DYLDRendezvous.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_Rendezvous_H_ +#define liblldb_Rendezvous_H_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { +class Process; +} + +/// @class DYLDRendezvous +/// @brief Interface to the runtime linker. +/// +/// A structure is present in a processes memory space which is updated by the +/// runtime liker each time a module is loaded or unloaded. This class provides +/// an interface to this structure and maintains a consistent snapshot of the +/// currently loaded modules. +class DYLDRendezvous { + + // This structure is used to hold the contents of the debug rendezvous + // information (struct r_debug) as found in the inferiors memory. Note that + // the layout of this struct is not binary compatible, it is simply large + // enough to hold the information on both 32 and 64 bit platforms. + struct Rendezvous { + uint64_t version; + lldb::addr_t map_addr; + lldb::addr_t brk; + uint64_t state; + lldb::addr_t ldbase; + + Rendezvous() + : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } + }; + +public: + DYLDRendezvous(lldb_private::Process *process); + + /// Update the internal snapshot of runtime linker rendezvous and recompute + /// the currently loaded modules. + /// + /// This method should be called once one start up, then once each time the + /// runtime linker enters the function given by GetBreakAddress(). + /// + /// @returns true on success and false on failure. + /// + /// @see GetBreakAddress(). + bool + Resolve(); + + /// @returns true if this rendezvous has been located in the inferiors + /// address space and false otherwise. + bool + IsValid(); + + /// @returns the address of the rendezvous structure in the inferiors + /// address space. + lldb::addr_t + GetRendezvousAddress() const { return m_rendezvous_addr; } + + /// @returns the version of the rendezvous protocol being used. + int + GetVersion() const { return m_current.version; } + + /// @returns address in the inferiors address space containing the linked + /// list of shared object descriptors. + lldb::addr_t + GetLinkMapAddress() const { return m_current.map_addr; } + + /// A breakpoint should be set at this address and Resolve called on each + /// hit. + /// + /// @returns the address of a function called by the runtime linker each + /// time a module is loaded/unloaded, or about to be loaded/unloaded. + /// + /// @see Resolve() + lldb::addr_t + GetBreakAddress() const { return m_current.brk; } + + /// Returns the current state of the rendezvous structure. + int + GetState() const { return m_current.state; } + + /// @returns the base address of the runtime linker in the inferiors address + /// space. + lldb::addr_t + GetLDBase() const { return m_current.ldbase; } + + /// @returns true if modules have been loaded into the inferior since the + /// last call to Resolve(). + bool + ModulesDidLoad() const { return !m_added_soentries.empty(); } + + /// @returns true if modules have been unloaded from the inferior since the + /// last call to Resolve(). + bool + ModulesDidUnload() const { return !m_removed_soentries.empty(); } + + void + DumpToLog(lldb::LogSP log) const; + + /// @brief Constants describing the state of the rendezvous. + /// + /// @see GetState(). + enum RendezvousState { + eConsistent, + eAdd, + eDelete + }; + + /// @brief Structure representing the shared objects currently loaded into + /// the inferior process. + /// + /// This object is a rough analogue to the struct link_map object which + /// actually lives in the inferiors memory. + struct SOEntry { + lldb::addr_t base_addr; ///< Base address of the loaded object. + lldb::addr_t path_addr; ///< String naming the shared object. + lldb::addr_t dyn_addr; ///< Dynamic section of shared object. + lldb::addr_t next; ///< Address of next so_entry. + lldb::addr_t prev; ///< Address of previous so_entry. + std::string path; ///< File name of shared object. + + SOEntry() { clear(); } + + bool operator ==(const SOEntry &entry) { + return this->path == entry.path; + } + + void clear() { + base_addr = 0; + path_addr = 0; + dyn_addr = 0; + next = 0; + prev = 0; + path.clear(); + } + }; + +protected: + typedef std::list SOEntryList; + +public: + typedef SOEntryList::const_iterator iterator; + + /// Iterators over all currently loaded modules. + iterator begin() const { return m_soentries.begin(); } + iterator end() const { return m_soentries.end(); } + + /// Iterators over all modules loaded into the inferior since the last call + /// to Resolve(). + iterator loaded_begin() const { return m_added_soentries.begin(); } + iterator loaded_end() const { return m_added_soentries.end(); } + + /// Iterators over all modules unloaded from the inferior since the last + /// call to Resolve(). + iterator unloaded_begin() const { return m_removed_soentries.begin(); } + iterator unloaded_end() const { return m_removed_soentries.end(); } + +protected: + lldb_private::Process *m_process; + + // Cached copy of executable pathname + char m_exe_path[PATH_MAX]; + + /// Location of the r_debug structure in the inferiors address space. + lldb::addr_t m_rendezvous_addr; + + /// Current and previous snapshots of the rendezvous structure. + Rendezvous m_current; + Rendezvous m_previous; + + /// List of SOEntry objects corresponding to the current link map state. + SOEntryList m_soentries; + + /// List of SOEntry's added to the link map since the last call to Resolve(). + SOEntryList m_added_soentries; + + /// List of SOEntry's removed from the link map since the last call to + /// Resolve(). + SOEntryList m_removed_soentries; + + /// Reads @p size bytes from the inferiors address space starting at @p + /// addr. + /// + /// @returns addr + size if the read was successful and false otherwise. + lldb::addr_t + ReadMemory(lldb::addr_t addr, void *dst, size_t size); + + /// Reads a null-terminated C string from the memory location starting at @p + /// addr. + std::string + ReadStringFromMemory(lldb::addr_t addr); + + /// Reads an SOEntry starting at @p addr. + bool + ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); + + /// Updates the current set of SOEntries, the set of added entries, and the + /// set of removed entries. + bool + UpdateSOEntries(); + + bool + UpdateSOEntriesForAddition(); + + bool + UpdateSOEntriesForDeletion(); + + /// Reads the current list of shared objects according to the link map + /// supplied by the runtime linker. + bool + TakeSnapshot(SOEntryList &entry_list); +}; + +#endif Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) @@ -0,0 +1,425 @@ +//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" + +#include "AuxVector.h" +#include "DynamicLoaderPOSIXDYLD.h" + +using namespace lldb; +using namespace lldb_private; + +void +DynamicLoaderPOSIXDYLD::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +DynamicLoaderPOSIXDYLD::Terminate() +{ +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginName() +{ + return "DynamicLoaderPOSIXDYLD"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetShortPluginName() +{ + return "linux-dyld"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginNameStatic() +{ + return "dynamic-loader.linux-dyld"; +} + +const char * +DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() +{ + return "Dynamic loader plug-in that watches for shared library " + "loads/unloads in POSIX processes."; +} + +void +DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) +{ +} + +uint32_t +DynamicLoaderPOSIXDYLD::GetPluginVersion() +{ + return 1; +} + +DynamicLoader * +DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) +{ + bool create = force; + if (!create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::Linux || + triple_ref.getOS() == llvm::Triple::FreeBSD) + create = true; + } + + if (create) + return new DynamicLoaderPOSIXDYLD (process); + return NULL; +} + +DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) + : DynamicLoader(process), + m_rendezvous(process), + m_load_offset(LLDB_INVALID_ADDRESS), + m_entry_point(LLDB_INVALID_ADDRESS), + m_auxv(NULL) +{ +} + +DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() +{ +} + +void +DynamicLoaderPOSIXDYLD::DidAttach() +{ + ModuleSP executable; + addr_t load_offset; + + m_auxv.reset(new AuxVector(m_process)); + + executable = m_process->GetTarget().GetExecutableModule(); + load_offset = ComputeLoadOffset(); + + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) + { + ModuleList module_list; + module_list.Append(executable); + UpdateLoadedSections(executable, load_offset); + LoadAllCurrentModules(); + m_process->GetTarget().ModulesDidLoad(module_list); + } +} + +void +DynamicLoaderPOSIXDYLD::DidLaunch() +{ + ModuleSP executable; + addr_t load_offset; + + m_auxv.reset(new AuxVector(m_process)); + + executable = m_process->GetTarget().GetExecutableModule(); + load_offset = ComputeLoadOffset(); + + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) + { + ModuleList module_list; + module_list.Append(executable); + UpdateLoadedSections(executable, load_offset); + ProbeEntry(); + m_process->GetTarget().ModulesDidLoad(module_list); + } +} + +Error +DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) +{ + return Error(); +} + +Log * +DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) +{ + return NULL; +} + +Error +DynamicLoaderPOSIXDYLD::CanLoadImage() +{ + return Error(); +} + +void +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) +{ + ObjectFile *obj_file = module->GetObjectFile(); + SectionList *sections = obj_file->GetSectionList(); + SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); + const size_t num_sections = sections->GetSize(); + + for (unsigned i = 0; i < num_sections; ++i) + { + Section *section = sections->GetSectionAtIndex(i).get(); + lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; + lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); + + // If the file address of the section is zero then this is not an + // allocatable/loadable section (property of ELF sh_addr). Skip it. + if (new_load_addr == base_addr) + continue; + + if (old_load_addr == LLDB_INVALID_ADDRESS || + old_load_addr != new_load_addr) + load_list.SetSectionLoadAddress(section, new_load_addr); + } +} + +void +DynamicLoaderPOSIXDYLD::ProbeEntry() +{ + Breakpoint *entry_break; + addr_t entry; + + if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + return; + + entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); + entry_break->SetCallback(EntryBreakpointHit, this, true); +} + +// The runtime linker has run and initialized the rendezvous structure once the +// process has hit its entry point. When we hit the corresponding breakpoint we +// interrogate the rendezvous structure to get the load addresses of all +// dependent modules for the process. Similarly, we can discover the runtime +// linker function and setup a breakpoint to notify us of any dynamically loaded +// modules (via dlopen). +bool +DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) +{ + DynamicLoaderPOSIXDYLD* dyld_instance; + + dyld_instance = static_cast(baton); + dyld_instance->LoadAllCurrentModules(); + dyld_instance->SetRendezvousBreakpoint(); + return false; // Continue running. +} + +void +DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() +{ + Breakpoint *dyld_break; + addr_t break_addr; + + break_addr = m_rendezvous.GetBreakAddress(); + dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); +} + +bool +DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) +{ + DynamicLoaderPOSIXDYLD* dyld_instance; + + dyld_instance = static_cast(baton); + dyld_instance->RefreshModules(); + + // Return true to stop the target, false to just let the target run. + return dyld_instance->GetStopWhenImagesChange(); +} + +void +DynamicLoaderPOSIXDYLD::RefreshModules() +{ + if (!m_rendezvous.Resolve()) + return; + + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + if (m_rendezvous.ModulesDidLoad()) + { + ModuleList new_modules; + + E = m_rendezvous.loaded_end(); + for (I = m_rendezvous.loaded_begin(); I != E; ++I) + { + FileSpec file(I->path.c_str(), true); + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); + if (module_sp.get()) + new_modules.Append(module_sp); + } + m_process->GetTarget().ModulesDidLoad(new_modules); + } + + if (m_rendezvous.ModulesDidUnload()) + { + ModuleList old_modules; + + E = m_rendezvous.unloaded_end(); + for (I = m_rendezvous.unloaded_begin(); I != E; ++I) + { + FileSpec file(I->path.c_str(), true); + ModuleSP module_sp = + loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); + if (module_sp.get()) + old_modules.Append(module_sp); + } + m_process->GetTarget().ModulesDidUnload(old_modules); + } +} + +ThreadPlanSP +DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) +{ + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); + ThreadPlanSP thread_plan_sp; + + StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); + const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); + Symbol *sym = context.symbol; + + if (sym == NULL || !sym->IsTrampoline()) + return thread_plan_sp; + + const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); + if (!sym_name) + return thread_plan_sp; + + SymbolContextList target_symbols; + Target &target = thread.GetProcess().GetTarget(); + ModuleList &images = target.GetImages(); + + images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); + size_t num_targets = target_symbols.GetSize(); + if (!num_targets) + return thread_plan_sp; + + typedef std::vector AddressVector; + AddressVector addrs; + for (size_t i = 0; i < num_targets; ++i) + { + SymbolContext context; + AddressRange range; + if (target_symbols.GetContextAtIndex(i, context)) + { + context.GetAddressRange(eSymbolContextEverything, 0, false, range); + lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); + if (addr != LLDB_INVALID_ADDRESS) + addrs.push_back(addr); + } + } + + if (addrs.size() > 0) + { + AddressVector::iterator start = addrs.begin(); + AddressVector::iterator end = addrs.end(); + + std::sort(start, end); + addrs.erase(std::unique(start, end), end); + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); + } + + return thread_plan_sp; +} + +void +DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() +{ + DYLDRendezvous::iterator I; + DYLDRendezvous::iterator E; + ModuleList module_list; + + if (!m_rendezvous.Resolve()) + return; + + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) + { + FileSpec file(I->path.c_str(), false); + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); + if (module_sp.get()) + module_list.Append(module_sp); + } + + m_process->GetTarget().ModulesDidLoad(module_list); +} + +ModuleSP +DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) +{ + Target &target = m_process->GetTarget(); + ModuleList &modules = target.GetImages(); + ModuleSP module_sp; + + if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) + { + UpdateLoadedSections(module_sp, base_addr); + } + else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) + { + UpdateLoadedSections(module_sp, base_addr); + modules.Append(module_sp); + } + + return module_sp; +} + +addr_t +DynamicLoaderPOSIXDYLD::ComputeLoadOffset() +{ + addr_t virt_entry; + + if (m_load_offset != LLDB_INVALID_ADDRESS) + return m_load_offset; + + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + + ModuleSP module = m_process->GetTarget().GetExecutableModule(); + ObjectFile *exe = module->GetObjectFile(); + Address file_entry = exe->GetEntryPointAddress(); + + if (!file_entry.IsValid()) + return LLDB_INVALID_ADDRESS; + + m_load_offset = virt_entry - file_entry.GetFileAddress(); + return m_load_offset; +} + +addr_t +DynamicLoaderPOSIXDYLD::GetEntryPoint() +{ + if (m_entry_point != LLDB_INVALID_ADDRESS) + return m_entry_point; + + if (m_auxv.get() == NULL) + return LLDB_INVALID_ADDRESS; + + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); + + if (I == m_auxv->end()) + return LLDB_INVALID_ADDRESS; + + m_entry_point = static_cast(I->value); + return m_entry_point; +} Index: source/Plugins/DynamicLoader/POSIX-DYLD/Makefile =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) +++ source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) @@ -0,0 +1,14 @@ +##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginDynamicLoaderPOSIX +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Makefile =================================================================== --- source/Plugins/Makefile (revision 147560) +++ source/Plugins/Makefile (working copy) @@ -30,7 +30,11 @@ endif ifeq ($(HOST_OS),Linux) -DIRS += Process/Linux DynamicLoader/Linux-DYLD +DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD endif +ifeq ($(HOST_OS),FreeBSD) +DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD +endif + include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/Linux/ProcessLinux.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy) @@ -20,10 +20,10 @@ #include "lldb/Target/Target.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "ProcessMonitor.h" -#include "LinuxThread.h" +#include "POSIXThread.h" using namespace lldb; using namespace lldb_private; @@ -50,42 +50,21 @@ CreateInstance); Log::Callbacks log_callbacks = { - ProcessLinuxLog::DisableLog, - ProcessLinuxLog::EnableLog, - ProcessLinuxLog::ListLogCategories + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories }; Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); } } -void -ProcessLinux::Terminate() -{ -} - -const char * -ProcessLinux::GetPluginNameStatic() -{ - return "plugin.process.linux"; -} - -const char * -ProcessLinux::GetPluginDescriptionStatic() -{ - return "Process plugin for Linux"; -} - - //------------------------------------------------------------------------------ // Constructors and destructors. ProcessLinux::ProcessLinux(Target& target, Listener &listener) - : Process(target, listener), - m_monitor(NULL), - m_module(NULL), - m_in_limbo(false), - m_exit_now(false) + : ProcessPOSIX(target, listener) { #if 0 // FIXME: Putting this code in the ctor and saving the byte order in a @@ -98,409 +77,28 @@ #endif } -ProcessLinux::~ProcessLinux() -{ - delete m_monitor; -} - -//------------------------------------------------------------------------------ -// Process protocol. - -bool -ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target.GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - return false; -} - -Error -ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid) -{ - Error error; - assert(m_monitor == NULL); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID()); - - m_monitor = new ProcessMonitor(this, pid, error); - - if (!error.Success()) - return error; - - SetID(pid); - return error; -} - -Error -ProcessLinux::WillLaunch(Module* module) -{ - Error error; - return error; -} - -Error -ProcessLinux::DoLaunch (Module *module, - const ProcessLaunchInfo &launch_info) -{ - Error error; - assert(m_monitor == NULL); - - SetPrivateState(eStateLaunching); - - const char *stdin_path = NULL; - const char *stdout_path = NULL; - const char *stderr_path = NULL; - const char *working_dir = launch_info.GetWorkingDirectory(); - - const ProcessLaunchInfo::FileAction *file_action; - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdin_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdout_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stderr_path = file_action->GetPath(); - } - - m_monitor = new ProcessMonitor (this, - module, - launch_info.GetArguments().GetConstArgumentVector(), - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), - stdin_path, - stdout_path, - stderr_path, - error); - - m_module = module; - - if (!error.Success()) - return error; - - SetID(m_monitor->GetPID()); - return error; -} - void -ProcessLinux::DidLaunch() +ProcessLinux::Terminate() { } - -Error -ProcessLinux::DoResume() +const char * +ProcessLinux::GetPluginNameStatic() { - StateType state = GetPrivateState(); - - assert(state == eStateStopped || state == eStateCrashed); - - // We are about to resume a thread that will cause the process to exit so - // set our exit status now. Do not change our state if the inferior - // crashed. - if (state == eStateStopped) - { - if (m_in_limbo) - SetExitStatus(m_exit_status, NULL); - else - SetPrivateState(eStateRunning); - } - - bool did_resume = false; - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - LinuxThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - did_resume = thread->Resume() || did_resume; - } - assert(did_resume && "Process resume failed!"); - - return Error(); + return "linux"; } -addr_t -ProcessLinux::GetImageInfoAddress() +const char * +ProcessLinux::GetPluginDescriptionStatic() { - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(); - - if (addr.IsValid()) - return addr.GetLoadAddress(target); - else - return LLDB_INVALID_ADDRESS; + return "Process plugin for Linux"; } -Error -ProcessLinux::DoHalt(bool &caused_stop) -{ - Error error; - if (IsStopped()) - { - caused_stop = false; - } - else if (kill(GetID(), SIGSTOP)) - { - caused_stop = false; - error.SetErrorToErrno(); - } - else - { - caused_stop = true; - } - - return error; -} - -Error -ProcessLinux::DoDetach() -{ - Error error; - - error = m_monitor->Detach(); - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - -Error -ProcessLinux::DoSignal(int signal) -{ - Error error; - - if (kill(GetID(), signal)) - error.SetErrorToErrno(); - - return error; -} - -Error -ProcessLinux::DoDestroy() -{ - Error error; - - if (!HasExited()) - { - // Drive the exit event to completion (do not keep the inferior in - // limbo). - m_exit_now = true; - - if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) - { - error.SetErrorToErrno(); - return error; - } - - SetPrivateState(eStateExited); - } - - return error; -} - -void -ProcessLinux::SendMessage(const ProcessMessage &message) -{ - Mutex::Locker lock(m_message_mutex); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected process message!"); - break; - - case ProcessMessage::eInvalidMessage: - return; - - case ProcessMessage::eLimboMessage: - m_in_limbo = true; - m_exit_status = message.GetExitStatus(); - if (m_exit_now) - { - SetPrivateState(eStateExited); - m_monitor->Detach(); - } - else - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eExitMessage: - m_exit_status = message.GetExitStatus(); - SetExitStatus(m_exit_status, NULL); - break; - - case ProcessMessage::eTraceMessage: - case ProcessMessage::eBreakpointMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eCrashMessage: - SetPrivateState(eStateCrashed); - break; - } - - m_message_queue.push(message); -} - -void -ProcessLinux::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s()", __FUNCTION__); - - Mutex::Locker lock(m_message_mutex); - if (m_message_queue.empty()) - return; - - ProcessMessage &message = m_message_queue.front(); - - // Resolve the thread this message corresponds to and pass it along. - // FIXME: we're really dealing with the pid here. This should get - // fixed when this code is fixed to handle multiple threads. - lldb::tid_t tid = message.GetTID(); - if (log) - log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid); - LinuxThread *thread = static_cast( - GetThreadList().FindThreadByID(tid, false).get()); - - assert(thread); - thread->Notify(message); - - m_message_queue.pop(); -} - -bool -ProcessLinux::IsAlive() -{ - StateType state = GetPrivateState(); - return state != eStateDetached && state != eStateExited && state != eStateInvalid; -} - -size_t -ProcessLinux::DoReadMemory(addr_t vm_addr, - void *buf, size_t size, Error &error) -{ - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t -ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, - Error &error) -{ - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t -ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) -{ - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } - - return allocated_addr; -} - -Error -ProcessLinux::DoDeallocateMemory(lldb::addr_t addr) -{ - Error error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); - - return error; -} - -size_t -ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) -{ - static const uint8_t g_i386_opcode[] = { 0xCC }; - - ArchSpec arch = GetTarget().GetArchitecture(); - const uint8_t *opcode = NULL; - size_t opcode_size = 0; - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_64_x86_64: - opcode = g_i386_opcode; - opcode_size = sizeof(g_i386_opcode); - break; - } - - bp_site->SetTrapOpcode(opcode, opcode_size); - return opcode_size; -} - -Error -ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site) -{ - return EnableSoftwareBreakpoint(bp_site); -} - -Error -ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site) -{ - return DisableSoftwareBreakpoint(bp_site); -} - uint32_t -ProcessLinux::UpdateThreadListIfNeeded() -{ - // Do not allow recursive updates. - return m_thread_list.GetSize(false); -} - -uint32_t ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID()); // Update the process thread list with this new thread. @@ -508,62 +106,16 @@ assert(m_monitor); ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); if (!thread_sp) - thread_sp.reset(new LinuxThread(*this, GetID())); + thread_sp.reset(new POSIXThread(*this, GetID())); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID()); new_thread_list.AddThread(thread_sp); return new_thread_list.GetSize(false); } -ByteOrder -ProcessLinux::GetByteOrder() const -{ - // FIXME: We should be able to extract this value directly. See comment in - // ProcessLinux(). - return m_byte_order; -} -size_t -ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error) -{ - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - error.SetErrorToErrno(); - return 0; - } - return status; -} - -size_t -ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error) -{ - ssize_t bytes_read; - - // The terminal file descriptor is always in non-block mode. - if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - if (errno != EAGAIN) - error.SetErrorToErrno(); - return 0; - } - return bytes_read; -} - -size_t -ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error) -{ - return GetSTDOUT(buf, len, error); -} - -UnixSignals & -ProcessLinux::GetUnixSignals() -{ - return m_linux_signals; -} - //------------------------------------------------------------------------------ // ProcessInterface protocol. @@ -601,39 +153,3 @@ { return NULL; } - -//------------------------------------------------------------------------------ -// Utility functions. - -bool -ProcessLinux::HasExited() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} - -bool -ProcessLinux::IsStopped() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - - return false; -} Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessLinuxLog.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp (working copy) @@ -1,193 +0,0 @@ -//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessLinuxLog.h" - -#include "lldb/Interpreter/Args.h" -#include "lldb/Core/StreamFile.h" - -#include "ProcessLinux.h" - -using namespace lldb; -using namespace lldb_private; - - -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_lob_sp the first time this function is -// called. -static LogSP & -GetLog () -{ - static LogSP g_log_sp; - return g_log_sp; -} - -LogSP -ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - LogSP log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return LogSP(); - } - return log; -} - -void -ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm) -{ - LogSP log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - const size_t argc = args.GetArgumentCount (); - if (argc > 0) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; i < argc; ++i) - { - const char *arg = args.GetArgumentAtIndex (i); - - - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS; - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE; - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - - } - } - - if (flag_bits == 0) - GetLog ().reset(); - else - log->GetMask().Reset (flag_bits); - } - - return; -} - -LogSP -ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - LogSP log(GetLog ()); - if (log) - flag_bits = log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - log = make_shared(log_stream_sp); - GetLog () = log; - } - - if (log) - { - bool got_unknown_category = false; - const size_t argc = args.GetArgumentCount(); - for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = LINUX_LOG_DEFAULT; - log->GetMask().Reset(flag_bits); - log->GetOptions().Reset(log_options); - } - return log; -} - -void -ProcessLinuxLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - " ptrace - log all calls to ptrace\n" -#endif - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic()); -} - - -void -ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } -} - -int ProcessLinuxLog::m_nestinglevel; Index: source/Plugins/Process/Linux/ProcessLinux.h =================================================================== --- source/Plugins/Process/Linux/ProcessLinux.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinux.h (working copy) @@ -19,11 +19,12 @@ #include "lldb/Target/Process.h" #include "LinuxSignals.h" #include "ProcessMessage.h" +#include "ProcessPOSIX.h" class ProcessMonitor; class ProcessLinux : - public lldb_private::Process + public ProcessPOSIX { public: //------------------------------------------------------------------ @@ -51,97 +52,8 @@ ProcessLinux(lldb_private::Target& target, lldb_private::Listener &listener); - virtual - ~ProcessLinux(); - - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - virtual bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); - - virtual lldb_private::Error - WillLaunch(lldb_private::Module *module); - - virtual lldb_private::Error - DoAttachToProcessWithID(lldb::pid_t pid); - - virtual lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - const lldb_private::ProcessLaunchInfo &launch_info); - - virtual void - DidLaunch(); - - virtual lldb_private::Error - DoResume(); - - virtual lldb_private::Error - DoHalt(bool &caused_stop); - - virtual lldb_private::Error - DoDetach(); - - virtual lldb_private::Error - DoSignal(int signal); - - virtual lldb_private::Error - DoDestroy(); - - virtual void - RefreshStateAfterStop(); - - virtual bool - IsAlive(); - - virtual size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error); - - virtual size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); - - virtual lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error); - - virtual lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr); - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - - virtual lldb_private::Error - EnableBreakpoint(lldb_private::BreakpointSite *bp_site); - - virtual lldb_private::Error - DisableBreakpoint(lldb_private::BreakpointSite *bp_site); - virtual uint32_t - UpdateThreadListIfNeeded(); - - uint32_t - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); - - virtual lldb::ByteOrder - GetByteOrder() const; - - virtual lldb::addr_t - GetImageInfoAddress(); - - virtual size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDERR(char *buf, size_t len, lldb_private::Error &error); - + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -165,59 +77,11 @@ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - //-------------------------------------------------------------------------- - // ProcessLinux internal API. - - /// Registers the given message with this process. - void SendMessage(const ProcessMessage &message); - - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } - - lldb_private::UnixSignals & - GetUnixSignals(); - private: - /// Target byte order. - lldb::ByteOrder m_byte_order; - /// Process monitor; - ProcessMonitor *m_monitor; - - /// The module we are executing. - lldb_private::Module *m_module; - - /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; - std::queue m_message_queue; - - /// True when the process has entered a state of "limbo". - /// - /// This flag qualifies eStateStopped. It lets us know that when we - /// continue from this state the process will exit. Also, when true, - /// Process::m_exit_status is set. - bool m_in_limbo; - - /// Drive any exit events to completion. - bool m_exit_now; - /// Linux-specific signal set. LinuxSignals m_linux_signals; - /// Updates the loaded sections provided by the executable. - /// - /// FIXME: It would probably be better to delegate this task to the - /// DynamicLoader plugin, when we have one. - void UpdateLoadedSections(); - - /// Returns true if the process has exited. - bool HasExited(); - - /// Returns true if the process is stopped. - bool IsStopped(); - - typedef std::map MMapMap; - MMapMap m_addr_to_mmap_size; }; #endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/Linux/ProcessLinuxLog.h =================================================================== --- source/Plugins/Process/Linux/ProcessLinuxLog.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessLinuxLog.h (working copy) @@ -1,98 +0,0 @@ -//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ -#define liblldb_ProcessLinuxLog_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes - -// Project includes -#include "lldb/Core/Log.h" - -#define LINUX_LOG_VERBOSE (1u << 0) -#define LINUX_LOG_PROCESS (1u << 1) -#define LINUX_LOG_THREAD (1u << 2) -#define LINUX_LOG_PACKETS (1u << 3) -#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define LINUX_LOG_BREAKPOINTS (1u << 7) -#define LINUX_LOG_WATCHPOINTS (1u << 8) -#define LINUX_LOG_STEP (1u << 9) -#define LINUX_LOG_COMM (1u << 10) -#define LINUX_LOG_ASYNC (1u << 11) -#define LINUX_LOG_PTRACE (1u << 12) -#define LINUX_LOG_REGISTERS (1u << 13) -#define LINUX_LOG_ALL (UINT32_MAX) -#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS - -// The size which determines "short memory reads/writes". -#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) - -class ProcessLinuxLog -{ - static int m_nestinglevel; - -public: - static lldb::LogSP - GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void - DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static lldb::LogSP - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, - lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories (lldb_private::Stream *strm); - - static void - LogIf (uint32_t mask, const char *format, ...); - - // The following functions can be used to enable the client to limit - // logging to only the top level function calls. This is useful for - // recursive functions. FIXME: not thread safe! - // Example: - // void NestingFunc() { - // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL)); - // if (log) - // { - // ProcessLinuxLog::IncNestLevel(); - // if (ProcessLinuxLog::AtTopNestLevel()) - // log->Print(msg); - // } - // NestingFunc(); - // if (log) - // ProcessLinuxLog::DecNestLevel(); - // } - - static bool - AtTopNestLevel() - { - return m_nestinglevel == 1; - } - - static void - IncNestLevel() - { - ++m_nestinglevel; - } - - static void - DecNestLevel() - { - --m_nestinglevel; - assert(m_nestinglevel >= 0); - } -}; - -#endif // liblldb_ProcessLinuxLog_h_ Index: source/Plugins/Process/Linux/RegisterContextLinux.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux.h (working copy) @@ -1,40 +0,0 @@ -//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextLinux_H_ -#define liblldb_RegisterContextLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Target/RegisterContext.h" - -//------------------------------------------------------------------------------ -/// @class RegisterContextLinux -/// -/// @brief Extends RegisterClass with a few virtual operations useful on Linux. -class RegisterContextLinux - : public lldb_private::RegisterContext -{ -public: - RegisterContextLinux(lldb_private::Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) { } - - /// Updates the register state of the associated thread after hitting a - /// breakpoint (if that make sense for the architecture). Default - /// implementation simply returns true for architectures which do not - /// require any update. - /// - /// @return - /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() { return true; } -}; - -#endif // #ifndef liblldb_RegisterContextLinux_H_ Index: source/Plugins/Process/Linux/LinuxStopInfo.cpp =================================================================== --- source/Plugins/Process/Linux/LinuxStopInfo.cpp (revision 147560) +++ source/Plugins/Process/Linux/LinuxStopInfo.cpp (working copy) @@ -1,60 +0,0 @@ -//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LinuxStopInfo.h" - -using namespace lldb; -using namespace lldb_private; - - -//===----------------------------------------------------------------------===// -// LinuxLimboStopInfo - -LinuxLimboStopInfo::~LinuxLimboStopInfo() { } - -lldb::StopReason -LinuxLimboStopInfo::GetStopReason() const -{ - return lldb::eStopReasonTrace; -} - -const char * -LinuxLimboStopInfo::GetDescription() -{ - return "thread exiting"; -} - -bool -LinuxLimboStopInfo::ShouldStop(Event *event_ptr) -{ - return true; -} - -bool -LinuxLimboStopInfo::ShouldNotify(Event *event_ptr) -{ - return true; -} - -//===----------------------------------------------------------------------===// -// LinuxCrashStopInfo - -LinuxCrashStopInfo::~LinuxCrashStopInfo() { } - -lldb::StopReason -LinuxCrashStopInfo::GetStopReason() const -{ - return lldb::eStopReasonException; -} - -const char * -LinuxCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason); -} Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (working copy) @@ -1,650 +0,0 @@ -//===-- RegisterContextLinux_i386.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/Core/DataExtractor.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" - -using namespace lldb_private; -using namespace lldb; - -enum -{ - k_first_gpr, - gpr_eax = k_first_gpr, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, - k_last_gpr = gpr_gs, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - k_last_fpr = fpu_xmm7, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum -{ - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags -}; - -enum -{ - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7 -}; - -enum -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fcw = 24, - gdb_fsw = 25, - gdb_ftw = 26, - gdb_fpu_cs = 27, - gdb_ip = 28, - gdb_fpu_ds = 29, - gdb_dp = 30, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, regs) + \ - offsetof(RegisterContextLinux_i386::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, i387) + \ - offsetof(RegisterContextLinux_i386::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), - - // Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), - - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - -}; - -#ifndef NDEBUG -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); -#endif - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not in use. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - - -RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_i386::~RegisterContextLinux_i386() -{ -} - -ProcessMonitor & -RegisterContextLinux_i386::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_i386::Invalidate() -{ -} - -void -RegisterContextLinux_i386::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_i386::GetRegisterCount() -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_i386::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_i386::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_i386::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - return false; -} - -bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data) -{ - return false; -} - -bool -RegisterContextLinux_i386::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case dwarf_eax: return gpr_eax; - case dwarf_edx: return gpr_edx; - case dwarf_ecx: return gpr_ecx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_ebp: return gpr_ebp; - case dwarf_esp: return gpr_esp; - case dwarf_eip: return gpr_eip; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_eax : return gpr_eax; - case gdb_ebx : return gpr_ebx; - case gdb_ecx : return gpr_ecx; - case gdb_edx : return gpr_edx; - case gdb_esi : return gpr_esi; - case gdb_edi : return gpr_edi; - case gdb_ebp : return gpr_ebp; - case gdb_esp : return gpr_esp; - case gdb_eip : return gpr_eip; - case gdb_eflags : return gpr_eflags; - case gdb_cs : return gpr_cs; - case gdb_ss : return gpr_ss; - case gdb_ds : return gpr_ds; - case gdb_es : return gpr_es; - case gdb_fs : return gpr_fs; - case gdb_gs : return gpr_gs; - case gdb_stmm0 : return fpu_stmm0; - case gdb_stmm1 : return fpu_stmm1; - case gdb_stmm2 : return fpu_stmm2; - case gdb_stmm3 : return fpu_stmm3; - case gdb_stmm4 : return fpu_stmm4; - case gdb_stmm5 : return fpu_stmm5; - case gdb_stmm6 : return fpu_stmm6; - case gdb_stmm7 : return fpu_stmm7; - case gdb_fcw : return fpu_fcw; - case gdb_fsw : return fpu_fsw; - case gdb_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_fos; - case gdb_dp : return fpu_foo; - case gdb_fop : return fpu_fop; - case gdb_xmm0 : return fpu_xmm0; - case gdb_xmm1 : return fpu_xmm1; - case gdb_xmm2 : return fpu_xmm2; - case gdb_xmm3 : return fpu_xmm3; - case gdb_xmm4 : return fpu_xmm4; - case gdb_xmm5 : return fpu_xmm5; - case gdb_xmm6 : return fpu_xmm6; - case gdb_xmm7 : return fpu_xmm7; - case gdb_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_i386::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t eflags; - - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (eflags & TRACE_BIT) - return true; - - eflags |= TRACE_BIT; - } - else - { - if (!(eflags & TRACE_BIT)) - return false; - - eflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_eflags, eflags); -} - -void -RegisterContextLinux_i386::LogGPR(const char *title) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); - if (log) - { - if (title) - log->Printf ("%s", title); - for (uint32_t i=0; iPrintf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); - } - } -} - -bool -RegisterContextLinux_i386::ReadGPR() -{ - bool result; - - ProcessMonitor &monitor = GetMonitor(); - result = monitor.ReadGPR(&user.regs); - LogGPR("RegisterContextLinux_i386::ReadGPR()"); - return result; -} - -bool -RegisterContextLinux_i386::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} Index: source/Plugins/Process/Linux/ProcessMessage.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessMessage.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessMessage.cpp (working copy) @@ -1,245 +0,0 @@ -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessMessage.h" - -using namespace lldb_private; - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason) -{ - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - break; - case ePrivilegedAddress: - str = "address access protected"; - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str; -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash rcase easons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash rcase easons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash rcase easons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash rcase easons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintCrashReason() const -{ - return PrintCrashReason(m_crash_reason); -} - -const char * -ProcessMessage::PrintKind(Kind kind) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (kind) - { - default: - assert(false && "invalid Kind"); - break; - - case eInvalidMessage: - str = "eInvalidMessage"; - break; - case eExitMessage: - str = "eExitMessage"; - break; - case eLimboMessage: - str = "eLimboMessage"; - break; - case eSignalMessage: - str = "eSignalMessage"; - break; - case eSignalDeliveredMessage: - str = "eSignalDeliveredMessage"; - break; - case eTraceMessage: - str = "eTraceMessage"; - break; - case eBreakpointMessage: - str = "eBreakpointMessage"; - break; - case eCrashMessage: - str = "eCrashMessage"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintKind() const -{ - return PrintKind(m_kind); -} Index: source/Plugins/Process/Linux/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 147560) +++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy) @@ -28,9 +28,9 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" -#include "LinuxThread.h" +#include "POSIXThread.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" @@ -63,8 +63,8 @@ static void PtraceDisplayBytes(__ptrace_request &req, void *data) { StreamString buf; - LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet ( - LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE)); + LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); if (verbose_log) { @@ -120,7 +120,7 @@ { long int result; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); if (log) log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d", @@ -170,10 +170,10 @@ size_t remainder; long data; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -187,7 +187,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -200,10 +200,10 @@ for (unsigned i = 0; i < remainder; ++i) dst[i] = ((data >> i*8) & 0xFF); - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data); @@ -212,7 +212,7 @@ } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -224,10 +224,10 @@ size_t bytes_written = 0; size_t remainder; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -244,10 +244,10 @@ for (unsigned i = 0; i < word_size; ++i) data |= (unsigned long)src[i] << i*8; - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, data); @@ -255,7 +255,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } } @@ -266,7 +266,7 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -276,14 +276,14 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); } @@ -292,7 +292,7 @@ src += word_size; } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -420,7 +420,7 @@ ReadRegOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); // Set errno to zero so that we can detect a failed peek. errno = 0; @@ -434,7 +434,7 @@ } if (log) log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), data); + POSIXThread::GetRegisterNameFromOffset(m_offset), data); } //------------------------------------------------------------------------------ @@ -460,7 +460,7 @@ { void* buf; lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); if (sizeof(void*) == sizeof(uint64_t)) buf = (void*) m_value.GetAsUInt64(); @@ -472,7 +472,7 @@ if (log) log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), buf); + POSIXThread::GetRegisterNameFromOffset(m_offset), buf); if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf)) m_result = false; else @@ -794,7 +794,7 @@ /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, Module *module, const char *argv[], const char *envp[], @@ -802,7 +802,7 @@ const char *stdout_path, const char *stderr_path, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -858,10 +858,10 @@ } } -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -978,7 +978,7 @@ lldb::pid_t pid; lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); // Propagate the environment if one is not supplied. if (envp == NULL || envp[0] == NULL) @@ -1101,11 +1101,10 @@ if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) goto FINISH; - // Update the process thread list with this new thread and mark it as - // current. + // Update the process thread list with this new thread. // FIXME: should we be letting UpdateThreadList handle this? // FIXME: by using pids instead of tids, we can only support one thread. - inferior.reset(new LinuxThread(process, pid)); + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); @@ -1167,9 +1166,8 @@ ProcessMonitor *monitor = args->m_monitor; ProcessLinux &process = monitor->GetProcess(); - lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (pid <= 1) { @@ -1192,13 +1190,11 @@ goto FINISH; } - // Update the process thread list with the attached thread and - // mark it as current. - inferior.reset(new LinuxThread(process, pid)); + // Update the process thread list with the attached thread. + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); - process.GetThreadList().SetSelectedThreadByID(pid); // Let our process instance know the thread has stopped. process.SendMessage(ProcessMessage::Trace(pid)); @@ -1568,7 +1564,7 @@ } bool -ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value) +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) { bool result; ReadRegOperation op(offset, value, result); Index: source/Plugins/Process/Linux/LinuxStopInfo.h =================================================================== --- source/Plugins/Process/Linux/LinuxStopInfo.h (revision 147560) +++ source/Plugins/Process/Linux/LinuxStopInfo.h (working copy) @@ -1,92 +0,0 @@ -//===-- LinuxStopInfo.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_LinuxStopInfo_H_ -#define liblldb_LinuxStopInfo_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/StopInfo.h" - -#include "LinuxThread.h" -#include "ProcessMessage.h" - -//===----------------------------------------------------------------------===// -/// @class LinuxStopInfo -/// @brief Simple base class for all Linux-specific StopInfo objects. -/// -class LinuxStopInfo - : public lldb_private::StopInfo -{ -public: - LinuxStopInfo(lldb_private::Thread &thread, uint32_t status) - : StopInfo(thread, status) - { } -}; - -//===----------------------------------------------------------------------===// -/// @class LinuxLimboStopInfo -/// @brief Represents the stop state of a process ready to exit. -/// -class LinuxLimboStopInfo - : public LinuxStopInfo -{ -public: - LinuxLimboStopInfo(LinuxThread &thread) - : LinuxStopInfo(thread, 0) - { } - - ~LinuxLimboStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - bool - ShouldStop(lldb_private::Event *event_ptr); - - bool - ShouldNotify(lldb_private::Event *event_ptr); -}; - - -//===----------------------------------------------------------------------===// -/// @class LinuxCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class LinuxCrashStopInfo - : public LinuxStopInfo -{ -public: - LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, - ProcessMessage::CrashReason reason) - : LinuxStopInfo(thread, status), - m_crash_reason(reason) - { } - - ~LinuxCrashStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - ProcessMessage::CrashReason - GetCrashReason() const; - -private: - ProcessMessage::CrashReason m_crash_reason; -}; - -#endif Index: source/Plugins/Process/Linux/LinuxThread.cpp =================================================================== --- source/Plugins/Process/Linux/LinuxThread.cpp (revision 147560) +++ source/Plugins/Process/Linux/LinuxThread.cpp (working copy) @@ -1,350 +0,0 @@ -//===-- LinuxThread.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 - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Debugger.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "LinuxStopInfo.h" -#include "LinuxThread.h" -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" -#include "RegisterContextLinux_x86_64.h" -#include "UnwindLLDB.h" - -using namespace lldb_private; - - -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), - m_frame_ap(0) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid); -} - -LinuxThread::~LinuxThread() -{ - DestroyThread(); -} - -ProcessMonitor & -LinuxThread::GetMonitor() -{ - ProcessLinux &process = static_cast(GetProcess()); - return process.GetMonitor(); -} - -void -LinuxThread::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - ProcessLinux &process = static_cast(GetProcess()); - process.GetThreadList().RefreshStateAfterStop(); -} - -const char * -LinuxThread::GetInfo() -{ - return NULL; -} - -lldb::RegisterContextSP -LinuxThread::GetRegisterContext() -{ - if (!m_reg_context_sp) - { - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); - break; - - case ArchSpec::eCore_x86_64_x86_64: - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); - break; - } - } - return m_reg_context_sp; -} - -lldb::RegisterContextSP -LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else - { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -lldb::StopInfoSP -LinuxThread::GetPrivateStopReason() -{ - return m_stop_info; -} - -Unwind * -LinuxThread::GetUnwinder() -{ - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - - return m_unwinder_ap.get(); -} - -bool -LinuxThread::WillResume(lldb::StateType resume_state) -{ - SetResumeState(resume_state); - - ClearStackFrames(); - if (m_unwinder_ap.get()) - m_unwinder_ap->Clear(); - - return Thread::WillResume(resume_state); -} - -bool -LinuxThread::Resume() -{ - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - switch (resume_state) - { - default: - assert(false && "Unexpected state for resume!"); - status = false; - break; - - case lldb::eStateRunning: - SetState(resume_state); - status = monitor.Resume(GetID(), GetResumeSignal()); - break; - - case lldb::eStateStepping: - SetState(resume_state); - status = monitor.SingleStep(GetID(), GetResumeSignal()); - break; - } - - return status; -} - -void -LinuxThread::Notify(const ProcessMessage &message) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected message kind!"); - break; - - case ProcessMessage::eLimboMessage: - LimboNotify(message); - break; - - case ProcessMessage::eSignalMessage: - SignalNotify(message); - break; - - case ProcessMessage::eSignalDeliveredMessage: - SignalDeliveredNotify(message); - break; - - case ProcessMessage::eTraceMessage: - TraceNotify(message); - break; - - case ProcessMessage::eBreakpointMessage: - BreakNotify(message); - break; - - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; - } -} - -void -LinuxThread::BreakNotify(const ProcessMessage &message) -{ - bool status; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - - assert(GetRegisterContextLinux()); - status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); - assert(status && "Breakpoint update failed!"); - - // With our register state restored, resolve the breakpoint object - // corresponding to our current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); - assert(bp_site); - lldb::break_id_t bp_id = bp_site->GetID(); - assert(bp_site && bp_site->ValidForThisThread(this)); - - - m_breakpoint = bp_site; - m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); -} - -void -LinuxThread::TraceNotify(const ProcessMessage &message) -{ - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); -} - -void -LinuxThread::LimboNotify(const ProcessMessage &message) -{ - m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this)); -} - -void -LinuxThread::SignalNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); - SetResumeSignal(signo); -} - -void -LinuxThread::SignalDeliveredNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - // Just treat debugger generated signal events like breakpoints for now. - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); - SetResumeSignal(signo); -} - -void -LinuxThread::CrashNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); - - m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo( - *this, signo, message.GetCrashReason())); - SetResumeSignal(signo); -} - -unsigned -LinuxThread::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset); - break; - - case ArchSpec::eCore_x86_64_x86_64: - reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset); - break; - } - return reg; -} - -const char * -LinuxThread::GetRegisterName(unsigned reg) -{ - const char * name; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - name = RegisterContextLinux_i386::GetRegisterName(reg); - break; - - case ArchSpec::eCore_x86_64_x86_64: - name = RegisterContextLinux_x86_64::GetRegisterName(reg); - break; - } - return name; -} - -const char * -LinuxThread::GetRegisterNameFromOffset(unsigned offset) -{ - return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} - Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_i386.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h (working copy) @@ -1,169 +0,0 @@ -//===-- RegisterContextLinux_i386.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_RegisterContextLinux_i386_h_ -#define liblldb_RegisterContextLinux_i386_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Log.h" -#include "RegisterContextLinux.h" - -class RegisterContextLinux_i386 : public RegisterContextLinux -{ -public: - RegisterContextLinux_i386(lldb_private::Thread &thread, - uint32_t concreate_frame_idx); - - ~RegisterContextLinux_i386(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - -#if 0 - bool - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); - - bool - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); -#endif - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - -#if 0 - bool - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); - - bool - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, - uint32_t data_offset = 0); -#endif - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR - { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - uint32_t orig_ax; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; - }; - - struct MMSReg - { - uint8_t bytes[8]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint32_t ip; - uint32_t cs; - uint32_t foo; - uint32_t fos; - uint32_t mxcsr; - uint32_t reserved; - MMSReg stmm[8]; - XMMReg xmm[8]; - uint32_t pad[56]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - FPU i387; // FPU registers. - uint32_t tsize; // Text segment size. - uint32_t dsize; // Data segment size. - uint32_t ssize; // Stack segment size. - uint32_t start_code; // VM address of text. - uint32_t start_stack; // VM address of stack bottom (top in rsp). - int32_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - uint32_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint32_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). - }; -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - void LogGPR(const char *title); - - bool ReadGPR(); - bool ReadFPR(); -}; - -#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (working copy) @@ -1,759 +0,0 @@ -//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include -#include -#include - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_x86_64.h" - -using namespace lldb_private; -using namespace lldb; - -// Internal codes for all x86_64 registers. -enum -{ - k_first_gpr, - gpr_rax = k_first_gpr, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es, - k_last_gpr = gpr_es, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - k_last_fpr = fpu_xmm15, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum gcc_dwarf_regnums -{ - gcc_dwarf_gpr_rax = 0, - gcc_dwarf_gpr_rdx, - gcc_dwarf_gpr_rcx, - gcc_dwarf_gpr_rbx, - gcc_dwarf_gpr_rsi, - gcc_dwarf_gpr_rdi, - gcc_dwarf_gpr_rbp, - gcc_dwarf_gpr_rsp, - gcc_dwarf_gpr_r8, - gcc_dwarf_gpr_r9, - gcc_dwarf_gpr_r10, - gcc_dwarf_gpr_r11, - gcc_dwarf_gpr_r12, - gcc_dwarf_gpr_r13, - gcc_dwarf_gpr_r14, - gcc_dwarf_gpr_r15, - gcc_dwarf_gpr_rip, - gcc_dwarf_fpu_xmm0, - gcc_dwarf_fpu_xmm1, - gcc_dwarf_fpu_xmm2, - gcc_dwarf_fpu_xmm3, - gcc_dwarf_fpu_xmm4, - gcc_dwarf_fpu_xmm5, - gcc_dwarf_fpu_xmm6, - gcc_dwarf_fpu_xmm7, - gcc_dwarf_fpu_xmm8, - gcc_dwarf_fpu_xmm9, - gcc_dwarf_fpu_xmm10, - gcc_dwarf_fpu_xmm11, - gcc_dwarf_fpu_xmm12, - gcc_dwarf_fpu_xmm13, - gcc_dwarf_fpu_xmm14, - gcc_dwarf_fpu_xmm15, - gcc_dwarf_fpu_stmm0, - gcc_dwarf_fpu_stmm1, - gcc_dwarf_fpu_stmm2, - gcc_dwarf_fpu_stmm3, - gcc_dwarf_fpu_stmm4, - gcc_dwarf_fpu_stmm5, - gcc_dwarf_fpu_stmm6, - gcc_dwarf_fpu_stmm7 -}; - -enum gdb_regnums -{ - gdb_gpr_rax = 0, - gdb_gpr_rbx = 1, - gdb_gpr_rcx = 2, - gdb_gpr_rdx = 3, - gdb_gpr_rsi = 4, - gdb_gpr_rdi = 5, - gdb_gpr_rbp = 6, - gdb_gpr_rsp = 7, - gdb_gpr_r8 = 8, - gdb_gpr_r9 = 9, - gdb_gpr_r10 = 10, - gdb_gpr_r11 = 11, - gdb_gpr_r12 = 12, - gdb_gpr_r13 = 13, - gdb_gpr_r14 = 14, - gdb_gpr_r15 = 15, - gdb_gpr_rip = 16, - gdb_gpr_rflags = 17, - gdb_gpr_cs = 18, - gdb_gpr_ss = 19, - gdb_gpr_ds = 20, - gdb_gpr_es = 21, - gdb_gpr_fs = 22, - gdb_gpr_gs = 23, - gdb_fpu_stmm0 = 24, - gdb_fpu_stmm1 = 25, - gdb_fpu_stmm2 = 26, - gdb_fpu_stmm3 = 27, - gdb_fpu_stmm4 = 28, - gdb_fpu_stmm5 = 29, - gdb_fpu_stmm6 = 30, - gdb_fpu_stmm7 = 31, - gdb_fpu_fcw = 32, - gdb_fpu_fsw = 33, - gdb_fpu_ftw = 34, - gdb_fpu_cs = 35, - gdb_fpu_ip = 36, - gdb_fpu_ds = 37, - gdb_fpu_dp = 38, - gdb_fpu_fop = 39, - gdb_fpu_xmm0 = 40, - gdb_fpu_xmm1 = 41, - gdb_fpu_xmm2 = 42, - gdb_fpu_xmm3 = 43, - gdb_fpu_xmm4 = 44, - gdb_fpu_xmm5 = 45, - gdb_fpu_xmm6 = 46, - gdb_fpu_xmm7 = 47, - gdb_fpu_xmm8 = 48, - gdb_fpu_xmm9 = 49, - gdb_fpu_xmm10 = 50, - gdb_fpu_xmm11 = 51, - gdb_fpu_xmm12 = 52, - gdb_fpu_xmm13 = 53, - gdb_fpu_xmm14 = 54, - gdb_fpu_xmm15 = 55, - gdb_fpu_mxcsr = 56 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \ - offsetof(RegisterContextLinux_x86_64::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \ - offsetof(RegisterContextLinux_x86_64::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU)) - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), - - // i387 Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), - // FIXME: Extract segment from ip. - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), - // FIXME: Extract segment from dp. - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - // FP registers. - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), - DEFINE_XMM(xmm, 15) -}; - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not being used. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() -{ -} - -ProcessMonitor & -RegisterContextLinux_x86_64::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_x86_64::Invalidate() -{ -} - -void -RegisterContextLinux_x86_64::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_x86_64::GetRegisterCount() -{ - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg) -{ - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_x86_64::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_x86_64::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &user.regs, sizeof(user.regs)); - dst += sizeof(user.regs); - - ::memcpy (dst, &user.i387, sizeof(user.i387)); - return true; - } - return false; -} - -bool -RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&user.regs, src, sizeof(user.regs)); - src += sizeof(user.regs); - - ::memcpy (&user.i387, src, sizeof(user.i387)); - return WriteGPR() & WriteFPR(); - } - return false; -} - -bool -RegisterContextLinux_x86_64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case gcc_dwarf_gpr_rax: return gpr_rax; - case gcc_dwarf_gpr_rdx: return gpr_rdx; - case gcc_dwarf_gpr_rcx: return gpr_rcx; - case gcc_dwarf_gpr_rbx: return gpr_rbx; - case gcc_dwarf_gpr_rsi: return gpr_rsi; - case gcc_dwarf_gpr_rdi: return gpr_rdi; - case gcc_dwarf_gpr_rbp: return gpr_rbp; - case gcc_dwarf_gpr_rsp: return gpr_rsp; - case gcc_dwarf_gpr_r8: return gpr_r8; - case gcc_dwarf_gpr_r9: return gpr_r9; - case gcc_dwarf_gpr_r10: return gpr_r10; - case gcc_dwarf_gpr_r11: return gpr_r11; - case gcc_dwarf_gpr_r12: return gpr_r12; - case gcc_dwarf_gpr_r13: return gpr_r13; - case gcc_dwarf_gpr_r14: return gpr_r14; - case gcc_dwarf_gpr_r15: return gpr_r15; - case gcc_dwarf_gpr_rip: return gpr_rip; - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_gpr_rax : return gpr_rax; - case gdb_gpr_rbx : return gpr_rbx; - case gdb_gpr_rcx : return gpr_rcx; - case gdb_gpr_rdx : return gpr_rdx; - case gdb_gpr_rsi : return gpr_rsi; - case gdb_gpr_rdi : return gpr_rdi; - case gdb_gpr_rbp : return gpr_rbp; - case gdb_gpr_rsp : return gpr_rsp; - case gdb_gpr_r8 : return gpr_r8; - case gdb_gpr_r9 : return gpr_r9; - case gdb_gpr_r10 : return gpr_r10; - case gdb_gpr_r11 : return gpr_r11; - case gdb_gpr_r12 : return gpr_r12; - case gdb_gpr_r13 : return gpr_r13; - case gdb_gpr_r14 : return gpr_r14; - case gdb_gpr_r15 : return gpr_r15; - case gdb_gpr_rip : return gpr_rip; - case gdb_gpr_rflags : return gpr_rflags; - case gdb_gpr_cs : return gpr_cs; - case gdb_gpr_ss : return gpr_ss; - case gdb_gpr_ds : return gpr_ds; - case gdb_gpr_es : return gpr_es; - case gdb_gpr_fs : return gpr_fs; - case gdb_gpr_gs : return gpr_gs; - case gdb_fpu_stmm0 : return fpu_stmm0; - case gdb_fpu_stmm1 : return fpu_stmm1; - case gdb_fpu_stmm2 : return fpu_stmm2; - case gdb_fpu_stmm3 : return fpu_stmm3; - case gdb_fpu_stmm4 : return fpu_stmm4; - case gdb_fpu_stmm5 : return fpu_stmm5; - case gdb_fpu_stmm6 : return fpu_stmm6; - case gdb_fpu_stmm7 : return fpu_stmm7; - case gdb_fpu_fcw : return fpu_fcw; - case gdb_fpu_fsw : return fpu_fsw; - case gdb_fpu_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_fpu_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_ds; - case gdb_fpu_dp : return fpu_dp; - case gdb_fpu_fop : return fpu_fop; - case gdb_fpu_xmm0 : return fpu_xmm0; - case gdb_fpu_xmm1 : return fpu_xmm1; - case gdb_fpu_xmm2 : return fpu_xmm2; - case gdb_fpu_xmm3 : return fpu_xmm3; - case gdb_fpu_xmm4 : return fpu_xmm4; - case gdb_fpu_xmm5 : return fpu_xmm5; - case gdb_fpu_xmm6 : return fpu_xmm6; - case gdb_fpu_xmm7 : return fpu_xmm7; - case gdb_fpu_xmm8 : return fpu_xmm8; - case gdb_fpu_xmm9 : return fpu_xmm9; - case gdb_fpu_xmm10 : return fpu_xmm10; - case gdb_fpu_xmm11 : return fpu_xmm11; - case gdb_fpu_xmm12 : return fpu_xmm12; - case gdb_fpu_xmm13 : return fpu_xmm13; - case gdb_fpu_xmm14 : return fpu_xmm14; - case gdb_fpu_xmm15 : return fpu_xmm15; - case gdb_fpu_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_x86_64::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; - - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (rflags & TRACE_BIT) - return true; - - rflags |= TRACE_BIT; - } - else - { - if (!(rflags & TRACE_BIT)) - return false; - - rflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_rflags, rflags); -} - -bool -RegisterContextLinux_x86_64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} - -bool -RegisterContextLinux_x86_64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(&user.i387); -} Index: source/Plugins/Process/Linux/ProcessMessage.h =================================================================== --- source/Plugins/Process/Linux/ProcessMessage.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessMessage.h (working copy) @@ -1,171 +0,0 @@ -//===-- ProcessMessage.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_ProcessMessage_H_ -#define liblldb_ProcessMessage_H_ - -#include - -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -class ProcessMessage -{ -public: - - /// The type of signal this message can correspond to. - enum Kind - { - eInvalidMessage, - eExitMessage, - eLimboMessage, - eSignalMessage, - eSignalDeliveredMessage, - eTraceMessage, - eBreakpointMessage, - eCrashMessage - }; - - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - - ProcessMessage() - : m_tid(LLDB_INVALID_PROCESS_ID), - m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), - m_status(0), - m_addr(0) { } - - Kind GetKind() const { return m_kind; } - - lldb::tid_t GetTID() const { return m_tid; } - - /// Indicates that the thread @p tid is about to exit with status @p status. - static ProcessMessage Limbo(lldb::tid_t tid, int status) { - return ProcessMessage(tid, eLimboMessage, status); - } - - /// Indicates that the thread @p tid had the signal @p signum delivered. - static ProcessMessage Signal(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalMessage, signum); - } - - /// Indicates that a signal @p signum generated by the debugging process was - /// delivered to the thread @p tid. - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalDeliveredMessage, signum); - } - - /// Indicates that the thread @p tid encountered a trace point. - static ProcessMessage Trace(lldb::tid_t tid) { - return ProcessMessage(tid, eTraceMessage); - } - - /// Indicates that the thread @p tid encountered a break point. - static ProcessMessage Break(lldb::tid_t tid) { - return ProcessMessage(tid, eBreakpointMessage); - } - - /// Indicates that the thread @p tid crashed. - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, - int signo, lldb::addr_t fault_addr) { - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); - message.m_crash_reason = reason; - return message; - } - - int GetExitStatus() const { - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); - return m_status; - } - - int GetSignal() const { - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || - GetKind() == eSignalDeliveredMessage); - return m_status; - } - - int GetStopStatus() const { - assert(GetKind() == eSignalMessage); - return m_status; - } - - CrashReason GetCrashReason() const { - assert(GetKind() == eCrashMessage); - return m_crash_reason; - } - - lldb::addr_t GetFaultAddress() const { - assert(GetKind() == eCrashMessage); - return m_addr; - } - - static const char * - GetCrashReasonString(CrashReason reason); - - const char * - PrintCrashReason() const; - - static const char * - PrintCrashReason(CrashReason reason); - - const char * - PrintKind() const; - - static const char * - PrintKind(Kind); - -private: - ProcessMessage(lldb::tid_t tid, Kind kind, - int status = 0, lldb::addr_t addr = 0) - : m_tid(tid), - m_kind(kind), - m_crash_reason(eInvalidCrashReason), - m_status(status), - m_addr(addr) { } - - lldb::tid_t m_tid; - Kind m_kind : 8; - CrashReason m_crash_reason : 8; - int m_status; - lldb::addr_t m_addr; -}; - -#endif // #ifndef liblldb_ProcessMessage_H_ Index: source/Plugins/Process/Linux/ProcessMonitor.h =================================================================== --- source/Plugins/Process/Linux/ProcessMonitor.h (revision 147560) +++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy) @@ -24,10 +24,12 @@ class Error; class Module; class Scalar; + } // End lldb_private namespace. class ProcessLinux; class Operation; +class ProcessPOSIX; /// @class ProcessMonitor /// @brief Manages communication with the inferior (debugee) process. @@ -47,7 +49,7 @@ /// Launches an inferior process ready for debugging. Forms the /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb_private::Module *module, char const *argv[], char const *envp[], @@ -56,7 +58,7 @@ const char *stderr_path, lldb_private::Error &error); - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error); @@ -104,7 +106,7 @@ /// /// This method is provided for use by RegisterContextLinux derivatives. bool - ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value); + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); /// Writes the given value to the register identified by the given /// (architecture dependent) offset. Index: source/Plugins/Process/Linux/Makefile =================================================================== --- source/Plugins/Process/Linux/Makefile (revision 147560) +++ source/Plugins/Process/Linux/Makefile (working copy) @@ -12,6 +12,6 @@ BUILD_ARCHIVE = 1 # Extend the include path so we may locate UnwindLLDB.h -CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/Linux/LinuxThread.h =================================================================== --- source/Plugins/Process/Linux/LinuxThread.h (revision 147560) +++ source/Plugins/Process/Linux/LinuxThread.h (working copy) @@ -1,102 +0,0 @@ -//===-- LinuxThread.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_LinuxThread_H_ -#define liblldb_LinuxThread_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/Target/Thread.h" - -class ProcessMessage; -class ProcessMonitor; -class RegisterContextLinux; - -//------------------------------------------------------------------------------ -// @class LinuxThread -// @brief Abstraction of a linux process (thread). -class LinuxThread - : public lldb_private::Thread -{ -public: - LinuxThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~LinuxThread(); - - void - RefreshStateAfterStop(); - - bool - WillResume(lldb::StateType resume_state); - - const char * - GetInfo(); - - virtual lldb::RegisterContextSP - GetRegisterContext(); - - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - - //-------------------------------------------------------------------------- - // These static functions provide a mapping from the register offset - // back to the register index or name for use in debugging or log - // output. - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - static const char * - GetRegisterNameFromOffset(unsigned offset); - - //-------------------------------------------------------------------------- - // These methods form a specialized interface to linux threads. - // - bool Resume(); - - void Notify(const ProcessMessage &message); - -private: - RegisterContextLinux * - GetRegisterContextLinux () - { - if (!m_reg_context_sp) - GetRegisterContext(); - return (RegisterContextLinux *)m_reg_context_sp.get(); - } - - std::auto_ptr m_frame_ap; - - lldb::BreakpointSiteSP m_breakpoint; - lldb::StopInfoSP m_stop_info; - - ProcessMonitor & - GetMonitor(); - - lldb::StopInfoSP - GetPrivateStopReason(); - - void BreakNotify(const ProcessMessage &message); - void TraceNotify(const ProcessMessage &message); - void LimboNotify(const ProcessMessage &message); - void SignalNotify(const ProcessMessage &message); - void SignalDeliveredNotify(const ProcessMessage &message); - void CrashNotify(const ProcessMessage &message); - - lldb_private::Unwind * - GetUnwinder(); -}; - -#endif // #ifndef liblldb_LinuxThread_H_ Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h =================================================================== --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (revision 147560) +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (working copy) @@ -10,67 +10,7 @@ #ifndef liblldb_RegisterContextLinux_x86_64_H_ #define liblldb_RegisterContextLinux_x86_64_H_ -#include "RegisterContextLinux.h" - -class ProcessMonitor; - -class RegisterContextLinux_x86_64 - : public RegisterContextLinux -{ -public: - RegisterContextLinux_x86_64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContextLinux_x86_64(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR + typedef struct _GPR { uint64_t r15; uint64_t r14; @@ -99,67 +39,6 @@ uint64_t es; uint64_t fs; uint64_t gs; - }; + } GPR; - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint64_t ip; - uint64_t dp; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[16]; - uint32_t padding[24]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - int32_t pad0; - FPU i387; // FPU registers. - uint64_t tsize; // Text segment size. - uint64_t dsize; // Data segment size. - uint64_t ssize; // Stack segment size. - uint64_t start_code; // VM address of text. - uint64_t start_stack; // VM address of stack bottom (top in rsp). - int64_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - int32_t pad1; - uint64_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint64_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). - uint64_t error_code; // CPU error code. - uint64_t fault_address; // Control register CR3. - }; - -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - bool ReadGPR(); - bool ReadFPR(); - - bool WriteGPR(); - bool WriteFPR(); -}; - -#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_ +#endif Index: source/Plugins/Process/POSIX/POSIXThread.h =================================================================== --- source/Plugins/Process/POSIX/POSIXThread.h (revision 0) +++ source/Plugins/Process/POSIX/POSIXThread.h (revision 0) @@ -0,0 +1,106 @@ +//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_POSIXThread_H_ +#define liblldb_POSIXThread_H_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIX.h" + +class ProcessMessage; +class ProcessMonitor; +class RegisterContextPOSIX; + +//------------------------------------------------------------------------------ +// @class POSIXThread +// @brief Abstraction of a linux process (thread). +class POSIXThread + : public lldb_private::Thread +{ +public: + POSIXThread(lldb_private::Process &process, lldb::tid_t tid); + + virtual ~POSIXThread(); + + void + RefreshStateAfterStop(); + + bool + WillResume(lldb::StateType resume_state); + + const char * + GetInfo(); + + virtual lldb::RegisterContextSP + GetRegisterContext(); + + virtual lldb::RegisterContextSP + CreateRegisterContextForFrame (lldb_private::StackFrame *frame); + + //-------------------------------------------------------------------------- + // These static functions provide a mapping from the register offset + // back to the register index or name for use in debugging or log + // output. + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + static const char * + GetRegisterNameFromOffset(unsigned offset); + + //-------------------------------------------------------------------------- + // These methods form a specialized interface to linux threads. + // + bool Resume(); + + void Notify(const ProcessMessage &message); + +private: + RegisterContextPOSIX * + GetRegisterContextPOSIX () + { + if (!m_reg_context_sp) + m_reg_context_sp = GetRegisterContext(); +#if 0 + return dynamic_cast(m_reg_context_sp.get()); +#endif + return (RegisterContextPOSIX *)m_reg_context_sp.get(); + } + + std::auto_ptr m_frame_ap; + + lldb::BreakpointSiteSP m_breakpoint; + lldb::StopInfoSP m_stop_info; + + ProcessMonitor & + GetMonitor(); + + lldb::StopInfoSP + GetPrivateStopReason(); + + void BreakNotify(const ProcessMessage &message); + void TraceNotify(const ProcessMessage &message); + void LimboNotify(const ProcessMessage &message); + void SignalNotify(const ProcessMessage &message); + void SignalDeliveredNotify(const ProcessMessage &message); + void CrashNotify(const ProcessMessage &message); + + lldb_private::Unwind * + GetUnwinder(); +}; + +#endif // #ifndef liblldb_POSIXThread_H_ Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) @@ -0,0 +1,594 @@ +//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Target.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "ProcessMonitor.h" +#include "POSIXThread.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------------ +// Static functions. +#if 0 +Process* +ProcessPOSIX::CreateInstance(Target& target, Listener &listener) +{ + return new ProcessPOSIX(target, listener); +} + + +void +ProcessPOSIX::Initialize() +{ + static bool g_initialized = false; + + if (!g_initialized) + { + g_initialized = true; + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + + Log::Callbacks log_callbacks = { + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories + }; + + Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks); + } +} +#endif + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) + : Process(target, listener), + m_monitor(NULL), + m_module(NULL), + m_in_limbo(false), + m_exit_now(false) +{ + // FIXME: Putting this code in the ctor and saving the byte order in a + // member variable is a hack to avoid const qual issues in GetByteOrder. + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); + m_byte_order = obj_file->GetByteOrder(); +} + +ProcessPOSIX::~ProcessPOSIX() +{ + delete m_monitor; +} + +//------------------------------------------------------------------------------ +// Process protocol. + +bool +ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) +{ + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target.GetExecutableModule()); + if (exe_module_sp.get()) + return exe_module_sp->GetFileSpec().Exists(); + return false; +} + +Error +ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid) +{ + Error error; + assert(m_monitor == NULL); + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID()); + + m_monitor = new ProcessMonitor(this, pid, error); + + if (!error.Success()) + return error; + + SetID(pid); + return error; +} + +Error +ProcessPOSIX::WillLaunch(Module* module) +{ + Error error; + return error; +} + +const char * +ProcessPOSIX::GetFilePath( + const lldb_private::ProcessLaunchInfo::FileAction *file_action, + const char *default_path) +{ + const char *pts_name = "/dev/pts/"; + const char *path = NULL; + + if (file_action) + { + if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) + path = file_action->GetPath(); + // By default the stdio paths passed in will be pseudo-terminal + // (/dev/pts). If so, convert to using a different default path + // instead to redirect I/O to the debugger console. This should + // also handle user overrides to /dev/null or a different file. + if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0) + path = default_path; + } + + return path; +} + +Error +ProcessPOSIX::DoLaunch (Module *module, + const ProcessLaunchInfo &launch_info) +{ + Error error; + assert(m_monitor == NULL); + + SetPrivateState(eStateLaunching); + + const lldb_private::ProcessLaunchInfo::FileAction *file_action; + + // Default of NULL will mean to use existing open file descriptors + const char *stdin_path = NULL; + const char *stdout_path = NULL; + const char *stderr_path = NULL; + + file_action = launch_info.GetFileActionForFD (STDIN_FILENO); + stdin_path = GetFilePath(file_action, stdin_path); + + file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); + stdout_path = GetFilePath(file_action, stdout_path); + + file_action = launch_info.GetFileActionForFD (STDERR_FILENO); + stderr_path = GetFilePath(file_action, stderr_path); + + m_monitor = new ProcessMonitor (this, + module, + launch_info.GetArguments().GetConstArgumentVector(), + launch_info.GetEnvironmentEntries().GetConstArgumentVector(), + stdin_path, + stdout_path, + stderr_path, + error); + + m_module = module; + + if (!error.Success()) + return error; + + SetID(m_monitor->GetPID()); + return error; +} + +void +ProcessPOSIX::DidLaunch() +{ +} + +Error +ProcessPOSIX::DoResume() +{ + StateType state = GetPrivateState(); + + assert(state == eStateStopped || state == eStateCrashed); + + // We are about to resume a thread that will cause the process to exit so + // set our exit status now. Do not change our state if the inferior + // crashed. + if (state == eStateStopped) + { + if (m_in_limbo) + SetExitStatus(m_exit_status, NULL); + else + SetPrivateState(eStateRunning); + } + + bool did_resume = false; + uint32_t thread_count = m_thread_list.GetSize(false); + for (uint32_t i = 0; i < thread_count; ++i) + { + POSIXThread *thread = static_cast( + m_thread_list.GetThreadAtIndex(i, false).get()); + did_resume = thread->Resume() || did_resume; + } + assert(did_resume && "Process resume failed!"); + + return Error(); +} + +addr_t +ProcessPOSIX::GetImageInfoAddress() +{ + Target *target = &GetTarget(); + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); + Address addr = obj_file->GetImageInfoAddress(); + + if (addr.IsValid()) + return addr.GetLoadAddress(target); + else + return LLDB_INVALID_ADDRESS; +} + +Error +ProcessPOSIX::DoHalt(bool &caused_stop) +{ + Error error; + + if (IsStopped()) + { + caused_stop = false; + } + else if (kill(GetID(), SIGSTOP)) + { + caused_stop = false; + error.SetErrorToErrno(); + } + else + { + caused_stop = true; + } + + return error; +} + +Error +ProcessPOSIX::DoDetach() +{ + Error error; + + error = m_monitor->Detach(); + if (error.Success()) + SetPrivateState(eStateDetached); + + return error; +} + +Error +ProcessPOSIX::DoSignal(int signal) +{ + Error error; + + if (kill(GetID(), signal)) + error.SetErrorToErrno(); + + return error; +} + +Error +ProcessPOSIX::DoDestroy() +{ + Error error; + + if (!HasExited()) + { + // Drive the exit event to completion (do not keep the inferior in + // limbo). + m_exit_now = true; + + if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) + { + error.SetErrorToErrno(); + return error; + } + + SetPrivateState(eStateExited); + } + + return error; +} + +void +ProcessPOSIX::SendMessage(const ProcessMessage &message) +{ + Mutex::Locker lock(m_message_mutex); + + switch (message.GetKind()) + { + default: + assert(false && "Unexpected process message!"); + break; + + case ProcessMessage::eInvalidMessage: + return; + + case ProcessMessage::eLimboMessage: + m_in_limbo = true; + m_exit_status = message.GetExitStatus(); + if (m_exit_now) + { + SetPrivateState(eStateExited); + m_monitor->Detach(); + } + else + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eExitMessage: + m_exit_status = message.GetExitStatus(); + SetExitStatus(m_exit_status, NULL); + break; + + case ProcessMessage::eTraceMessage: + case ProcessMessage::eBreakpointMessage: + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eSignalMessage: + case ProcessMessage::eSignalDeliveredMessage: + SetPrivateState(eStateStopped); + break; + + case ProcessMessage::eCrashMessage: + SetPrivateState(eStateCrashed); + break; + } + + m_message_queue.push(message); +} + +void +ProcessPOSIX::RefreshStateAfterStop() +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s()", __FUNCTION__); + + Mutex::Locker lock(m_message_mutex); + if (m_message_queue.empty()) + return; + + ProcessMessage &message = m_message_queue.front(); + + // Resolve the thread this message corresponds to and pass it along. + // FIXME: we're really dealing with the pid here. This should get + // fixed when this code is fixed to handle multiple threads. + lldb::tid_t tid = message.GetTID(); + if (log) + log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid); + POSIXThread *thread = static_cast( + GetThreadList().FindThreadByID(tid, false).get()); + + assert(thread); + thread->Notify(message); + + m_message_queue.pop(); +} + +bool +ProcessPOSIX::IsAlive() +{ + StateType state = GetPrivateState(); + return state != eStateDetached && state != eStateExited && state != eStateInvalid; +} + +size_t +ProcessPOSIX::DoReadMemory(addr_t vm_addr, + void *buf, size_t size, Error &error) +{ + assert(m_monitor); + return m_monitor->ReadMemory(vm_addr, buf, size, error); +} + +size_t +ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, + Error &error) +{ + assert(m_monitor); + return m_monitor->WriteMemory(vm_addr, buf, size, error); +} + +addr_t +ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, + Error &error) +{ + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { + m_addr_to_mmap_size[allocated_addr] = size; + error.Clear(); + } else { + allocated_addr = LLDB_INVALID_ADDRESS; + error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); + } + + return allocated_addr; +} + +Error +ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) +{ + Error error; + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); + if (pos != m_addr_to_mmap_size.end() && + InferiorCallMunmap(this, addr, pos->second)) + m_addr_to_mmap_size.erase (pos); + else + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); + + return error; +} + +size_t +ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) +{ + static const uint8_t g_i386_opcode[] = { 0xCC }; + + ArchSpec arch = GetTarget().GetArchitecture(); + const uint8_t *opcode = NULL; + size_t opcode_size = 0; + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_64_x86_64: + opcode = g_i386_opcode; + opcode_size = sizeof(g_i386_opcode); + break; + } + + bp_site->SetTrapOpcode(opcode, opcode_size); + return opcode_size; +} + +Error +ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site) +{ + return EnableSoftwareBreakpoint(bp_site); +} + +Error +ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site) +{ + return DisableSoftwareBreakpoint(bp_site); +} + +uint32_t +ProcessPOSIX::UpdateThreadListIfNeeded() +{ + // Do not allow recursive updates. + return m_thread_list.GetSize(false); +} + +uint32_t +ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID()); + + // Update the process thread list with this new thread. + // FIXME: We should be using tid, not pid. + assert(m_monitor); + ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); + if (!thread_sp) + thread_sp.reset(new POSIXThread(*this, GetID())); + + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID()); + new_thread_list.AddThread(thread_sp); + + return new_thread_list.GetSize(false); +} + +ByteOrder +ProcessPOSIX::GetByteOrder() const +{ + // FIXME: We should be able to extract this value directly. See comment in + // ProcessPOSIX(). + return m_byte_order; +} + +size_t +ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) +{ + ssize_t status; + if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) + { + error.SetErrorToErrno(); + return 0; + } + return status; +} + +size_t +ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error) +{ + ssize_t bytes_read; + + // The terminal file descriptor is always in non-block mode. + if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) + { + if (errno != EAGAIN) + error.SetErrorToErrno(); + return 0; + } + return bytes_read; +} + +size_t +ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error) +{ + return GetSTDOUT(buf, len, error); +} + +UnixSignals & +ProcessPOSIX::GetUnixSignals() +{ + return m_signals; +} + +//------------------------------------------------------------------------------ +// Utility functions. + +bool +ProcessPOSIX::HasExited() +{ + switch (GetPrivateState()) + { + default: + break; + + case eStateDetached: + case eStateExited: + return true; + } + + return false; +} + +bool +ProcessPOSIX::IsStopped() +{ + switch (GetPrivateState()) + { + default: + break; + + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + return true; + } + + return false; +} Index: source/Plugins/Process/POSIX/RegisterContext_i386.cpp =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) @@ -0,0 +1,643 @@ +//===-- RegisterContextPOSIX_i386.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/Core/DataExtractor.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContext_i386.h" + +using namespace lldb_private; +using namespace lldb; + +enum +{ + k_first_gpr, + gpr_eax = k_first_gpr, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_ss, + gpr_eflags, +#ifdef __FreeBSD__ + gpr_orig_ax, +#endif + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, + k_last_gpr = gpr_gs, + + k_first_fpr, + fpu_fcw = k_first_fpr, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_foo, + fpu_fos, + fpu_mxcsr, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + k_last_fpr = fpu_xmm7, + + k_num_registers, + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +enum +{ + gcc_eax = 0, + gcc_ecx, + gcc_edx, + gcc_ebx, + gcc_ebp, + gcc_esp, + gcc_esi, + gcc_edi, + gcc_eip, + gcc_eflags +}; + +enum +{ + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + dwarf_stmm0 = 11, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7 +}; + +enum +{ + gdb_eax = 0, + gdb_ecx = 1, + gdb_edx = 2, + gdb_ebx = 3, + gdb_esp = 4, + gdb_ebp = 5, + gdb_esi = 6, + gdb_edi = 7, + gdb_eip = 8, + gdb_eflags = 9, + gdb_cs = 10, + gdb_ss = 11, + gdb_ds = 12, + gdb_es = 13, + gdb_fs = 14, + gdb_gs = 15, + gdb_stmm0 = 16, + gdb_stmm1 = 17, + gdb_stmm2 = 18, + gdb_stmm3 = 19, + gdb_stmm4 = 20, + gdb_stmm5 = 21, + gdb_stmm6 = 22, + gdb_stmm7 = 23, + gdb_fcw = 24, + gdb_fsw = 25, + gdb_ftw = 26, + gdb_fpu_cs = 27, + gdb_ip = 28, + gdb_fpu_ds = 29, + gdb_dp = 30, + gdb_fop = 31, + gdb_xmm0 = 32, + gdb_xmm1 = 33, + gdb_xmm2 = 34, + gdb_xmm3 = 35, + gdb_xmm4 = 36, + gdb_xmm5 = 37, + gdb_xmm6 = 38, + gdb_xmm7 = 39, + gdb_mxcsr = 40, + gdb_mm0 = 41, + gdb_mm1 = 42, + gdb_mm2 = 43, + gdb_mm3 = 44, + gdb_mm4 = 45, + gdb_mm5 = 46, + gdb_mm6 = 47, + gdb_mm7 = 48 +}; + +static const +uint32_t g_gpr_regnums[k_num_gpr_registers] = +{ + gpr_eax, + gpr_ebx, + gpr_ecx, + gpr_edx, + gpr_edi, + gpr_esi, + gpr_ebp, + gpr_esp, + gpr_ss, + gpr_eflags, +#ifdef __FreeBSD__ + gpr_orig_ax, +#endif + gpr_eip, + gpr_cs, + gpr_ds, + gpr_es, + gpr_fs, + gpr_gs, +}; + +static const uint32_t +g_fpu_regnums[k_num_fpu_registers] = +{ + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_foo, + fpu_fos, + fpu_mxcsr, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, +}; + +static const RegisterSet +g_reg_sets[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } +}; + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (offsetof(RegisterContext_i386::UserArea, regs) + \ + offsetof(RegisterContext_i386::GPR, regname)) + +// Computes the offset of the given FPR in the user data area. +#define FPR_OFFSET(regname) \ + (offsetof(RegisterContext_i386::UserArea, i387) + \ + offsetof(RegisterContext_i386::FPU, regname)) + +// Number of bytes needed to represent a GPR. +#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } + +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } + +#define DEFINE_FP(reg, i) \ + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { dwarf_##reg##i, dwarf_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { dwarf_##reg##i, dwarf_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } + +static RegisterInfo +g_register_infos[k_num_registers] = +{ + // General purpose registers. + DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), + DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), + DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), + DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), + DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), + DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), + DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), + DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), + DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), + DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), + + // Floating point registers. + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), + DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), + DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), + DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), + + DEFINE_FP(stmm, 0), + DEFINE_FP(stmm, 1), + DEFINE_FP(stmm, 2), + DEFINE_FP(stmm, 3), + DEFINE_FP(stmm, 4), + DEFINE_FP(stmm, 5), + DEFINE_FP(stmm, 6), + DEFINE_FP(stmm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + +}; + +#ifndef NDEBUG +static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); +#endif + +static unsigned GetRegOffset(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_offset; +} + +static unsigned GetRegSize(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_size; +} + +RegisterContext_i386::RegisterContext_i386(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextPOSIX(thread, concrete_frame_idx) +{ +} + +RegisterContext_i386::~RegisterContext_i386() +{ +} + +ProcessMonitor & +RegisterContext_i386::GetMonitor() +{ + ProcessPOSIX *process = static_cast(CalculateProcess()); + return process->GetMonitor(); +} + +void +RegisterContext_i386::Invalidate() +{ +} + +void +RegisterContext_i386::InvalidateAllRegisters() +{ +} + +size_t +RegisterContext_i386::GetRegisterCount() +{ + assert(k_num_register_infos == k_num_registers); + return k_num_registers; +} + +const RegisterInfo * +RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg) +{ + assert(k_num_register_infos == k_num_registers); + if (reg < k_num_registers) + return &g_register_infos[reg]; + else + return NULL; +} + +size_t +RegisterContext_i386::GetRegisterSetCount() +{ + return k_num_register_sets; +} + +const RegisterSet * +RegisterContext_i386::GetRegisterSet(uint32_t set) +{ + if (set < k_num_register_sets) + return &g_reg_sets[set]; + else + return NULL; +} + +unsigned +RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < k_num_registers; reg++) + { + if (g_register_infos[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers && "Invalid register offset."); + return reg; +} + +const char * +RegisterContext_i386::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register offset."); + return g_register_infos[reg].name; +} + +bool +RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); +} + +bool +RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + return false; +} + +bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(GetRegOffset(reg), value); +} + +bool +RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data) +{ + return false; +} + +bool +RegisterContext_i386::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +uint32_t +RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + if (kind == eRegisterKindGeneric) + { + switch (num) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_eip; + case LLDB_REGNUM_GENERIC_SP: return gpr_esp; + case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; + case LLDB_REGNUM_GENERIC_RA: + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) + { + switch (num) + { + case dwarf_eax: return gpr_eax; + case dwarf_edx: return gpr_edx; + case dwarf_ecx: return gpr_ecx; + case dwarf_ebx: return gpr_ebx; + case dwarf_esi: return gpr_esi; + case dwarf_edi: return gpr_edi; + case dwarf_ebp: return gpr_ebp; + case dwarf_esp: return gpr_esp; + case dwarf_eip: return gpr_eip; + case dwarf_xmm0: return fpu_xmm0; + case dwarf_xmm1: return fpu_xmm1; + case dwarf_xmm2: return fpu_xmm2; + case dwarf_xmm3: return fpu_xmm3; + case dwarf_xmm4: return fpu_xmm4; + case dwarf_xmm5: return fpu_xmm5; + case dwarf_xmm6: return fpu_xmm6; + case dwarf_xmm7: return fpu_xmm7; + case dwarf_stmm0: return fpu_stmm0; + case dwarf_stmm1: return fpu_stmm1; + case dwarf_stmm2: return fpu_stmm2; + case dwarf_stmm3: return fpu_stmm3; + case dwarf_stmm4: return fpu_stmm4; + case dwarf_stmm5: return fpu_stmm5; + case dwarf_stmm6: return fpu_stmm6; + case dwarf_stmm7: return fpu_stmm7; + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGDB) + { + switch (num) + { + case gdb_eax : return gpr_eax; + case gdb_ebx : return gpr_ebx; + case gdb_ecx : return gpr_ecx; + case gdb_edx : return gpr_edx; + case gdb_esi : return gpr_esi; + case gdb_edi : return gpr_edi; + case gdb_ebp : return gpr_ebp; + case gdb_esp : return gpr_esp; + case gdb_eip : return gpr_eip; + case gdb_eflags : return gpr_eflags; + case gdb_cs : return gpr_cs; + case gdb_ss : return gpr_ss; + case gdb_ds : return gpr_ds; + case gdb_es : return gpr_es; + case gdb_fs : return gpr_fs; + case gdb_gs : return gpr_gs; + case gdb_stmm0 : return fpu_stmm0; + case gdb_stmm1 : return fpu_stmm1; + case gdb_stmm2 : return fpu_stmm2; + case gdb_stmm3 : return fpu_stmm3; + case gdb_stmm4 : return fpu_stmm4; + case gdb_stmm5 : return fpu_stmm5; + case gdb_stmm6 : return fpu_stmm6; + case gdb_stmm7 : return fpu_stmm7; + case gdb_fcw : return fpu_fcw; + case gdb_fsw : return fpu_fsw; + case gdb_ftw : return fpu_ftw; + case gdb_fpu_cs : return fpu_cs; + case gdb_ip : return fpu_ip; + case gdb_fpu_ds : return fpu_fos; + case gdb_dp : return fpu_foo; + case gdb_fop : return fpu_fop; + case gdb_xmm0 : return fpu_xmm0; + case gdb_xmm1 : return fpu_xmm1; + case gdb_xmm2 : return fpu_xmm2; + case gdb_xmm3 : return fpu_xmm3; + case gdb_xmm4 : return fpu_xmm4; + case gdb_xmm5 : return fpu_xmm5; + case gdb_xmm6 : return fpu_xmm6; + case gdb_xmm7 : return fpu_xmm7; + case gdb_mxcsr : return fpu_mxcsr; + default: + return LLDB_INVALID_REGNUM; + } + } + else if (kind == eRegisterKindLLDB) + { + return num; + } + + return LLDB_INVALID_REGNUM; +} + +bool +RegisterContext_i386::HardwareSingleStep(bool enable) +{ + enum { TRACE_BIT = 0x100 }; + uint64_t eflags; + + if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) + return false; + + if (enable) + { + if (eflags & TRACE_BIT) + return true; + + eflags |= TRACE_BIT; + } + else + { + if (!(eflags & TRACE_BIT)) + return false; + + eflags &= ~TRACE_BIT; + } + + return WriteRegisterFromUnsigned(gpr_eflags, eflags); +} + +void +RegisterContext_i386::LogGPR(const char *title) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); + if (log) + { + if (title) + log->Printf ("%s", title); + for (uint32_t i=0; iPrintf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); + } + } +} + +bool +RegisterContext_i386::ReadGPR() +{ + bool result; + + ProcessMonitor &monitor = GetMonitor(); + result = monitor.ReadGPR(&user.regs); + LogGPR("RegisterContext_i386::ReadGPR()"); + return result; +} + +bool +RegisterContext_i386::ReadFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(&user.i387); +} Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) @@ -0,0 +1,195 @@ +//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessPOSIXLog.h" + +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/StreamFile.h" + +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" + +using namespace lldb; +using namespace lldb_private; + + +// We want to avoid global constructors where code needs to be run so here we +// control access to our static g_log_sp by hiding it in a singleton function +// that will construct the static g_lob_sp the first time this function is +// called. +static LogSP & +GetLog () +{ + static LogSP g_log_sp; + return g_log_sp; +} + +LogSP +ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) +{ + LogSP log(GetLog ()); + if (log && mask) + { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return LogSP(); + } + return log; +} + +void +ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm) +{ + LogSP log (GetLog ()); + if (log) + { + uint32_t flag_bits = 0; + + const size_t argc = args.GetArgumentCount (); + if (argc > 0) + { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; i < argc; ++i) + { + const char *arg = args.GetArgumentAtIndex (i); + + + if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; + else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; + else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; + else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; + else + { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories (feedback_strm); + } + + } + } + + if (flag_bits == 0) + GetLog ().reset(); + else + log->GetMask().Reset (flag_bits); + } + + return; +} + +LogSP +ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) +{ + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the same. + uint32_t flag_bits = 0; + LogSP log(GetLog ()); + if (log) + flag_bits = log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) + { + log = make_shared(log_stream_sp); + GetLog () = log; + } + + if (log) + { + bool got_unknown_category = false; + const size_t argc = args.GetArgumentCount(); + for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) + { + got_unknown_category = true; + ListLogCategories (feedback_strm); + } + } + } + if (flag_bits == 0) + flag_bits = POSIX_LOG_DEFAULT; + log->GetMask().Reset(flag_bits); + log->GetOptions().Reset(log_options); + } + return log; +} + +void +ProcessPOSIXLog::ListLogCategories (Stream *strm) +{ + strm->Printf ("Logging categories for '%s':\n" + " all - turn on all available logging categories\n" + " async - log asynchronous activity\n" + " break - log breakpoints\n" + " communication - log communication activity\n" + " default - enable the default set of logging categories for liblldb\n" + " packets - log gdb remote packets\n" + " memory - log memory reads and writes\n" + " data-short - log memory bytes for memory reads and writes for short transactions only\n" + " data-long - log memory bytes for memory reads and writes for all transactions\n" + " process - log process events and activities\n" +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION + " ptrace - log all calls to ptrace\n" +#endif + " registers - log register read/writes\n" + " thread - log thread events and activities\n" + " step - log step related activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); +} + + +void +ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); + if (log) + { + va_list args; + va_start (args, format); + log->VAPrintf (format, args); + va_end (args); + } +} + +int ProcessPOSIXLog::m_nestinglevel; +const char *ProcessPOSIXLog::m_pluginname = ""; Index: source/Plugins/Process/POSIX/ProcessPOSIX.h =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) @@ -0,0 +1,180 @@ +//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessPOSIX_H_ +#define liblldb_ProcessPOSIX_H_ + +// C Includes + +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Process.h" +#include "lldb/Target/UnixSignals.h" +#include "ProcessMessage.h" + +class ProcessMonitor; + +class ProcessPOSIX : + public lldb_private::Process +{ +public: + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessPOSIX(lldb_private::Target& target, + lldb_private::Listener &listener); + + virtual + ~ProcessPOSIX(); + + //------------------------------------------------------------------ + // Process protocol. + //------------------------------------------------------------------ + virtual bool + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); + + virtual lldb_private::Error + WillLaunch(lldb_private::Module *module); + + virtual lldb_private::Error + DoAttachToProcessWithID(lldb::pid_t pid); + + virtual lldb_private::Error + DoLaunch (lldb_private::Module *exe_module, + const lldb_private::ProcessLaunchInfo &launch_info); + + virtual void + DidLaunch(); + + virtual lldb_private::Error + DoResume(); + + virtual lldb_private::Error + DoHalt(bool &caused_stop); + + virtual lldb_private::Error + DoDetach(); + + virtual lldb_private::Error + DoSignal(int signal); + + virtual lldb_private::Error + DoDestroy(); + + virtual void + RefreshStateAfterStop(); + + virtual bool + IsAlive(); + + virtual size_t + DoReadMemory(lldb::addr_t vm_addr, + void *buf, + size_t size, + lldb_private::Error &error); + + virtual size_t + DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error); + + virtual lldb::addr_t + DoAllocateMemory(size_t size, uint32_t permissions, + lldb_private::Error &error); + + virtual lldb_private::Error + DoDeallocateMemory(lldb::addr_t ptr); + + virtual size_t + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); + + virtual lldb_private::Error + EnableBreakpoint(lldb_private::BreakpointSite *bp_site); + + virtual lldb_private::Error + DisableBreakpoint(lldb_private::BreakpointSite *bp_site); + + virtual uint32_t + UpdateThreadListIfNeeded(); + + virtual uint32_t + UpdateThreadList(lldb_private::ThreadList &old_thread_list, + lldb_private::ThreadList &new_thread_list) = 0; + + virtual lldb::ByteOrder + GetByteOrder() const; + + virtual lldb::addr_t + GetImageInfoAddress(); + + virtual size_t + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); + + virtual size_t + GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); + + virtual size_t + GetSTDERR(char *buf, size_t len, lldb_private::Error &error); + + //-------------------------------------------------------------------------- + // ProcessPOSIX internal API. + + /// Registers the given message with this process. + void SendMessage(const ProcessMessage &message); + + ProcessMonitor & + GetMonitor() { assert(m_monitor); return *m_monitor; } + + lldb_private::UnixSignals & + GetUnixSignals(); + + const char * + GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action, + const char *default_path); + +protected: + /// Target byte order. + lldb::ByteOrder m_byte_order; + + /// Process monitor; + ProcessMonitor *m_monitor; + + /// The module we are executing. + lldb_private::Module *m_module; + + /// Message queue notifying this instance of inferior process state changes. + lldb_private::Mutex m_message_mutex; + std::queue m_message_queue; + + /// True when the process has entered a state of "limbo". + /// + /// This flag qualifies eStateStopped. It lets us know that when we + /// continue from this state the process will exit. Also, when true, + /// Process::m_exit_status is set. + bool m_in_limbo; + + /// Drive any exit events to completion. + bool m_exit_now; + + /// OS-specific signal set. + lldb_private::UnixSignals m_signals; + + /// Returns true if the process has exited. + bool HasExited(); + + /// Returns true if the process is stopped. + bool IsStopped(); + + typedef std::map MMapMap; + MMapMap m_addr_to_mmap_size; +}; + +#endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/POSIX/RegisterContext_i386.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) @@ -0,0 +1,169 @@ +//===-- RegisterContext_i386.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_RegisterContext_i386_h_ +#define liblldb_RegisterContext_i386_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" + +class RegisterContext_i386 : public RegisterContextPOSIX +{ +public: + RegisterContext_i386(lldb_private::Thread &thread, + uint32_t concreate_frame_idx); + + ~RegisterContext_i386(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(uint32_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(uint32_t set); + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + bool + ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); + + bool + ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + bool + WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); + + bool + WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, + uint32_t data_offset = 0); + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + + bool + HardwareSingleStep(bool enable); + + bool + UpdateAfterBreakpoint(); + + struct GPR + { + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t ds; + uint32_t es; + uint32_t fs; + uint32_t gs; + uint32_t orig_ax; + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; + }; + + struct MMSReg + { + uint8_t bytes[8]; + }; + + struct XMMReg + { + uint8_t bytes[16]; + }; + + struct FPU + { + uint16_t fcw; + uint16_t fsw; + uint16_t ftw; + uint16_t fop; + uint32_t ip; + uint32_t cs; + uint32_t foo; + uint32_t fos; + uint32_t mxcsr; + uint32_t reserved; + MMSReg stmm[8]; + XMMReg xmm[8]; + uint32_t pad[56]; + }; + + // A user area like this no longer exists on FreeBSD + // making this a Linux artifact. Nonetheless, it is safe + // leaving it here while the code is being cleaned up and generalized. + + struct UserArea + { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + FPU i387; // FPU registers. + uint32_t tsize; // Text segment size. + uint32_t dsize; // Data segment size. + uint32_t ssize; // Stack segment size. + uint32_t start_code; // VM address of text. + uint32_t start_stack; // VM address of stack bottom (top in rsp). + int32_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + uint32_t ar0; // Location of GPR's. + FPU* fpstate; // Location of FPR's. + uint32_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). + }; +private: + UserArea user; + + ProcessMonitor &GetMonitor(); + + void LogGPR(const char *title); + + bool ReadGPR(); + bool ReadFPR(); +}; + +#endif // #ifndef liblldb_RegisterContext_i386_h_ Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) @@ -0,0 +1,757 @@ +//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Target/Thread.h" +#include "lldb/Host/Endian.h" + +#include "ProcessPOSIX.h" +#include "ProcessMonitor.h" +#include "RegisterContext_x86_64.h" + +using namespace lldb_private; +using namespace lldb; + +// Internal codes for all x86_64 registers. +enum +{ + k_first_gpr, + gpr_rax = k_first_gpr, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + gpr_ss, + gpr_ds, + gpr_es, + k_last_gpr = gpr_es, + + k_first_fpr, + fpu_fcw = k_first_fpr, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15, + k_last_fpr = fpu_xmm15, + + k_num_registers, + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 +}; + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +enum gcc_dwarf_regnums +{ + gcc_dwarf_gpr_rax = 0, + gcc_dwarf_gpr_rdx, + gcc_dwarf_gpr_rcx, + gcc_dwarf_gpr_rbx, + gcc_dwarf_gpr_rsi, + gcc_dwarf_gpr_rdi, + gcc_dwarf_gpr_rbp, + gcc_dwarf_gpr_rsp, + gcc_dwarf_gpr_r8, + gcc_dwarf_gpr_r9, + gcc_dwarf_gpr_r10, + gcc_dwarf_gpr_r11, + gcc_dwarf_gpr_r12, + gcc_dwarf_gpr_r13, + gcc_dwarf_gpr_r14, + gcc_dwarf_gpr_r15, + gcc_dwarf_gpr_rip, + gcc_dwarf_fpu_xmm0, + gcc_dwarf_fpu_xmm1, + gcc_dwarf_fpu_xmm2, + gcc_dwarf_fpu_xmm3, + gcc_dwarf_fpu_xmm4, + gcc_dwarf_fpu_xmm5, + gcc_dwarf_fpu_xmm6, + gcc_dwarf_fpu_xmm7, + gcc_dwarf_fpu_xmm8, + gcc_dwarf_fpu_xmm9, + gcc_dwarf_fpu_xmm10, + gcc_dwarf_fpu_xmm11, + gcc_dwarf_fpu_xmm12, + gcc_dwarf_fpu_xmm13, + gcc_dwarf_fpu_xmm14, + gcc_dwarf_fpu_xmm15, + gcc_dwarf_fpu_stmm0, + gcc_dwarf_fpu_stmm1, + gcc_dwarf_fpu_stmm2, + gcc_dwarf_fpu_stmm3, + gcc_dwarf_fpu_stmm4, + gcc_dwarf_fpu_stmm5, + gcc_dwarf_fpu_stmm6, + gcc_dwarf_fpu_stmm7 +}; + +enum gdb_regnums +{ + gdb_gpr_rax = 0, + gdb_gpr_rbx = 1, + gdb_gpr_rcx = 2, + gdb_gpr_rdx = 3, + gdb_gpr_rsi = 4, + gdb_gpr_rdi = 5, + gdb_gpr_rbp = 6, + gdb_gpr_rsp = 7, + gdb_gpr_r8 = 8, + gdb_gpr_r9 = 9, + gdb_gpr_r10 = 10, + gdb_gpr_r11 = 11, + gdb_gpr_r12 = 12, + gdb_gpr_r13 = 13, + gdb_gpr_r14 = 14, + gdb_gpr_r15 = 15, + gdb_gpr_rip = 16, + gdb_gpr_rflags = 17, + gdb_gpr_cs = 18, + gdb_gpr_ss = 19, + gdb_gpr_ds = 20, + gdb_gpr_es = 21, + gdb_gpr_fs = 22, + gdb_gpr_gs = 23, + gdb_fpu_stmm0 = 24, + gdb_fpu_stmm1 = 25, + gdb_fpu_stmm2 = 26, + gdb_fpu_stmm3 = 27, + gdb_fpu_stmm4 = 28, + gdb_fpu_stmm5 = 29, + gdb_fpu_stmm6 = 30, + gdb_fpu_stmm7 = 31, + gdb_fpu_fcw = 32, + gdb_fpu_fsw = 33, + gdb_fpu_ftw = 34, + gdb_fpu_cs = 35, + gdb_fpu_ip = 36, + gdb_fpu_ds = 37, + gdb_fpu_dp = 38, + gdb_fpu_fop = 39, + gdb_fpu_xmm0 = 40, + gdb_fpu_xmm1 = 41, + gdb_fpu_xmm2 = 42, + gdb_fpu_xmm3 = 43, + gdb_fpu_xmm4 = 44, + gdb_fpu_xmm5 = 45, + gdb_fpu_xmm6 = 46, + gdb_fpu_xmm7 = 47, + gdb_fpu_xmm8 = 48, + gdb_fpu_xmm9 = 49, + gdb_fpu_xmm10 = 50, + gdb_fpu_xmm11 = 51, + gdb_fpu_xmm12 = 52, + gdb_fpu_xmm13 = 53, + gdb_fpu_xmm14 = 54, + gdb_fpu_xmm15 = 55, + gdb_fpu_mxcsr = 56 +}; + +static const +uint32_t g_gpr_regnums[k_num_gpr_registers] = +{ + gpr_rax, + gpr_rbx, + gpr_rcx, + gpr_rdx, + gpr_rdi, + gpr_rsi, + gpr_rbp, + gpr_rsp, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_rip, + gpr_rflags, + gpr_cs, + gpr_fs, + gpr_gs, + gpr_ss, + gpr_ds, + gpr_es +}; + +static const uint32_t +g_fpu_regnums[k_num_fpu_registers] = +{ + fpu_fcw, + fpu_fsw, + fpu_ftw, + fpu_fop, + fpu_ip, + fpu_cs, + fpu_dp, + fpu_ds, + fpu_mxcsr, + fpu_mxcsrmask, + fpu_stmm0, + fpu_stmm1, + fpu_stmm2, + fpu_stmm3, + fpu_stmm4, + fpu_stmm5, + fpu_stmm6, + fpu_stmm7, + fpu_xmm0, + fpu_xmm1, + fpu_xmm2, + fpu_xmm3, + fpu_xmm4, + fpu_xmm5, + fpu_xmm6, + fpu_xmm7, + fpu_xmm8, + fpu_xmm9, + fpu_xmm10, + fpu_xmm11, + fpu_xmm12, + fpu_xmm13, + fpu_xmm14, + fpu_xmm15 +}; + +static const RegisterSet +g_reg_sets[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } +}; + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (offsetof(RegisterContext_x86_64::UserArea, regs) + \ + offsetof(GPR, regname)) + +// Computes the offset of the given FPR in the user data area. +#define FPR_OFFSET(regname) \ + (offsetof(RegisterContext_x86_64::UserArea, i387) + \ + offsetof(RegisterContext_x86_64::FPU, regname)) + +// Number of bytes needed to represent a GPR. +#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg) + +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } + +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } + +#define DEFINE_FP(reg, i) \ + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } + +#define DEFINE_XMM(reg, i) \ + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ + eFormatVectorOfUInt8, \ + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } + +#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU)) + +static RegisterInfo +g_register_infos[k_num_registers] = +{ + // General purpose registers. + DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), + DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), + DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), + DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), + DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), + DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), + DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), + DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), + DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), + DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), + DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), + DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), + DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), + DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), + DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), + DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), + DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), + DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), + + // i387 Floating point registers. + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), + // FIXME: Extract segment from ip. + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), + // FIXME: Extract segment from dp. + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), + DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + + // FP registers. + DEFINE_FP(stmm, 0), + DEFINE_FP(stmm, 1), + DEFINE_FP(stmm, 2), + DEFINE_FP(stmm, 3), + DEFINE_FP(stmm, 4), + DEFINE_FP(stmm, 5), + DEFINE_FP(stmm, 6), + DEFINE_FP(stmm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), + DEFINE_XMM(xmm, 10), + DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), + DEFINE_XMM(xmm, 13), + DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 15) +}; + +static unsigned GetRegOffset(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_offset; +} + +static unsigned GetRegSize(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register number."); + return g_register_infos[reg].byte_size; +} + +static bool IsGPR(unsigned reg) +{ + return reg <= k_last_gpr; // GPR's come first. +} + +static bool IsFPR(unsigned reg) +{ + return (k_first_fpr <= reg && reg <= k_last_fpr); +} + +RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContextPOSIX(thread, concrete_frame_idx) +{ +} + +RegisterContext_x86_64::~RegisterContext_x86_64() +{ +} + +ProcessMonitor & +RegisterContext_x86_64::GetMonitor() +{ + ProcessPOSIX *process = static_cast(CalculateProcess()); + return process->GetMonitor(); +} + +void +RegisterContext_x86_64::Invalidate() +{ +} + +void +RegisterContext_x86_64::InvalidateAllRegisters() +{ +} + +size_t +RegisterContext_x86_64::GetRegisterCount() +{ + return k_num_registers; +} + +const RegisterInfo * +RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg) +{ + if (reg < k_num_registers) + return &g_register_infos[reg]; + else + return NULL; +} + +size_t +RegisterContext_x86_64::GetRegisterSetCount() +{ + return k_num_register_sets; +} + +const RegisterSet * +RegisterContext_x86_64::GetRegisterSet(uint32_t set) +{ + if (set < k_num_register_sets) + return &g_reg_sets[set]; + else + return NULL; +} + +unsigned +RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + for (reg = 0; reg < k_num_registers; reg++) + { + if (g_register_infos[reg].byte_offset == offset) + break; + } + assert(reg < k_num_registers && "Invalid register offset."); + return reg; +} + +const char * +RegisterContext_x86_64::GetRegisterName(unsigned reg) +{ + assert(reg < k_num_registers && "Invalid register offset."); + return g_register_infos[reg].name; +} + +bool +RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); +} + +bool +RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) +{ + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); + if (data_sp && ReadGPR () && ReadFPR ()) + { + uint8_t *dst = data_sp->GetBytes(); + ::memcpy (dst, &user.regs, sizeof(user.regs)); + dst += sizeof(user.regs); + + ::memcpy (dst, &user.i387, sizeof(user.i387)); + return true; + } + return false; +} + +bool +RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteRegisterValue(GetRegOffset(reg), value); +} + +bool +RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) +{ + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) + { + const uint8_t *src = data_sp->GetBytes(); + ::memcpy (&user.regs, src, sizeof(user.regs)); + src += sizeof(user.regs); + + ::memcpy (&user.i387, src, sizeof(user.i387)); + return WriteGPR() & WriteFPR(); + } + return false; +} + +bool +RegisterContext_x86_64::UpdateAfterBreakpoint() +{ + // PC points one byte past the int3 responsible for the breakpoint. + lldb::addr_t pc; + + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) + return false; + + SetPC(pc - 1); + return true; +} + +uint32_t +RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, + uint32_t num) +{ + if (kind == eRegisterKindGeneric) + { + switch (num) + { + case LLDB_REGNUM_GENERIC_PC: return gpr_rip; + case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; + case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; + case LLDB_REGNUM_GENERIC_RA: + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) + { + switch (num) + { + case gcc_dwarf_gpr_rax: return gpr_rax; + case gcc_dwarf_gpr_rdx: return gpr_rdx; + case gcc_dwarf_gpr_rcx: return gpr_rcx; + case gcc_dwarf_gpr_rbx: return gpr_rbx; + case gcc_dwarf_gpr_rsi: return gpr_rsi; + case gcc_dwarf_gpr_rdi: return gpr_rdi; + case gcc_dwarf_gpr_rbp: return gpr_rbp; + case gcc_dwarf_gpr_rsp: return gpr_rsp; + case gcc_dwarf_gpr_r8: return gpr_r8; + case gcc_dwarf_gpr_r9: return gpr_r9; + case gcc_dwarf_gpr_r10: return gpr_r10; + case gcc_dwarf_gpr_r11: return gpr_r11; + case gcc_dwarf_gpr_r12: return gpr_r12; + case gcc_dwarf_gpr_r13: return gpr_r13; + case gcc_dwarf_gpr_r14: return gpr_r14; + case gcc_dwarf_gpr_r15: return gpr_r15; + case gcc_dwarf_gpr_rip: return gpr_rip; + case gcc_dwarf_fpu_xmm0: return fpu_xmm0; + case gcc_dwarf_fpu_xmm1: return fpu_xmm1; + case gcc_dwarf_fpu_xmm2: return fpu_xmm2; + case gcc_dwarf_fpu_xmm3: return fpu_xmm3; + case gcc_dwarf_fpu_xmm4: return fpu_xmm4; + case gcc_dwarf_fpu_xmm5: return fpu_xmm5; + case gcc_dwarf_fpu_xmm6: return fpu_xmm6; + case gcc_dwarf_fpu_xmm7: return fpu_xmm7; + case gcc_dwarf_fpu_xmm8: return fpu_xmm8; + case gcc_dwarf_fpu_xmm9: return fpu_xmm9; + case gcc_dwarf_fpu_xmm10: return fpu_xmm10; + case gcc_dwarf_fpu_xmm11: return fpu_xmm11; + case gcc_dwarf_fpu_xmm12: return fpu_xmm12; + case gcc_dwarf_fpu_xmm13: return fpu_xmm13; + case gcc_dwarf_fpu_xmm14: return fpu_xmm14; + case gcc_dwarf_fpu_xmm15: return fpu_xmm15; + case gcc_dwarf_fpu_stmm0: return fpu_stmm0; + case gcc_dwarf_fpu_stmm1: return fpu_stmm1; + case gcc_dwarf_fpu_stmm2: return fpu_stmm2; + case gcc_dwarf_fpu_stmm3: return fpu_stmm3; + case gcc_dwarf_fpu_stmm4: return fpu_stmm4; + case gcc_dwarf_fpu_stmm5: return fpu_stmm5; + case gcc_dwarf_fpu_stmm6: return fpu_stmm6; + case gcc_dwarf_fpu_stmm7: return fpu_stmm7; + default: + return LLDB_INVALID_REGNUM; + } + } + + if (kind == eRegisterKindGDB) + { + switch (num) + { + case gdb_gpr_rax : return gpr_rax; + case gdb_gpr_rbx : return gpr_rbx; + case gdb_gpr_rcx : return gpr_rcx; + case gdb_gpr_rdx : return gpr_rdx; + case gdb_gpr_rsi : return gpr_rsi; + case gdb_gpr_rdi : return gpr_rdi; + case gdb_gpr_rbp : return gpr_rbp; + case gdb_gpr_rsp : return gpr_rsp; + case gdb_gpr_r8 : return gpr_r8; + case gdb_gpr_r9 : return gpr_r9; + case gdb_gpr_r10 : return gpr_r10; + case gdb_gpr_r11 : return gpr_r11; + case gdb_gpr_r12 : return gpr_r12; + case gdb_gpr_r13 : return gpr_r13; + case gdb_gpr_r14 : return gpr_r14; + case gdb_gpr_r15 : return gpr_r15; + case gdb_gpr_rip : return gpr_rip; + case gdb_gpr_rflags : return gpr_rflags; + case gdb_gpr_cs : return gpr_cs; + case gdb_gpr_ss : return gpr_ss; + case gdb_gpr_ds : return gpr_ds; + case gdb_gpr_es : return gpr_es; + case gdb_gpr_fs : return gpr_fs; + case gdb_gpr_gs : return gpr_gs; + case gdb_fpu_stmm0 : return fpu_stmm0; + case gdb_fpu_stmm1 : return fpu_stmm1; + case gdb_fpu_stmm2 : return fpu_stmm2; + case gdb_fpu_stmm3 : return fpu_stmm3; + case gdb_fpu_stmm4 : return fpu_stmm4; + case gdb_fpu_stmm5 : return fpu_stmm5; + case gdb_fpu_stmm6 : return fpu_stmm6; + case gdb_fpu_stmm7 : return fpu_stmm7; + case gdb_fpu_fcw : return fpu_fcw; + case gdb_fpu_fsw : return fpu_fsw; + case gdb_fpu_ftw : return fpu_ftw; + case gdb_fpu_cs : return fpu_cs; + case gdb_fpu_ip : return fpu_ip; + case gdb_fpu_ds : return fpu_ds; + case gdb_fpu_dp : return fpu_dp; + case gdb_fpu_fop : return fpu_fop; + case gdb_fpu_xmm0 : return fpu_xmm0; + case gdb_fpu_xmm1 : return fpu_xmm1; + case gdb_fpu_xmm2 : return fpu_xmm2; + case gdb_fpu_xmm3 : return fpu_xmm3; + case gdb_fpu_xmm4 : return fpu_xmm4; + case gdb_fpu_xmm5 : return fpu_xmm5; + case gdb_fpu_xmm6 : return fpu_xmm6; + case gdb_fpu_xmm7 : return fpu_xmm7; + case gdb_fpu_xmm8 : return fpu_xmm8; + case gdb_fpu_xmm9 : return fpu_xmm9; + case gdb_fpu_xmm10 : return fpu_xmm10; + case gdb_fpu_xmm11 : return fpu_xmm11; + case gdb_fpu_xmm12 : return fpu_xmm12; + case gdb_fpu_xmm13 : return fpu_xmm13; + case gdb_fpu_xmm14 : return fpu_xmm14; + case gdb_fpu_xmm15 : return fpu_xmm15; + case gdb_fpu_mxcsr : return fpu_mxcsr; + default: + return LLDB_INVALID_REGNUM; + } + } + else if (kind == eRegisterKindLLDB) + { + return num; + } + + return LLDB_INVALID_REGNUM; +} + +bool +RegisterContext_x86_64::HardwareSingleStep(bool enable) +{ + enum { TRACE_BIT = 0x100 }; + uint64_t rflags; + + if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) + return false; + + if (enable) + { + if (rflags & TRACE_BIT) + return true; + + rflags |= TRACE_BIT; + } + else + { + if (!(rflags & TRACE_BIT)) + return false; + + rflags &= ~TRACE_BIT; + } + + return WriteRegisterFromUnsigned(gpr_rflags, rflags); +} + +bool +RegisterContext_x86_64::ReadGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadGPR(&user.regs); +} + +bool +RegisterContext_x86_64::ReadFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.ReadFPR(&user.i387); +} + +bool +RegisterContext_x86_64::WriteGPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteGPR(&user.regs); +} + +bool +RegisterContext_x86_64::WriteFPR() +{ + ProcessMonitor &monitor = GetMonitor(); + return monitor.WriteFPR(&user.i387); +} Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.h =================================================================== --- source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) @@ -0,0 +1,106 @@ +//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ +#define liblldb_ProcessLinuxLog_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes + +// Project includes +#include "lldb/Core/Log.h" + +#define POSIX_LOG_VERBOSE (1u << 0) +#define POSIX_LOG_PROCESS (1u << 1) +#define POSIX_LOG_THREAD (1u << 2) +#define POSIX_LOG_PACKETS (1u << 3) +#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes +#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes +#define POSIX_LOG_BREAKPOINTS (1u << 7) +#define POSIX_LOG_WATCHPOINTS (1u << 8) +#define POSIX_LOG_STEP (1u << 9) +#define POSIX_LOG_COMM (1u << 10) +#define POSIX_LOG_ASYNC (1u << 11) +#define POSIX_LOG_PTRACE (1u << 12) +#define POSIX_LOG_REGISTERS (1u << 13) +#define POSIX_LOG_ALL (UINT32_MAX) +#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS + +// The size which determines "short memory reads/writes". +#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) + +class ProcessPOSIXLog +{ + static int m_nestinglevel; + static const char *m_pluginname; + +public: + static void + RegisterPluginName(const char *pluginName) + { + m_pluginname = pluginName; + } + + + static lldb::LogSP + GetLogIfAllCategoriesSet(uint32_t mask = 0); + + static void + DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static lldb::LogSP + EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, + lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static void + ListLogCategories (lldb_private::Stream *strm); + + static void + LogIf (uint32_t mask, const char *format, ...); + + // The following functions can be used to enable the client to limit + // logging to only the top level function calls. This is useful for + // recursive functions. FIXME: not thread safe! + // Example: + // void NestingFunc() { + // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); + // if (log) + // { + // ProcessLinuxLog::IncNestLevel(); + // if (ProcessLinuxLog::AtTopNestLevel()) + // log->Print(msg); + // } + // NestingFunc(); + // if (log) + // ProcessLinuxLog::DecNestLevel(); + // } + + static bool + AtTopNestLevel() + { + return m_nestinglevel == 1; + } + + static void + IncNestLevel() + { + ++m_nestinglevel; + } + + static void + DecNestLevel() + { + --m_nestinglevel; + assert(m_nestinglevel >= 0); + } +}; + +#endif // liblldb_ProcessLinuxLog_h_ Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) @@ -0,0 +1,143 @@ +//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContext_x86_64_H_ +#define liblldb_RegisterContext_x86_64_H_ + +#include "lldb/Core/Log.h" +#include "RegisterContextPOSIX.h" + +#ifdef __FreeBSD__ +#include "RegisterContextFreeBSD_x86_64.h" +#endif + +#ifdef __linux__ +#include "RegisterContextLinux_x86_64.h" +#endif + +class ProcessMonitor; + +class RegisterContext_x86_64 + : public RegisterContextPOSIX +{ +public: + RegisterContext_x86_64 (lldb_private::Thread &thread, + uint32_t concrete_frame_idx); + + ~RegisterContext_x86_64(); + + void + Invalidate(); + + void + InvalidateAllRegisters(); + + size_t + GetRegisterCount(); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(uint32_t reg); + + size_t + GetRegisterSetCount(); + + const lldb_private::RegisterSet * + GetRegisterSet(uint32_t set); + + static unsigned + GetRegisterIndexFromOffset(unsigned offset); + + static const char * + GetRegisterName(unsigned reg); + + virtual bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue &value); + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); + + virtual bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue &value); + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); + + uint32_t + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); + + bool + HardwareSingleStep(bool enable); + + bool + UpdateAfterBreakpoint(); + + struct MMSReg + { + uint8_t bytes[10]; + uint8_t pad[6]; + }; + + struct XMMReg + { + uint8_t bytes[16]; + }; + + struct FPU + { + uint16_t fcw; + uint16_t fsw; + uint16_t ftw; + uint16_t fop; + uint64_t ip; + uint64_t dp; + uint32_t mxcsr; + uint32_t mxcsrmask; + MMSReg stmm[8]; + XMMReg xmm[16]; + uint32_t padding[24]; + }; + + struct UserArea + { + GPR regs; // General purpose registers. + int32_t fpvalid; // True if FPU is being used. + int32_t pad0; + FPU i387; // FPU registers. + uint64_t tsize; // Text segment size. + uint64_t dsize; // Data segment size. + uint64_t ssize; // Stack segment size. + uint64_t start_code; // VM address of text. + uint64_t start_stack; // VM address of stack bottom (top in rsp). + int64_t signal; // Signal causing core dump. + int32_t reserved; // Unused. + int32_t pad1; + uint64_t ar0; // Location of GPR's. + FPU* fpstate; // Location of FPR's. + uint64_t magic; // Identifier for core dumps. + char u_comm[32]; // Command causing core dump. + uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). + uint64_t error_code; // CPU error code. + uint64_t fault_address; // Control register CR3. + }; + +private: + UserArea user; + + ProcessMonitor &GetMonitor(); + + bool ReadGPR(); + bool ReadFPR(); + + bool WriteGPR(); + bool WriteFPR(); +}; + +#endif // #ifndef liblldb_RegisterContext_x86_64_H_ Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h =================================================================== --- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) +++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) @@ -0,0 +1,40 @@ +//===-- RegisterContextPOSIX.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_RegisterContextPOSIX_H_ +#define liblldb_RegisterContextPOSIX_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "lldb/Target/RegisterContext.h" + +//------------------------------------------------------------------------------ +/// @class RegisterContextPOSIX +/// +/// @brief Extends RegisterClass with a few virtual operations useful on POSIX. +class RegisterContextPOSIX + : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX(lldb_private::Thread &thread, + uint32_t concrete_frame_idx) + : RegisterContext(thread, concrete_frame_idx) { } + + /// Updates the register state of the associated thread after hitting a + /// breakpoint (if that make sense for the architecture). Default + /// implementation simply returns true for architectures which do not + /// require any update. + /// + /// @return + /// True if the operation succeeded and false otherwise. + virtual bool UpdateAfterBreakpoint() { return true; } +}; + +#endif // #ifndef liblldb_RegisterContextPOSIX_H_ Index: source/Plugins/Process/POSIX/ProcessMessage.cpp =================================================================== --- source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) +++ source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) @@ -0,0 +1,245 @@ +//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessMessage.h" + +using namespace lldb_private; + +const char * +ProcessMessage::GetCrashReasonString(CrashReason reason) +{ + const char *str = NULL; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case eInvalidAddress: + str = "invalid address"; + break; + case ePrivilegedAddress: + str = "address access protected"; + break; + case eIllegalOpcode: + str = "illegal instruction"; + break; + case eIllegalOperand: + str = "illegal instruction operand"; + break; + case eIllegalAddressingMode: + str = "illegal addressing mode"; + break; + case eIllegalTrap: + str = "illegal trap"; + break; + case ePrivilegedOpcode: + str = "privileged instruction"; + break; + case ePrivilegedRegister: + str = "privileged register"; + break; + case eCoprocessorError: + str = "coprocessor error"; + break; + case eInternalStackError: + str = "internal stack error"; + break; + case eIllegalAlignment: + str = "illegal alignment"; + break; + case eIllegalAddress: + str = "illegal address"; + break; + case eHardwareError: + str = "hardware error"; + break; + case eIntegerDivideByZero: + str = "integer divide by zero"; + break; + case eIntegerOverflow: + str = "integer overflow"; + break; + case eFloatDivideByZero: + str = "floating point divide by zero"; + break; + case eFloatOverflow: + str = "floating point overflow"; + break; + case eFloatUnderflow: + str = "floating point underflow"; + break; + case eFloatInexactResult: + str = "inexact floating point result"; + break; + case eFloatInvalidOperation: + str = "invalid floating point operation"; + break; + case eFloatSubscriptRange: + str = "invalid floating point subscript range"; + break; + } + + return str; +} + +const char * +ProcessMessage::PrintCrashReason(CrashReason reason) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in asci for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = NULL; + + switch (reason) + { + default: + assert(false && "invalid CrashReason"); + break; + + case eInvalidCrashReason: + str = "eInvalidCrashReason"; + break; + + // SIGSEGV crash reasons. + case eInvalidAddress: + str = "eInvalidAddress"; + break; + case ePrivilegedAddress: + str = "ePrivilegedAddress"; + break; + + // SIGILL crash reasons. + case eIllegalOpcode: + str = "eIllegalOpcode"; + break; + case eIllegalOperand: + str = "eIllegalOperand"; + break; + case eIllegalAddressingMode: + str = "eIllegalAddressingMode"; + break; + case eIllegalTrap: + str = "eIllegalTrap"; + break; + case ePrivilegedOpcode: + str = "ePrivilegedOpcode"; + break; + case ePrivilegedRegister: + str = "ePrivilegedRegister"; + break; + case eCoprocessorError: + str = "eCoprocessorError"; + break; + case eInternalStackError: + str = "eInternalStackError"; + break; + + // SIGBUS crash reasons: + case eIllegalAlignment: + str = "eIllegalAlignment"; + break; + case eIllegalAddress: + str = "eIllegalAddress"; + break; + case eHardwareError: + str = "eHardwareError"; + break; + + // SIGFPE crash reasons: + case eIntegerDivideByZero: + str = "eIntegerDivideByZero"; + break; + case eIntegerOverflow: + str = "eIntegerOverflow"; + break; + case eFloatDivideByZero: + str = "eFloatDivideByZero"; + break; + case eFloatOverflow: + str = "eFloatOverflow"; + break; + case eFloatUnderflow: + str = "eFloatUnderflow"; + break; + case eFloatInexactResult: + str = "eFloatInexactResult"; + break; + case eFloatInvalidOperation: + str = "eFloatInvalidOperation"; + break; + case eFloatSubscriptRange: + str = "eFloatSubscriptRange"; + break; + } +#endif + + return str; +} + +const char * +ProcessMessage::PrintCrashReason() const +{ + return PrintCrashReason(m_crash_reason); +} + +const char * +ProcessMessage::PrintKind(Kind kind) +{ +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION + // Just return the code in asci for integration builds. + chcar str[8]; + sprintf(str, "%d", reason); +#else + const char *str = NULL; + + switch (kind) + { + default: + assert(false && "invalid Kind"); + break; + + case eInvalidMessage: + str = "eInvalidMessage"; + break; + case eExitMessage: + str = "eExitMessage"; + break; + case eLimboMessage: + str = "eLimboMessage"; + break; + case eSignalMessage: + str = "eSignalMessage"; + break; + case eSignalDeliveredMessage: + str = "eSignalDeliveredMessage"; + break; + case eTraceMessage: + str = "eTraceMessage"; + break; + case eBreakpointMessage: + str = "eBreakpointMessage"; + break; + case eCrashMessage: + str = "eCrashMessage"; + break; + } +#endif + + return str; +} + +const char * +ProcessMessage::PrintKind() const +{ + return PrintKind(m_kind); +} Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp =================================================================== --- source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) +++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) @@ -0,0 +1,60 @@ +//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "POSIXStopInfo.h" + +using namespace lldb; +using namespace lldb_private; + + +//===----------------------------------------------------------------------===// +// POSIXLimboStopInfo + +POSIXLimboStopInfo::~POSIXLimboStopInfo() { } + +lldb::StopReason +POSIXLimboStopInfo::GetStopReason() const +{ + return lldb::eStopReasonTrace; +} + +const char * +POSIXLimboStopInfo::GetDescription() +{ + return "thread exiting"; +} + +bool +POSIXLimboStopInfo::ShouldStop(Event *event_ptr) +{ + return true; +} + +bool +POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) +{ + return true; +} + +//===----------------------------------------------------------------------===// +// POSIXCrashStopInfo + +POSIXCrashStopInfo::~POSIXCrashStopInfo() { } + +lldb::StopReason +POSIXCrashStopInfo::GetStopReason() const +{ + return lldb::eStopReasonException; +} + +const char * +POSIXCrashStopInfo::GetDescription() +{ + return ProcessMessage::GetCrashReasonString(m_crash_reason); +} Index: source/Plugins/Process/POSIX/ProcessMessage.h =================================================================== --- source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) +++ source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) @@ -0,0 +1,171 @@ +//===-- ProcessMessage.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_ProcessMessage_H_ +#define liblldb_ProcessMessage_H_ + +#include + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +class ProcessMessage +{ +public: + + /// The type of signal this message can correspond to. + enum Kind + { + eInvalidMessage, + eExitMessage, + eLimboMessage, + eSignalMessage, + eSignalDeliveredMessage, + eTraceMessage, + eBreakpointMessage, + eCrashMessage + }; + + enum CrashReason + { + eInvalidCrashReason, + + // SIGSEGV crash reasons. + eInvalidAddress, + ePrivilegedAddress, + + // SIGILL crash reasons. + eIllegalOpcode, + eIllegalOperand, + eIllegalAddressingMode, + eIllegalTrap, + ePrivilegedOpcode, + ePrivilegedRegister, + eCoprocessorError, + eInternalStackError, + + // SIGBUS crash reasons, + eIllegalAlignment, + eIllegalAddress, + eHardwareError, + + // SIGFPE crash reasons, + eIntegerDivideByZero, + eIntegerOverflow, + eFloatDivideByZero, + eFloatOverflow, + eFloatUnderflow, + eFloatInexactResult, + eFloatInvalidOperation, + eFloatSubscriptRange + }; + + ProcessMessage() + : m_tid(LLDB_INVALID_PROCESS_ID), + m_kind(eInvalidMessage), + m_crash_reason(eInvalidCrashReason), + m_status(0), + m_addr(0) { } + + Kind GetKind() const { return m_kind; } + + lldb::tid_t GetTID() const { return m_tid; } + + /// Indicates that the thread @p tid is about to exit with status @p status. + static ProcessMessage Limbo(lldb::tid_t tid, int status) { + return ProcessMessage(tid, eLimboMessage, status); + } + + /// Indicates that the thread @p tid had the signal @p signum delivered. + static ProcessMessage Signal(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalMessage, signum); + } + + /// Indicates that a signal @p signum generated by the debugging process was + /// delivered to the thread @p tid. + static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { + return ProcessMessage(tid, eSignalDeliveredMessage, signum); + } + + /// Indicates that the thread @p tid encountered a trace point. + static ProcessMessage Trace(lldb::tid_t tid) { + return ProcessMessage(tid, eTraceMessage); + } + + /// Indicates that the thread @p tid encountered a break point. + static ProcessMessage Break(lldb::tid_t tid) { + return ProcessMessage(tid, eBreakpointMessage); + } + + /// Indicates that the thread @p tid crashed. + static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, + int signo, lldb::addr_t fault_addr) { + ProcessMessage message(pid, eCrashMessage, signo, fault_addr); + message.m_crash_reason = reason; + return message; + } + + int GetExitStatus() const { + assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); + return m_status; + } + + int GetSignal() const { + assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || + GetKind() == eSignalDeliveredMessage); + return m_status; + } + + int GetStopStatus() const { + assert(GetKind() == eSignalMessage); + return m_status; + } + + CrashReason GetCrashReason() const { + assert(GetKind() == eCrashMessage); + return m_crash_reason; + } + + lldb::addr_t GetFaultAddress() const { + assert(GetKind() == eCrashMessage); + return m_addr; + } + + static const char * + GetCrashReasonString(CrashReason reason); + + const char * + PrintCrashReason() const; + + static const char * + PrintCrashReason(CrashReason reason); + + const char * + PrintKind() const; + + static const char * + PrintKind(Kind); + +private: + ProcessMessage(lldb::tid_t tid, Kind kind, + int status = 0, lldb::addr_t addr = 0) + : m_tid(tid), + m_kind(kind), + m_crash_reason(eInvalidCrashReason), + m_status(status), + m_addr(addr) { } + + lldb::tid_t m_tid; + Kind m_kind : 8; + CrashReason m_crash_reason : 8; + int m_status; + lldb::addr_t m_addr; +}; + +#endif // #ifndef liblldb_ProcessMessage_H_ Index: source/Plugins/Process/POSIX/POSIXStopInfo.h =================================================================== --- source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) +++ source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) @@ -0,0 +1,92 @@ +//===-- POSIXStopInfo.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_POSIXStopInfo_H_ +#define liblldb_POSIXStopInfo_H_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/StopInfo.h" + +#include "POSIXThread.h" +#include "ProcessMessage.h" + +//===----------------------------------------------------------------------===// +/// @class POSIXStopInfo +/// @brief Simple base class for all POSIX-specific StopInfo objects. +/// +class POSIXStopInfo + : public lldb_private::StopInfo +{ +public: + POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) + : StopInfo(thread, status) + { } +}; + +//===----------------------------------------------------------------------===// +/// @class POSIXLimboStopInfo +/// @brief Represents the stop state of a process ready to exit. +/// +class POSIXLimboStopInfo + : public POSIXStopInfo +{ +public: + POSIXLimboStopInfo(POSIXThread &thread) + : POSIXStopInfo(thread, 0) + { } + + ~POSIXLimboStopInfo(); + + lldb::StopReason + GetStopReason() const; + + const char * + GetDescription(); + + bool + ShouldStop(lldb_private::Event *event_ptr); + + bool + ShouldNotify(lldb_private::Event *event_ptr); +}; + + +//===----------------------------------------------------------------------===// +/// @class POSIXCrashStopInfo +/// @brief Represents the stop state of process that is ready to crash. +/// +class POSIXCrashStopInfo + : public POSIXStopInfo +{ +public: + POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, + ProcessMessage::CrashReason reason) + : POSIXStopInfo(thread, status), + m_crash_reason(reason) + { } + + ~POSIXCrashStopInfo(); + + lldb::StopReason + GetStopReason() const; + + const char * + GetDescription(); + + ProcessMessage::CrashReason + GetCrashReason() const; + +private: + ProcessMessage::CrashReason m_crash_reason; +}; + +#endif Index: source/Plugins/Process/POSIX/POSIXThread.cpp =================================================================== --- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) +++ source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) @@ -0,0 +1,352 @@ +//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Debugger.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "POSIXStopInfo.h" +#include "POSIXThread.h" +#include "ProcessPOSIX.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" +#include "RegisterContext_i386.h" +#include "RegisterContext_x86_64.h" +#include "RegisterContextPOSIX.h" + +#include "UnwindLLDB.h" + +using namespace lldb_private; + + +POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) + : Thread(process, tid), + m_frame_ap(0) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid); +} + +POSIXThread::~POSIXThread() +{ + DestroyThread(); +} + +ProcessMonitor & +POSIXThread::GetMonitor() +{ + ProcessPOSIX &process = static_cast(GetProcess()); + return process.GetMonitor(); +} + +void +POSIXThread::RefreshStateAfterStop() +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + // Let all threads recover from stopping and do any clean up based + // on the previous thread state (if any). + ProcessPOSIX &process = static_cast(GetProcess()); + process.GetThreadList().RefreshStateAfterStop(); +} + +const char * +POSIXThread::GetInfo() +{ + return NULL; +} + +lldb::RegisterContextSP +POSIXThread::GetRegisterContext() +{ + if (!m_reg_context_sp) + { + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); + break; + + case ArchSpec::eCore_x86_64_x86_64: + m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0)); + break; + } + } + return m_reg_context_sp; +} + +lldb::RegisterContextSP +POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) +{ + lldb::RegisterContextSP reg_ctx_sp; + uint32_t concrete_frame_idx = 0; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) + reg_ctx_sp = GetRegisterContext(); + else + { + assert(GetUnwinder()); + reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); + } + + return reg_ctx_sp; +} + +lldb::StopInfoSP +POSIXThread::GetPrivateStopReason() +{ + return m_stop_info; +} + +Unwind * +POSIXThread::GetUnwinder() +{ + if (m_unwinder_ap.get() == NULL) + m_unwinder_ap.reset(new UnwindLLDB(*this)); + + return m_unwinder_ap.get(); +} + +bool +POSIXThread::WillResume(lldb::StateType resume_state) +{ + SetResumeState(resume_state); + + ClearStackFrames(); + if (m_unwinder_ap.get()) + m_unwinder_ap->Clear(); + + return Thread::WillResume(resume_state); +} + +bool +POSIXThread::Resume() +{ + lldb::StateType resume_state = GetResumeState(); + ProcessMonitor &monitor = GetMonitor(); + bool status; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) + log->Printf ("POSIXThread::%s ()", __FUNCTION__); + + switch (resume_state) + { + default: + assert(false && "Unexpected state for resume!"); + status = false; + break; + + case lldb::eStateRunning: + SetState(resume_state); + status = monitor.Resume(GetID(), GetResumeSignal()); + break; + + case lldb::eStateStepping: + SetState(resume_state); + status = monitor.SingleStep(GetID(), GetResumeSignal()); + break; + } + + return status; +} + +void +POSIXThread::Notify(const ProcessMessage &message) +{ + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); + + switch (message.GetKind()) + { + default: + assert(false && "Unexpected message kind!"); + break; + + case ProcessMessage::eLimboMessage: + LimboNotify(message); + break; + + case ProcessMessage::eSignalMessage: + SignalNotify(message); + break; + + case ProcessMessage::eSignalDeliveredMessage: + SignalDeliveredNotify(message); + break; + + case ProcessMessage::eTraceMessage: + TraceNotify(message); + break; + + case ProcessMessage::eBreakpointMessage: + BreakNotify(message); + break; + + case ProcessMessage::eCrashMessage: + CrashNotify(message); + break; + } +} + +void +POSIXThread::BreakNotify(const ProcessMessage &message) +{ + bool status; + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + + assert(GetRegisterContext()); + status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); + assert(status && "Breakpoint update failed!"); + + // With our register state restored, resolve the breakpoint object + // corresponding to our current PC. + assert(GetRegisterContext()); + lldb::addr_t pc = GetRegisterContext()->GetPC(); + if (log) + log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); + lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); + assert(bp_site); + lldb::break_id_t bp_id = bp_site->GetID(); + assert(bp_site && bp_site->ValidForThisThread(this)); + + + m_breakpoint = bp_site; + m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); +} + +void +POSIXThread::TraceNotify(const ProcessMessage &message) +{ + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); +} + +void +POSIXThread::LimboNotify(const ProcessMessage &message) +{ + m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this)); +} + +void +POSIXThread::SignalNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); + SetResumeSignal(signo); +} + +void +POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + // Just treat debugger generated signal events like breakpoints for now. + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); + SetResumeSignal(signo); +} + +void +POSIXThread::CrashNotify(const ProcessMessage &message) +{ + int signo = message.GetSignal(); + + assert(message.GetKind() == ProcessMessage::eCrashMessage); + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log) + log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); + + m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo( + *this, signo, message.GetCrashReason())); + SetResumeSignal(signo); +} + +unsigned +POSIXThread::GetRegisterIndexFromOffset(unsigned offset) +{ + unsigned reg; + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset); + break; + + case ArchSpec::eCore_x86_64_x86_64: + reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset); + break; + } + return reg; +} + +const char * +POSIXThread::GetRegisterName(unsigned reg) +{ + const char * name; + ArchSpec arch = Host::GetArchitecture(); + + switch (arch.GetCore()) + { + default: + assert(false && "CPU type not supported!"); + break; + + case ArchSpec::eCore_x86_32_i386: + case ArchSpec::eCore_x86_32_i486: + case ArchSpec::eCore_x86_32_i486sx: + name = RegisterContext_i386::GetRegisterName(reg); + break; + + case ArchSpec::eCore_x86_64_x86_64: + name = RegisterContext_x86_64::GetRegisterName(reg); + break; + } + return name; +} + +const char * +POSIXThread::GetRegisterNameFromOffset(unsigned offset) +{ + return GetRegisterName(GetRegisterIndexFromOffset(offset)); +} + Index: source/Plugins/Process/POSIX/Makefile =================================================================== --- source/Plugins/Process/POSIX/Makefile (revision 0) +++ source/Plugins/Process/POSIX/Makefile (revision 0) @@ -0,0 +1,28 @@ +##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginProcessPOSIX +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/../../Makefile.config + +# Extend the include path so we may locate UnwindLLDB.h +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility + +ifeq ($(HOST_OS),Linux) +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux +endif + +ifeq ($(HOST_OS),FreeBSD) +# Extend the include path so we may locate ProcessMonitor +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD +endif + +include $(LLDB_LEVEL)/Makefile Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) @@ -0,0 +1,84 @@ +//===-- ProcessFreeBSD.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_ProcessFreeBSD_H_ +#define liblldb_ProcessFreeBSD_H_ + +// C Includes + +// C++ Includes +#include + +// Other libraries and framework includes +#include "lldb/Target/Process.h" +#include "lldb/Target/ThreadList.h" +#include "ProcessMessage.h" +#include "ProcessPOSIX.h" + +class ProcessMonitor; + +class ProcessFreeBSD : + public ProcessPOSIX +{ + +public: + //------------------------------------------------------------------ + // Static functions. + //------------------------------------------------------------------ + static Process* + CreateInstance(lldb_private::Target& target, + lldb_private::Listener &listener); + + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and destructors + //------------------------------------------------------------------ + ProcessFreeBSD(lldb_private::Target& target, + lldb_private::Listener &listener); + + virtual uint32_t + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + + virtual void + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + + virtual lldb_private::Error + ExecutePluginCommand(lldb_private::Args &command, + lldb_private::Stream *strm); + + virtual lldb_private::Log * + EnablePluginLogging(lldb_private::Stream *strm, + lldb_private::Args &command); + +}; + +#endif // liblldb_MacOSXProcess_H_ Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) @@ -0,0 +1,1558 @@ +//===-- ProcessMonitor.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 +#include +#include +#include +#include +#include +#include +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/Error.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/PseudoTerminal.h" + + +#include "POSIXThread.h" +#include "ProcessFreeBSD.h" +#include "ProcessPOSIXLog.h" +#include "ProcessMonitor.h" + +extern "C" { + extern char ** environ; + } + +using namespace lldb; +using namespace lldb_private; + +// We disable the tracing of ptrace calls for integration builds to +// avoid the additional indirection and checks. +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION +// Wrapper for ptrace to catch errors and log calls. + +const char * +Get_PT_IO_OP(int op) +{ + switch (op) { + case PIOD_READ_D: return "READ_D"; + case PIOD_WRITE_D: return "WRITE_D"; + case PIOD_READ_I: return "READ_I"; + case PIOD_WRITE_I: return "WRITE_I"; + default: return "Unknown op"; + } +} + +extern long +PtraceWrapper(int req, ::pid_t pid, void *addr, int data, + const char* reqName, const char* file, int line) +{ + long int result; + + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); + + if (log) { + log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d", + reqName, pid, addr, data, file, line); + if (req == PT_IO) { + struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; + + log->Printf("PT_IO: op=%s offs=%zx size=%ld", + Get_PT_IO_OP(pi->piod_op), pi->piod_offs, pi->piod_len); + } + } + + //PtraceDisplayBytes(req, data); + + errno = 0; + result = ptrace(req, pid, (caddr_t) addr, data); + + //PtraceDisplayBytes(req, data); + + if (log && (result == -1 || errno != 0)) + { + const char* str; + switch (errno) + { + case ESRCH: str = "ESRCH"; break; + case EINVAL: str = "EINVAL"; break; + case EBUSY: str = "EBUSY"; break; + case EPERM: str = "EPERM"; break; + default: str = ""; + } + log->Printf("ptrace() failed; errno=%d (%s)", errno, str); + } + + if (log) { + if (req == PT_GETREGS) { + struct reg *r = (struct reg *) addr; + + log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip); + log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp); + log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); + log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); + } + } + + return result; +} + +#define PTRACE(req, pid, addr, data) \ + PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) +#else +#define PTRACE ptrace +#endif + +//------------------------------------------------------------------------------ +// Static implementations of ProcessMonitor::ReadMemory and +// ProcessMonitor::WriteMemory. This enables mutual recursion between these +// functions without needed to go thru the thread funnel. + +static size_t +DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, + Error &error) +{ + struct ptrace_io_desc pi_desc; + + pi_desc.piod_op = PIOD_READ_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = buf; + pi_desc.piod_len = size; + + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; +} + +static size_t +DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, + size_t size, Error &error) +{ + struct ptrace_io_desc pi_desc; + + pi_desc.piod_op = PIOD_WRITE_D; + pi_desc.piod_offs = (void *)vm_addr; + pi_desc.piod_addr = (void *)buf; + pi_desc.piod_len = size; + + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) + error.SetErrorToErrno(); + return pi_desc.piod_len; +} + +// Simple helper function to ensure flags are enabled on the given file +// descriptor. +static bool +EnsureFDFlags(int fd, int flags, Error &error) +{ + int status; + + if ((status = fcntl(fd, F_GETFL)) == -1) + { + error.SetErrorToErrno(); + return false; + } + + if (fcntl(fd, F_SETFL, status | flags) == -1) + { + error.SetErrorToErrno(); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------ +/// @class Operation +/// @brief Represents a ProcessMonitor operation. +/// +/// Under FreeBSD, it is not possible to ptrace() from any other thread but the +/// one that spawned or attached to the process from the start. Therefore, when +/// a ProcessMonitor is asked to deliver or change the state of an inferior +/// process the operation must be "funneled" to a specific thread to perform the +/// task. The Operation class provides an abstract base for all services the +/// ProcessMonitor must perform via the single virtual function Execute, thus +/// encapsulating the code that needs to run in the privileged context. +class Operation +{ +public: + virtual void Execute(ProcessMonitor *monitor) = 0; +}; + +//------------------------------------------------------------------------------ +/// @class ReadOperation +/// @brief Implements ProcessMonitor::ReadMemory. +class ReadOperation : public Operation +{ +public: + ReadOperation(lldb::addr_t addr, void *buff, size_t size, + Error &error, size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), + m_error(error), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::addr_t m_addr; + void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; +}; + +void +ReadOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); +} + +//------------------------------------------------------------------------------ +/// @class ReadOperation +/// @brief Implements ProcessMonitor::WriteMemory. +class WriteOperation : public Operation +{ +public: + WriteOperation(lldb::addr_t addr, const void *buff, size_t size, + Error &error, size_t &result) + : m_addr(addr), m_buff(buff), m_size(size), + m_error(error), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::addr_t m_addr; + const void *m_buff; + size_t m_size; + Error &m_error; + size_t &m_result; +}; + +void +WriteOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); +} + +//------------------------------------------------------------------------------ +/// @class ReadRegOperation +/// @brief Implements ProcessMonitor::ReadRegisterValue. +class ReadRegOperation : public Operation +{ +public: + ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result) + : m_offset(offset), m_size(size), m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + unsigned m_offset; + unsigned m_size; + RegisterValue &m_value; + bool &m_result; +}; + +void +ReadRegOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + struct reg regs; + int rc; + + if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0)) < 0) { + m_result = false; + } else { + if (m_size == sizeof(uintptr_t)) + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); + else + memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); + m_result = true; + } +} + +//------------------------------------------------------------------------------ +/// @class WriteRegOperation +/// @brief Implements ProcessMonitor::WriteRegisterValue. +class WriteRegOperation : public Operation +{ +public: + WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result) + : m_offset(offset), m_value(value), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + unsigned m_offset; + const RegisterValue &m_value; + bool &m_result; +}; + +void +WriteRegOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + struct reg regs; + + if (PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0) < 0) { + m_result = false; + return; + } + *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); + if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ReadGPROperation +/// @brief Implements ProcessMonitor::ReadGPR. +class ReadGPROperation : public Operation +{ +public: + ReadGPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +ReadGPROperation::Execute(ProcessMonitor *monitor) +{ + int rc; + + errno = 0; + rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0); + if (errno != 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ReadFPROperation +/// @brief Implements ProcessMonitor::ReadFPR. +class ReadFPROperation : public Operation +{ +public: + ReadFPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +ReadFPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class WriteGPROperation +/// @brief Implements ProcessMonitor::WriteGPR. +class WriteGPROperation : public Operation +{ +public: + WriteGPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +WriteGPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class WriteFPROperation +/// @brief Implements ProcessMonitor::WriteFPR. +class WriteFPROperation : public Operation +{ +public: + WriteFPROperation(void *buf, bool &result) + : m_buf(buf), m_result(result) + { } + + void Execute(ProcessMonitor *monitor); + +private: + void *m_buf; + bool &m_result; +}; + +void +WriteFPROperation::Execute(ProcessMonitor *monitor) +{ + if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ResumeOperation +/// @brief Implements ProcessMonitor::Resume. +class ResumeOperation : public Operation +{ +public: + ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : + m_tid(tid), m_signo(signo), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + uint32_t m_signo; + bool &m_result; +}; + +void +ResumeOperation::Execute(ProcessMonitor *monitor) +{ + int data = 0; + + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; + + if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class ResumeOperation +/// @brief Implements ProcessMonitor::SingleStep. +class SingleStepOperation : public Operation +{ +public: + SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) + : m_tid(tid), m_signo(signo), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + uint32_t m_signo; + bool &m_result; +}; + +void +SingleStepOperation::Execute(ProcessMonitor *monitor) +{ + int data = 0; + + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) + data = m_signo; + + if (PTRACE(PT_STEP, m_tid, NULL, data)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class SiginfoOperation +/// @brief Implements ProcessMonitor::GetSignalInfo. +class SiginfoOperation : public Operation +{ +public: + SiginfoOperation(lldb::tid_t tid, void *info, bool &result) + : m_tid(tid), m_info(info), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + void *m_info; + bool &m_result; +}; + +void +SiginfoOperation::Execute(ProcessMonitor *monitor) +{ + struct ptrace_lwpinfo plwp; + + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) + m_result = false; + else { + memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t)); + m_result = true; + } +} + +//------------------------------------------------------------------------------ +/// @class EventMessageOperation +/// @brief Implements ProcessMonitor::GetEventMessage. +class EventMessageOperation : public Operation +{ +public: + EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) + : m_tid(tid), m_message(message), m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + lldb::tid_t m_tid; + unsigned long *m_message; + bool &m_result; +}; + +void +EventMessageOperation::Execute(ProcessMonitor *monitor) +{ + struct ptrace_lwpinfo plwp; + + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) + m_result = false; + else { + if (plwp.pl_flags & PL_FLAG_FORKED) { + m_message = (unsigned long *)plwp.pl_child_pid; + m_result = true; + } else + m_result = false; + } +} + +//------------------------------------------------------------------------------ +/// @class KillOperation +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. +class KillOperation : public Operation +{ +public: + KillOperation(bool &result) : m_result(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + bool &m_result; +}; + +void +KillOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + if (PTRACE(PT_KILL, pid, NULL, 0)) + m_result = false; + else + m_result = true; +} + +//------------------------------------------------------------------------------ +/// @class KillOperation +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. +class DetachOperation : public Operation +{ +public: + DetachOperation(Error &result) : m_error(result) { } + + void Execute(ProcessMonitor *monitor); + +private: + Error &m_error; +}; + +void +DetachOperation::Execute(ProcessMonitor *monitor) +{ + lldb::pid_t pid = monitor->GetPID(); + + if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) + m_error.SetErrorToErrno(); + +} + +ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) + : m_monitor(monitor) +{ + sem_init(&m_semaphore, 0, 0); +} + +ProcessMonitor::OperationArgs::~OperationArgs() +{ + sem_destroy(&m_semaphore); +} + +ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, + lldb_private::Module *module, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path) + : OperationArgs(monitor), + m_module(module), + m_argv(argv), + m_envp(envp), + m_stdin_path(stdin_path), + m_stdout_path(stdout_path), + m_stderr_path(stderr_path) { } + +ProcessMonitor::LaunchArgs::~LaunchArgs() +{ } + +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, + lldb::pid_t pid) + : OperationArgs(monitor), m_pid(pid) { } + +ProcessMonitor::AttachArgs::~AttachArgs() +{ } + +//------------------------------------------------------------------------------ +/// The basic design of the ProcessMonitor is built around two threads. +/// +/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking +/// for changes in the debugee state. When a change is detected a +/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread +/// "drives" state changes in the debugger. +/// +/// The second thread (@see OperationThread) is responsible for two things 1) +/// launching or attaching to the inferior process, and then 2) servicing +/// operations such as register reads/writes, stepping, etc. See the comments +/// on the Operation class for more info as to why this is needed. +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, + Module *module, + const char *argv[], + const char *envp[], + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + lldb_private::Error &error) + : m_process(static_cast(process)), + m_operation_thread(LLDB_INVALID_HOST_THREAD), + m_monitor_thread(LLDB_INVALID_HOST_THREAD), + m_pid(LLDB_INVALID_PROCESS_ID), + m_server_mutex(Mutex::eMutexTypeRecursive), + m_terminal_fd(-1), + m_client_fd(-1), + m_server_fd(-1) +{ + std::auto_ptr args; + + args.reset(new LaunchArgs(this, module, argv, envp, + stdin_path, stdout_path, stderr_path)); + + + // Server/client descriptors. + if (!EnableIPC()) + { + error.SetErrorToGenericError(); + error.SetErrorString("Monitor failed to initialize."); + } + + StartLaunchOpThread(args.get(), error); + if (!error.Success()) + return; + +WAIT_AGAIN: + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) + { + if (errno == EINTR) + goto WAIT_AGAIN; + else + { + error.SetErrorToErrno(); + return; + } + } + + // Check that the launch was a success. + if (!args->m_error.Success()) + { + StopLaunchOpThread(); + error = args->m_error; + return; + } + + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + ProcessMonitor::MonitorCallback, this, GetPID(), true); + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + error.SetErrorToGenericError(); + error.SetErrorString("Process launch failed."); + return; + } +} + +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, + lldb::pid_t pid, + lldb_private::Error &error) + : m_process(static_cast(process)), + m_operation_thread(LLDB_INVALID_HOST_THREAD), + m_monitor_thread(LLDB_INVALID_HOST_THREAD), + m_pid(pid), + m_server_mutex(Mutex::eMutexTypeRecursive), + m_terminal_fd(-1), + m_client_fd(-1), + m_server_fd(-1) +{ + std::auto_ptr args; + + args.reset(new AttachArgs(this, pid)); + + // Server/client descriptors. + if (!EnableIPC()) + { + error.SetErrorToGenericError(); + error.SetErrorString("Monitor failed to initialize."); + } + + StartAttachOpThread(args.get(), error); + if (!error.Success()) + return; + +WAIT_AGAIN: + // Wait for the operation thread to initialize. + if (sem_wait(&args->m_semaphore)) + { + if (errno == EINTR) + goto WAIT_AGAIN; + else + { + error.SetErrorToErrno(); + return; + } + } + + // Check that the launch was a success. + if (!args->m_error.Success()) + { + StopAttachOpThread(); + error = args->m_error; + return; + } + + // Finally, start monitoring the child process for change in state. + m_monitor_thread = Host::StartMonitoringChildProcess( + ProcessMonitor::MonitorCallback, this, GetPID(), true); + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + error.SetErrorToGenericError(); + error.SetErrorString("Process attach failed."); + return; + } +} + +ProcessMonitor::~ProcessMonitor() +{ + StopMonitor(); +} + +//------------------------------------------------------------------------------ +// Thread setup and tear down. +void +ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) +{ + static const char *g_thread_name = "lldb.process.freebsd.operation"; + + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + m_operation_thread = + Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error); +} + +void +ProcessMonitor::StopLaunchOpThread() +{ + lldb::thread_result_t result; + + if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + Host::ThreadCancel(m_operation_thread, NULL); + Host::ThreadJoin(m_operation_thread, &result, NULL); +} + +void * +ProcessMonitor::LaunchOpThread(void *arg) +{ + LaunchArgs *args = static_cast(arg); + + if (!Launch(args)) { + sem_post(&args->m_semaphore); + return NULL; + } + + ServeOperation(args); + return NULL; +} + +bool +ProcessMonitor::Launch(LaunchArgs *args) +{ + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); + const char **argv = args->m_argv; + const char **envp = args->m_envp; + const char *stdin_path = args->m_stdin_path; + const char *stdout_path = args->m_stdout_path; + const char *stderr_path = args->m_stderr_path; + lldb::pid_t pid; + + lldb::ThreadSP inferior; + + // Propagate the environment if one is not supplied. + if (envp == NULL || envp[0] == NULL) + envp = const_cast(environ); + + // Recognized child exit status codes. + enum { + ePtraceFailed = 1, + eDupStdinFailed, + eDupStdoutFailed, + eDupStderrFailed, + eExecFailed + }; + + pid = fork(); + + // Child process. + if (pid == 0) + { + // Trace this process. + if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) + exit(ePtraceFailed); + + // Do not inherit setgid powers. + setgid(getgid()); + + // Let us have our own process group. + setpgid(0, 0); + + // Dup file descriptors if needed. + // + // FIXME: If two or more of the paths are the same we needlessly open + // the same file multiple times. + if (stdin_path != NULL && stdin_path[0]) + if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY)) + exit(eDupStdinFailed); + + if (stdout_path != NULL && stdout_path[0]) + if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStdoutFailed); + + if (stderr_path != NULL && stderr_path[0]) + if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT)) + exit(eDupStderrFailed); + + // Execute. We should never return. + execve(argv[0], + const_cast(argv), + const_cast(envp)); + exit(eExecFailed); + } + + // Wait for the child process to to trap on its call to execve. + ::pid_t wpid; + int status; + if ((wpid = waitpid(pid, &status, 0)) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + else if (WIFEXITED(status)) + { + // open, dup or execve likely failed for some reason. + args->m_error.SetErrorToGenericError(); + switch (WEXITSTATUS(status)) + { + case ePtraceFailed: + args->m_error.SetErrorString("Child ptrace failed."); + break; + case eDupStdinFailed: + args->m_error.SetErrorString("Child open stdin failed."); + break; + case eDupStdoutFailed: + args->m_error.SetErrorString("Child open stdout failed."); + break; + case eDupStderrFailed: + args->m_error.SetErrorString("Child open stderr failed."); + break; + case eExecFailed: + args->m_error.SetErrorString("Child exec failed."); + break; + default: + args->m_error.SetErrorString("Child returned unknown exit status."); + break; + } + goto FINISH; + } + assert(WIFSTOPPED(status) && wpid == pid && + "Could not sync with inferior process."); + +#ifdef notyet + // Have the child raise an event on exit. This is used to keep the child in + // limbo until it is destroyed. + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } +#endif + // XXX - Release the master terminal descriptor and pass it off to the + // XXX - ProcessMonitor instance. Similarly stash the inferior pid. + // For now just use stdin fd + monitor->m_terminal_fd = STDIN_FILENO; + monitor->m_pid = pid; + + // Set the terminal fd to be in non blocking mode (it simplifies the + // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking + // descriptor to read from). + if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) + goto FINISH; + + // Update the process thread list with this new thread. + inferior.reset(new POSIXThread(process, pid)); + process.GetThreadList().AddThread(inferior); + + // Let our process instance know the thread has stopped. + process.SendMessage(ProcessMessage::Trace(pid)); + +FINISH: + return args->m_error.Success(); +} + +bool +ProcessMonitor::EnableIPC() +{ + int fd[2]; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) + return false; + + m_client_fd = fd[0]; + m_server_fd = fd[1]; + return true; +} + +void +ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) +{ + static const char *g_thread_name = "lldb.process.freebsd.operation"; + + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) + return; + + m_operation_thread = + Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error); +} + +void +ProcessMonitor::StopAttachOpThread() +{ + assert(!"Not implemented yet!!!"); +} + +void * +ProcessMonitor::AttachOpThread(void *arg) +{ + AttachArgs *args = static_cast(arg); + + if (!Attach(args)) + return NULL; + + ServeOperation(args); + return NULL; +} + +bool +ProcessMonitor::Attach(AttachArgs *args) +{ + lldb::pid_t pid = args->m_pid; + + ProcessMonitor *monitor = args->m_monitor; + ProcessFreeBSD &process = monitor->GetProcess(); + ThreadList &tl = process.GetThreadList(); + lldb::ThreadSP inferior; + + if (pid <= 1) + { + args->m_error.SetErrorToGenericError(); + args->m_error.SetErrorString("Attaching to process 1 is not allowed."); + goto FINISH; + } + + // Attach to the requested process. + if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + + int status; + if ((status = waitpid(pid, NULL, 0)) < 0) + { + args->m_error.SetErrorToErrno(); + goto FINISH; + } + + // Update the process thread list with the attached thread. + inferior.reset(new POSIXThread(process, pid)); + tl.AddThread(inferior); + + // Let our process instance know the thread has stopped. + process.SendMessage(ProcessMessage::Trace(pid)); + + FINISH: + return args->m_error.Success(); +} + +bool +ProcessMonitor::MonitorCallback(void *callback_baton, + lldb::pid_t pid, + bool exited, + int signal, + int status) +{ + ProcessMessage message; + ProcessMonitor *monitor = static_cast(callback_baton); + ProcessFreeBSD *process = monitor->m_process; + bool stop_monitoring; + siginfo_t info; + + if (!monitor->GetSignalInfo(pid, &info)) + stop_monitoring = true; // pid is gone. Bail. + else { + switch (info.si_signo) + { + case SIGTRAP: + message = MonitorSIGTRAP(monitor, &info, pid); + break; + + default: + message = MonitorSignal(monitor, &info, pid); + break; + } + + process->SendMessage(message); + stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; + } + + return stop_monitoring; +} + +ProcessMessage +ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid) +{ + ProcessMessage message; + + assert(info->si_signo == SIGTRAP && "Unexpected child signal!"); + + switch (info->si_code) + { + default: + assert(false && "Unexpected SIGTRAP code!"); + break; + + case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): + { + // The inferior process is about to exit. Maintain the process in a + // state of "limbo" until we are explicitly commanded to detach, + // destroy, resume, etc. + unsigned long data = 0; + if (!monitor->GetEventMessage(pid, &data)) + data = -1; + message = ProcessMessage::Limbo(pid, (data >> 8)); + break; + } + + case 0: + case TRAP_TRACE: + message = ProcessMessage::Trace(pid); + break; + + case SI_KERNEL: + case TRAP_BRKPT: + message = ProcessMessage::Break(pid); + break; + } + + return message; +} + +ProcessMessage +ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid) +{ + ProcessMessage message; + int signo = info->si_signo; + + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a + // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. + // + // IOW, user generated signals never generate what we consider to be a + // "crash". + // + // Similarly, ACK signals generated by this monitor. + if (info->si_code == SI_USER) + { + if (info->si_pid == getpid()) + return ProcessMessage::SignalDelivered(pid, signo); + else + return ProcessMessage::Signal(pid, signo); + } + + if (signo == SIGSEGV) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGILL) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGFPE) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + if (signo == SIGBUS) { + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); + ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); + return ProcessMessage::Crash(pid, reason, signo, fault_addr); + } + + // Everything else is "normal" and does not require any special action on + // our part. + return ProcessMessage::Signal(pid, signo); +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGSEGV); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGSEGV"); + break; + case SEGV_MAPERR: + reason = ProcessMessage::eInvalidAddress; + break; + case SEGV_ACCERR: + reason = ProcessMessage::ePrivilegedAddress; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGILL); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGILL"); + break; + case ILL_ILLOPC: + reason = ProcessMessage::eIllegalOpcode; + break; + case ILL_ILLOPN: + reason = ProcessMessage::eIllegalOperand; + break; + case ILL_ILLADR: + reason = ProcessMessage::eIllegalAddressingMode; + break; + case ILL_ILLTRP: + reason = ProcessMessage::eIllegalTrap; + break; + case ILL_PRVOPC: + reason = ProcessMessage::ePrivilegedOpcode; + break; + case ILL_PRVREG: + reason = ProcessMessage::ePrivilegedRegister; + break; + case ILL_COPROC: + reason = ProcessMessage::eCoprocessorError; + break; + case ILL_BADSTK: + reason = ProcessMessage::eInternalStackError; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGFPE); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGFPE"); + break; + case FPE_INTDIV: + reason = ProcessMessage::eIntegerDivideByZero; + break; + case FPE_INTOVF: + reason = ProcessMessage::eIntegerOverflow; + break; + case FPE_FLTDIV: + reason = ProcessMessage::eFloatDivideByZero; + break; + case FPE_FLTOVF: + reason = ProcessMessage::eFloatOverflow; + break; + case FPE_FLTUND: + reason = ProcessMessage::eFloatUnderflow; + break; + case FPE_FLTRES: + reason = ProcessMessage::eFloatInexactResult; + break; + case FPE_FLTINV: + reason = ProcessMessage::eFloatInvalidOperation; + break; + case FPE_FLTSUB: + reason = ProcessMessage::eFloatSubscriptRange; + break; + } + + return reason; +} + +ProcessMessage::CrashReason +ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) +{ + ProcessMessage::CrashReason reason; + assert(info->si_signo == SIGBUS); + + reason = ProcessMessage::eInvalidCrashReason; + + switch (info->si_code) + { + default: + assert(false && "unexpected si_code for SIGBUS"); + break; + case BUS_ADRALN: + reason = ProcessMessage::eIllegalAlignment; + break; + case BUS_ADRERR: + reason = ProcessMessage::eIllegalAddress; + break; + case BUS_OBJERR: + reason = ProcessMessage::eHardwareError; + break; + } + + return reason; +} + +void +ProcessMonitor::ServeOperation(OperationArgs *args) +{ + int status; + pollfd fdset; + + ProcessMonitor *monitor = args->m_monitor; + + fdset.fd = monitor->m_server_fd; + fdset.events = POLLIN | POLLPRI; + fdset.revents = 0; + + // We are finised with the arguments and are ready to go. Sync with the + // parent thread and start serving operations on the inferior. + sem_post(&args->m_semaphore); + + for (;;) + { + if ((status = poll(&fdset, 1, -1)) < 0) + { + switch (errno) + { + default: + assert(false && "Unexpected poll() failure!"); + continue; + + case EINTR: continue; // Just poll again. + case EBADF: return; // Connection terminated. + } + } + + assert(status == 1 && "Too many descriptors!"); + + if (fdset.revents & POLLIN) + { + Operation *op = NULL; + + READ_AGAIN: + if ((status = read(fdset.fd, &op, sizeof(op))) < 0) + { + // There is only one acceptable failure. + assert(errno == EINTR); + goto READ_AGAIN; + } + + assert(status == sizeof(op)); + op->Execute(monitor); + write(fdset.fd, &op, sizeof(op)); + } + } +} + +void +ProcessMonitor::DoOperation(Operation *op) +{ + int status; + Operation *ack = NULL; + Mutex::Locker lock(m_server_mutex); + + // FIXME: Do proper error checking here. + write(m_client_fd, &op, sizeof(op)); + +READ_AGAIN: + if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0) + { + // If interrupted by a signal handler try again. Otherwise the monitor + // thread probably died and we have a stale file descriptor -- abort the + // operation. + if (errno == EINTR) + goto READ_AGAIN; + return; + } + + assert(status == sizeof(ack)); + assert(ack == op && "Invalid monitor thread response!"); +} + +size_t +ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + Error &error) +{ + size_t result; + ReadOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; +} + +size_t +ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error) +{ + size_t result; + WriteOperation op(vm_addr, buf, size, error, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) +{ + bool result; + ReadRegOperation op(offset, size, value, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value) +{ + bool result; + WriteRegOperation op(offset, value, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadGPR(void *buf) +{ + bool result; + ReadGPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::ReadFPR(void *buf) +{ + bool result; + ReadFPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteGPR(void *buf) +{ + bool result; + WriteGPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::WriteFPR(void *buf) +{ + bool result; + WriteFPROperation op(buf, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) +{ + bool result; + ResumeOperation op(tid, signo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo) +{ + bool result; + SingleStepOperation op(tid, signo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::BringProcessIntoLimbo() +{ + bool result; + KillOperation op(result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo) +{ + bool result; + SiginfoOperation op(tid, siginfo, result); + DoOperation(&op); + return result; +} + +bool +ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) +{ + bool result; + EventMessageOperation op(tid, message, result); + DoOperation(&op); + return result; +} + +Error +ProcessMonitor::Detach() +{ + Error result; + DetachOperation op(result); + DoOperation(&op); + StopMonitor(); + return result; +} + +bool +ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) +{ + int target_fd = open(path, flags, 0666); + + if (target_fd == -1) + return false; + + return (dup2(target_fd, fd) == -1) ? false : true; +} + +void +ProcessMonitor::StopMonitoringChildProcess() +{ + lldb::thread_result_t thread_result; + + if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) + { + Host::ThreadCancel(m_monitor_thread, NULL); + Host::ThreadJoin(m_monitor_thread, &thread_result, NULL); + m_monitor_thread = LLDB_INVALID_HOST_THREAD; + } +} + +void +ProcessMonitor::StopMonitor() +{ + StopMonitoringChildProcess(); + StopLaunchOpThread(); + CloseFD(m_terminal_fd); + CloseFD(m_client_fd); + CloseFD(m_server_fd); +} + +void +ProcessMonitor::CloseFD(int &fd) +{ + if (fd != -1) + { + close(fd); + fd = -1; + } +} Index: source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h =================================================================== --- source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) +++ source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) @@ -0,0 +1,43 @@ +//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ +#define liblldb_RegisterContextFreeBSD_x86_64_H_ + + typedef struct _GPR + { + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rbx; + uint64_t rdx; + uint64_t rcx; + uint64_t rax; + uint32_t trapno; + uint16_t fs; + uint16_t gs; + uint32_t err; + uint16_t es; + uint16_t ds; + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; + } GPR; + +#endif Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp =================================================================== --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) @@ -0,0 +1,136 @@ +//===-- ProcessFreeBSD.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 + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/Target.h" + +#include "ProcessFreeBSD.h" +#include "ProcessPOSIXLog.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "ProcessMonitor.h" +#include "POSIXThread.h" + +using namespace lldb; +using namespace lldb_private; + +//------------------------------------------------------------------------------ +// Static functions. + +Process* +ProcessFreeBSD::CreateInstance(Target& target, Listener &listener) +{ + return new ProcessFreeBSD(target, listener); +} + +void +ProcessFreeBSD::Initialize() +{ + static bool g_initialized = false; + + if (!g_initialized) + { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + Log::Callbacks log_callbacks = { + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories + }; + + Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks); + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); + g_initialized = true; + } +} + +const char * +ProcessFreeBSD::GetPluginNameStatic() +{ + return "freebsd"; +} + +const char * +ProcessFreeBSD::GetPluginDescriptionStatic() +{ + return "Process plugin for FreeBSD"; +} + +//------------------------------------------------------------------------------ +// ProcessInterface protocol. + +const char * +ProcessFreeBSD::GetPluginName() +{ + return "process.freebsd"; +} + +const char * +ProcessFreeBSD::GetShortPluginName() +{ + return "process.freebsd"; +} + +uint32_t +ProcessFreeBSD::GetPluginVersion() +{ + return 1; +} + +void +ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) +{ +} + +Error +ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) +{ + return Error(1, eErrorTypeGeneric); +} + +Log * +ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) +{ + return NULL; +} + +//------------------------------------------------------------------------------ +// Constructors and destructors. + +ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) + : ProcessPOSIX(target, listener) +{ + // FIXME: Putting this code in the ctor and saving the byte order in a + // member variable is a hack to avoid const qual issues in GetByteOrder. + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); + m_byte_order = obj_file->GetByteOrder(); +} + +void +ProcessFreeBSD::Terminate() +{ +} + +uint32_t +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + // XXX haxx + new_thread_list = old_thread_list; + + return 0; +} Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h =================================================================== --- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) @@ -0,0 +1,292 @@ +//===-- ProcessMonitor.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_ProcessMonitor_H_ +#define liblldb_ProcessMonitor_H_ + +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/lldb-types.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private +{ +class Error; +class Module; +class Scalar; +} // End lldb_private namespace. + +class ProcessFreeBSD; +class Operation; + +/// @class ProcessMonitor +/// @brief Manages communication with the inferior (debugee) process. +/// +/// Upon construction, this class prepares and launches an inferior process for +/// debugging. +/// +/// Changes in the inferior process state are propagated to the associated +/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the +/// appropriate ProcessMessage events. +/// +/// A purposely minimal set of operations are provided to interrogate and change +/// the inferior process state. +class ProcessMonitor +{ +public: + + /// Launches an inferior process ready for debugging. Forms the + /// implementation of Process::DoLaunch. + ProcessMonitor(ProcessPOSIX *process, + lldb_private::Module *module, + char const *argv[], + char const *envp[], + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + lldb_private::Error &error); + + ProcessMonitor(ProcessPOSIX *process, + lldb::pid_t pid, + lldb_private::Error &error); + + ~ProcessMonitor(); + + /// Provides the process number of debugee. + lldb::pid_t + GetPID() const { return m_pid; } + + /// Returns the process associated with this ProcessMonitor. + ProcessFreeBSD & + GetProcess() { return *m_process; } + + /// Returns a file descriptor to the controlling terminal of the inferior + /// process. + /// + /// Reads from this file descriptor yield both the standard output and + /// standard error of this debugee. Even if stderr and stdout were + /// redirected on launch it may still happen that data is available on this + /// descriptor (if the inferior process opens /dev/tty, for example). + /// + /// If this monitor was attached to an existing process this method returns + /// -1. + int + GetTerminalFD() const { return m_terminal_fd; } + + /// Reads @p size bytes from address @vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoReadMemory. + size_t + ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + lldb_private::Error &error); + + /// Writes @p size bytes from address @p vm_adder in the inferior process + /// address space. + /// + /// This method is provided to implement Process::DoWriteMemory. + size_t + WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, + lldb_private::Error &error); + + /// Reads the contents from the register identified by the given (architecture + /// dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); + + /// Writes the given value to the register identified by the given + /// (architecture dependent) offset. + /// + /// This method is provided for use by RegisterContextFreeBSD derivatives. + bool + WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value); + + /// Reads all general purpose registers into the specified buffer. + bool + ReadGPR(void *buf); + + /// Reads all floating point registers into the specified buffer. + bool + ReadFPR(void *buf); + + /// Writes all general purpose registers into the specified buffer. + bool + WriteGPR(void *buf); + + /// Writes all floating point registers into the specified buffer. + bool + WriteFPR(void *buf); + + /// Writes a siginfo_t structure corresponding to the given thread ID to the + /// memory region pointed to by @p siginfo. + bool + GetSignalInfo(lldb::tid_t tid, void *siginfo); + + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) + /// corresponding to the given thread IDto the memory pointed to by @p + /// message. + bool + GetEventMessage(lldb::tid_t tid, unsigned long *message); + + /// Resumes the given thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + bool + Resume(lldb::tid_t tid, uint32_t signo); + + /// Single steps the given thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + bool + SingleStep(lldb::tid_t tid, uint32_t signo); + + /// Sends the inferior process a PTRACE_KILL signal. The inferior will + /// still exists and can be interrogated. Once resumed it will exit as + /// though it received a SIGKILL. + bool + BringProcessIntoLimbo(); + + lldb_private::Error + Detach(); + + +private: + ProcessFreeBSD *m_process; + + lldb::thread_t m_operation_thread; + lldb::thread_t m_monitor_thread; + lldb::pid_t m_pid; + + + lldb_private::Mutex m_server_mutex; + int m_terminal_fd; + int m_client_fd; + int m_server_fd; + + struct OperationArgs + { + OperationArgs(ProcessMonitor *monitor); + + ~OperationArgs(); + + ProcessMonitor *m_monitor; // The monitor performing the attach. + sem_t m_semaphore; // Posted to once operation complete. + lldb_private::Error m_error; // Set if process operation failed. + }; + + /// @class LauchArgs + /// + /// @brief Simple structure to pass data to the thread responsible for + /// launching a child process. + struct LaunchArgs : OperationArgs + { + LaunchArgs(ProcessMonitor *monitor, + lldb_private::Module *module, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path); + + ~LaunchArgs(); + + lldb_private::Module *m_module; // The executable image to launch. + char const **m_argv; // Process arguments. + char const **m_envp; // Process environment. + const char *m_stdin_path; // Redirect stdin or NULL. + const char *m_stdout_path; // Redirect stdout or NULL. + const char *m_stderr_path; // Redirect stderr or NULL. + }; + + void + StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); + + void + StopLaunchOpThread(); + + static void * + LaunchOpThread(void *arg); + + static bool + Launch(LaunchArgs *args); + + bool + EnableIPC(); + + struct AttachArgs : OperationArgs + { + AttachArgs(ProcessMonitor *monitor, + lldb::pid_t pid); + + ~AttachArgs(); + + lldb::pid_t m_pid; // pid of the process to be attached. + }; + + void + StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); + + void + StopAttachOpThread(); + + static void * + AttachOpThread(void *args); + + static bool + Attach(AttachArgs *args); + + static void + ServeOperation(OperationArgs *args); + + static bool + DupDescriptor(const char *path, int fd, int flags); + + static bool + MonitorCallback(void *callback_baton, + lldb::pid_t pid, bool exited, int signal, int status); + + static ProcessMessage + MonitorSIGTRAP(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); + + static ProcessMessage + MonitorSignal(ProcessMonitor *monitor, + const siginfo_t *info, lldb::pid_t pid); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGSEGV(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGILL(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGFPE(const siginfo_t *info); + + static ProcessMessage::CrashReason + GetCrashReasonForSIGBUS(const siginfo_t *info); + + void + DoOperation(Operation *op); + + /// Stops the child monitor thread. + void + StopMonitoringChildProcess(); + + void + StopMonitor(); + + void + CloseFD(int &fd); +}; + +#endif // #ifndef liblldb_ProcessMonitor_H_ Index: source/Plugins/Process/FreeBSD/Makefile =================================================================== --- source/Plugins/Process/FreeBSD/Makefile (revision 0) +++ source/Plugins/Process/FreeBSD/Makefile (revision 0) @@ -0,0 +1,17 @@ +##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginProcessFreeBSD +BUILD_ARCHIVE = 1 + +# Extend the include path so we may locate UnwindLLDB.h +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility + +include $(LLDB_LEVEL)/Makefile Index: source/Host/linux/Host.cpp =================================================================== --- source/Host/linux/Host.cpp (revision 147560) +++ source/Host/linux/Host.cpp (working copy) @@ -10,12 +10,20 @@ // C Includes #include #include +#include +#include +#include + // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Error.h" +#include "lldb/Target/Process.h" + #include "lldb/Host/Host.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" using namespace lldb; using namespace lldb_private; @@ -43,3 +51,48 @@ return error; } +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + static const size_t path_size = 128; + static char path[path_size]; + lldb::DataBufferSP buf_sp; + + int fd; + + // Ideally, we would simply create a FileSpec and call ReadFileContents. + // However, files in procfs have zero size (since they are, in general, + // dynamically generated by the kernel) which is incompatible with the + // current ReadFileContents implementation. Therefore we simply stream the + // data into a DataBuffer ourselves. + if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0) + return buf_sp; + + if ((fd = open(path, O_RDONLY, 0)) < 0) + return buf_sp; + + size_t bytes_read = 0; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + for (;;) + { + size_t avail = buf_ap->GetByteSize() - bytes_read; + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); + + if (status < 0) + break; + + bytes_read += status; + + if (status == 0) + { + buf_ap->SetByteSize(bytes_read); + buf_sp.reset(buf_ap.release()); + break; + } + + if (avail - status == 0) + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); + } + + return buf_sp; +} Index: source/Host/freebsd/Host.cpp =================================================================== --- source/Host/freebsd/Host.cpp (revision 147560) +++ source/Host/freebsd/Host.cpp (working copy) @@ -9,12 +9,18 @@ // C Includes #include +#include #include #include #include #include #include +#include +#include +#include + + // C++ Includes // Other libraries and framework includes // Project includes @@ -26,15 +32,19 @@ #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "llvm/Support/Host.h" + extern "C" { - char **environ; + extern char **environ; } using namespace lldb; using namespace lldb_private; + class FreeBSDThread { public: @@ -77,7 +87,7 @@ std::vector frame_buffer (max_frames, NULL); int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); - + const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) @@ -101,7 +111,7 @@ { char *v; char **var = environ; - for (var = environ; var != NULL; ++var) { + for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; @@ -168,49 +178,47 @@ ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; char arg_data[8192]; size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) { DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); uint32_t offset = 0; - uint32_t start_offset; - uint32_t argc = data.GetU32 (&offset); const char *cstr; - + cstr = data.GetCStr (&offset); if (cstr) { process_info.GetExecutableFile().SetFile(cstr, false); - if (match_info_ptr == NULL || + if (!(match_info_ptr == NULL || NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName())) + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) { - // Skip NULLs - while (1) + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - const uint8_t *p = data.PeekData(offset, 1); - if ((p == NULL) || (*p != '\0')) - break; ++offset; + p = data.PeekData(offset, 1); } - // Now extract all arguments - Args &proc_args = process_info.GetArguments(); - for (int i=0; i= arg_data_size) + return true; + + cstr = data.GetCStr(&offset); + if (cstr) + proc_args.AppendArgument(cstr); + else + return true; } } - } + } } return false; } @@ -219,8 +227,8 @@ GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - // TODO: This - // return true; + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); + return true; } process_info.GetArchitecture().Clear(); return false; @@ -249,7 +257,7 @@ if (proc_kinfo.ki_ngroups > 0) process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); else - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return true; } } @@ -258,7 +266,7 @@ process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return false; } @@ -275,3 +283,46 @@ process_info.Clear(); return false; } + +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; + void *ps_strings_addr, *auxv_addr; + size_t ps_strings_size = sizeof(void *); + Elf_Auxinfo aux_info[AT_COUNT]; + struct ps_strings ps_strings; + struct ptrace_io_desc pid; + DataBufferSP buf_sp; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { + pid.piod_op = PIOD_READ_D; + pid.piod_addr = &ps_strings; + pid.piod_offs = ps_strings_addr; + pid.piod_len = sizeof(ps_strings); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch ps_strings"); + buf_ap.release(); + goto done; + } + + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; + + pid.piod_addr = aux_info; + pid.piod_offs = auxv_addr; + pid.piod_len = sizeof(aux_info); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch aux_info"); + buf_ap.release(); + goto done; + } + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); + buf_sp.reset(buf_ap.release()); + } else { + perror("sysctl failed on ps_strings"); + } + + done: + return buf_sp; +} Index: source/lldb.cpp =================================================================== --- source/lldb.cpp (revision 147560) +++ source/lldb.cpp (working copy) @@ -52,13 +52,16 @@ #endif #if defined (__linux__) -#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h" +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/Linux/PlatformLinux.h" #include "Plugins/Process/Linux/ProcessLinux.h" #endif #if defined (__FreeBSD__) +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" +#include "Plugins/Process/POSIX/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #endif #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" @@ -120,10 +123,12 @@ //---------------------------------------------------------------------- PlatformLinux::Initialize(); ProcessLinux::Initialize(); - DynamicLoaderLinuxDYLD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Initialize(); + PlatformFreeBSD::Initialize(); + ProcessFreeBSD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif //---------------------------------------------------------------------- // Platform agnostic plugins @@ -190,11 +195,13 @@ #if defined (__linux__) PlatformLinux::Terminate(); ProcessLinux::Terminate(); - DynamicLoaderLinuxDYLD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Terminate(); + PlatformFreeBSD::Terminate(); + ProcessFreeBSD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif DynamicLoaderStatic::Terminate(); Index: tools/driver/Makefile =================================================================== --- tools/driver/Makefile (revision 147560) +++ tools/driver/Makefile (working copy) @@ -25,7 +25,6 @@ ifeq ($(HOST_OS),FreeBSD) CPP.Flags += -I/usr/include/edit #-v - LD.Flags += -lEnhancedDisassembly LD.Flags += -Wl,-rpath,$(LibDir) endif Index: lib/Makefile =================================================================== --- lib/Makefile (revision 147560) +++ lib/Makefile (working copy) @@ -81,15 +81,19 @@ endif ifeq ($(HOST_OS),Linux) - USEDLIBS += lldbPluginProcessLinux.a \ - lldbPluginDynamicLoaderLinux.a \ + USEDLIBS += lldbPluginProcessPOSIX.a \ + lldbPluginProcessLinux.a \ + lldbPluginDynamicLoaderPOSIX.a \ lldbPluginPlatformLinux.a \ lldbHostLinux.a endif ifeq ($(HOST_OS),FreeBSD) USEDLIBS += lldbHostFreeBSD.a \ - lldbPluginPlatformFreeBSD.a + lldbPluginDynamicLoaderPOSIX.a \ + lldbPluginProcessPOSIX.a \ + lldbPluginProcessFreeBSD.a \ + lldbPluginPlatformFreeBSD.a endif include $(LEVEL)/Makefile.common @@ -130,8 +134,8 @@ # Include everything from the .a's into the shared library. ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \ -Wl,--no-whole-archive - # Don't allow unresolved symbols. - LLVMLibsOptions += -Wl,--no-undefined + # Allow unresolved symbols. + LLVMLibsOptions += -Wl,--allow-shlib-undefined # Link in python LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo endif Index: Makefile =================================================================== --- Makefile (revision 147560) +++ Makefile (working copy) @@ -39,6 +39,7 @@ CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX ifeq ($(HOST_OS),Darwin) CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks endif From dawn at burble.org Wed Jan 4 21:25:30 2012 From: dawn at burble.org (dawn at burble.org) Date: Wed, 4 Jan 2012 19:25:30 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120105020417.GA31220@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> <20120105011113.GA30805@bloodbath.burble.org> <20120105020417.GA31220@bloodbath.burble.org> Message-ID: <20120105032530.GA32500@bloodbath.burble.org> The commit failed with: svn: Commit failed (details follow): svn: Server sent unexpected return value (400 Bad Request) in response to MKACTIVITY request for '/svn/llvm-project/!svn/act/171a3442-2c78-47b3-89ac-63b98af59774' svn: Your commit message was left in a temporary file: svn: '/home/dawn/dev/llvm_svnR146622/tools/lldb/svn-commit.tmp' I tried checking out the tree with: svn co https://llvm.org/svn/llvm-project but that gave me: svn: access to '/svn/llvm-project/!svn/vcc/default' forbidden Please commit lldb_svnR147560_POSIX.patch for me? Commit message is: This patch combines common code from Linux and FreeBSD into a new POSIX platform. It also contains fixes for 64bit FreeBSD. The patch is based on changes by Mark Peek and "K. Macy" in their github repo located at https://github.com/fbsd/lldb. Thanks, -Dawn On Wed, Jan 04, 2012 at 06:04:17PM -0800, dawn at burble.org wrote: > Looks like only source/Target/Platform.cpp had left-overs from the > bad git patch, so we're good now. > > New patches attached: > lldb_svnR147560_POSIX_TargetList.patch - changes to TargetList.cpp separated out. > lldb_svnR147560_POSIX.patch - changes sans Platform.cpp and TargetList.cpp > > The changes to TargetList.cpp are needed by both BSD and Linux in order for > Attach() to work. I spent a lot of time debugging this one, and the BSD folks > came to the same conclusion. I'll dig through my notes and try to write up my > findings - should this be discussed here or on lldb-dev? > > So I should go ahead and commit the rest of the patch? I've commited to clang > but never lldb - I can give it a try... > > Thanks, > -Dawn > > On Wed, Jan 04, 2012 at 05:11:13PM -0800, dawn at burble.org wrote: > > On Wed, Jan 04, 2012 at 04:41:08PM -0800, Johnny Chen wrote: > > > Hi Dawn, > > > > > > The patch looks good. I have a couple of questions on source/Target/Platform.cpp and source/Target/TargetList.cpp, though. > > > Please commit the patch except the two files. > > > > > > Here are my questions: > > > > > > The Platform.cpp patch looks wrong? > > > > Sorry - you're right. That was a left over from a mis-applied git patch > > that I thought I had reverted. I will fix ASAP and resubmit. > > > > Thanks for catching this!!! > > > > ...stay tuned... > > > > > Index: source/Target/Platform.cpp > > > =================================================================== > > > --- source/Target/Platform.cpp (revision 147560) > > > +++ source/Target/Platform.cpp (working copy) > > > @@ -572,6 +572,16 @@ > > > Error &error) > > > { > > > ProcessSP process_sp; > > > + > > > + launch_info.GetFlags ().Set (eLaunchFlagDebug); > > > + const char *plugin_name = launch_info.GetProcessPluginName(); > > > + process_sp = target->CreateProcess (listener, plugin_name).get(); > > > + error = process_sp->Launch (launch_info); > > > + return process_sp; > > > + > > > + > > > +#if 0 > > > + ProcessSP process_sp; > > > // Make sure we stop at the entry point > > > launch_info.GetFlags ().Set (eLaunchFlagDebug); > > > error = LaunchProcess (launch_info); > > > @@ -602,4 +612,5 @@ > > > } > > > } > > > return process_sp; > > > +#endif > > > } > > > > > > Also, I'll ask Greg to review the TargetList.cpp question you have. > > > Please don't commit it for the time being. > > > > > > Index: source/Target/TargetList.cpp > > > =================================================================== > > > --- source/Target/TargetList.cpp (revision 147560) > > > +++ source/Target/TargetList.cpp (working copy) > > > @@ -72,7 +72,8 @@ > > > if (!platform_sp) > > > platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); > > > > > > - ArchSpec arch; > > > + // Unclear why I need to init this and others don't > > > + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); > > > > > > if (triple_cstr) > > > { > > > @@ -83,6 +84,7 @@ > > > return error; > > > } > > > } > > > + > > > error = TargetList::CreateTarget (debugger, > > > file, > > > arch, > > > > > > On Jan 4, 2012, at 3:26 PM, dawn at burble.org wrote: > > > > > > > > > > > This patch combines common code from Linux and FreeBSD into > > > > a new POSIX platform. It also contains fixes for 64bit FreeBSD. > > > > > > > > The patch is based on changes by Mark Peek and > > > > "K. Macy" in their > > > > github repo located at https://github.com/fbsd/lldb. > > > > > > > > Ok to commit? > > > > Thanks! > > > > -Dawn > > > > _______________________________________________ > > > > lldb-commits mailing list > > > > lldb-commits at cs.uiuc.edu > > > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > > _______________________________________________ > > lldb-commits mailing list > > lldb-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > Index: source/Target/TargetList.cpp > =================================================================== > --- source/Target/TargetList.cpp (revision 147560) > +++ source/Target/TargetList.cpp (working copy) > @@ -72,7 +72,8 @@ > if (!platform_sp) > platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); > > - ArchSpec arch; > + // Unclear why I need to init this and others don't > + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); > > if (triple_cstr) > { > @@ -83,6 +84,7 @@ > return error; > } > } > + > error = TargetList::CreateTarget (debugger, > file, > arch, > Index: include/lldb/Host/Host.h > =================================================================== > --- include/lldb/Host/Host.h (revision 147560) > +++ include/lldb/Host/Host.h (working copy) > @@ -355,7 +355,10 @@ > > static Error > LaunchProcess (ProcessLaunchInfo &launch_info); > - > + > + static lldb::DataBufferSP > + GetAuxvData (lldb_private::Process *process); > + > static lldb::TargetSP > GetDummyTarget (Debugger &debugger); > > Index: source/Plugins/Platform/Linux/PlatformLinux.h > =================================================================== > --- source/Plugins/Platform/Linux/PlatformLinux.h (revision 147560) > +++ source/Plugins/Platform/Linux/PlatformLinux.h (working copy) > @@ -104,6 +104,7 @@ > Attach(ProcessAttachInfo &attach_info, Debugger &debugger, > Target *target, Listener &listener, Error &error); > > + // Linux processes can not be launched by spawning and attaching. > virtual bool > CanDebugProcess () > { > Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp > =================================================================== > --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (revision 147560) > +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (working copy) > @@ -27,16 +27,13 @@ > Platform * > PlatformFreeBSD::CreateInstance () > { > - // The only time we create an instance is when we are creating a remote > - // freebsd platform > - const bool is_host = false; > - return new PlatformFreeBSD (is_host); > + return new PlatformFreeBSD (true); > } > > const char * > PlatformFreeBSD::GetPluginNameStatic() > { > - return "PlatformFreeBSD"; > + return "plugin.platform.freebsd"; > } > > const char * > @@ -66,7 +63,7 @@ > { > #if defined (__FreeBSD__) > PlatformSP default_platform_sp (CreateInstance()); > - //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); > + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); > Platform::SetDefaultPlatform (default_platform_sp); > #endif > PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false), > @@ -79,7 +76,7 @@ > void > PlatformFreeBSD::Terminate () > { > - PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); > + PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); > } > > //------------------------------------------------------------------ > @@ -385,17 +382,16 @@ > bool > PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) > { > - bool sucess = false; > + bool success = false; > if (IsHost()) > { > - sucess = Platform::GetProcessInfo (pid, process_info); > + success = Platform::GetProcessInfo (pid, process_info); > } > - else > + else if (m_remote_platform_sp) > { > - if (m_remote_platform_sp) > - sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); > + success = m_remote_platform_sp->GetProcessInfo (pid, process_info); > } > - return sucess; > + return success; > } > > > @@ -438,11 +434,11 @@ > } > > lldb::ProcessSP > -PlatformFreeBSD::Attach(lldb::pid_t pid, > - Debugger &debugger, > - Target *target, > - Listener &listener, > - Error &error) > +PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, > + Debugger &debugger, > + Target *target, > + Listener &listener, > + Error &error) > { > lldb::ProcessSP process_sp; > if (IsHost()) > @@ -457,6 +453,7 @@ > emptyFileSpec, > emptyArchSpec, > false, > + m_remote_platform_sp, > new_target_sp); > target = new_target_sp.get(); > } > @@ -472,13 +469,13 @@ > process_sp = target->CreateProcess (listener, "gdb-remote"); > > if (process_sp) > - error = process_sp->Attach (pid); > + error = process_sp->Attach (attach_info); > } > } > else > { > if (m_remote_platform_sp) > - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); > + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); > else > error.SetErrorString ("the platform is not currently connected"); > } > Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h > =================================================================== > --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (revision 147560) > +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (working copy) > @@ -132,12 +132,16 @@ > LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); > > virtual lldb::ProcessSP > - Attach(lldb::pid_t pid, > + Attach(lldb_private::ProcessAttachInfo &attach_info, > lldb_private::Debugger &debugger, > lldb_private::Target *target, > lldb_private::Listener &listener, > lldb_private::Error &error); > > + // FreeBSD processes can not be launched by spawning and attaching. > + virtual bool > + CanDebugProcess () { return false; } > + > // Only on PlatformMacOSX: > virtual lldb_private::Error > GetFile (const lldb_private::FileSpec &platform_file, > Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (working copy) > @@ -1,191 +0,0 @@ > -//===-- AuxVector.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 > -#include > -#include > - > -// C++ Includes > -// Other libraries and framework includes > -#include "lldb/Core/DataBufferHeap.h" > -#include "lldb/Core/DataExtractor.h" > -#include "lldb/Core/Log.h" > -#include "lldb/Target/Process.h" > - > -#include "AuxVector.h" > - > -using namespace lldb; > -using namespace lldb_private; > - > -static bool > -GetMaxU64(DataExtractor &data, > - uint32_t *offset, uint64_t *value, unsigned int byte_size) > -{ > - uint32_t saved_offset = *offset; > - *value = data.GetMaxU64(offset, byte_size); > - return *offset != saved_offset; > -} > - > -static bool > -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, > - uint32_t *offset, unsigned int byte_size) > -{ > - if (!GetMaxU64(data, offset, &entry.type, byte_size)) > - return false; > - > - if (!GetMaxU64(data, offset, &entry.value, byte_size)) > - return false; > - > - return true; > -} > - > -DataBufferSP > -AuxVector::GetAuxvData() > -{ > - static const size_t path_size = 128; > - static char path[path_size]; > - DataBufferSP buf_sp; > - int fd; > - > - // Ideally, we would simply create a FileSpec and call ReadFileContents. > - // However, files in procfs have zero size (since they are, in general, > - // dynamically generated by the kernel) which is incompatible with the > - // current ReadFileContents implementation. Therefore we simply stream the > - // data into a DataBuffer ourselves. > - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) > - return buf_sp; > - > - if ((fd = open(path, O_RDONLY, 0)) < 0) > - return buf_sp; > - > - size_t bytes_read = 0; > - std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); > - for (;;) > - { > - size_t avail = buf_ap->GetByteSize() - bytes_read; > - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); > - > - if (status < 0) > - break; > - > - bytes_read += status; > - > - if (status == 0) > - { > - buf_ap->SetByteSize(bytes_read); > - buf_sp.reset(buf_ap.release()); > - break; > - } > - > - if (avail - status == 0) > - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); > - } > - > - return buf_sp; > -} > - > -void > -AuxVector::ParseAuxv(DataExtractor &data) > -{ > - const unsigned int byte_size = m_process->GetAddressByteSize(); > - uint32_t offset = 0; > - > - for (;;) > - { > - Entry entry; > - > - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) > - break; > - > - if (entry.type == AT_NULL) > - break; > - > - if (entry.type == AT_IGNORE) > - continue; > - > - m_auxv.push_back(entry); > - } > -} > - > -AuxVector::AuxVector(Process *process) > - : m_process(process) > -{ > - DataExtractor data; > - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); > - > - data.SetData(GetAuxvData()); > - data.SetByteOrder(m_process->GetByteOrder()); > - data.SetAddressByteSize(m_process->GetAddressByteSize()); > - > - ParseAuxv(data); > - > - if (log) > - DumpToLog(log); > -} > - > -AuxVector::iterator > -AuxVector::FindEntry(EntryType type) const > -{ > - for (iterator I = begin(); I != end(); ++I) > - { > - if (I->type == static_cast(type)) > - return I; > - } > - > - return end(); > -} > - > -void > -AuxVector::DumpToLog(LogSP log) const > -{ > - if (!log) > - return; > - > - log->PutCString("AuxVector: "); > - for (iterator I = begin(); I != end(); ++I) > - { > - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); > - } > -} > - > -const char * > -AuxVector::GetEntryName(EntryType type) > -{ > - const char *name; > - > -#define ENTRY_NAME(_type) _type: name = #_type > - switch (type) > - { > - default: > - name = "unkown"; > - break; > - > - case ENTRY_NAME(AT_NULL); break; > - case ENTRY_NAME(AT_IGNORE); break; > - case ENTRY_NAME(AT_EXECFD); break; > - case ENTRY_NAME(AT_PHDR); break; > - case ENTRY_NAME(AT_PHENT); break; > - case ENTRY_NAME(AT_PHNUM); break; > - case ENTRY_NAME(AT_PAGESZ); break; > - case ENTRY_NAME(AT_BASE); break; > - case ENTRY_NAME(AT_FLAGS); break; > - case ENTRY_NAME(AT_ENTRY); break; > - case ENTRY_NAME(AT_NOTELF); break; > - case ENTRY_NAME(AT_UID); break; > - case ENTRY_NAME(AT_EUID); break; > - case ENTRY_NAME(AT_GID); break; > - case ENTRY_NAME(AT_EGID); break; > - case ENTRY_NAME(AT_CLKTCK); break; > - } > -#undef ENTRY_NAME > - > - return name; > -} > - > Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (working copy) > @@ -1,322 +0,0 @@ > -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -#include "lldb/Core/ArchSpec.h" > -#include "lldb/Core/Error.h" > -#include "lldb/Core/Log.h" > -#include "lldb/Target/Process.h" > -#include "lldb/Target/Target.h" > - > -#include "DYLDRendezvous.h" > - > -using namespace lldb; > -using namespace lldb_private; > - > -/// Locates the address of the rendezvous structure. Returns the address on > -/// success and LLDB_INVALID_ADDRESS on failure. > -static addr_t > -ResolveRendezvousAddress(Process *process) > -{ > - addr_t info_location; > - addr_t info_addr; > - Error error; > - size_t size; > - > - info_location = process->GetImageInfoAddress(); > - > - if (info_location == LLDB_INVALID_ADDRESS) > - return LLDB_INVALID_ADDRESS; > - > - info_addr = 0; > - size = process->DoReadMemory(info_location, &info_addr, > - process->GetAddressByteSize(), error); > - if (size != process->GetAddressByteSize() || error.Fail()) > - return LLDB_INVALID_ADDRESS; > - > - if (info_addr == 0) > - return LLDB_INVALID_ADDRESS; > - > - return info_addr; > -} > - > -DYLDRendezvous::DYLDRendezvous(Process *process) > - : m_process(process), > - m_rendezvous_addr(LLDB_INVALID_ADDRESS), > - m_current(), > - m_previous(), > - m_soentries(), > - m_added_soentries(), > - m_removed_soentries() > -{ > -} > - > -bool > -DYLDRendezvous::Resolve() > -{ > - const size_t word_size = 4; > - Rendezvous info; > - size_t address_size; > - size_t padding; > - addr_t info_addr; > - addr_t cursor; > - > - address_size = m_process->GetAddressByteSize(); > - padding = address_size - word_size; > - > - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) > - cursor = info_addr = ResolveRendezvousAddress(m_process); > - else > - cursor = info_addr = m_rendezvous_addr; > - > - if (cursor == LLDB_INVALID_ADDRESS) > - return false; > - > - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) > - return false; > - > - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) > - return false; > - > - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) > - return false; > - > - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) > - return false; > - > - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) > - return false; > - > - // The rendezvous was successfully read. Update our internal state. > - m_rendezvous_addr = info_addr; > - m_previous = m_current; > - m_current = info; > - > - return UpdateSOEntries(); > -} > - > -bool > -DYLDRendezvous::IsValid() > -{ > - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; > -} > - > -bool > -DYLDRendezvous::UpdateSOEntries() > -{ > - SOEntry entry; > - > - if (m_current.map_addr == 0) > - return false; > - > - // When the previous and current states are consistent this is the first > - // time we have been asked to update. Just take a snapshot of the currently > - // loaded modules. > - if (m_previous.state == eConsistent && m_current.state == eConsistent) > - return TakeSnapshot(m_soentries); > - > - // If we are about to add or remove a shared object clear out the current > - // state and take a snapshot of the currently loaded images. > - if (m_current.state == eAdd || m_current.state == eDelete) > - { > - assert(m_previous.state == eConsistent); > - m_soentries.clear(); > - m_added_soentries.clear(); > - m_removed_soentries.clear(); > - return TakeSnapshot(m_soentries); > - } > - assert(m_current.state == eConsistent); > - > - // Otherwise check the previous state to determine what to expect and update > - // accordingly. > - if (m_previous.state == eAdd) > - return UpdateSOEntriesForAddition(); > - else if (m_previous.state == eDelete) > - return UpdateSOEntriesForDeletion(); > - > - return false; > -} > - > -bool > -DYLDRendezvous::UpdateSOEntriesForAddition() > -{ > - SOEntry entry; > - iterator pos; > - > - assert(m_previous.state == eAdd); > - > - if (m_current.map_addr == 0) > - return false; > - > - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) > - { > - if (!ReadSOEntryFromMemory(cursor, entry)) > - return false; > - > - if (entry.path.empty()) > - continue; > - > - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); > - if (pos == m_soentries.end()) > - { > - m_soentries.push_back(entry); > - m_added_soentries.push_back(entry); > - } > - } > - > - return true; > -} > - > -bool > -DYLDRendezvous::UpdateSOEntriesForDeletion() > -{ > - SOEntryList entry_list; > - iterator pos; > - > - assert(m_previous.state == eDelete); > - > - if (!TakeSnapshot(entry_list)) > - return false; > - > - for (iterator I = begin(); I != end(); ++I) > - { > - pos = std::find(entry_list.begin(), entry_list.end(), *I); > - if (pos == entry_list.end()) > - m_removed_soentries.push_back(*I); > - } > - > - m_soentries = entry_list; > - return true; > -} > - > -bool > -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) > -{ > - SOEntry entry; > - > - if (m_current.map_addr == 0) > - return false; > - > - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) > - { > - if (!ReadSOEntryFromMemory(cursor, entry)) > - return false; > - > - if (entry.path.empty()) > - continue; > - > - entry_list.push_back(entry); > - } > - > - return true; > -} > - > -addr_t > -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) > -{ > - size_t bytes_read; > - Error error; > - > - bytes_read = m_process->DoReadMemory(addr, dst, size, error); > - if (bytes_read != size || error.Fail()) > - return 0; > - > - return addr + bytes_read; > -} > - > -std::string > -DYLDRendezvous::ReadStringFromMemory(addr_t addr) > -{ > - std::string str; > - Error error; > - size_t size; > - char c; > - > - if (addr == LLDB_INVALID_ADDRESS) > - return std::string(); > - > - for (;;) { > - size = m_process->DoReadMemory(addr, &c, 1, error); > - if (size != 1 || error.Fail()) > - return std::string(); > - if (c == 0) > - break; > - else { > - str.push_back(c); > - addr++; > - } > - } > - > - return str; > -} > - > -bool > -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) > -{ > - size_t address_size = m_process->GetAddressByteSize(); > - > - entry.clear(); > - > - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) > - return false; > - > - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) > - return false; > - > - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) > - return false; > - > - if (!(addr = ReadMemory(addr, &entry.next, address_size))) > - return false; > - > - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) > - return false; > - > - entry.path = ReadStringFromMemory(entry.path_addr); > - > - return true; > -} > - > -void > -DYLDRendezvous::DumpToLog(LogSP log) const > -{ > - int state = GetState(); > - > - if (!log) > - return; > - > - log->PutCString("DYLDRendezvous:"); > - log->Printf(" Address: %lx", GetRendezvousAddress()); > - log->Printf(" Version: %d", GetVersion()); > - log->Printf(" Link : %lx", GetLinkMapAddress()); > - log->Printf(" Break : %lx", GetBreakAddress()); > - log->Printf(" LDBase : %lx", GetLDBase()); > - log->Printf(" State : %s", > - (state == eConsistent) ? "consistent" : > - (state == eAdd) ? "add" : > - (state == eDelete) ? "delete" : "unknown"); > - > - iterator I = begin(); > - iterator E = end(); > - > - if (I != E) > - log->PutCString("DYLDRendezvous SOEntries:"); > - > - for (int i = 1; I != E; ++I, ++i) > - { > - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); > - log->Printf(" Base : %lx", I->base_addr); > - log->Printf(" Path : %lx", I->path_addr); > - log->Printf(" Dyn : %lx", I->dyn_addr); > - log->Printf(" Next : %lx", I->next); > - log->Printf(" Prev : %lx", I->prev); > - } > -} > Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (working copy) > @@ -1,97 +0,0 @@ > -//===-- AuxVector.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_AuxVector_H_ > -#define liblldb_AuxVector_H_ > - > -// C Includes > -// C++ Includes > -#include > - > -// Other libraries and framework includes > -#include "lldb/lldb-forward-rtti.h" > - > -namespace lldb_private { > -class DataExtractor; > -} > - > -/// @class AuxVector > -/// @brief Represents a processes auxiliary vector. > -/// > -/// When a process is loaded on Linux a vector of values is placed onto the > -/// stack communicating operating system specific information. On construction > -/// this class locates and parses this information and provides a simple > -/// read-only interface to the entries found. > -class AuxVector { > - > -public: > - AuxVector(lldb_private::Process *process); > - > - struct Entry { > - uint64_t type; > - uint64_t value; > - > - Entry() : type(0), value(0) { } > - }; > - > - /// Constants describing the type of entry. > - enum EntryType { > - AT_NULL = 0, ///< End of auxv. > - AT_IGNORE = 1, ///< Ignore entry. > - AT_EXECFD = 2, ///< File descriptor of program. > - AT_PHDR = 3, ///< Program headers. > - AT_PHENT = 4, ///< Size of program header. > - AT_PHNUM = 5, ///< Number of program headers. > - AT_PAGESZ = 6, ///< Page size. > - AT_BASE = 7, ///< Interpreter base address. > - AT_FLAGS = 8, ///< Flags. > - AT_ENTRY = 9, ///< Program entry point. > - AT_NOTELF = 10, ///< Set if program is not an ELF. > - AT_UID = 11, ///< UID. > - AT_EUID = 12, ///< Effective UID. > - AT_GID = 13, ///< GID. > - AT_EGID = 14, ///< Effective GID. > - AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). > - }; > - > -private: > - typedef std::vector EntryVector; > - > -public: > - typedef EntryVector::const_iterator iterator; > - > - iterator begin() const { return m_auxv.begin(); } > - iterator end() const { return m_auxv.end(); } > - > - iterator > - FindEntry(EntryType type) const; > - > - static const char * > - GetEntryName(const Entry &entry) { > - return GetEntryName(static_cast(entry.type)); > - } > - > - static const char * > - GetEntryName(EntryType type); > - > - void > - DumpToLog(lldb::LogSP log) const; > - > -private: > - lldb_private::Process *m_process; > - EntryVector m_auxv; > - > - lldb::DataBufferSP > - GetAuxvData(); > - > - void > - ParseAuxv(lldb_private::DataExtractor &data); > -}; > - > -#endif > Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (working copy) > @@ -1,227 +0,0 @@ > -//===-- DYLDRendezvous.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_Rendezvous_H_ > -#define liblldb_Rendezvous_H_ > - > -// C Includes > -// C++ Includes > -#include > -#include > - > -// Other libraries and framework includes > -#include "lldb/lldb-defines.h" > -#include "lldb/lldb-types.h" > - > -namespace lldb_private { > -class Process; > -} > - > -/// @class DYLDRendezvous > -/// @brief Interface to the runtime linker. > -/// > -/// A structure is present in a processes memory space which is updated by the > -/// runtime liker each time a module is loaded or unloaded. This class provides > -/// an interface to this structure and maintains a consistent snapshot of the > -/// currently loaded modules. > -class DYLDRendezvous { > - > - // This structure is used to hold the contents of the debug rendezvous > - // information (struct r_debug) as found in the inferiors memory. Note that > - // the layout of this struct is not binary compatible, it is simply large > - // enough to hold the information on both 32 and 64 bit platforms. > - struct Rendezvous { > - uint64_t version; > - lldb::addr_t map_addr; > - lldb::addr_t brk; > - uint64_t state; > - lldb::addr_t ldbase; > - > - Rendezvous() > - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } > - }; > - > -public: > - DYLDRendezvous(lldb_private::Process *process); > - > - /// Update the internal snapshot of runtime linker rendezvous and recompute > - /// the currently loaded modules. > - /// > - /// This method should be called once one start up, then once each time the > - /// runtime linker enters the function given by GetBreakAddress(). > - /// > - /// @returns true on success and false on failure. > - /// > - /// @see GetBreakAddress(). > - bool > - Resolve(); > - > - /// @returns true if this rendezvous has been located in the inferiors > - /// address space and false otherwise. > - bool > - IsValid(); > - > - /// @returns the address of the rendezvous structure in the inferiors > - /// address space. > - lldb::addr_t > - GetRendezvousAddress() const { return m_rendezvous_addr; } > - > - /// @returns the version of the rendezvous protocol being used. > - int > - GetVersion() const { return m_current.version; } > - > - /// @returns address in the inferiors address space containing the linked > - /// list of shared object descriptors. > - lldb::addr_t > - GetLinkMapAddress() const { return m_current.map_addr; } > - > - /// A breakpoint should be set at this address and Resolve called on each > - /// hit. > - /// > - /// @returns the address of a function called by the runtime linker each > - /// time a module is loaded/unloaded, or about to be loaded/unloaded. > - /// > - /// @see Resolve() > - lldb::addr_t > - GetBreakAddress() const { return m_current.brk; } > - > - /// Returns the current state of the rendezvous structure. > - int > - GetState() const { return m_current.state; } > - > - /// @returns the base address of the runtime linker in the inferiors address > - /// space. > - lldb::addr_t > - GetLDBase() const { return m_current.ldbase; } > - > - /// @returns true if modules have been loaded into the inferior since the > - /// last call to Resolve(). > - bool > - ModulesDidLoad() const { return !m_added_soentries.empty(); } > - > - /// @returns true if modules have been unloaded from the inferior since the > - /// last call to Resolve(). > - bool > - ModulesDidUnload() const { return !m_removed_soentries.empty(); } > - > - void > - DumpToLog(lldb::LogSP log) const; > - > - /// @brief Constants describing the state of the rendezvous. > - /// > - /// @see GetState(). > - enum RendezvousState { > - eConsistent, > - eAdd, > - eDelete > - }; > - > - /// @brief Structure representing the shared objects currently loaded into > - /// the inferior process. > - /// > - /// This object is a rough analogue to the struct link_map object which > - /// actually lives in the inferiors memory. > - struct SOEntry { > - lldb::addr_t base_addr; ///< Base address of the loaded object. > - lldb::addr_t path_addr; ///< String naming the shared object. > - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. > - lldb::addr_t next; ///< Address of next so_entry. > - lldb::addr_t prev; ///< Address of previous so_entry. > - std::string path; ///< File name of shared object. > - > - SOEntry() { clear(); } > - > - bool operator ==(const SOEntry &entry) { > - return this->path == entry.path; > - } > - > - void clear() { > - base_addr = 0; > - path_addr = 0; > - dyn_addr = 0; > - next = 0; > - prev = 0; > - path.clear(); > - } > - }; > - > -protected: > - typedef std::list SOEntryList; > - > -public: > - typedef SOEntryList::const_iterator iterator; > - > - /// Iterators over all currently loaded modules. > - iterator begin() const { return m_soentries.begin(); } > - iterator end() const { return m_soentries.end(); } > - > - /// Iterators over all modules loaded into the inferior since the last call > - /// to Resolve(). > - iterator loaded_begin() const { return m_added_soentries.begin(); } > - iterator loaded_end() const { return m_added_soentries.end(); } > - > - /// Iterators over all modules unloaded from the inferior since the last > - /// call to Resolve(). > - iterator unloaded_begin() const { return m_removed_soentries.begin(); } > - iterator unloaded_end() const { return m_removed_soentries.end(); } > - > -protected: > - lldb_private::Process *m_process; > - > - /// Location of the r_debug structure in the inferiors address space. > - lldb::addr_t m_rendezvous_addr; > - > - /// Current and previous snapshots of the rendezvous structure. > - Rendezvous m_current; > - Rendezvous m_previous; > - > - /// List of SOEntry objects corresponding to the current link map state. > - SOEntryList m_soentries; > - > - /// List of SOEntry's added to the link map since the last call to Resolve(). > - SOEntryList m_added_soentries; > - > - /// List of SOEntry's removed from the link map since the last call to > - /// Resolve(). > - SOEntryList m_removed_soentries; > - > - /// Reads @p size bytes from the inferiors address space starting at @p > - /// addr. > - /// > - /// @returns addr + size if the read was successful and false otherwise. > - lldb::addr_t > - ReadMemory(lldb::addr_t addr, void *dst, size_t size); > - > - /// Reads a null-terminated C string from the memory location starting at @p > - /// addr. > - std::string > - ReadStringFromMemory(lldb::addr_t addr); > - > - /// Reads an SOEntry starting at @p addr. > - bool > - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); > - > - /// Updates the current set of SOEntries, the set of added entries, and the > - /// set of removed entries. > - bool > - UpdateSOEntries(); > - > - bool > - UpdateSOEntriesForAddition(); > - > - bool > - UpdateSOEntriesForDeletion(); > - > - /// Reads the current list of shared objects according to the link map > - /// supplied by the runtime linker. > - bool > - TakeSnapshot(SOEntryList &entry_list); > -}; > - > -#endif > Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (working copy) > @@ -1,423 +0,0 @@ > -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -#include "lldb/Core/PluginManager.h" > -#include "lldb/Core/Log.h" > -#include "lldb/Target/Process.h" > -#include "lldb/Target/Target.h" > -#include "lldb/Target/Thread.h" > -#include "lldb/Target/ThreadPlanRunToAddress.h" > - > -#include "AuxVector.h" > -#include "DynamicLoaderLinuxDYLD.h" > - > -using namespace lldb; > -using namespace lldb_private; > - > -void > -DynamicLoaderLinuxDYLD::Initialize() > -{ > - PluginManager::RegisterPlugin(GetPluginNameStatic(), > - GetPluginDescriptionStatic(), > - CreateInstance); > -} > - > -void > -DynamicLoaderLinuxDYLD::Terminate() > -{ > -} > - > -const char * > -DynamicLoaderLinuxDYLD::GetPluginName() > -{ > - return "DynamicLoaderLinuxDYLD"; > -} > - > -const char * > -DynamicLoaderLinuxDYLD::GetShortPluginName() > -{ > - return "linux-dyld"; > -} > - > -const char * > -DynamicLoaderLinuxDYLD::GetPluginNameStatic() > -{ > - return "dynamic-loader.linux-dyld"; > -} > - > -const char * > -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() > -{ > - return "Dynamic loader plug-in that watches for shared library " > - "loads/unloads in Linux processes."; > -} > - > -void > -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) > -{ > -} > - > -uint32_t > -DynamicLoaderLinuxDYLD::GetPluginVersion() > -{ > - return 1; > -} > - > -DynamicLoader * > -DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force) > -{ > - bool create = force; > - if (!create) > - { > - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); > - if (triple_ref.getOS() == llvm::Triple::Linux) > - create = true; > - } > - > - if (create) > - return new DynamicLoaderLinuxDYLD (process); > - return NULL; > -} > - > -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) > - : DynamicLoader(process), > - m_rendezvous(process), > - m_load_offset(LLDB_INVALID_ADDRESS), > - m_entry_point(LLDB_INVALID_ADDRESS), > - m_auxv(NULL) > -{ > -} > - > -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() > -{ > -} > - > -void > -DynamicLoaderLinuxDYLD::DidAttach() > -{ > - ModuleSP executable; > - addr_t load_offset; > - > - m_auxv.reset(new AuxVector(m_process)); > - > - executable = m_process->GetTarget().GetExecutableModule(); > - load_offset = ComputeLoadOffset(); > - > - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) > - { > - ModuleList module_list; > - module_list.Append(executable); > - UpdateLoadedSections(executable, load_offset); > - m_process->GetTarget().ModulesDidLoad(module_list); > - } > -} > - > -void > -DynamicLoaderLinuxDYLD::DidLaunch() > -{ > - ModuleSP executable; > - addr_t load_offset; > - > - m_auxv.reset(new AuxVector(m_process)); > - > - executable = m_process->GetTarget().GetExecutableModule(); > - load_offset = ComputeLoadOffset(); > - > - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) > - { > - ModuleList module_list; > - module_list.Append(executable); > - UpdateLoadedSections(executable, load_offset); > - ProbeEntry(); > - m_process->GetTarget().ModulesDidLoad(module_list); > - } > -} > - > -Error > -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) > -{ > - return Error(); > -} > - > -Log * > -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) > -{ > - return NULL; > -} > - > -Error > -DynamicLoaderLinuxDYLD::CanLoadImage() > -{ > - return Error(); > -} > - > -void > -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) > -{ > - ObjectFile *obj_file = module->GetObjectFile(); > - SectionList *sections = obj_file->GetSectionList(); > - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); > - const size_t num_sections = sections->GetSize(); > - > - for (unsigned i = 0; i < num_sections; ++i) > - { > - Section *section = sections->GetSectionAtIndex(i).get(); > - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; > - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); > - > - // If the file address of the section is zero then this is not an > - // allocatable/loadable section (property of ELF sh_addr). Skip it. > - if (new_load_addr == base_addr) > - continue; > - > - if (old_load_addr == LLDB_INVALID_ADDRESS || > - old_load_addr != new_load_addr) > - load_list.SetSectionLoadAddress(section, new_load_addr); > - } > -} > - > -void > -DynamicLoaderLinuxDYLD::ProbeEntry() > -{ > - Breakpoint *entry_break; > - addr_t entry; > - > - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) > - return; > - > - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); > - entry_break->SetCallback(EntryBreakpointHit, this, true); > -} > - > -// The runtime linker has run and initialized the rendezvous structure once the > -// process has hit its entry point. When we hit the corresponding breakpoint we > -// interrogate the rendezvous structure to get the load addresses of all > -// dependent modules for the process. Similarly, we can discover the runtime > -// linker function and setup a breakpoint to notify us of any dynamically loaded > -// modules (via dlopen). > -bool > -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, > - StoppointCallbackContext *context, > - user_id_t break_id, > - user_id_t break_loc_id) > -{ > - DynamicLoaderLinuxDYLD* dyld_instance; > - > - dyld_instance = static_cast(baton); > - dyld_instance->LoadAllCurrentModules(); > - dyld_instance->SetRendezvousBreakpoint(); > - return false; // Continue running. > -} > - > -void > -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() > -{ > - Breakpoint *dyld_break; > - addr_t break_addr; > - > - break_addr = m_rendezvous.GetBreakAddress(); > - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); > - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); > -} > - > -bool > -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, > - StoppointCallbackContext *context, > - user_id_t break_id, > - user_id_t break_loc_id) > -{ > - DynamicLoaderLinuxDYLD* dyld_instance; > - > - dyld_instance = static_cast(baton); > - dyld_instance->RefreshModules(); > - > - // Return true to stop the target, false to just let the target run. > - return dyld_instance->GetStopWhenImagesChange(); > -} > - > -void > -DynamicLoaderLinuxDYLD::RefreshModules() > -{ > - if (!m_rendezvous.Resolve()) > - return; > - > - DYLDRendezvous::iterator I; > - DYLDRendezvous::iterator E; > - > - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); > - > - if (m_rendezvous.ModulesDidLoad()) > - { > - ModuleList new_modules; > - > - E = m_rendezvous.loaded_end(); > - for (I = m_rendezvous.loaded_begin(); I != E; ++I) > - { > - FileSpec file(I->path.c_str(), true); > - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); > - if (module_sp.get()) > - new_modules.Append(module_sp); > - } > - m_process->GetTarget().ModulesDidLoad(new_modules); > - } > - > - if (m_rendezvous.ModulesDidUnload()) > - { > - ModuleList old_modules; > - > - E = m_rendezvous.unloaded_end(); > - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) > - { > - FileSpec file(I->path.c_str(), true); > - ModuleSP module_sp = > - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); > - if (module_sp.get()) > - old_modules.Append(module_sp); > - } > - m_process->GetTarget().ModulesDidUnload(old_modules); > - } > -} > - > -ThreadPlanSP > -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) > -{ > - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); > - ThreadPlanSP thread_plan_sp; > - > - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); > - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); > - Symbol *sym = context.symbol; > - > - if (sym == NULL || !sym->IsTrampoline()) > - return thread_plan_sp; > - > - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); > - if (!sym_name) > - return thread_plan_sp; > - > - SymbolContextList target_symbols; > - Target &target = thread.GetProcess().GetTarget(); > - ModuleList &images = target.GetImages(); > - > - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); > - size_t num_targets = target_symbols.GetSize(); > - if (!num_targets) > - return thread_plan_sp; > - > - typedef std::vector AddressVector; > - AddressVector addrs; > - for (size_t i = 0; i < num_targets; ++i) > - { > - SymbolContext context; > - AddressRange range; > - if (target_symbols.GetContextAtIndex(i, context)) > - { > - context.GetAddressRange(eSymbolContextEverything, 0, false, range); > - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); > - if (addr != LLDB_INVALID_ADDRESS) > - addrs.push_back(addr); > - } > - } > - > - if (addrs.size() > 0) > - { > - AddressVector::iterator start = addrs.begin(); > - AddressVector::iterator end = addrs.end(); > - > - std::sort(start, end); > - addrs.erase(std::unique(start, end), end); > - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); > - } > - > - return thread_plan_sp; > -} > - > -void > -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() > -{ > - DYLDRendezvous::iterator I; > - DYLDRendezvous::iterator E; > - ModuleList module_list; > - > - if (!m_rendezvous.Resolve()) > - return; > - > - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) > - { > - FileSpec file(I->path.c_str(), false); > - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); > - if (module_sp.get()) > - module_list.Append(module_sp); > - } > - > - m_process->GetTarget().ModulesDidLoad(module_list); > -} > - > -ModuleSP > -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) > -{ > - Target &target = m_process->GetTarget(); > - ModuleList &modules = target.GetImages(); > - ModuleSP module_sp; > - > - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) > - { > - UpdateLoadedSections(module_sp, base_addr); > - } > - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) > - { > - UpdateLoadedSections(module_sp, base_addr); > - modules.Append(module_sp); > - } > - > - return module_sp; > -} > - > -addr_t > -DynamicLoaderLinuxDYLD::ComputeLoadOffset() > -{ > - addr_t virt_entry; > - > - if (m_load_offset != LLDB_INVALID_ADDRESS) > - return m_load_offset; > - > - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) > - return LLDB_INVALID_ADDRESS; > - > - ModuleSP module = m_process->GetTarget().GetExecutableModule(); > - ObjectFile *exe = module->GetObjectFile(); > - Address file_entry = exe->GetEntryPointAddress(); > - > - if (!file_entry.IsValid()) > - return LLDB_INVALID_ADDRESS; > - > - m_load_offset = virt_entry - file_entry.GetFileAddress(); > - return m_load_offset; > -} > - > -addr_t > -DynamicLoaderLinuxDYLD::GetEntryPoint() > -{ > - if (m_entry_point != LLDB_INVALID_ADDRESS) > - return m_entry_point; > - > - if (m_auxv.get() == NULL) > - return LLDB_INVALID_ADDRESS; > - > - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); > - > - if (I == m_auxv->end()) > - return LLDB_INVALID_ADDRESS; > - > - m_entry_point = static_cast(I->value); > - return m_entry_point; > -} > Index: source/Plugins/DynamicLoader/Linux-DYLD/Makefile > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/Makefile (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/Makefile (working copy) > @@ -1,14 +0,0 @@ > -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## > -# > -# The LLVM Compiler Infrastructure > -# > -# This file is distributed under the University of Illinois Open Source > -# License. See LICENSE.TXT for details. > -# > -##===----------------------------------------------------------------------===## > - > -LLDB_LEVEL := ../../../.. > -LIBRARYNAME := lldbPluginDynamicLoaderLinux > -BUILD_ARCHIVE = 1 > - > -include $(LLDB_LEVEL)/Makefile > Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h > =================================================================== > --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (revision 147560) > +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (working copy) > @@ -1,165 +0,0 @@ > -//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_ > -#define liblldb_DynamicLoaderLinux_H_ > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -#include "lldb/Breakpoint/StoppointCallbackContext.h" > -#include "lldb/Target/DynamicLoader.h" > - > -#include "DYLDRendezvous.h" > - > -class AuxVector; > - > -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader > -{ > -public: > - > - static void > - Initialize(); > - > - static void > - Terminate(); > - > - static const char * > - GetPluginNameStatic(); > - > - static const char * > - GetPluginDescriptionStatic(); > - > - static lldb_private::DynamicLoader * > - CreateInstance(lldb_private::Process *process, bool force); > - > - DynamicLoaderLinuxDYLD(lldb_private::Process *process); > - > - virtual > - ~DynamicLoaderLinuxDYLD(); > - > - //------------------------------------------------------------------ > - // DynamicLoader protocol > - //------------------------------------------------------------------ > - > - virtual void > - DidAttach(); > - > - virtual void > - DidLaunch(); > - > - virtual lldb::ThreadPlanSP > - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, > - bool stop_others); > - > - virtual lldb_private::Error > - CanLoadImage(); > - > - //------------------------------------------------------------------ > - // PluginInterface protocol > - //------------------------------------------------------------------ > - virtual const char * > - GetPluginName(); > - > - virtual const char * > - GetShortPluginName(); > - > - virtual uint32_t > - GetPluginVersion(); > - > - virtual void > - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); > - > - virtual lldb_private::Error > - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); > - > - virtual lldb_private::Log * > - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); > - > -protected: > - /// Runtime linker rendezvous structure. > - DYLDRendezvous m_rendezvous; > - > - /// Virtual load address of the inferior process. > - lldb::addr_t m_load_offset; > - > - /// Virtual entry address of the inferior process. > - lldb::addr_t m_entry_point; > - > - /// Auxiliary vector of the inferior process. > - std::auto_ptr m_auxv; > - > - /// Enables a breakpoint on a function called by the runtime > - /// linker each time a module is loaded or unloaded. > - void > - SetRendezvousBreakpoint(); > - > - /// Callback routine which updates the current list of loaded modules based > - /// on the information supplied by the runtime linker. > - static bool > - RendezvousBreakpointHit(void *baton, > - lldb_private::StoppointCallbackContext *context, > - lldb::user_id_t break_id, > - lldb::user_id_t break_loc_id); > - > - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set > - /// of loaded modules. > - void > - RefreshModules(); > - > - /// Updates the load address of every allocatable section in @p module. > - /// > - /// @param module The module to traverse. > - /// > - /// @param base_addr The virtual base address @p module is loaded at. > - void > - UpdateLoadedSections(lldb::ModuleSP module, > - lldb::addr_t base_addr = 0); > - > - /// Locates or creates a module given by @p file and updates/loads the > - /// resulting module at the virtual base address @p base_addr. > - lldb::ModuleSP > - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); > - > - /// Resolves the entry point for the current inferior process and sets a > - /// breakpoint at that address. > - void > - ProbeEntry(); > - > - /// Callback routine invoked when we hit the breakpoint on process entry. > - /// > - /// This routine is responsible for resolving the load addresses of all > - /// dependent modules required by the inferior and setting up the rendezvous > - /// breakpoint. > - static bool > - EntryBreakpointHit(void *baton, > - lldb_private::StoppointCallbackContext *context, > - lldb::user_id_t break_id, > - lldb::user_id_t break_loc_id); > - > - /// Helper for the entry breakpoint callback. Resolves the load addresses > - /// of all dependent modules. > - void > - LoadAllCurrentModules(); > - > - /// Computes a value for m_load_offset returning the computed address on > - /// success and LLDB_INVALID_ADDRESS on failure. > - lldb::addr_t > - ComputeLoadOffset(); > - > - /// Computes a value for m_entry_point returning the computed address on > - /// success and LLDB_INVALID_ADDRESS on failure. > - lldb::addr_t > - GetEntryPoint(); > - > -private: > - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); > -}; > - > -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ > Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) > @@ -0,0 +1,165 @@ > +//===-- DynamicLoaderPOSIX.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_DynamicLoaderPOSIX_H_ > +#define liblldb_DynamicLoaderPOSIX_H_ > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Breakpoint/StoppointCallbackContext.h" > +#include "lldb/Target/DynamicLoader.h" > + > +#include "DYLDRendezvous.h" > + > +class AuxVector; > + > +class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader > +{ > +public: > + > + static void > + Initialize(); > + > + static void > + Terminate(); > + > + static const char * > + GetPluginNameStatic(); > + > + static const char * > + GetPluginDescriptionStatic(); > + > + static lldb_private::DynamicLoader * > + CreateInstance(lldb_private::Process *process, bool force); > + > + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); > + > + virtual > + ~DynamicLoaderPOSIXDYLD(); > + > + //------------------------------------------------------------------ > + // DynamicLoader protocol > + //------------------------------------------------------------------ > + > + virtual void > + DidAttach(); > + > + virtual void > + DidLaunch(); > + > + virtual lldb::ThreadPlanSP > + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, > + bool stop_others); > + > + virtual lldb_private::Error > + CanLoadImage(); > + > + //------------------------------------------------------------------ > + // PluginInterface protocol > + //------------------------------------------------------------------ > + virtual const char * > + GetPluginName(); > + > + virtual const char * > + GetShortPluginName(); > + > + virtual uint32_t > + GetPluginVersion(); > + > + virtual void > + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); > + > + virtual lldb_private::Error > + ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); > + > + virtual lldb_private::Log * > + EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); > + > +protected: > + /// Runtime linker rendezvous structure. > + DYLDRendezvous m_rendezvous; > + > + /// Virtual load address of the inferior process. > + lldb::addr_t m_load_offset; > + > + /// Virtual entry address of the inferior process. > + lldb::addr_t m_entry_point; > + > + /// Auxiliary vector of the inferior process. > + std::auto_ptr m_auxv; > + > + /// Enables a breakpoint on a function called by the runtime > + /// linker each time a module is loaded or unloaded. > + void > + SetRendezvousBreakpoint(); > + > + /// Callback routine which updates the current list of loaded modules based > + /// on the information supplied by the runtime linker. > + static bool > + RendezvousBreakpointHit(void *baton, > + lldb_private::StoppointCallbackContext *context, > + lldb::user_id_t break_id, > + lldb::user_id_t break_loc_id); > + > + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set > + /// of loaded modules. > + void > + RefreshModules(); > + > + /// Updates the load address of every allocatable section in @p module. > + /// > + /// @param module The module to traverse. > + /// > + /// @param base_addr The virtual base address @p module is loaded at. > + void > + UpdateLoadedSections(lldb::ModuleSP module, > + lldb::addr_t base_addr = 0); > + > + /// Locates or creates a module given by @p file and updates/loads the > + /// resulting module at the virtual base address @p base_addr. > + lldb::ModuleSP > + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); > + > + /// Resolves the entry point for the current inferior process and sets a > + /// breakpoint at that address. > + void > + ProbeEntry(); > + > + /// Callback routine invoked when we hit the breakpoint on process entry. > + /// > + /// This routine is responsible for resolving the load addresses of all > + /// dependent modules required by the inferior and setting up the rendezvous > + /// breakpoint. > + static bool > + EntryBreakpointHit(void *baton, > + lldb_private::StoppointCallbackContext *context, > + lldb::user_id_t break_id, > + lldb::user_id_t break_loc_id); > + > + /// Helper for the entry breakpoint callback. Resolves the load addresses > + /// of all dependent modules. > + void > + LoadAllCurrentModules(); > + > + /// Computes a value for m_load_offset returning the computed address on > + /// success and LLDB_INVALID_ADDRESS on failure. > + lldb::addr_t > + ComputeLoadOffset(); > + > + /// Computes a value for m_entry_point returning the computed address on > + /// success and LLDB_INVALID_ADDRESS on failure. > + lldb::addr_t > + GetEntryPoint(); > + > +private: > + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); > +}; > + > +#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ > Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) > @@ -0,0 +1,153 @@ > +//===-- AuxVector.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 > +#include > +#include > + > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/DataBufferHeap.h" > +#include "lldb/Core/DataExtractor.h" > +#include "lldb/Core/Log.h" > +#include "lldb/Target/Process.h" > + > +#include "AuxVector.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > +static bool > +GetMaxU64(DataExtractor &data, > + uint32_t *offset, uint64_t *value, unsigned int byte_size) > +{ > + uint32_t saved_offset = *offset; > + *value = data.GetMaxU64(offset, byte_size); > + return *offset != saved_offset; > +} > + > +static bool > +ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, > + uint32_t *offset, unsigned int byte_size) > +{ > + if (!GetMaxU64(data, offset, &entry.type, byte_size)) > + return false; > + > + if (!GetMaxU64(data, offset, &entry.value, byte_size)) > + return false; > + > + return true; > +} > + > +DataBufferSP > +AuxVector::GetAuxvData() > +{ > + > + return lldb_private::Host::GetAuxvData(m_process); > +} > + > +void > +AuxVector::ParseAuxv(DataExtractor &data) > +{ > + const unsigned int byte_size = m_process->GetAddressByteSize(); > + uint32_t offset = 0; > + > + for (;;) > + { > + Entry entry; > + > + if (!ParseAuxvEntry(data, entry, &offset, byte_size)) > + break; > + > + if (entry.type == AT_NULL) > + break; > + > + if (entry.type == AT_IGNORE) > + continue; > + > + m_auxv.push_back(entry); > + } > +} > + > +AuxVector::AuxVector(Process *process) > + : m_process(process) > +{ > + DataExtractor data; > + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); > + > + data.SetData(GetAuxvData()); > + data.SetByteOrder(m_process->GetByteOrder()); > + data.SetAddressByteSize(m_process->GetAddressByteSize()); > + > + ParseAuxv(data); > + > + if (log) > + DumpToLog(log); > +} > + > +AuxVector::iterator > +AuxVector::FindEntry(EntryType type) const > +{ > + for (iterator I = begin(); I != end(); ++I) > + { > + if (I->type == static_cast(type)) > + return I; > + } > + > + return end(); > +} > + > +void > +AuxVector::DumpToLog(LogSP log) const > +{ > + if (!log) > + return; > + > + log->PutCString("AuxVector: "); > + for (iterator I = begin(); I != end(); ++I) > + { > + log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); > + } > +} > + > +const char * > +AuxVector::GetEntryName(EntryType type) > +{ > + const char *name; > + > +#define ENTRY_NAME(_type) _type: name = #_type > + switch (type) > + { > + default: > + name = "unkown"; > + break; > + > + case ENTRY_NAME(AT_NULL); break; > + case ENTRY_NAME(AT_IGNORE); break; > + case ENTRY_NAME(AT_EXECFD); break; > + case ENTRY_NAME(AT_PHDR); break; > + case ENTRY_NAME(AT_PHENT); break; > + case ENTRY_NAME(AT_PHNUM); break; > + case ENTRY_NAME(AT_PAGESZ); break; > + case ENTRY_NAME(AT_BASE); break; > + case ENTRY_NAME(AT_FLAGS); break; > + case ENTRY_NAME(AT_ENTRY); break; > + case ENTRY_NAME(AT_NOTELF); break; > + case ENTRY_NAME(AT_UID); break; > + case ENTRY_NAME(AT_EUID); break; > + case ENTRY_NAME(AT_GID); break; > + case ENTRY_NAME(AT_EGID); break; > + case ENTRY_NAME(AT_CLKTCK); break; > + } > +#undef ENTRY_NAME > + > + return name; > +} > + > Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) > @@ -0,0 +1,330 @@ > +//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/ArchSpec.h" > +#include "lldb/Core/Error.h" > +#include "lldb/Core/Log.h" > +#include "lldb/Target/Process.h" > +#include "lldb/Target/Target.h" > + > +#include "DYLDRendezvous.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > +/// Locates the address of the rendezvous structure. Returns the address on > +/// success and LLDB_INVALID_ADDRESS on failure. > +static addr_t > +ResolveRendezvousAddress(Process *process) > +{ > + addr_t info_location; > + addr_t info_addr; > + Error error; > + size_t size; > + > + info_location = process->GetImageInfoAddress(); > + > + if (info_location == LLDB_INVALID_ADDRESS) > + return LLDB_INVALID_ADDRESS; > + > + info_addr = 0; > + size = process->DoReadMemory(info_location, &info_addr, > + process->GetAddressByteSize(), error); > + if (size != process->GetAddressByteSize() || error.Fail()) > + return LLDB_INVALID_ADDRESS; > + > + if (info_addr == 0) > + return LLDB_INVALID_ADDRESS; > + > + return info_addr; > +} > + > +DYLDRendezvous::DYLDRendezvous(Process *process) > + : m_process(process), > + m_rendezvous_addr(LLDB_INVALID_ADDRESS), > + m_current(), > + m_previous(), > + m_soentries(), > + m_added_soentries(), > + m_removed_soentries() > +{ > + // Cache a copy of the executable path > + m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX); > +} > + > +bool > +DYLDRendezvous::Resolve() > +{ > + const size_t word_size = 4; > + Rendezvous info; > + size_t address_size; > + size_t padding; > + addr_t info_addr; > + addr_t cursor; > + > + address_size = m_process->GetAddressByteSize(); > + padding = address_size - word_size; > + > + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) > + cursor = info_addr = ResolveRendezvousAddress(m_process); > + else > + cursor = info_addr = m_rendezvous_addr; > + > + if (cursor == LLDB_INVALID_ADDRESS) > + return false; > + > + if (!(cursor = ReadMemory(cursor, &info.version, word_size))) > + return false; > + > + if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) > + return false; > + > + if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) > + return false; > + > + if (!(cursor = ReadMemory(cursor, &info.state, word_size))) > + return false; > + > + if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) > + return false; > + > + // The rendezvous was successfully read. Update our internal state. > + m_rendezvous_addr = info_addr; > + m_previous = m_current; > + m_current = info; > + > + return UpdateSOEntries(); > +} > + > +bool > +DYLDRendezvous::IsValid() > +{ > + return m_rendezvous_addr != LLDB_INVALID_ADDRESS; > +} > + > +bool > +DYLDRendezvous::UpdateSOEntries() > +{ > + SOEntry entry; > + > + if (m_current.map_addr == 0) > + return false; > + > + // When the previous and current states are consistent this is the first > + // time we have been asked to update. Just take a snapshot of the currently > + // loaded modules. > + if (m_previous.state == eConsistent && m_current.state == eConsistent) > + return TakeSnapshot(m_soentries); > + > + // If we are about to add or remove a shared object clear out the current > + // state and take a snapshot of the currently loaded images. > + if (m_current.state == eAdd || m_current.state == eDelete) > + { > + assert(m_previous.state == eConsistent); > + m_soentries.clear(); > + m_added_soentries.clear(); > + m_removed_soentries.clear(); > + return TakeSnapshot(m_soentries); > + } > + assert(m_current.state == eConsistent); > + > + // Otherwise check the previous state to determine what to expect and update > + // accordingly. > + if (m_previous.state == eAdd) > + return UpdateSOEntriesForAddition(); > + else if (m_previous.state == eDelete) > + return UpdateSOEntriesForDeletion(); > + > + return false; > +} > + > +bool > +DYLDRendezvous::UpdateSOEntriesForAddition() > +{ > + SOEntry entry; > + iterator pos; > + > + assert(m_previous.state == eAdd); > + > + if (m_current.map_addr == 0) > + return false; > + > + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) > + { > + if (!ReadSOEntryFromMemory(cursor, entry)) > + return false; > + > + // Only add shared libraries and not the executable. > + // On Linux this is indicated by an empty path in the entry. > + // On FreeBSD it is the name of the executable. > + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) > + continue; > + > + pos = std::find(m_soentries.begin(), m_soentries.end(), entry); > + if (pos == m_soentries.end()) > + { > + m_soentries.push_back(entry); > + m_added_soentries.push_back(entry); > + } > + } > + > + return true; > +} > + > +bool > +DYLDRendezvous::UpdateSOEntriesForDeletion() > +{ > + SOEntryList entry_list; > + iterator pos; > + > + assert(m_previous.state == eDelete); > + > + if (!TakeSnapshot(entry_list)) > + return false; > + > + for (iterator I = begin(); I != end(); ++I) > + { > + pos = std::find(entry_list.begin(), entry_list.end(), *I); > + if (pos == entry_list.end()) > + m_removed_soentries.push_back(*I); > + } > + > + m_soentries = entry_list; > + return true; > +} > + > +bool > +DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) > +{ > + SOEntry entry; > + > + if (m_current.map_addr == 0) > + return false; > + > + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) > + { > + if (!ReadSOEntryFromMemory(cursor, entry)) > + return false; > + > + // Only add shared libraries and not the executable. > + // On Linux this is indicated by an empty path in the entry. > + // On FreeBSD it is the name of the executable. > + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) > + continue; > + > + entry_list.push_back(entry); > + } > + > + return true; > +} > + > +addr_t > +DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) > +{ > + size_t bytes_read; > + Error error; > + > + bytes_read = m_process->DoReadMemory(addr, dst, size, error); > + if (bytes_read != size || error.Fail()) > + return 0; > + > + return addr + bytes_read; > +} > + > +std::string > +DYLDRendezvous::ReadStringFromMemory(addr_t addr) > +{ > + std::string str; > + Error error; > + size_t size; > + char c; > + > + if (addr == LLDB_INVALID_ADDRESS) > + return std::string(); > + > + for (;;) { > + size = m_process->DoReadMemory(addr, &c, 1, error); > + if (size != 1 || error.Fail()) > + return std::string(); > + if (c == 0) > + break; > + else { > + str.push_back(c); > + addr++; > + } > + } > + > + return str; > +} > + > +bool > +DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) > +{ > + size_t address_size = m_process->GetAddressByteSize(); > + > + entry.clear(); > + > + if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) > + return false; > + > + if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) > + return false; > + > + if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) > + return false; > + > + if (!(addr = ReadMemory(addr, &entry.next, address_size))) > + return false; > + > + if (!(addr = ReadMemory(addr, &entry.prev, address_size))) > + return false; > + > + entry.path = ReadStringFromMemory(entry.path_addr); > + > + return true; > +} > + > +void > +DYLDRendezvous::DumpToLog(LogSP log) const > +{ > + int state = GetState(); > + > + if (!log) > + return; > + > + log->PutCString("DYLDRendezvous:"); > + log->Printf(" Address: %lx", GetRendezvousAddress()); > + log->Printf(" Version: %d", GetVersion()); > + log->Printf(" Link : %lx", GetLinkMapAddress()); > + log->Printf(" Break : %lx", GetBreakAddress()); > + log->Printf(" LDBase : %lx", GetLDBase()); > + log->Printf(" State : %s", > + (state == eConsistent) ? "consistent" : > + (state == eAdd) ? "add" : > + (state == eDelete) ? "delete" : "unknown"); > + > + iterator I = begin(); > + iterator E = end(); > + > + if (I != E) > + log->PutCString("DYLDRendezvous SOEntries:"); > + > + for (int i = 1; I != E; ++I, ++i) > + { > + log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); > + log->Printf(" Base : %lx", I->base_addr); > + log->Printf(" Path : %lx", I->path_addr); > + log->Printf(" Dyn : %lx", I->dyn_addr); > + log->Printf(" Next : %lx", I->next); > + log->Printf(" Prev : %lx", I->prev); > + } > +} > Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) > @@ -0,0 +1,97 @@ > +//===-- AuxVector.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_AuxVector_H_ > +#define liblldb_AuxVector_H_ > + > +// C Includes > +// C++ Includes > +#include > + > +// Other libraries and framework includes > +#include "lldb/lldb-forward-rtti.h" > + > +namespace lldb_private { > +class DataExtractor; > +} > + > +/// @class AuxVector > +/// @brief Represents a processes auxiliary vector. > +/// > +/// When a process is loaded on Linux a vector of values is placed onto the > +/// stack communicating operating system specific information. On construction > +/// this class locates and parses this information and provides a simple > +/// read-only interface to the entries found. > +class AuxVector { > + > +public: > + AuxVector(lldb_private::Process *process); > + > + struct Entry { > + uint64_t type; > + uint64_t value; > + > + Entry() : type(0), value(0) { } > + }; > + > + /// Constants describing the type of entry. > + enum EntryType { > + AT_NULL = 0, ///< End of auxv. > + AT_IGNORE = 1, ///< Ignore entry. > + AT_EXECFD = 2, ///< File descriptor of program. > + AT_PHDR = 3, ///< Program headers. > + AT_PHENT = 4, ///< Size of program header. > + AT_PHNUM = 5, ///< Number of program headers. > + AT_PAGESZ = 6, ///< Page size. > + AT_BASE = 7, ///< Interpreter base address. > + AT_FLAGS = 8, ///< Flags. > + AT_ENTRY = 9, ///< Program entry point. > + AT_NOTELF = 10, ///< Set if program is not an ELF. > + AT_UID = 11, ///< UID. > + AT_EUID = 12, ///< Effective UID. > + AT_GID = 13, ///< GID. > + AT_EGID = 14, ///< Effective GID. > + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). > + }; > + > +private: > + typedef std::vector EntryVector; > + > +public: > + typedef EntryVector::const_iterator iterator; > + > + iterator begin() const { return m_auxv.begin(); } > + iterator end() const { return m_auxv.end(); } > + > + iterator > + FindEntry(EntryType type) const; > + > + static const char * > + GetEntryName(const Entry &entry) { > + return GetEntryName(static_cast(entry.type)); > + } > + > + static const char * > + GetEntryName(EntryType type); > + > + void > + DumpToLog(lldb::LogSP log) const; > + > +private: > + lldb_private::Process *m_process; > + EntryVector m_auxv; > + > + lldb::DataBufferSP > + GetAuxvData(); > + > + void > + ParseAuxv(lldb_private::DataExtractor &data); > +}; > + > +#endif > Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) > @@ -0,0 +1,230 @@ > +//===-- DYLDRendezvous.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_Rendezvous_H_ > +#define liblldb_Rendezvous_H_ > + > +// C Includes > +// C++ Includes > +#include > +#include > + > +// Other libraries and framework includes > +#include "lldb/lldb-defines.h" > +#include "lldb/lldb-types.h" > + > +namespace lldb_private { > +class Process; > +} > + > +/// @class DYLDRendezvous > +/// @brief Interface to the runtime linker. > +/// > +/// A structure is present in a processes memory space which is updated by the > +/// runtime liker each time a module is loaded or unloaded. This class provides > +/// an interface to this structure and maintains a consistent snapshot of the > +/// currently loaded modules. > +class DYLDRendezvous { > + > + // This structure is used to hold the contents of the debug rendezvous > + // information (struct r_debug) as found in the inferiors memory. Note that > + // the layout of this struct is not binary compatible, it is simply large > + // enough to hold the information on both 32 and 64 bit platforms. > + struct Rendezvous { > + uint64_t version; > + lldb::addr_t map_addr; > + lldb::addr_t brk; > + uint64_t state; > + lldb::addr_t ldbase; > + > + Rendezvous() > + : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } > + }; > + > +public: > + DYLDRendezvous(lldb_private::Process *process); > + > + /// Update the internal snapshot of runtime linker rendezvous and recompute > + /// the currently loaded modules. > + /// > + /// This method should be called once one start up, then once each time the > + /// runtime linker enters the function given by GetBreakAddress(). > + /// > + /// @returns true on success and false on failure. > + /// > + /// @see GetBreakAddress(). > + bool > + Resolve(); > + > + /// @returns true if this rendezvous has been located in the inferiors > + /// address space and false otherwise. > + bool > + IsValid(); > + > + /// @returns the address of the rendezvous structure in the inferiors > + /// address space. > + lldb::addr_t > + GetRendezvousAddress() const { return m_rendezvous_addr; } > + > + /// @returns the version of the rendezvous protocol being used. > + int > + GetVersion() const { return m_current.version; } > + > + /// @returns address in the inferiors address space containing the linked > + /// list of shared object descriptors. > + lldb::addr_t > + GetLinkMapAddress() const { return m_current.map_addr; } > + > + /// A breakpoint should be set at this address and Resolve called on each > + /// hit. > + /// > + /// @returns the address of a function called by the runtime linker each > + /// time a module is loaded/unloaded, or about to be loaded/unloaded. > + /// > + /// @see Resolve() > + lldb::addr_t > + GetBreakAddress() const { return m_current.brk; } > + > + /// Returns the current state of the rendezvous structure. > + int > + GetState() const { return m_current.state; } > + > + /// @returns the base address of the runtime linker in the inferiors address > + /// space. > + lldb::addr_t > + GetLDBase() const { return m_current.ldbase; } > + > + /// @returns true if modules have been loaded into the inferior since the > + /// last call to Resolve(). > + bool > + ModulesDidLoad() const { return !m_added_soentries.empty(); } > + > + /// @returns true if modules have been unloaded from the inferior since the > + /// last call to Resolve(). > + bool > + ModulesDidUnload() const { return !m_removed_soentries.empty(); } > + > + void > + DumpToLog(lldb::LogSP log) const; > + > + /// @brief Constants describing the state of the rendezvous. > + /// > + /// @see GetState(). > + enum RendezvousState { > + eConsistent, > + eAdd, > + eDelete > + }; > + > + /// @brief Structure representing the shared objects currently loaded into > + /// the inferior process. > + /// > + /// This object is a rough analogue to the struct link_map object which > + /// actually lives in the inferiors memory. > + struct SOEntry { > + lldb::addr_t base_addr; ///< Base address of the loaded object. > + lldb::addr_t path_addr; ///< String naming the shared object. > + lldb::addr_t dyn_addr; ///< Dynamic section of shared object. > + lldb::addr_t next; ///< Address of next so_entry. > + lldb::addr_t prev; ///< Address of previous so_entry. > + std::string path; ///< File name of shared object. > + > + SOEntry() { clear(); } > + > + bool operator ==(const SOEntry &entry) { > + return this->path == entry.path; > + } > + > + void clear() { > + base_addr = 0; > + path_addr = 0; > + dyn_addr = 0; > + next = 0; > + prev = 0; > + path.clear(); > + } > + }; > + > +protected: > + typedef std::list SOEntryList; > + > +public: > + typedef SOEntryList::const_iterator iterator; > + > + /// Iterators over all currently loaded modules. > + iterator begin() const { return m_soentries.begin(); } > + iterator end() const { return m_soentries.end(); } > + > + /// Iterators over all modules loaded into the inferior since the last call > + /// to Resolve(). > + iterator loaded_begin() const { return m_added_soentries.begin(); } > + iterator loaded_end() const { return m_added_soentries.end(); } > + > + /// Iterators over all modules unloaded from the inferior since the last > + /// call to Resolve(). > + iterator unloaded_begin() const { return m_removed_soentries.begin(); } > + iterator unloaded_end() const { return m_removed_soentries.end(); } > + > +protected: > + lldb_private::Process *m_process; > + > + // Cached copy of executable pathname > + char m_exe_path[PATH_MAX]; > + > + /// Location of the r_debug structure in the inferiors address space. > + lldb::addr_t m_rendezvous_addr; > + > + /// Current and previous snapshots of the rendezvous structure. > + Rendezvous m_current; > + Rendezvous m_previous; > + > + /// List of SOEntry objects corresponding to the current link map state. > + SOEntryList m_soentries; > + > + /// List of SOEntry's added to the link map since the last call to Resolve(). > + SOEntryList m_added_soentries; > + > + /// List of SOEntry's removed from the link map since the last call to > + /// Resolve(). > + SOEntryList m_removed_soentries; > + > + /// Reads @p size bytes from the inferiors address space starting at @p > + /// addr. > + /// > + /// @returns addr + size if the read was successful and false otherwise. > + lldb::addr_t > + ReadMemory(lldb::addr_t addr, void *dst, size_t size); > + > + /// Reads a null-terminated C string from the memory location starting at @p > + /// addr. > + std::string > + ReadStringFromMemory(lldb::addr_t addr); > + > + /// Reads an SOEntry starting at @p addr. > + bool > + ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); > + > + /// Updates the current set of SOEntries, the set of added entries, and the > + /// set of removed entries. > + bool > + UpdateSOEntries(); > + > + bool > + UpdateSOEntriesForAddition(); > + > + bool > + UpdateSOEntriesForDeletion(); > + > + /// Reads the current list of shared objects according to the link map > + /// supplied by the runtime linker. > + bool > + TakeSnapshot(SOEntryList &entry_list); > +}; > + > +#endif > Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) > @@ -0,0 +1,425 @@ > +//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/PluginManager.h" > +#include "lldb/Core/Log.h" > +#include "lldb/Target/Process.h" > +#include "lldb/Target/Target.h" > +#include "lldb/Target/Thread.h" > +#include "lldb/Target/ThreadPlanRunToAddress.h" > + > +#include "AuxVector.h" > +#include "DynamicLoaderPOSIXDYLD.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > +void > +DynamicLoaderPOSIXDYLD::Initialize() > +{ > + PluginManager::RegisterPlugin(GetPluginNameStatic(), > + GetPluginDescriptionStatic(), > + CreateInstance); > +} > + > +void > +DynamicLoaderPOSIXDYLD::Terminate() > +{ > +} > + > +const char * > +DynamicLoaderPOSIXDYLD::GetPluginName() > +{ > + return "DynamicLoaderPOSIXDYLD"; > +} > + > +const char * > +DynamicLoaderPOSIXDYLD::GetShortPluginName() > +{ > + return "linux-dyld"; > +} > + > +const char * > +DynamicLoaderPOSIXDYLD::GetPluginNameStatic() > +{ > + return "dynamic-loader.linux-dyld"; > +} > + > +const char * > +DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() > +{ > + return "Dynamic loader plug-in that watches for shared library " > + "loads/unloads in POSIX processes."; > +} > + > +void > +DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) > +{ > +} > + > +uint32_t > +DynamicLoaderPOSIXDYLD::GetPluginVersion() > +{ > + return 1; > +} > + > +DynamicLoader * > +DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) > +{ > + bool create = force; > + if (!create) > + { > + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); > + if (triple_ref.getOS() == llvm::Triple::Linux || > + triple_ref.getOS() == llvm::Triple::FreeBSD) > + create = true; > + } > + > + if (create) > + return new DynamicLoaderPOSIXDYLD (process); > + return NULL; > +} > + > +DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) > + : DynamicLoader(process), > + m_rendezvous(process), > + m_load_offset(LLDB_INVALID_ADDRESS), > + m_entry_point(LLDB_INVALID_ADDRESS), > + m_auxv(NULL) > +{ > +} > + > +DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() > +{ > +} > + > +void > +DynamicLoaderPOSIXDYLD::DidAttach() > +{ > + ModuleSP executable; > + addr_t load_offset; > + > + m_auxv.reset(new AuxVector(m_process)); > + > + executable = m_process->GetTarget().GetExecutableModule(); > + load_offset = ComputeLoadOffset(); > + > + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) > + { > + ModuleList module_list; > + module_list.Append(executable); > + UpdateLoadedSections(executable, load_offset); > + LoadAllCurrentModules(); > + m_process->GetTarget().ModulesDidLoad(module_list); > + } > +} > + > +void > +DynamicLoaderPOSIXDYLD::DidLaunch() > +{ > + ModuleSP executable; > + addr_t load_offset; > + > + m_auxv.reset(new AuxVector(m_process)); > + > + executable = m_process->GetTarget().GetExecutableModule(); > + load_offset = ComputeLoadOffset(); > + > + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) > + { > + ModuleList module_list; > + module_list.Append(executable); > + UpdateLoadedSections(executable, load_offset); > + ProbeEntry(); > + m_process->GetTarget().ModulesDidLoad(module_list); > + } > +} > + > +Error > +DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) > +{ > + return Error(); > +} > + > +Log * > +DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) > +{ > + return NULL; > +} > + > +Error > +DynamicLoaderPOSIXDYLD::CanLoadImage() > +{ > + return Error(); > +} > + > +void > +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) > +{ > + ObjectFile *obj_file = module->GetObjectFile(); > + SectionList *sections = obj_file->GetSectionList(); > + SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); > + const size_t num_sections = sections->GetSize(); > + > + for (unsigned i = 0; i < num_sections; ++i) > + { > + Section *section = sections->GetSectionAtIndex(i).get(); > + lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; > + lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); > + > + // If the file address of the section is zero then this is not an > + // allocatable/loadable section (property of ELF sh_addr). Skip it. > + if (new_load_addr == base_addr) > + continue; > + > + if (old_load_addr == LLDB_INVALID_ADDRESS || > + old_load_addr != new_load_addr) > + load_list.SetSectionLoadAddress(section, new_load_addr); > + } > +} > + > +void > +DynamicLoaderPOSIXDYLD::ProbeEntry() > +{ > + Breakpoint *entry_break; > + addr_t entry; > + > + if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) > + return; > + > + entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); > + entry_break->SetCallback(EntryBreakpointHit, this, true); > +} > + > +// The runtime linker has run and initialized the rendezvous structure once the > +// process has hit its entry point. When we hit the corresponding breakpoint we > +// interrogate the rendezvous structure to get the load addresses of all > +// dependent modules for the process. Similarly, we can discover the runtime > +// linker function and setup a breakpoint to notify us of any dynamically loaded > +// modules (via dlopen). > +bool > +DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, > + StoppointCallbackContext *context, > + user_id_t break_id, > + user_id_t break_loc_id) > +{ > + DynamicLoaderPOSIXDYLD* dyld_instance; > + > + dyld_instance = static_cast(baton); > + dyld_instance->LoadAllCurrentModules(); > + dyld_instance->SetRendezvousBreakpoint(); > + return false; // Continue running. > +} > + > +void > +DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() > +{ > + Breakpoint *dyld_break; > + addr_t break_addr; > + > + break_addr = m_rendezvous.GetBreakAddress(); > + dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); > + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); > +} > + > +bool > +DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, > + StoppointCallbackContext *context, > + user_id_t break_id, > + user_id_t break_loc_id) > +{ > + DynamicLoaderPOSIXDYLD* dyld_instance; > + > + dyld_instance = static_cast(baton); > + dyld_instance->RefreshModules(); > + > + // Return true to stop the target, false to just let the target run. > + return dyld_instance->GetStopWhenImagesChange(); > +} > + > +void > +DynamicLoaderPOSIXDYLD::RefreshModules() > +{ > + if (!m_rendezvous.Resolve()) > + return; > + > + DYLDRendezvous::iterator I; > + DYLDRendezvous::iterator E; > + > + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); > + > + if (m_rendezvous.ModulesDidLoad()) > + { > + ModuleList new_modules; > + > + E = m_rendezvous.loaded_end(); > + for (I = m_rendezvous.loaded_begin(); I != E; ++I) > + { > + FileSpec file(I->path.c_str(), true); > + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); > + if (module_sp.get()) > + new_modules.Append(module_sp); > + } > + m_process->GetTarget().ModulesDidLoad(new_modules); > + } > + > + if (m_rendezvous.ModulesDidUnload()) > + { > + ModuleList old_modules; > + > + E = m_rendezvous.unloaded_end(); > + for (I = m_rendezvous.unloaded_begin(); I != E; ++I) > + { > + FileSpec file(I->path.c_str(), true); > + ModuleSP module_sp = > + loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); > + if (module_sp.get()) > + old_modules.Append(module_sp); > + } > + m_process->GetTarget().ModulesDidUnload(old_modules); > + } > +} > + > +ThreadPlanSP > +DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) > +{ > + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); > + ThreadPlanSP thread_plan_sp; > + > + StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); > + const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); > + Symbol *sym = context.symbol; > + > + if (sym == NULL || !sym->IsTrampoline()) > + return thread_plan_sp; > + > + const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); > + if (!sym_name) > + return thread_plan_sp; > + > + SymbolContextList target_symbols; > + Target &target = thread.GetProcess().GetTarget(); > + ModuleList &images = target.GetImages(); > + > + images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); > + size_t num_targets = target_symbols.GetSize(); > + if (!num_targets) > + return thread_plan_sp; > + > + typedef std::vector AddressVector; > + AddressVector addrs; > + for (size_t i = 0; i < num_targets; ++i) > + { > + SymbolContext context; > + AddressRange range; > + if (target_symbols.GetContextAtIndex(i, context)) > + { > + context.GetAddressRange(eSymbolContextEverything, 0, false, range); > + lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); > + if (addr != LLDB_INVALID_ADDRESS) > + addrs.push_back(addr); > + } > + } > + > + if (addrs.size() > 0) > + { > + AddressVector::iterator start = addrs.begin(); > + AddressVector::iterator end = addrs.end(); > + > + std::sort(start, end); > + addrs.erase(std::unique(start, end), end); > + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); > + } > + > + return thread_plan_sp; > +} > + > +void > +DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() > +{ > + DYLDRendezvous::iterator I; > + DYLDRendezvous::iterator E; > + ModuleList module_list; > + > + if (!m_rendezvous.Resolve()) > + return; > + > + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) > + { > + FileSpec file(I->path.c_str(), false); > + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); > + if (module_sp.get()) > + module_list.Append(module_sp); > + } > + > + m_process->GetTarget().ModulesDidLoad(module_list); > +} > + > +ModuleSP > +DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) > +{ > + Target &target = m_process->GetTarget(); > + ModuleList &modules = target.GetImages(); > + ModuleSP module_sp; > + > + if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) > + { > + UpdateLoadedSections(module_sp, base_addr); > + } > + else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) > + { > + UpdateLoadedSections(module_sp, base_addr); > + modules.Append(module_sp); > + } > + > + return module_sp; > +} > + > +addr_t > +DynamicLoaderPOSIXDYLD::ComputeLoadOffset() > +{ > + addr_t virt_entry; > + > + if (m_load_offset != LLDB_INVALID_ADDRESS) > + return m_load_offset; > + > + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) > + return LLDB_INVALID_ADDRESS; > + > + ModuleSP module = m_process->GetTarget().GetExecutableModule(); > + ObjectFile *exe = module->GetObjectFile(); > + Address file_entry = exe->GetEntryPointAddress(); > + > + if (!file_entry.IsValid()) > + return LLDB_INVALID_ADDRESS; > + > + m_load_offset = virt_entry - file_entry.GetFileAddress(); > + return m_load_offset; > +} > + > +addr_t > +DynamicLoaderPOSIXDYLD::GetEntryPoint() > +{ > + if (m_entry_point != LLDB_INVALID_ADDRESS) > + return m_entry_point; > + > + if (m_auxv.get() == NULL) > + return LLDB_INVALID_ADDRESS; > + > + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); > + > + if (I == m_auxv->end()) > + return LLDB_INVALID_ADDRESS; > + > + m_entry_point = static_cast(I->value); > + return m_entry_point; > +} > Index: source/Plugins/DynamicLoader/POSIX-DYLD/Makefile > =================================================================== > --- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) > +++ source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) > @@ -0,0 +1,14 @@ > +##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===## > +# > +# The LLVM Compiler Infrastructure > +# > +# This file is distributed under the University of Illinois Open Source > +# License. See LICENSE.TXT for details. > +# > +##===----------------------------------------------------------------------===## > + > +LLDB_LEVEL := ../../../.. > +LIBRARYNAME := lldbPluginDynamicLoaderPOSIX > +BUILD_ARCHIVE = 1 > + > +include $(LLDB_LEVEL)/Makefile > Index: source/Plugins/Makefile > =================================================================== > --- source/Plugins/Makefile (revision 147560) > +++ source/Plugins/Makefile (working copy) > @@ -30,7 +30,11 @@ > endif > > ifeq ($(HOST_OS),Linux) > -DIRS += Process/Linux DynamicLoader/Linux-DYLD > +DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD > endif > > +ifeq ($(HOST_OS),FreeBSD) > +DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD > +endif > + > include $(LLDB_LEVEL)/Makefile > Index: source/Plugins/Process/Linux/ProcessLinux.cpp > =================================================================== > --- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 147560) > +++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy) > @@ -20,10 +20,10 @@ > #include "lldb/Target/Target.h" > > #include "ProcessLinux.h" > -#include "ProcessLinuxLog.h" > +#include "ProcessPOSIXLog.h" > #include "Plugins/Process/Utility/InferiorCallPOSIX.h" > #include "ProcessMonitor.h" > -#include "LinuxThread.h" > +#include "POSIXThread.h" > > using namespace lldb; > using namespace lldb_private; > @@ -50,42 +50,21 @@ > CreateInstance); > > Log::Callbacks log_callbacks = { > - ProcessLinuxLog::DisableLog, > - ProcessLinuxLog::EnableLog, > - ProcessLinuxLog::ListLogCategories > + ProcessPOSIXLog::DisableLog, > + ProcessPOSIXLog::EnableLog, > + ProcessPOSIXLog::ListLogCategories > }; > > Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); > + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); > } > } > > -void > -ProcessLinux::Terminate() > -{ > -} > - > -const char * > -ProcessLinux::GetPluginNameStatic() > -{ > - return "plugin.process.linux"; > -} > - > -const char * > -ProcessLinux::GetPluginDescriptionStatic() > -{ > - return "Process plugin for Linux"; > -} > - > - > //------------------------------------------------------------------------------ > // Constructors and destructors. > > ProcessLinux::ProcessLinux(Target& target, Listener &listener) > - : Process(target, listener), > - m_monitor(NULL), > - m_module(NULL), > - m_in_limbo(false), > - m_exit_now(false) > + : ProcessPOSIX(target, listener) > { > #if 0 > // FIXME: Putting this code in the ctor and saving the byte order in a > @@ -98,409 +77,28 @@ > #endif > } > > -ProcessLinux::~ProcessLinux() > -{ > - delete m_monitor; > -} > - > -//------------------------------------------------------------------------------ > -// Process protocol. > - > -bool > -ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) > -{ > - // For now we are just making sure the file exists for a given module > - ModuleSP exe_module_sp(target.GetExecutableModule()); > - if (exe_module_sp.get()) > - return exe_module_sp->GetFileSpec().Exists(); > - return false; > -} > - > -Error > -ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid) > -{ > - Error error; > - assert(m_monitor == NULL); > - > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID()); > - > - m_monitor = new ProcessMonitor(this, pid, error); > - > - if (!error.Success()) > - return error; > - > - SetID(pid); > - return error; > -} > - > -Error > -ProcessLinux::WillLaunch(Module* module) > -{ > - Error error; > - return error; > -} > - > -Error > -ProcessLinux::DoLaunch (Module *module, > - const ProcessLaunchInfo &launch_info) > -{ > - Error error; > - assert(m_monitor == NULL); > - > - SetPrivateState(eStateLaunching); > - > - const char *stdin_path = NULL; > - const char *stdout_path = NULL; > - const char *stderr_path = NULL; > - const char *working_dir = launch_info.GetWorkingDirectory(); > - > - const ProcessLaunchInfo::FileAction *file_action; > - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); > - if (file_action) > - { > - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) > - stdin_path = file_action->GetPath(); > - } > - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); > - if (file_action) > - { > - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) > - stdout_path = file_action->GetPath(); > - } > - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); > - if (file_action) > - { > - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) > - stderr_path = file_action->GetPath(); > - } > - > - m_monitor = new ProcessMonitor (this, > - module, > - launch_info.GetArguments().GetConstArgumentVector(), > - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), > - stdin_path, > - stdout_path, > - stderr_path, > - error); > - > - m_module = module; > - > - if (!error.Success()) > - return error; > - > - SetID(m_monitor->GetPID()); > - return error; > -} > - > void > -ProcessLinux::DidLaunch() > +ProcessLinux::Terminate() > { > } > - > -Error > -ProcessLinux::DoResume() > +const char * > +ProcessLinux::GetPluginNameStatic() > { > - StateType state = GetPrivateState(); > - > - assert(state == eStateStopped || state == eStateCrashed); > - > - // We are about to resume a thread that will cause the process to exit so > - // set our exit status now. Do not change our state if the inferior > - // crashed. > - if (state == eStateStopped) > - { > - if (m_in_limbo) > - SetExitStatus(m_exit_status, NULL); > - else > - SetPrivateState(eStateRunning); > - } > - > - bool did_resume = false; > - uint32_t thread_count = m_thread_list.GetSize(false); > - for (uint32_t i = 0; i < thread_count; ++i) > - { > - LinuxThread *thread = static_cast( > - m_thread_list.GetThreadAtIndex(i, false).get()); > - did_resume = thread->Resume() || did_resume; > - } > - assert(did_resume && "Process resume failed!"); > - > - return Error(); > + return "linux"; > } > > -addr_t > -ProcessLinux::GetImageInfoAddress() > +const char * > +ProcessLinux::GetPluginDescriptionStatic() > { > - Target *target = &GetTarget(); > - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); > - Address addr = obj_file->GetImageInfoAddress(); > - > - if (addr.IsValid()) > - return addr.GetLoadAddress(target); > - else > - return LLDB_INVALID_ADDRESS; > + return "Process plugin for Linux"; > } > > -Error > -ProcessLinux::DoHalt(bool &caused_stop) > -{ > - Error error; > > - if (IsStopped()) > - { > - caused_stop = false; > - } > - else if (kill(GetID(), SIGSTOP)) > - { > - caused_stop = false; > - error.SetErrorToErrno(); > - } > - else > - { > - caused_stop = true; > - } > - > - return error; > -} > - > -Error > -ProcessLinux::DoDetach() > -{ > - Error error; > - > - error = m_monitor->Detach(); > - if (error.Success()) > - SetPrivateState(eStateDetached); > - > - return error; > -} > - > -Error > -ProcessLinux::DoSignal(int signal) > -{ > - Error error; > - > - if (kill(GetID(), signal)) > - error.SetErrorToErrno(); > - > - return error; > -} > - > -Error > -ProcessLinux::DoDestroy() > -{ > - Error error; > - > - if (!HasExited()) > - { > - // Drive the exit event to completion (do not keep the inferior in > - // limbo). > - m_exit_now = true; > - > - if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) > - { > - error.SetErrorToErrno(); > - return error; > - } > - > - SetPrivateState(eStateExited); > - } > - > - return error; > -} > - > -void > -ProcessLinux::SendMessage(const ProcessMessage &message) > -{ > - Mutex::Locker lock(m_message_mutex); > - > - switch (message.GetKind()) > - { > - default: > - assert(false && "Unexpected process message!"); > - break; > - > - case ProcessMessage::eInvalidMessage: > - return; > - > - case ProcessMessage::eLimboMessage: > - m_in_limbo = true; > - m_exit_status = message.GetExitStatus(); > - if (m_exit_now) > - { > - SetPrivateState(eStateExited); > - m_monitor->Detach(); > - } > - else > - SetPrivateState(eStateStopped); > - break; > - > - case ProcessMessage::eExitMessage: > - m_exit_status = message.GetExitStatus(); > - SetExitStatus(m_exit_status, NULL); > - break; > - > - case ProcessMessage::eTraceMessage: > - case ProcessMessage::eBreakpointMessage: > - SetPrivateState(eStateStopped); > - break; > - > - case ProcessMessage::eSignalMessage: > - case ProcessMessage::eSignalDeliveredMessage: > - SetPrivateState(eStateStopped); > - break; > - > - case ProcessMessage::eCrashMessage: > - SetPrivateState(eStateCrashed); > - break; > - } > - > - m_message_queue.push(message); > -} > - > -void > -ProcessLinux::RefreshStateAfterStop() > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("ProcessLinux::%s()", __FUNCTION__); > - > - Mutex::Locker lock(m_message_mutex); > - if (m_message_queue.empty()) > - return; > - > - ProcessMessage &message = m_message_queue.front(); > - > - // Resolve the thread this message corresponds to and pass it along. > - // FIXME: we're really dealing with the pid here. This should get > - // fixed when this code is fixed to handle multiple threads. > - lldb::tid_t tid = message.GetTID(); > - if (log) > - log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid); > - LinuxThread *thread = static_cast( > - GetThreadList().FindThreadByID(tid, false).get()); > - > - assert(thread); > - thread->Notify(message); > - > - m_message_queue.pop(); > -} > - > -bool > -ProcessLinux::IsAlive() > -{ > - StateType state = GetPrivateState(); > - return state != eStateDetached && state != eStateExited && state != eStateInvalid; > -} > - > -size_t > -ProcessLinux::DoReadMemory(addr_t vm_addr, > - void *buf, size_t size, Error &error) > -{ > - assert(m_monitor); > - return m_monitor->ReadMemory(vm_addr, buf, size, error); > -} > - > -size_t > -ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, > - Error &error) > -{ > - assert(m_monitor); > - return m_monitor->WriteMemory(vm_addr, buf, size, error); > -} > - > -addr_t > -ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions, > - Error &error) > -{ > - addr_t allocated_addr = LLDB_INVALID_ADDRESS; > - > - unsigned prot = 0; > - if (permissions & lldb::ePermissionsReadable) > - prot |= eMmapProtRead; > - if (permissions & lldb::ePermissionsWritable) > - prot |= eMmapProtWrite; > - if (permissions & lldb::ePermissionsExecutable) > - prot |= eMmapProtExec; > - > - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, > - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { > - m_addr_to_mmap_size[allocated_addr] = size; > - error.Clear(); > - } else { > - allocated_addr = LLDB_INVALID_ADDRESS; > - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); > - } > - > - return allocated_addr; > -} > - > -Error > -ProcessLinux::DoDeallocateMemory(lldb::addr_t addr) > -{ > - Error error; > - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); > - if (pos != m_addr_to_mmap_size.end() && > - InferiorCallMunmap(this, addr, pos->second)) > - m_addr_to_mmap_size.erase (pos); > - else > - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); > - > - return error; > -} > - > -size_t > -ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) > -{ > - static const uint8_t g_i386_opcode[] = { 0xCC }; > - > - ArchSpec arch = GetTarget().GetArchitecture(); > - const uint8_t *opcode = NULL; > - size_t opcode_size = 0; > - > - switch (arch.GetCore()) > - { > - default: > - assert(false && "CPU type not supported!"); > - break; > - > - case ArchSpec::eCore_x86_32_i386: > - case ArchSpec::eCore_x86_64_x86_64: > - opcode = g_i386_opcode; > - opcode_size = sizeof(g_i386_opcode); > - break; > - } > - > - bp_site->SetTrapOpcode(opcode, opcode_size); > - return opcode_size; > -} > - > -Error > -ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site) > -{ > - return EnableSoftwareBreakpoint(bp_site); > -} > - > -Error > -ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site) > -{ > - return DisableSoftwareBreakpoint(bp_site); > -} > - > uint32_t > -ProcessLinux::UpdateThreadListIfNeeded() > -{ > - // Do not allow recursive updates. > - return m_thread_list.GetSize(false); > -} > - > -uint32_t > ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) > { > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID()); > > // Update the process thread list with this new thread. > @@ -508,62 +106,16 @@ > assert(m_monitor); > ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); > if (!thread_sp) > - thread_sp.reset(new LinuxThread(*this, GetID())); > + thread_sp.reset(new POSIXThread(*this, GetID())); > > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID()); > new_thread_list.AddThread(thread_sp); > > return new_thread_list.GetSize(false); > } > > -ByteOrder > -ProcessLinux::GetByteOrder() const > -{ > - // FIXME: We should be able to extract this value directly. See comment in > - // ProcessLinux(). > - return m_byte_order; > -} > > -size_t > -ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error) > -{ > - ssize_t status; > - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) > - { > - error.SetErrorToErrno(); > - return 0; > - } > - return status; > -} > - > -size_t > -ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error) > -{ > - ssize_t bytes_read; > - > - // The terminal file descriptor is always in non-block mode. > - if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) > - { > - if (errno != EAGAIN) > - error.SetErrorToErrno(); > - return 0; > - } > - return bytes_read; > -} > - > -size_t > -ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error) > -{ > - return GetSTDOUT(buf, len, error); > -} > - > -UnixSignals & > -ProcessLinux::GetUnixSignals() > -{ > - return m_linux_signals; > -} > - > //------------------------------------------------------------------------------ > // ProcessInterface protocol. > > @@ -601,39 +153,3 @@ > { > return NULL; > } > - > -//------------------------------------------------------------------------------ > -// Utility functions. > - > -bool > -ProcessLinux::HasExited() > -{ > - switch (GetPrivateState()) > - { > - default: > - break; > - > - case eStateDetached: > - case eStateExited: > - return true; > - } > - > - return false; > -} > - > -bool > -ProcessLinux::IsStopped() > -{ > - switch (GetPrivateState()) > - { > - default: > - break; > - > - case eStateStopped: > - case eStateCrashed: > - case eStateSuspended: > - return true; > - } > - > - return false; > -} > Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp > =================================================================== > --- source/Plugins/Process/Linux/ProcessLinuxLog.cpp (revision 147560) > +++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp (working copy) > @@ -1,193 +0,0 @@ > -//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -#include "ProcessLinuxLog.h" > - > -#include "lldb/Interpreter/Args.h" > -#include "lldb/Core/StreamFile.h" > - > -#include "ProcessLinux.h" > - > -using namespace lldb; > -using namespace lldb_private; > - > - > -// We want to avoid global constructors where code needs to be run so here we > -// control access to our static g_log_sp by hiding it in a singleton function > -// that will construct the static g_lob_sp the first time this function is > -// called. > -static LogSP & > -GetLog () > -{ > - static LogSP g_log_sp; > - return g_log_sp; > -} > - > -LogSP > -ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask) > -{ > - LogSP log(GetLog ()); > - if (log && mask) > - { > - uint32_t log_mask = log->GetMask().Get(); > - if ((log_mask & mask) != mask) > - return LogSP(); > - } > - return log; > -} > - > -void > -ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm) > -{ > - LogSP log (GetLog ()); > - if (log) > - { > - uint32_t flag_bits = 0; > - > - const size_t argc = args.GetArgumentCount (); > - if (argc > 0) > - { > - flag_bits = log->GetMask().Get(); > - for (size_t i = 0; i < argc; ++i) > - { > - const char *arg = args.GetArgumentAtIndex (i); > - > - > - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL; > - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC; > - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS; > - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM; > - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT; > - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS; > - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY; > - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT; > - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG; > - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS; > - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE; > - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS; > - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP; > - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD; > - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE; > - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS; > - else > - { > - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); > - ListLogCategories (feedback_strm); > - } > - > - } > - } > - > - if (flag_bits == 0) > - GetLog ().reset(); > - else > - log->GetMask().Reset (flag_bits); > - } > - > - return; > -} > - > -LogSP > -ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) > -{ > - // Try see if there already is a log - that way we can reuse its settings. > - // We could reuse the log in toto, but we don't know that the stream is the same. > - uint32_t flag_bits = 0; > - LogSP log(GetLog ()); > - if (log) > - flag_bits = log->GetMask().Get(); > - > - // Now make a new log with this stream if one was provided > - if (log_stream_sp) > - { > - log = make_shared(log_stream_sp); > - GetLog () = log; > - } > - > - if (log) > - { > - bool got_unknown_category = false; > - const size_t argc = args.GetArgumentCount(); > - for (size_t i=0; i - { > - const char *arg = args.GetArgumentAtIndex(i); > - > - if (::strcasecmp (arg, "all") == 0 ) flag_bits |= LINUX_LOG_ALL; > - else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= LINUX_LOG_ASYNC; > - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= LINUX_LOG_BREAKPOINTS; > - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= LINUX_LOG_COMM; > - else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= LINUX_LOG_DEFAULT; > - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= LINUX_LOG_PACKETS; > - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= LINUX_LOG_MEMORY; > - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_SHORT; > - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_LONG; > - else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= LINUX_LOG_PROCESS; > - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= LINUX_LOG_PTRACE; > - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= LINUX_LOG_REGISTERS; > - else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= LINUX_LOG_STEP; > - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= LINUX_LOG_THREAD; > - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= LINUX_LOG_VERBOSE; > - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= LINUX_LOG_WATCHPOINTS; > - else > - { > - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); > - if (got_unknown_category == false) > - { > - got_unknown_category = true; > - ListLogCategories (feedback_strm); > - } > - } > - } > - if (flag_bits == 0) > - flag_bits = LINUX_LOG_DEFAULT; > - log->GetMask().Reset(flag_bits); > - log->GetOptions().Reset(log_options); > - } > - return log; > -} > - > -void > -ProcessLinuxLog::ListLogCategories (Stream *strm) > -{ > - strm->Printf ("Logging categories for '%s':\n" > - " all - turn on all available logging categories\n" > - " async - log asynchronous activity\n" > - " break - log breakpoints\n" > - " communication - log communication activity\n" > - " default - enable the default set of logging categories for liblldb\n" > - " packets - log gdb remote packets\n" > - " memory - log memory reads and writes\n" > - " data-short - log memory bytes for memory reads and writes for short transactions only\n" > - " data-long - log memory bytes for memory reads and writes for all transactions\n" > - " process - log process events and activities\n" > -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION > - " ptrace - log all calls to ptrace\n" > -#endif > - " registers - log register read/writes\n" > - " thread - log thread events and activities\n" > - " step - log step related activities\n" > - " verbose - enable verbose logging\n" > - " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic()); > -} > - > - > -void > -ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...) > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask)); > - if (log) > - { > - va_list args; > - va_start (args, format); > - log->VAPrintf (format, args); > - va_end (args); > - } > -} > - > -int ProcessLinuxLog::m_nestinglevel; > Index: source/Plugins/Process/Linux/ProcessLinux.h > =================================================================== > --- source/Plugins/Process/Linux/ProcessLinux.h (revision 147560) > +++ source/Plugins/Process/Linux/ProcessLinux.h (working copy) > @@ -19,11 +19,12 @@ > #include "lldb/Target/Process.h" > #include "LinuxSignals.h" > #include "ProcessMessage.h" > +#include "ProcessPOSIX.h" > > class ProcessMonitor; > > class ProcessLinux : > - public lldb_private::Process > + public ProcessPOSIX > { > public: > //------------------------------------------------------------------ > @@ -51,97 +52,8 @@ > ProcessLinux(lldb_private::Target& target, > lldb_private::Listener &listener); > > - virtual > - ~ProcessLinux(); > - > - //------------------------------------------------------------------ > - // Process protocol. > - //------------------------------------------------------------------ > - virtual bool > - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); > - > - virtual lldb_private::Error > - WillLaunch(lldb_private::Module *module); > - > - virtual lldb_private::Error > - DoAttachToProcessWithID(lldb::pid_t pid); > - > - virtual lldb_private::Error > - DoLaunch (lldb_private::Module *exe_module, > - const lldb_private::ProcessLaunchInfo &launch_info); > - > - virtual void > - DidLaunch(); > - > - virtual lldb_private::Error > - DoResume(); > - > - virtual lldb_private::Error > - DoHalt(bool &caused_stop); > - > - virtual lldb_private::Error > - DoDetach(); > - > - virtual lldb_private::Error > - DoSignal(int signal); > - > - virtual lldb_private::Error > - DoDestroy(); > - > - virtual void > - RefreshStateAfterStop(); > - > - virtual bool > - IsAlive(); > - > - virtual size_t > - DoReadMemory(lldb::addr_t vm_addr, > - void *buf, > - size_t size, > - lldb_private::Error &error); > - > - virtual size_t > - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, > - lldb_private::Error &error); > - > - virtual lldb::addr_t > - DoAllocateMemory(size_t size, uint32_t permissions, > - lldb_private::Error &error); > - > - virtual lldb_private::Error > - DoDeallocateMemory(lldb::addr_t ptr); > - > - virtual size_t > - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); > - > - virtual lldb_private::Error > - EnableBreakpoint(lldb_private::BreakpointSite *bp_site); > - > - virtual lldb_private::Error > - DisableBreakpoint(lldb_private::BreakpointSite *bp_site); > - > virtual uint32_t > - UpdateThreadListIfNeeded(); > - > - uint32_t > - UpdateThreadList(lldb_private::ThreadList &old_thread_list, > - lldb_private::ThreadList &new_thread_list); > - > - virtual lldb::ByteOrder > - GetByteOrder() const; > - > - virtual lldb::addr_t > - GetImageInfoAddress(); > - > - virtual size_t > - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); > - > - virtual size_t > - GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); > - > - virtual size_t > - GetSTDERR(char *buf, size_t len, lldb_private::Error &error); > - > + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); > //------------------------------------------------------------------ > // PluginInterface protocol > //------------------------------------------------------------------ > @@ -165,59 +77,11 @@ > EnablePluginLogging(lldb_private::Stream *strm, > lldb_private::Args &command); > > - //-------------------------------------------------------------------------- > - // ProcessLinux internal API. > - > - /// Registers the given message with this process. > - void SendMessage(const ProcessMessage &message); > - > - ProcessMonitor & > - GetMonitor() { assert(m_monitor); return *m_monitor; } > - > - lldb_private::UnixSignals & > - GetUnixSignals(); > - > private: > - /// Target byte order. > - lldb::ByteOrder m_byte_order; > > - /// Process monitor; > - ProcessMonitor *m_monitor; > - > - /// The module we are executing. > - lldb_private::Module *m_module; > - > - /// Message queue notifying this instance of inferior process state changes. > - lldb_private::Mutex m_message_mutex; > - std::queue m_message_queue; > - > - /// True when the process has entered a state of "limbo". > - /// > - /// This flag qualifies eStateStopped. It lets us know that when we > - /// continue from this state the process will exit. Also, when true, > - /// Process::m_exit_status is set. > - bool m_in_limbo; > - > - /// Drive any exit events to completion. > - bool m_exit_now; > - > /// Linux-specific signal set. > LinuxSignals m_linux_signals; > > - /// Updates the loaded sections provided by the executable. > - /// > - /// FIXME: It would probably be better to delegate this task to the > - /// DynamicLoader plugin, when we have one. > - void UpdateLoadedSections(); > - > - /// Returns true if the process has exited. > - bool HasExited(); > - > - /// Returns true if the process is stopped. > - bool IsStopped(); > - > - typedef std::map MMapMap; > - MMapMap m_addr_to_mmap_size; > }; > > #endif // liblldb_MacOSXProcess_H_ > Index: source/Plugins/Process/Linux/ProcessLinuxLog.h > =================================================================== > --- source/Plugins/Process/Linux/ProcessLinuxLog.h (revision 147560) > +++ source/Plugins/Process/Linux/ProcessLinuxLog.h (working copy) > @@ -1,98 +0,0 @@ > -//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ > -#define liblldb_ProcessLinuxLog_h_ > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > - > -// Project includes > -#include "lldb/Core/Log.h" > - > -#define LINUX_LOG_VERBOSE (1u << 0) > -#define LINUX_LOG_PROCESS (1u << 1) > -#define LINUX_LOG_THREAD (1u << 2) > -#define LINUX_LOG_PACKETS (1u << 3) > -#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls > -#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes > -#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes > -#define LINUX_LOG_BREAKPOINTS (1u << 7) > -#define LINUX_LOG_WATCHPOINTS (1u << 8) > -#define LINUX_LOG_STEP (1u << 9) > -#define LINUX_LOG_COMM (1u << 10) > -#define LINUX_LOG_ASYNC (1u << 11) > -#define LINUX_LOG_PTRACE (1u << 12) > -#define LINUX_LOG_REGISTERS (1u << 13) > -#define LINUX_LOG_ALL (UINT32_MAX) > -#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS > - > -// The size which determines "short memory reads/writes". > -#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) > - > -class ProcessLinuxLog > -{ > - static int m_nestinglevel; > - > -public: > - static lldb::LogSP > - GetLogIfAllCategoriesSet(uint32_t mask = 0); > - > - static void > - DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); > - > - static lldb::LogSP > - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, > - lldb_private::Args &args, lldb_private::Stream *feedback_strm); > - > - static void > - ListLogCategories (lldb_private::Stream *strm); > - > - static void > - LogIf (uint32_t mask, const char *format, ...); > - > - // The following functions can be used to enable the client to limit > - // logging to only the top level function calls. This is useful for > - // recursive functions. FIXME: not thread safe! > - // Example: > - // void NestingFunc() { > - // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL)); > - // if (log) > - // { > - // ProcessLinuxLog::IncNestLevel(); > - // if (ProcessLinuxLog::AtTopNestLevel()) > - // log->Print(msg); > - // } > - // NestingFunc(); > - // if (log) > - // ProcessLinuxLog::DecNestLevel(); > - // } > - > - static bool > - AtTopNestLevel() > - { > - return m_nestinglevel == 1; > - } > - > - static void > - IncNestLevel() > - { > - ++m_nestinglevel; > - } > - > - static void > - DecNestLevel() > - { > - --m_nestinglevel; > - assert(m_nestinglevel >= 0); > - } > -}; > - > -#endif // liblldb_ProcessLinuxLog_h_ > Index: source/Plugins/Process/Linux/RegisterContextLinux.h > =================================================================== > --- source/Plugins/Process/Linux/RegisterContextLinux.h (revision 147560) > +++ source/Plugins/Process/Linux/RegisterContextLinux.h (working copy) > @@ -1,40 +0,0 @@ > -//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -#ifndef liblldb_RegisterContextLinux_H_ > -#define liblldb_RegisterContextLinux_H_ > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -#include "lldb/Target/RegisterContext.h" > - > -//------------------------------------------------------------------------------ > -/// @class RegisterContextLinux > -/// > -/// @brief Extends RegisterClass with a few virtual operations useful on Linux. > -class RegisterContextLinux > - : public lldb_private::RegisterContext > -{ > -public: > - RegisterContextLinux(lldb_private::Thread &thread, > - uint32_t concrete_frame_idx) > - : RegisterContext(thread, concrete_frame_idx) { } > - > - /// Updates the register state of the associated thread after hitting a > - /// breakpoint (if that make sense for the architecture). Default > - /// implementation simply returns true for architectures which do not > - /// require any update. > - /// > - /// @return > - /// True if the operation succeeded and false otherwise. > - virtual bool UpdateAfterBreakpoint() { return true; } > -}; > - > -#endif // #ifndef liblldb_RegisterContextLinux_H_ > Index: source/Plugins/Process/Linux/LinuxStopInfo.cpp > =================================================================== > --- source/Plugins/Process/Linux/LinuxStopInfo.cpp (revision 147560) > +++ source/Plugins/Process/Linux/LinuxStopInfo.cpp (working copy) > @@ -1,60 +0,0 @@ > -//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -#include "LinuxStopInfo.h" > - > -using namespace lldb; > -using namespace lldb_private; > - > - > -//===----------------------------------------------------------------------===// > -// LinuxLimboStopInfo > - > -LinuxLimboStopInfo::~LinuxLimboStopInfo() { } > - > -lldb::StopReason > -LinuxLimboStopInfo::GetStopReason() const > -{ > - return lldb::eStopReasonTrace; > -} > - > -const char * > -LinuxLimboStopInfo::GetDescription() > -{ > - return "thread exiting"; > -} > - > -bool > -LinuxLimboStopInfo::ShouldStop(Event *event_ptr) > -{ > - return true; > -} > - > -bool > -LinuxLimboStopInfo::ShouldNotify(Event *event_ptr) > -{ > - return true; > -} > - > -//===----------------------------------------------------------------------===// > -// LinuxCrashStopInfo > - > -LinuxCrashStopInfo::~LinuxCrashStopInfo() { } > - > -lldb::StopReason > -LinuxCrashStopInfo::GetStopReason() const > -{ > - return lldb::eStopReasonException; > -} > - > -const char * > -LinuxCrashStopInfo::GetDescription() > -{ > - return ProcessMessage::GetCrashReasonString(m_crash_reason); > -} > Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp > =================================================================== > --- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (revision 147560) > +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (working copy) > @@ -1,650 +0,0 @@ > -//===-- RegisterContextLinux_i386.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/Core/DataExtractor.h" > -#include "lldb/Target/Thread.h" > -#include "lldb/Host/Endian.h" > - > -#include "ProcessLinux.h" > -#include "ProcessLinuxLog.h" > -#include "ProcessMonitor.h" > -#include "RegisterContextLinux_i386.h" > - > -using namespace lldb_private; > -using namespace lldb; > - > -enum > -{ > - k_first_gpr, > - gpr_eax = k_first_gpr, > - gpr_ebx, > - gpr_ecx, > - gpr_edx, > - gpr_edi, > - gpr_esi, > - gpr_ebp, > - gpr_esp, > - gpr_ss, > - gpr_eflags, > - gpr_eip, > - gpr_cs, > - gpr_ds, > - gpr_es, > - gpr_fs, > - gpr_gs, > - k_last_gpr = gpr_gs, > - > - k_first_fpr, > - fpu_fcw = k_first_fpr, > - fpu_fsw, > - fpu_ftw, > - fpu_fop, > - fpu_ip, > - fpu_cs, > - fpu_foo, > - fpu_fos, > - fpu_mxcsr, > - fpu_stmm0, > - fpu_stmm1, > - fpu_stmm2, > - fpu_stmm3, > - fpu_stmm4, > - fpu_stmm5, > - fpu_stmm6, > - fpu_stmm7, > - fpu_xmm0, > - fpu_xmm1, > - fpu_xmm2, > - fpu_xmm3, > - fpu_xmm4, > - fpu_xmm5, > - fpu_xmm6, > - fpu_xmm7, > - k_last_fpr = fpu_xmm7, > - > - k_num_registers, > - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, > - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 > -}; > - > -// Number of register sets provided by this context. > -enum > -{ > - k_num_register_sets = 2 > -}; > - > -enum > -{ > - gcc_eax = 0, > - gcc_ecx, > - gcc_edx, > - gcc_ebx, > - gcc_ebp, > - gcc_esp, > - gcc_esi, > - gcc_edi, > - gcc_eip, > - gcc_eflags > -}; > - > -enum > -{ > - dwarf_eax = 0, > - dwarf_ecx, > - dwarf_edx, > - dwarf_ebx, > - dwarf_esp, > - dwarf_ebp, > - dwarf_esi, > - dwarf_edi, > - dwarf_eip, > - dwarf_eflags, > - dwarf_stmm0 = 11, > - dwarf_stmm1, > - dwarf_stmm2, > - dwarf_stmm3, > - dwarf_stmm4, > - dwarf_stmm5, > - dwarf_stmm6, > - dwarf_stmm7, > - dwarf_xmm0 = 21, > - dwarf_xmm1, > - dwarf_xmm2, > - dwarf_xmm3, > - dwarf_xmm4, > - dwarf_xmm5, > - dwarf_xmm6, > - dwarf_xmm7 > -}; > - > -enum > -{ > - gdb_eax = 0, > - gdb_ecx = 1, > - gdb_edx = 2, > - gdb_ebx = 3, > - gdb_esp = 4, > - gdb_ebp = 5, > - gdb_esi = 6, > - gdb_edi = 7, > - gdb_eip = 8, > - gdb_eflags = 9, > - gdb_cs = 10, > - gdb_ss = 11, > - gdb_ds = 12, > - gdb_es = 13, > - gdb_fs = 14, > - gdb_gs = 15, > - gdb_stmm0 = 16, > - gdb_stmm1 = 17, > - gdb_stmm2 = 18, > - gdb_stmm3 = 19, > - gdb_stmm4 = 20, > - gdb_stmm5 = 21, > - gdb_stmm6 = 22, > - gdb_stmm7 = 23, > - gdb_fcw = 24, > - gdb_fsw = 25, > - gdb_ftw = 26, > - gdb_fpu_cs = 27, > - gdb_ip = 28, > - gdb_fpu_ds = 29, > - gdb_dp = 30, > - gdb_fop = 31, > - gdb_xmm0 = 32, > - gdb_xmm1 = 33, > - gdb_xmm2 = 34, > - gdb_xmm3 = 35, > - gdb_xmm4 = 36, > - gdb_xmm5 = 37, > - gdb_xmm6 = 38, > - gdb_xmm7 = 39, > - gdb_mxcsr = 40, > - gdb_mm0 = 41, > - gdb_mm1 = 42, > - gdb_mm2 = 43, > - gdb_mm3 = 44, > - gdb_mm4 = 45, > - gdb_mm5 = 46, > - gdb_mm6 = 47, > - gdb_mm7 = 48 > -}; > - > -static const > -uint32_t g_gpr_regnums[k_num_gpr_registers] = > -{ > - gpr_eax, > - gpr_ebx, > - gpr_ecx, > - gpr_edx, > - gpr_edi, > - gpr_esi, > - gpr_ebp, > - gpr_esp, > - gpr_ss, > - gpr_eflags, > - gpr_eip, > - gpr_cs, > - gpr_ds, > - gpr_es, > - gpr_fs, > - gpr_gs, > -}; > - > -static const uint32_t > -g_fpu_regnums[k_num_fpu_registers] = > -{ > - fpu_fcw, > - fpu_fsw, > - fpu_ftw, > - fpu_fop, > - fpu_ip, > - fpu_cs, > - fpu_foo, > - fpu_fos, > - fpu_mxcsr, > - fpu_stmm0, > - fpu_stmm1, > - fpu_stmm2, > - fpu_stmm3, > - fpu_stmm4, > - fpu_stmm5, > - fpu_stmm6, > - fpu_stmm7, > - fpu_xmm0, > - fpu_xmm1, > - fpu_xmm2, > - fpu_xmm3, > - fpu_xmm4, > - fpu_xmm5, > - fpu_xmm6, > - fpu_xmm7, > -}; > - > -static const RegisterSet > -g_reg_sets[k_num_register_sets] = > -{ > - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, > - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } > -}; > - > -// Computes the offset of the given GPR in the user data area. > -#define GPR_OFFSET(regname) \ > - (offsetof(RegisterContextLinux_i386::UserArea, regs) + \ > - offsetof(RegisterContextLinux_i386::GPR, regname)) > - > -// Computes the offset of the given FPR in the user data area. > -#define FPR_OFFSET(regname) \ > - (offsetof(RegisterContextLinux_i386::UserArea, i387) + \ > - offsetof(RegisterContextLinux_i386::FPU, regname)) > - > -// Number of bytes needed to represent a GPR. > -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg) > - > -// Number of bytes needed to represent a FPR. > -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg) > - > -// Number of bytes needed to represent the i'th FP register. > -#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes) > - > -// Number of bytes needed to represent an XMM register. > -#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg) > - > -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ > - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ > - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } > - > -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ > - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ > - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } > - > -#define DEFINE_FP(reg, i) \ > - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > - eFormatVectorOfUInt8, \ > - { dwarf_##reg##i, dwarf_##reg##i, \ > - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } > - > -#define DEFINE_XMM(reg, i) \ > - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > - eFormatVectorOfUInt8, \ > - { dwarf_##reg##i, dwarf_##reg##i, \ > - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } > - > -static RegisterInfo > -g_register_infos[k_num_registers] = > -{ > - // General purpose registers. > - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), > - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), > - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), > - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), > - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), > - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), > - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), > - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), > - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), > - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), > - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), > - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), > - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), > - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), > - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), > - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), > - > - // Floating point registers. > - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), > - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), > - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), > - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), > - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), > - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), > - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), > - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), > - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), > - > - DEFINE_FP(stmm, 0), > - DEFINE_FP(stmm, 1), > - DEFINE_FP(stmm, 2), > - DEFINE_FP(stmm, 3), > - DEFINE_FP(stmm, 4), > - DEFINE_FP(stmm, 5), > - DEFINE_FP(stmm, 6), > - DEFINE_FP(stmm, 7), > - > - // XMM registers > - DEFINE_XMM(xmm, 0), > - DEFINE_XMM(xmm, 1), > - DEFINE_XMM(xmm, 2), > - DEFINE_XMM(xmm, 3), > - DEFINE_XMM(xmm, 4), > - DEFINE_XMM(xmm, 5), > - DEFINE_XMM(xmm, 6), > - DEFINE_XMM(xmm, 7), > - > -}; > - > -#ifndef NDEBUG > -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); > -#endif > - > -static unsigned GetRegOffset(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register number."); > - return g_register_infos[reg].byte_offset; > -} > - > -#if 0 // These functions are currently not in use. > -static unsigned GetRegSize(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register number."); > - return g_register_infos[reg].byte_size; > -} > - > -static bool IsGPR(unsigned reg) > -{ > - return reg <= k_last_gpr; // GPR's come first. > -} > - > -static bool IsFPR(unsigned reg) > -{ > - return (k_first_fpr <= reg && reg <= k_last_fpr); > -} > -#endif > - > - > -RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread, > - uint32_t concrete_frame_idx) > - : RegisterContextLinux(thread, concrete_frame_idx) > -{ > -} > - > -RegisterContextLinux_i386::~RegisterContextLinux_i386() > -{ > -} > - > -ProcessMonitor & > -RegisterContextLinux_i386::GetMonitor() > -{ > - ProcessLinux *process = static_cast(CalculateProcess()); > - return process->GetMonitor(); > -} > - > -void > -RegisterContextLinux_i386::Invalidate() > -{ > -} > - > -void > -RegisterContextLinux_i386::InvalidateAllRegisters() > -{ > -} > - > -size_t > -RegisterContextLinux_i386::GetRegisterCount() > -{ > - assert(k_num_register_infos == k_num_registers); > - return k_num_registers; > -} > - > -const RegisterInfo * > -RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg) > -{ > - assert(k_num_register_infos == k_num_registers); > - if (reg < k_num_registers) > - return &g_register_infos[reg]; > - else > - return NULL; > -} > - > -size_t > -RegisterContextLinux_i386::GetRegisterSetCount() > -{ > - return k_num_register_sets; > -} > - > -const RegisterSet * > -RegisterContextLinux_i386::GetRegisterSet(uint32_t set) > -{ > - if (set < k_num_register_sets) > - return &g_reg_sets[set]; > - else > - return NULL; > -} > - > -unsigned > -RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset) > -{ > - unsigned reg; > - for (reg = 0; reg < k_num_registers; reg++) > - { > - if (g_register_infos[reg].byte_offset == offset) > - break; > - } > - assert(reg < k_num_registers && "Invalid register offset."); > - return reg; > -} > - > -const char * > -RegisterContextLinux_i386::GetRegisterName(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register offset."); > - return g_register_infos[reg].name; > -} > - > -bool > -RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info, > - RegisterValue &value) > -{ > - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.ReadRegisterValue(GetRegOffset(reg), value); > -} > - > -bool > -RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp) > -{ > - return false; > -} > - > -bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info, > - const RegisterValue &value) > -{ > - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.WriteRegisterValue(GetRegOffset(reg), value); > -} > - > -bool > -RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data) > -{ > - return false; > -} > - > -bool > -RegisterContextLinux_i386::UpdateAfterBreakpoint() > -{ > - // PC points one byte past the int3 responsible for the breakpoint. > - lldb::addr_t pc; > - > - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) > - return false; > - > - SetPC(pc - 1); > - return true; > -} > - > -uint32_t > -RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, > - uint32_t num) > -{ > - if (kind == eRegisterKindGeneric) > - { > - switch (num) > - { > - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; > - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; > - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; > - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; > - case LLDB_REGNUM_GENERIC_RA: > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - > - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) > - { > - switch (num) > - { > - case dwarf_eax: return gpr_eax; > - case dwarf_edx: return gpr_edx; > - case dwarf_ecx: return gpr_ecx; > - case dwarf_ebx: return gpr_ebx; > - case dwarf_esi: return gpr_esi; > - case dwarf_edi: return gpr_edi; > - case dwarf_ebp: return gpr_ebp; > - case dwarf_esp: return gpr_esp; > - case dwarf_eip: return gpr_eip; > - case dwarf_xmm0: return fpu_xmm0; > - case dwarf_xmm1: return fpu_xmm1; > - case dwarf_xmm2: return fpu_xmm2; > - case dwarf_xmm3: return fpu_xmm3; > - case dwarf_xmm4: return fpu_xmm4; > - case dwarf_xmm5: return fpu_xmm5; > - case dwarf_xmm6: return fpu_xmm6; > - case dwarf_xmm7: return fpu_xmm7; > - case dwarf_stmm0: return fpu_stmm0; > - case dwarf_stmm1: return fpu_stmm1; > - case dwarf_stmm2: return fpu_stmm2; > - case dwarf_stmm3: return fpu_stmm3; > - case dwarf_stmm4: return fpu_stmm4; > - case dwarf_stmm5: return fpu_stmm5; > - case dwarf_stmm6: return fpu_stmm6; > - case dwarf_stmm7: return fpu_stmm7; > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - > - if (kind == eRegisterKindGDB) > - { > - switch (num) > - { > - case gdb_eax : return gpr_eax; > - case gdb_ebx : return gpr_ebx; > - case gdb_ecx : return gpr_ecx; > - case gdb_edx : return gpr_edx; > - case gdb_esi : return gpr_esi; > - case gdb_edi : return gpr_edi; > - case gdb_ebp : return gpr_ebp; > - case gdb_esp : return gpr_esp; > - case gdb_eip : return gpr_eip; > - case gdb_eflags : return gpr_eflags; > - case gdb_cs : return gpr_cs; > - case gdb_ss : return gpr_ss; > - case gdb_ds : return gpr_ds; > - case gdb_es : return gpr_es; > - case gdb_fs : return gpr_fs; > - case gdb_gs : return gpr_gs; > - case gdb_stmm0 : return fpu_stmm0; > - case gdb_stmm1 : return fpu_stmm1; > - case gdb_stmm2 : return fpu_stmm2; > - case gdb_stmm3 : return fpu_stmm3; > - case gdb_stmm4 : return fpu_stmm4; > - case gdb_stmm5 : return fpu_stmm5; > - case gdb_stmm6 : return fpu_stmm6; > - case gdb_stmm7 : return fpu_stmm7; > - case gdb_fcw : return fpu_fcw; > - case gdb_fsw : return fpu_fsw; > - case gdb_ftw : return fpu_ftw; > - case gdb_fpu_cs : return fpu_cs; > - case gdb_ip : return fpu_ip; > - case gdb_fpu_ds : return fpu_fos; > - case gdb_dp : return fpu_foo; > - case gdb_fop : return fpu_fop; > - case gdb_xmm0 : return fpu_xmm0; > - case gdb_xmm1 : return fpu_xmm1; > - case gdb_xmm2 : return fpu_xmm2; > - case gdb_xmm3 : return fpu_xmm3; > - case gdb_xmm4 : return fpu_xmm4; > - case gdb_xmm5 : return fpu_xmm5; > - case gdb_xmm6 : return fpu_xmm6; > - case gdb_xmm7 : return fpu_xmm7; > - case gdb_mxcsr : return fpu_mxcsr; > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - else if (kind == eRegisterKindLLDB) > - { > - return num; > - } > - > - return LLDB_INVALID_REGNUM; > -} > - > -bool > -RegisterContextLinux_i386::HardwareSingleStep(bool enable) > -{ > - enum { TRACE_BIT = 0x100 }; > - uint64_t eflags; > - > - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) > - return false; > - > - if (enable) > - { > - if (eflags & TRACE_BIT) > - return true; > - > - eflags |= TRACE_BIT; > - } > - else > - { > - if (!(eflags & TRACE_BIT)) > - return false; > - > - eflags &= ~TRACE_BIT; > - } > - > - return WriteRegisterFromUnsigned(gpr_eflags, eflags); > -} > - > -void > -RegisterContextLinux_i386::LogGPR(const char *title) > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); > - if (log) > - { > - if (title) > - log->Printf ("%s", title); > - for (uint32_t i=0; i - { > - uint32_t reg = gpr_eax + i; > - log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); > - } > - } > -} > - > -bool > -RegisterContextLinux_i386::ReadGPR() > -{ > - bool result; > - > - ProcessMonitor &monitor = GetMonitor(); > - result = monitor.ReadGPR(&user.regs); > - LogGPR("RegisterContextLinux_i386::ReadGPR()"); > - return result; > -} > - > -bool > -RegisterContextLinux_i386::ReadFPR() > -{ > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.ReadFPR(&user.i387); > -} > Index: source/Plugins/Process/Linux/ProcessMessage.cpp > =================================================================== > --- source/Plugins/Process/Linux/ProcessMessage.cpp (revision 147560) > +++ source/Plugins/Process/Linux/ProcessMessage.cpp (working copy) > @@ -1,245 +0,0 @@ > -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -#include "ProcessMessage.h" > - > -using namespace lldb_private; > - > -const char * > -ProcessMessage::GetCrashReasonString(CrashReason reason) > -{ > - const char *str = NULL; > - > - switch (reason) > - { > - default: > - assert(false && "invalid CrashReason"); > - break; > - > - case eInvalidAddress: > - str = "invalid address"; > - break; > - case ePrivilegedAddress: > - str = "address access protected"; > - break; > - case eIllegalOpcode: > - str = "illegal instruction"; > - break; > - case eIllegalOperand: > - str = "illegal instruction operand"; > - break; > - case eIllegalAddressingMode: > - str = "illegal addressing mode"; > - break; > - case eIllegalTrap: > - str = "illegal trap"; > - break; > - case ePrivilegedOpcode: > - str = "privileged instruction"; > - break; > - case ePrivilegedRegister: > - str = "privileged register"; > - break; > - case eCoprocessorError: > - str = "coprocessor error"; > - break; > - case eInternalStackError: > - str = "internal stack error"; > - break; > - case eIllegalAlignment: > - str = "illegal alignment"; > - break; > - case eIllegalAddress: > - str = "illegal address"; > - break; > - case eHardwareError: > - str = "hardware error"; > - break; > - case eIntegerDivideByZero: > - str = "integer divide by zero"; > - break; > - case eIntegerOverflow: > - str = "integer overflow"; > - break; > - case eFloatDivideByZero: > - str = "floating point divide by zero"; > - break; > - case eFloatOverflow: > - str = "floating point overflow"; > - break; > - case eFloatUnderflow: > - str = "floating point underflow"; > - break; > - case eFloatInexactResult: > - str = "inexact floating point result"; > - break; > - case eFloatInvalidOperation: > - str = "invalid floating point operation"; > - break; > - case eFloatSubscriptRange: > - str = "invalid floating point subscript range"; > - break; > - } > - > - return str; > -} > - > -const char * > -ProcessMessage::PrintCrashReason(CrashReason reason) > -{ > -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION > - // Just return the code in asci for integration builds. > - chcar str[8]; > - sprintf(str, "%d", reason); > -#else > - const char *str = NULL; > - > - switch (reason) > - { > - default: > - assert(false && "invalid CrashReason"); > - break; > - > - case eInvalidCrashReason: > - str = "eInvalidCrashReason"; > - break; > - > - // SIGSEGV crash rcase easons. > - case eInvalidAddress: > - str = "eInvalidAddress"; > - break; > - case ePrivilegedAddress: > - str = "ePrivilegedAddress"; > - break; > - > - // SIGILL crash rcase easons. > - case eIllegalOpcode: > - str = "eIllegalOpcode"; > - break; > - case eIllegalOperand: > - str = "eIllegalOperand"; > - break; > - case eIllegalAddressingMode: > - str = "eIllegalAddressingMode"; > - break; > - case eIllegalTrap: > - str = "eIllegalTrap"; > - break; > - case ePrivilegedOpcode: > - str = "ePrivilegedOpcode"; > - break; > - case ePrivilegedRegister: > - str = "ePrivilegedRegister"; > - break; > - case eCoprocessorError: > - str = "eCoprocessorError"; > - break; > - case eInternalStackError: > - str = "eInternalStackError"; > - break; > - > - // SIGBUS crash rcase easons: > - case eIllegalAlignment: > - str = "eIllegalAlignment"; > - break; > - case eIllegalAddress: > - str = "eIllegalAddress"; > - break; > - case eHardwareError: > - str = "eHardwareError"; > - break; > - > - // SIGFPE crash rcase easons: > - case eIntegerDivideByZero: > - str = "eIntegerDivideByZero"; > - break; > - case eIntegerOverflow: > - str = "eIntegerOverflow"; > - break; > - case eFloatDivideByZero: > - str = "eFloatDivideByZero"; > - break; > - case eFloatOverflow: > - str = "eFloatOverflow"; > - break; > - case eFloatUnderflow: > - str = "eFloatUnderflow"; > - break; > - case eFloatInexactResult: > - str = "eFloatInexactResult"; > - break; > - case eFloatInvalidOperation: > - str = "eFloatInvalidOperation"; > - break; > - case eFloatSubscriptRange: > - str = "eFloatSubscriptRange"; > - break; > - } > -#endif > - > - return str; > -} > - > -const char * > -ProcessMessage::PrintCrashReason() const > -{ > - return PrintCrashReason(m_crash_reason); > -} > - > -const char * > -ProcessMessage::PrintKind(Kind kind) > -{ > -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION > - // Just return the code in asci for integration builds. > - chcar str[8]; > - sprintf(str, "%d", reason); > -#else > - const char *str = NULL; > - > - switch (kind) > - { > - default: > - assert(false && "invalid Kind"); > - break; > - > - case eInvalidMessage: > - str = "eInvalidMessage"; > - break; > - case eExitMessage: > - str = "eExitMessage"; > - break; > - case eLimboMessage: > - str = "eLimboMessage"; > - break; > - case eSignalMessage: > - str = "eSignalMessage"; > - break; > - case eSignalDeliveredMessage: > - str = "eSignalDeliveredMessage"; > - break; > - case eTraceMessage: > - str = "eTraceMessage"; > - break; > - case eBreakpointMessage: > - str = "eBreakpointMessage"; > - break; > - case eCrashMessage: > - str = "eCrashMessage"; > - break; > - } > -#endif > - > - return str; > -} > - > -const char * > -ProcessMessage::PrintKind() const > -{ > - return PrintKind(m_kind); > -} > Index: source/Plugins/Process/Linux/ProcessMonitor.cpp > =================================================================== > --- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 147560) > +++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy) > @@ -28,9 +28,9 @@ > #include "lldb/Target/RegisterContext.h" > #include "lldb/Utility/PseudoTerminal.h" > > -#include "LinuxThread.h" > +#include "POSIXThread.h" > #include "ProcessLinux.h" > -#include "ProcessLinuxLog.h" > +#include "ProcessPOSIXLog.h" > #include "ProcessMonitor.h" > > > @@ -63,8 +63,8 @@ > static void PtraceDisplayBytes(__ptrace_request &req, void *data) > { > StreamString buf; > - LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet ( > - LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE)); > + LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( > + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); > > if (verbose_log) > { > @@ -120,7 +120,7 @@ > { > long int result; > > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); > > if (log) > log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d", > @@ -170,10 +170,10 @@ > size_t remainder; > long data; > > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); > if (log) > - ProcessLinuxLog::IncNestLevel(); > - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) > + ProcessPOSIXLog::IncNestLevel(); > + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) > log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, > pid, word_size, (void*)vm_addr, buf, size); > > @@ -187,7 +187,7 @@ > { > error.SetErrorToErrno(); > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_read; > } > > @@ -200,10 +200,10 @@ > for (unsigned i = 0; i < remainder; ++i) > dst[i] = ((data >> i*8) & 0xFF); > > - if (log && ProcessLinuxLog::AtTopNestLevel() && > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && > - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) > + if (log && ProcessPOSIXLog::AtTopNestLevel() && > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && > + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) > log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, > (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data); > > @@ -212,7 +212,7 @@ > } > > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_read; > } > > @@ -224,10 +224,10 @@ > size_t bytes_written = 0; > size_t remainder; > > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); > if (log) > - ProcessLinuxLog::IncNestLevel(); > - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) > + ProcessPOSIXLog::IncNestLevel(); > + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) > log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, > pid, word_size, (void*)vm_addr, buf, size); > > @@ -244,10 +244,10 @@ > for (unsigned i = 0; i < word_size; ++i) > data |= (unsigned long)src[i] << i*8; > > - if (log && ProcessLinuxLog::AtTopNestLevel() && > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && > - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) > + if (log && ProcessPOSIXLog::AtTopNestLevel() && > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && > + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) > log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, > (void*)vm_addr, *(unsigned long*)src, data); > > @@ -255,7 +255,7 @@ > { > error.SetErrorToErrno(); > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_written; > } > } > @@ -266,7 +266,7 @@ > buff, word_size, error) != word_size) > { > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_written; > } > > @@ -276,14 +276,14 @@ > buff, word_size, error) != word_size) > { > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_written; > } > > - if (log && ProcessLinuxLog::AtTopNestLevel() && > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || > - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && > - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) > + if (log && ProcessPOSIXLog::AtTopNestLevel() && > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || > + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && > + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) > log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, > (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); > } > @@ -292,7 +292,7 @@ > src += word_size; > } > if (log) > - ProcessLinuxLog::DecNestLevel(); > + ProcessPOSIXLog::DecNestLevel(); > return bytes_written; > } > > @@ -420,7 +420,7 @@ > ReadRegOperation::Execute(ProcessMonitor *monitor) > { > lldb::pid_t pid = monitor->GetPID(); > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); > > // Set errno to zero so that we can detect a failed peek. > errno = 0; > @@ -434,7 +434,7 @@ > } > if (log) > log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__, > - LinuxThread::GetRegisterNameFromOffset(m_offset), data); > + POSIXThread::GetRegisterNameFromOffset(m_offset), data); > } > > //------------------------------------------------------------------------------ > @@ -460,7 +460,7 @@ > { > void* buf; > lldb::pid_t pid = monitor->GetPID(); > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); > > if (sizeof(void*) == sizeof(uint64_t)) > buf = (void*) m_value.GetAsUInt64(); > @@ -472,7 +472,7 @@ > > if (log) > log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, > - LinuxThread::GetRegisterNameFromOffset(m_offset), buf); > + POSIXThread::GetRegisterNameFromOffset(m_offset), buf); > if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf)) > m_result = false; > else > @@ -794,7 +794,7 @@ > /// launching or attaching to the inferior process, and then 2) servicing > /// operations such as register reads/writes, stepping, etc. See the comments > /// on the Operation class for more info as to why this is needed. > -ProcessMonitor::ProcessMonitor(ProcessLinux *process, > +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, > Module *module, > const char *argv[], > const char *envp[], > @@ -802,7 +802,7 @@ > const char *stdout_path, > const char *stderr_path, > lldb_private::Error &error) > - : m_process(process), > + : m_process(static_cast(process)), > m_operation_thread(LLDB_INVALID_HOST_THREAD), > m_pid(LLDB_INVALID_PROCESS_ID), > m_terminal_fd(-1), > @@ -858,10 +858,10 @@ > } > } > > -ProcessMonitor::ProcessMonitor(ProcessLinux *process, > +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, > lldb::pid_t pid, > lldb_private::Error &error) > - : m_process(process), > + : m_process(static_cast(process)), > m_operation_thread(LLDB_INVALID_HOST_THREAD), > m_pid(LLDB_INVALID_PROCESS_ID), > m_terminal_fd(-1), > @@ -978,7 +978,7 @@ > lldb::pid_t pid; > > lldb::ThreadSP inferior; > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); > > // Propagate the environment if one is not supplied. > if (envp == NULL || envp[0] == NULL) > @@ -1101,11 +1101,10 @@ > if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) > goto FINISH; > > - // Update the process thread list with this new thread and mark it as > - // current. > + // Update the process thread list with this new thread. > // FIXME: should we be letting UpdateThreadList handle this? > // FIXME: by using pids instead of tids, we can only support one thread. > - inferior.reset(new LinuxThread(process, pid)); > + inferior.reset(new POSIXThread(process, pid)); > if (log) > log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid); > process.GetThreadList().AddThread(inferior); > @@ -1167,9 +1166,8 @@ > > ProcessMonitor *monitor = args->m_monitor; > ProcessLinux &process = monitor->GetProcess(); > - > lldb::ThreadSP inferior; > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); > > if (pid <= 1) > { > @@ -1192,13 +1190,11 @@ > goto FINISH; > } > > - // Update the process thread list with the attached thread and > - // mark it as current. > - inferior.reset(new LinuxThread(process, pid)); > + // Update the process thread list with the attached thread. > + inferior.reset(new POSIXThread(process, pid)); > if (log) > log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid); > process.GetThreadList().AddThread(inferior); > - process.GetThreadList().SetSelectedThreadByID(pid); > > // Let our process instance know the thread has stopped. > process.SendMessage(ProcessMessage::Trace(pid)); > @@ -1568,7 +1564,7 @@ > } > > bool > -ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value) > +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) > { > bool result; > ReadRegOperation op(offset, value, result); > Index: source/Plugins/Process/Linux/LinuxStopInfo.h > =================================================================== > --- source/Plugins/Process/Linux/LinuxStopInfo.h (revision 147560) > +++ source/Plugins/Process/Linux/LinuxStopInfo.h (working copy) > @@ -1,92 +0,0 @@ > -//===-- LinuxStopInfo.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_LinuxStopInfo_H_ > -#define liblldb_LinuxStopInfo_H_ > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -// Project includes > -#include "lldb/Target/StopInfo.h" > - > -#include "LinuxThread.h" > -#include "ProcessMessage.h" > - > -//===----------------------------------------------------------------------===// > -/// @class LinuxStopInfo > -/// @brief Simple base class for all Linux-specific StopInfo objects. > -/// > -class LinuxStopInfo > - : public lldb_private::StopInfo > -{ > -public: > - LinuxStopInfo(lldb_private::Thread &thread, uint32_t status) > - : StopInfo(thread, status) > - { } > -}; > - > -//===----------------------------------------------------------------------===// > -/// @class LinuxLimboStopInfo > -/// @brief Represents the stop state of a process ready to exit. > -/// > -class LinuxLimboStopInfo > - : public LinuxStopInfo > -{ > -public: > - LinuxLimboStopInfo(LinuxThread &thread) > - : LinuxStopInfo(thread, 0) > - { } > - > - ~LinuxLimboStopInfo(); > - > - lldb::StopReason > - GetStopReason() const; > - > - const char * > - GetDescription(); > - > - bool > - ShouldStop(lldb_private::Event *event_ptr); > - > - bool > - ShouldNotify(lldb_private::Event *event_ptr); > -}; > - > - > -//===----------------------------------------------------------------------===// > -/// @class LinuxCrashStopInfo > -/// @brief Represents the stop state of process that is ready to crash. > -/// > -class LinuxCrashStopInfo > - : public LinuxStopInfo > -{ > -public: > - LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, > - ProcessMessage::CrashReason reason) > - : LinuxStopInfo(thread, status), > - m_crash_reason(reason) > - { } > - > - ~LinuxCrashStopInfo(); > - > - lldb::StopReason > - GetStopReason() const; > - > - const char * > - GetDescription(); > - > - ProcessMessage::CrashReason > - GetCrashReason() const; > - > -private: > - ProcessMessage::CrashReason m_crash_reason; > -}; > - > -#endif > Index: source/Plugins/Process/Linux/LinuxThread.cpp > =================================================================== > --- source/Plugins/Process/Linux/LinuxThread.cpp (revision 147560) > +++ source/Plugins/Process/Linux/LinuxThread.cpp (working copy) > @@ -1,350 +0,0 @@ > -//===-- LinuxThread.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 > - > -// C++ Includes > -// Other libraries and framework includes > -// Project includes > -#include "lldb/Core/Debugger.h" > -#include "lldb/Host/Host.h" > -#include "lldb/Target/Process.h" > -#include "lldb/Target/StopInfo.h" > -#include "lldb/Target/Target.h" > -#include "LinuxStopInfo.h" > -#include "LinuxThread.h" > -#include "ProcessLinux.h" > -#include "ProcessLinuxLog.h" > -#include "ProcessMonitor.h" > -#include "RegisterContextLinux_i386.h" > -#include "RegisterContextLinux_x86_64.h" > -#include "UnwindLLDB.h" > - > -using namespace lldb_private; > - > - > -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) > - : Thread(process, tid), > - m_frame_ap(0) > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid); > -} > - > -LinuxThread::~LinuxThread() > -{ > - DestroyThread(); > -} > - > -ProcessMonitor & > -LinuxThread::GetMonitor() > -{ > - ProcessLinux &process = static_cast(GetProcess()); > - return process.GetMonitor(); > -} > - > -void > -LinuxThread::RefreshStateAfterStop() > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("LinuxThread::%s ()", __FUNCTION__); > - > - // Let all threads recover from stopping and do any clean up based > - // on the previous thread state (if any). > - ProcessLinux &process = static_cast(GetProcess()); > - process.GetThreadList().RefreshStateAfterStop(); > -} > - > -const char * > -LinuxThread::GetInfo() > -{ > - return NULL; > -} > - > -lldb::RegisterContextSP > -LinuxThread::GetRegisterContext() > -{ > - if (!m_reg_context_sp) > - { > - ArchSpec arch = Host::GetArchitecture(); > - > - switch (arch.GetCore()) > - { > - default: > - assert(false && "CPU type not supported!"); > - break; > - > - case ArchSpec::eCore_x86_32_i386: > - case ArchSpec::eCore_x86_32_i486: > - case ArchSpec::eCore_x86_32_i486sx: > - m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); > - break; > - > - case ArchSpec::eCore_x86_64_x86_64: > - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); > - break; > - } > - } > - return m_reg_context_sp; > -} > - > -lldb::RegisterContextSP > -LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) > -{ > - lldb::RegisterContextSP reg_ctx_sp; > - uint32_t concrete_frame_idx = 0; > - > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("LinuxThread::%s ()", __FUNCTION__); > - > - if (frame) > - concrete_frame_idx = frame->GetConcreteFrameIndex(); > - > - if (concrete_frame_idx == 0) > - reg_ctx_sp = GetRegisterContext(); > - else > - { > - assert(GetUnwinder()); > - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); > - } > - > - return reg_ctx_sp; > -} > - > -lldb::StopInfoSP > -LinuxThread::GetPrivateStopReason() > -{ > - return m_stop_info; > -} > - > -Unwind * > -LinuxThread::GetUnwinder() > -{ > - if (m_unwinder_ap.get() == NULL) > - m_unwinder_ap.reset(new UnwindLLDB(*this)); > - > - return m_unwinder_ap.get(); > -} > - > -bool > -LinuxThread::WillResume(lldb::StateType resume_state) > -{ > - SetResumeState(resume_state); > - > - ClearStackFrames(); > - if (m_unwinder_ap.get()) > - m_unwinder_ap->Clear(); > - > - return Thread::WillResume(resume_state); > -} > - > -bool > -LinuxThread::Resume() > -{ > - lldb::StateType resume_state = GetResumeState(); > - ProcessMonitor &monitor = GetMonitor(); > - bool status; > - > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) > - log->Printf ("LinuxThread::%s ()", __FUNCTION__); > - > - switch (resume_state) > - { > - default: > - assert(false && "Unexpected state for resume!"); > - status = false; > - break; > - > - case lldb::eStateRunning: > - SetState(resume_state); > - status = monitor.Resume(GetID(), GetResumeSignal()); > - break; > - > - case lldb::eStateStepping: > - SetState(resume_state); > - status = monitor.SingleStep(GetID(), GetResumeSignal()); > - break; > - } > - > - return status; > -} > - > -void > -LinuxThread::Notify(const ProcessMessage &message) > -{ > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log) > - log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); > - > - switch (message.GetKind()) > - { > - default: > - assert(false && "Unexpected message kind!"); > - break; > - > - case ProcessMessage::eLimboMessage: > - LimboNotify(message); > - break; > - > - case ProcessMessage::eSignalMessage: > - SignalNotify(message); > - break; > - > - case ProcessMessage::eSignalDeliveredMessage: > - SignalDeliveredNotify(message); > - break; > - > - case ProcessMessage::eTraceMessage: > - TraceNotify(message); > - break; > - > - case ProcessMessage::eBreakpointMessage: > - BreakNotify(message); > - break; > - > - case ProcessMessage::eCrashMessage: > - CrashNotify(message); > - break; > - } > -} > - > -void > -LinuxThread::BreakNotify(const ProcessMessage &message) > -{ > - bool status; > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - > - assert(GetRegisterContextLinux()); > - status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); > - assert(status && "Breakpoint update failed!"); > - > - // With our register state restored, resolve the breakpoint object > - // corresponding to our current PC. > - assert(GetRegisterContext()); > - lldb::addr_t pc = GetRegisterContext()->GetPC(); > - if (log) > - log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); > - lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); > - assert(bp_site); > - lldb::break_id_t bp_id = bp_site->GetID(); > - assert(bp_site && bp_site->ValidForThisThread(this)); > - > - > - m_breakpoint = bp_site; > - m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); > -} > - > -void > -LinuxThread::TraceNotify(const ProcessMessage &message) > -{ > - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); > -} > - > -void > -LinuxThread::LimboNotify(const ProcessMessage &message) > -{ > - m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this)); > -} > - > -void > -LinuxThread::SignalNotify(const ProcessMessage &message) > -{ > - int signo = message.GetSignal(); > - > - m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); > - SetResumeSignal(signo); > -} > - > -void > -LinuxThread::SignalDeliveredNotify(const ProcessMessage &message) > -{ > - int signo = message.GetSignal(); > - > - // Just treat debugger generated signal events like breakpoints for now. > - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); > - SetResumeSignal(signo); > -} > - > -void > -LinuxThread::CrashNotify(const ProcessMessage &message) > -{ > - int signo = message.GetSignal(); > - > - assert(message.GetKind() == ProcessMessage::eCrashMessage); > - > - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); > - if (log) > - log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); > - > - m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo( > - *this, signo, message.GetCrashReason())); > - SetResumeSignal(signo); > -} > - > -unsigned > -LinuxThread::GetRegisterIndexFromOffset(unsigned offset) > -{ > - unsigned reg; > - ArchSpec arch = Host::GetArchitecture(); > - > - switch (arch.GetCore()) > - { > - default: > - assert(false && "CPU type not supported!"); > - break; > - > - case ArchSpec::eCore_x86_32_i386: > - case ArchSpec::eCore_x86_32_i486: > - case ArchSpec::eCore_x86_32_i486sx: > - reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset); > - break; > - > - case ArchSpec::eCore_x86_64_x86_64: > - reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset); > - break; > - } > - return reg; > -} > - > -const char * > -LinuxThread::GetRegisterName(unsigned reg) > -{ > - const char * name; > - ArchSpec arch = Host::GetArchitecture(); > - > - switch (arch.GetCore()) > - { > - default: > - assert(false && "CPU type not supported!"); > - break; > - > - case ArchSpec::eCore_x86_32_i386: > - case ArchSpec::eCore_x86_32_i486: > - case ArchSpec::eCore_x86_32_i486sx: > - name = RegisterContextLinux_i386::GetRegisterName(reg); > - break; > - > - case ArchSpec::eCore_x86_64_x86_64: > - name = RegisterContextLinux_x86_64::GetRegisterName(reg); > - break; > - } > - return name; > -} > - > -const char * > -LinuxThread::GetRegisterNameFromOffset(unsigned offset) > -{ > - return GetRegisterName(GetRegisterIndexFromOffset(offset)); > -} > - > Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h > =================================================================== > --- source/Plugins/Process/Linux/RegisterContextLinux_i386.h (revision 147560) > +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h (working copy) > @@ -1,169 +0,0 @@ > -//===-- RegisterContextLinux_i386.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_RegisterContextLinux_i386_h_ > -#define liblldb_RegisterContextLinux_i386_h_ > - > -// C Includes > -// C++ Includes > -// Other libraries and framework includes > -// Project includes > -#include "lldb/Core/Log.h" > -#include "RegisterContextLinux.h" > - > -class RegisterContextLinux_i386 : public RegisterContextLinux > -{ > -public: > - RegisterContextLinux_i386(lldb_private::Thread &thread, > - uint32_t concreate_frame_idx); > - > - ~RegisterContextLinux_i386(); > - > - void > - Invalidate(); > - > - void > - InvalidateAllRegisters(); > - > - size_t > - GetRegisterCount(); > - > - const lldb_private::RegisterInfo * > - GetRegisterInfoAtIndex(uint32_t reg); > - > - size_t > - GetRegisterSetCount(); > - > - const lldb_private::RegisterSet * > - GetRegisterSet(uint32_t set); > - > - static unsigned > - GetRegisterIndexFromOffset(unsigned offset); > - > - static const char * > - GetRegisterName(unsigned reg); > - > -#if 0 > - bool > - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); > - > - bool > - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); > -#endif > - > - virtual bool > - ReadRegister(const lldb_private::RegisterInfo *reg_info, > - lldb_private::RegisterValue &value); > - > - bool > - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); > - > -#if 0 > - bool > - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); > - > - bool > - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, > - uint32_t data_offset = 0); > -#endif > - > - virtual bool > - WriteRegister(const lldb_private::RegisterInfo *reg_info, > - const lldb_private::RegisterValue &value); > - > - bool > - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); > - > - uint32_t > - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); > - > - bool > - HardwareSingleStep(bool enable); > - > - bool > - UpdateAfterBreakpoint(); > - > - struct GPR > - { > - uint32_t ebx; > - uint32_t ecx; > - uint32_t edx; > - uint32_t esi; > - uint32_t edi; > - uint32_t ebp; > - uint32_t eax; > - uint32_t ds; > - uint32_t es; > - uint32_t fs; > - uint32_t gs; > - uint32_t orig_ax; > - uint32_t eip; > - uint32_t cs; > - uint32_t eflags; > - uint32_t esp; > - uint32_t ss; > - }; > - > - struct MMSReg > - { > - uint8_t bytes[8]; > - }; > - > - struct XMMReg > - { > - uint8_t bytes[16]; > - }; > - > - struct FPU > - { > - uint16_t fcw; > - uint16_t fsw; > - uint16_t ftw; > - uint16_t fop; > - uint32_t ip; > - uint32_t cs; > - uint32_t foo; > - uint32_t fos; > - uint32_t mxcsr; > - uint32_t reserved; > - MMSReg stmm[8]; > - XMMReg xmm[8]; > - uint32_t pad[56]; > - }; > - > - struct UserArea > - { > - GPR regs; // General purpose registers. > - int32_t fpvalid; // True if FPU is being used. > - FPU i387; // FPU registers. > - uint32_t tsize; // Text segment size. > - uint32_t dsize; // Data segment size. > - uint32_t ssize; // Stack segment size. > - uint32_t start_code; // VM address of text. > - uint32_t start_stack; // VM address of stack bottom (top in rsp). > - int32_t signal; // Signal causing core dump. > - int32_t reserved; // Unused. > - uint32_t ar0; // Location of GPR's. > - FPU* fpstate; // Location of FPR's. > - uint32_t magic; // Identifier for core dumps. > - char u_comm[32]; // Command causing core dump. > - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). > - }; > -private: > - UserArea user; > - > - ProcessMonitor &GetMonitor(); > - > - void LogGPR(const char *title); > - > - bool ReadGPR(); > - bool ReadFPR(); > -}; > - > -#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ > Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp > =================================================================== > --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (revision 147560) > +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (working copy) > @@ -1,759 +0,0 @@ > -//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===// > -// > -// The LLVM Compiler Infrastructure > -// > -// This file is distributed under the University of Illinois Open Source > -// License. See LICENSE.TXT for details. > -// > -//===----------------------------------------------------------------------===// > - > -#include > -#include > -#include > - > -#include "lldb/Core/DataBufferHeap.h" > -#include "lldb/Core/DataExtractor.h" > -#include "lldb/Core/Scalar.h" > -#include "lldb/Target/Thread.h" > -#include "lldb/Host/Endian.h" > - > -#include "ProcessLinux.h" > -#include "ProcessMonitor.h" > -#include "RegisterContextLinux_x86_64.h" > - > -using namespace lldb_private; > -using namespace lldb; > - > -// Internal codes for all x86_64 registers. > -enum > -{ > - k_first_gpr, > - gpr_rax = k_first_gpr, > - gpr_rbx, > - gpr_rcx, > - gpr_rdx, > - gpr_rdi, > - gpr_rsi, > - gpr_rbp, > - gpr_rsp, > - gpr_r8, > - gpr_r9, > - gpr_r10, > - gpr_r11, > - gpr_r12, > - gpr_r13, > - gpr_r14, > - gpr_r15, > - gpr_rip, > - gpr_rflags, > - gpr_cs, > - gpr_fs, > - gpr_gs, > - gpr_ss, > - gpr_ds, > - gpr_es, > - k_last_gpr = gpr_es, > - > - k_first_fpr, > - fpu_fcw = k_first_fpr, > - fpu_fsw, > - fpu_ftw, > - fpu_fop, > - fpu_ip, > - fpu_cs, > - fpu_dp, > - fpu_ds, > - fpu_mxcsr, > - fpu_mxcsrmask, > - fpu_stmm0, > - fpu_stmm1, > - fpu_stmm2, > - fpu_stmm3, > - fpu_stmm4, > - fpu_stmm5, > - fpu_stmm6, > - fpu_stmm7, > - fpu_xmm0, > - fpu_xmm1, > - fpu_xmm2, > - fpu_xmm3, > - fpu_xmm4, > - fpu_xmm5, > - fpu_xmm6, > - fpu_xmm7, > - fpu_xmm8, > - fpu_xmm9, > - fpu_xmm10, > - fpu_xmm11, > - fpu_xmm12, > - fpu_xmm13, > - fpu_xmm14, > - fpu_xmm15, > - k_last_fpr = fpu_xmm15, > - > - k_num_registers, > - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, > - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 > -}; > - > -// Number of register sets provided by this context. > -enum > -{ > - k_num_register_sets = 2 > -}; > - > -enum gcc_dwarf_regnums > -{ > - gcc_dwarf_gpr_rax = 0, > - gcc_dwarf_gpr_rdx, > - gcc_dwarf_gpr_rcx, > - gcc_dwarf_gpr_rbx, > - gcc_dwarf_gpr_rsi, > - gcc_dwarf_gpr_rdi, > - gcc_dwarf_gpr_rbp, > - gcc_dwarf_gpr_rsp, > - gcc_dwarf_gpr_r8, > - gcc_dwarf_gpr_r9, > - gcc_dwarf_gpr_r10, > - gcc_dwarf_gpr_r11, > - gcc_dwarf_gpr_r12, > - gcc_dwarf_gpr_r13, > - gcc_dwarf_gpr_r14, > - gcc_dwarf_gpr_r15, > - gcc_dwarf_gpr_rip, > - gcc_dwarf_fpu_xmm0, > - gcc_dwarf_fpu_xmm1, > - gcc_dwarf_fpu_xmm2, > - gcc_dwarf_fpu_xmm3, > - gcc_dwarf_fpu_xmm4, > - gcc_dwarf_fpu_xmm5, > - gcc_dwarf_fpu_xmm6, > - gcc_dwarf_fpu_xmm7, > - gcc_dwarf_fpu_xmm8, > - gcc_dwarf_fpu_xmm9, > - gcc_dwarf_fpu_xmm10, > - gcc_dwarf_fpu_xmm11, > - gcc_dwarf_fpu_xmm12, > - gcc_dwarf_fpu_xmm13, > - gcc_dwarf_fpu_xmm14, > - gcc_dwarf_fpu_xmm15, > - gcc_dwarf_fpu_stmm0, > - gcc_dwarf_fpu_stmm1, > - gcc_dwarf_fpu_stmm2, > - gcc_dwarf_fpu_stmm3, > - gcc_dwarf_fpu_stmm4, > - gcc_dwarf_fpu_stmm5, > - gcc_dwarf_fpu_stmm6, > - gcc_dwarf_fpu_stmm7 > -}; > - > -enum gdb_regnums > -{ > - gdb_gpr_rax = 0, > - gdb_gpr_rbx = 1, > - gdb_gpr_rcx = 2, > - gdb_gpr_rdx = 3, > - gdb_gpr_rsi = 4, > - gdb_gpr_rdi = 5, > - gdb_gpr_rbp = 6, > - gdb_gpr_rsp = 7, > - gdb_gpr_r8 = 8, > - gdb_gpr_r9 = 9, > - gdb_gpr_r10 = 10, > - gdb_gpr_r11 = 11, > - gdb_gpr_r12 = 12, > - gdb_gpr_r13 = 13, > - gdb_gpr_r14 = 14, > - gdb_gpr_r15 = 15, > - gdb_gpr_rip = 16, > - gdb_gpr_rflags = 17, > - gdb_gpr_cs = 18, > - gdb_gpr_ss = 19, > - gdb_gpr_ds = 20, > - gdb_gpr_es = 21, > - gdb_gpr_fs = 22, > - gdb_gpr_gs = 23, > - gdb_fpu_stmm0 = 24, > - gdb_fpu_stmm1 = 25, > - gdb_fpu_stmm2 = 26, > - gdb_fpu_stmm3 = 27, > - gdb_fpu_stmm4 = 28, > - gdb_fpu_stmm5 = 29, > - gdb_fpu_stmm6 = 30, > - gdb_fpu_stmm7 = 31, > - gdb_fpu_fcw = 32, > - gdb_fpu_fsw = 33, > - gdb_fpu_ftw = 34, > - gdb_fpu_cs = 35, > - gdb_fpu_ip = 36, > - gdb_fpu_ds = 37, > - gdb_fpu_dp = 38, > - gdb_fpu_fop = 39, > - gdb_fpu_xmm0 = 40, > - gdb_fpu_xmm1 = 41, > - gdb_fpu_xmm2 = 42, > - gdb_fpu_xmm3 = 43, > - gdb_fpu_xmm4 = 44, > - gdb_fpu_xmm5 = 45, > - gdb_fpu_xmm6 = 46, > - gdb_fpu_xmm7 = 47, > - gdb_fpu_xmm8 = 48, > - gdb_fpu_xmm9 = 49, > - gdb_fpu_xmm10 = 50, > - gdb_fpu_xmm11 = 51, > - gdb_fpu_xmm12 = 52, > - gdb_fpu_xmm13 = 53, > - gdb_fpu_xmm14 = 54, > - gdb_fpu_xmm15 = 55, > - gdb_fpu_mxcsr = 56 > -}; > - > -static const > -uint32_t g_gpr_regnums[k_num_gpr_registers] = > -{ > - gpr_rax, > - gpr_rbx, > - gpr_rcx, > - gpr_rdx, > - gpr_rdi, > - gpr_rsi, > - gpr_rbp, > - gpr_rsp, > - gpr_r8, > - gpr_r9, > - gpr_r10, > - gpr_r11, > - gpr_r12, > - gpr_r13, > - gpr_r14, > - gpr_r15, > - gpr_rip, > - gpr_rflags, > - gpr_cs, > - gpr_fs, > - gpr_gs, > - gpr_ss, > - gpr_ds, > - gpr_es > -}; > - > -static const uint32_t > -g_fpu_regnums[k_num_fpu_registers] = > -{ > - fpu_fcw, > - fpu_fsw, > - fpu_ftw, > - fpu_fop, > - fpu_ip, > - fpu_cs, > - fpu_dp, > - fpu_ds, > - fpu_mxcsr, > - fpu_mxcsrmask, > - fpu_stmm0, > - fpu_stmm1, > - fpu_stmm2, > - fpu_stmm3, > - fpu_stmm4, > - fpu_stmm5, > - fpu_stmm6, > - fpu_stmm7, > - fpu_xmm0, > - fpu_xmm1, > - fpu_xmm2, > - fpu_xmm3, > - fpu_xmm4, > - fpu_xmm5, > - fpu_xmm6, > - fpu_xmm7, > - fpu_xmm8, > - fpu_xmm9, > - fpu_xmm10, > - fpu_xmm11, > - fpu_xmm12, > - fpu_xmm13, > - fpu_xmm14, > - fpu_xmm15 > -}; > - > -static const RegisterSet > -g_reg_sets[k_num_register_sets] = > -{ > - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, > - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } > -}; > - > -// Computes the offset of the given GPR in the user data area. > -#define GPR_OFFSET(regname) \ > - (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \ > - offsetof(RegisterContextLinux_x86_64::GPR, regname)) > - > -// Computes the offset of the given FPR in the user data area. > -#define FPR_OFFSET(regname) \ > - (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \ > - offsetof(RegisterContextLinux_x86_64::FPU, regname)) > - > -// Number of bytes needed to represent a GPR. > -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg) > - > -// Number of bytes needed to represent a FPR. > -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg) > - > -// Number of bytes needed to represent the i'th FP register. > -#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes) > - > -// Number of bytes needed to represent an XMM register. > -#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg) > - > -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ > - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ > - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } > - > -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ > - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ > - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } > - > -#define DEFINE_FP(reg, i) \ > - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > - eFormatVectorOfUInt8, \ > - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ > - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } > - > -#define DEFINE_XMM(reg, i) \ > - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > - eFormatVectorOfUInt8, \ > - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ > - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } > - > -#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU)) > - > -static RegisterInfo > -g_register_infos[k_num_registers] = > -{ > - // General purpose registers. > - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), > - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), > - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), > - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), > - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), > - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), > - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), > - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), > - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), > - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), > - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), > - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), > - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), > - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), > - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), > - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), > - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), > - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), > - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), > - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), > - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), > - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), > - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), > - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), > - > - // i387 Floating point registers. > - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), > - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), > - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), > - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), > - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), > - // FIXME: Extract segment from ip. > - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), > - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), > - // FIXME: Extract segment from dp. > - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), > - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), > - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), > - > - // FP registers. > - DEFINE_FP(stmm, 0), > - DEFINE_FP(stmm, 1), > - DEFINE_FP(stmm, 2), > - DEFINE_FP(stmm, 3), > - DEFINE_FP(stmm, 4), > - DEFINE_FP(stmm, 5), > - DEFINE_FP(stmm, 6), > - DEFINE_FP(stmm, 7), > - > - // XMM registers > - DEFINE_XMM(xmm, 0), > - DEFINE_XMM(xmm, 1), > - DEFINE_XMM(xmm, 2), > - DEFINE_XMM(xmm, 3), > - DEFINE_XMM(xmm, 4), > - DEFINE_XMM(xmm, 5), > - DEFINE_XMM(xmm, 6), > - DEFINE_XMM(xmm, 7), > - DEFINE_XMM(xmm, 8), > - DEFINE_XMM(xmm, 9), > - DEFINE_XMM(xmm, 10), > - DEFINE_XMM(xmm, 11), > - DEFINE_XMM(xmm, 12), > - DEFINE_XMM(xmm, 13), > - DEFINE_XMM(xmm, 14), > - DEFINE_XMM(xmm, 15) > -}; > - > -static unsigned GetRegOffset(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register number."); > - return g_register_infos[reg].byte_offset; > -} > - > -#if 0 // These functions are currently not being used. > -static unsigned GetRegSize(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register number."); > - return g_register_infos[reg].byte_size; > -} > - > -static bool IsGPR(unsigned reg) > -{ > - return reg <= k_last_gpr; // GPR's come first. > -} > - > -static bool IsFPR(unsigned reg) > -{ > - return (k_first_fpr <= reg && reg <= k_last_fpr); > -} > -#endif > - > -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, > - uint32_t concrete_frame_idx) > - : RegisterContextLinux(thread, concrete_frame_idx) > -{ > -} > - > -RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() > -{ > -} > - > -ProcessMonitor & > -RegisterContextLinux_x86_64::GetMonitor() > -{ > - ProcessLinux *process = static_cast(CalculateProcess()); > - return process->GetMonitor(); > -} > - > -void > -RegisterContextLinux_x86_64::Invalidate() > -{ > -} > - > -void > -RegisterContextLinux_x86_64::InvalidateAllRegisters() > -{ > -} > - > -size_t > -RegisterContextLinux_x86_64::GetRegisterCount() > -{ > - return k_num_registers; > -} > - > -const RegisterInfo * > -RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg) > -{ > - if (reg < k_num_registers) > - return &g_register_infos[reg]; > - else > - return NULL; > -} > - > -size_t > -RegisterContextLinux_x86_64::GetRegisterSetCount() > -{ > - return k_num_register_sets; > -} > - > -const RegisterSet * > -RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set) > -{ > - if (set < k_num_register_sets) > - return &g_reg_sets[set]; > - else > - return NULL; > -} > - > -unsigned > -RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset) > -{ > - unsigned reg; > - for (reg = 0; reg < k_num_registers; reg++) > - { > - if (g_register_infos[reg].byte_offset == offset) > - break; > - } > - assert(reg < k_num_registers && "Invalid register offset."); > - return reg; > -} > - > -const char * > -RegisterContextLinux_x86_64::GetRegisterName(unsigned reg) > -{ > - assert(reg < k_num_registers && "Invalid register offset."); > - return g_register_infos[reg].name; > -} > - > -bool > -RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, > - RegisterValue &value) > -{ > - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.ReadRegisterValue(GetRegOffset(reg), value); > -} > - > -bool > -RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) > -{ > - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); > - if (data_sp && ReadGPR () && ReadFPR ()) > - { > - uint8_t *dst = data_sp->GetBytes(); > - ::memcpy (dst, &user.regs, sizeof(user.regs)); > - dst += sizeof(user.regs); > - > - ::memcpy (dst, &user.i387, sizeof(user.i387)); > - return true; > - } > - return false; > -} > - > -bool > -RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, > - const lldb_private::RegisterValue &value) > -{ > - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.WriteRegisterValue(GetRegOffset(reg), value); > -} > - > -bool > -RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) > -{ > - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) > - { > - const uint8_t *src = data_sp->GetBytes(); > - ::memcpy (&user.regs, src, sizeof(user.regs)); > - src += sizeof(user.regs); > - > - ::memcpy (&user.i387, src, sizeof(user.i387)); > - return WriteGPR() & WriteFPR(); > - } > - return false; > -} > - > -bool > -RegisterContextLinux_x86_64::UpdateAfterBreakpoint() > -{ > - // PC points one byte past the int3 responsible for the breakpoint. > - lldb::addr_t pc; > - > - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) > - return false; > - > - SetPC(pc - 1); > - return true; > -} > - > -uint32_t > -RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, > - uint32_t num) > -{ > - if (kind == eRegisterKindGeneric) > - { > - switch (num) > - { > - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; > - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; > - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; > - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; > - case LLDB_REGNUM_GENERIC_RA: > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - > - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) > - { > - switch (num) > - { > - case gcc_dwarf_gpr_rax: return gpr_rax; > - case gcc_dwarf_gpr_rdx: return gpr_rdx; > - case gcc_dwarf_gpr_rcx: return gpr_rcx; > - case gcc_dwarf_gpr_rbx: return gpr_rbx; > - case gcc_dwarf_gpr_rsi: return gpr_rsi; > - case gcc_dwarf_gpr_rdi: return gpr_rdi; > - case gcc_dwarf_gpr_rbp: return gpr_rbp; > - case gcc_dwarf_gpr_rsp: return gpr_rsp; > - case gcc_dwarf_gpr_r8: return gpr_r8; > - case gcc_dwarf_gpr_r9: return gpr_r9; > - case gcc_dwarf_gpr_r10: return gpr_r10; > - case gcc_dwarf_gpr_r11: return gpr_r11; > - case gcc_dwarf_gpr_r12: return gpr_r12; > - case gcc_dwarf_gpr_r13: return gpr_r13; > - case gcc_dwarf_gpr_r14: return gpr_r14; > - case gcc_dwarf_gpr_r15: return gpr_r15; > - case gcc_dwarf_gpr_rip: return gpr_rip; > - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; > - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; > - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; > - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; > - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; > - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; > - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; > - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; > - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; > - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; > - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; > - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; > - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; > - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; > - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; > - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; > - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; > - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; > - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; > - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; > - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; > - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; > - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; > - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - > - if (kind == eRegisterKindGDB) > - { > - switch (num) > - { > - case gdb_gpr_rax : return gpr_rax; > - case gdb_gpr_rbx : return gpr_rbx; > - case gdb_gpr_rcx : return gpr_rcx; > - case gdb_gpr_rdx : return gpr_rdx; > - case gdb_gpr_rsi : return gpr_rsi; > - case gdb_gpr_rdi : return gpr_rdi; > - case gdb_gpr_rbp : return gpr_rbp; > - case gdb_gpr_rsp : return gpr_rsp; > - case gdb_gpr_r8 : return gpr_r8; > - case gdb_gpr_r9 : return gpr_r9; > - case gdb_gpr_r10 : return gpr_r10; > - case gdb_gpr_r11 : return gpr_r11; > - case gdb_gpr_r12 : return gpr_r12; > - case gdb_gpr_r13 : return gpr_r13; > - case gdb_gpr_r14 : return gpr_r14; > - case gdb_gpr_r15 : return gpr_r15; > - case gdb_gpr_rip : return gpr_rip; > - case gdb_gpr_rflags : return gpr_rflags; > - case gdb_gpr_cs : return gpr_cs; > - case gdb_gpr_ss : return gpr_ss; > - case gdb_gpr_ds : return gpr_ds; > - case gdb_gpr_es : return gpr_es; > - case gdb_gpr_fs : return gpr_fs; > - case gdb_gpr_gs : return gpr_gs; > - case gdb_fpu_stmm0 : return fpu_stmm0; > - case gdb_fpu_stmm1 : return fpu_stmm1; > - case gdb_fpu_stmm2 : return fpu_stmm2; > - case gdb_fpu_stmm3 : return fpu_stmm3; > - case gdb_fpu_stmm4 : return fpu_stmm4; > - case gdb_fpu_stmm5 : return fpu_stmm5; > - case gdb_fpu_stmm6 : return fpu_stmm6; > - case gdb_fpu_stmm7 : return fpu_stmm7; > - case gdb_fpu_fcw : return fpu_fcw; > - case gdb_fpu_fsw : return fpu_fsw; > - case gdb_fpu_ftw : return fpu_ftw; > - case gdb_fpu_cs : return fpu_cs; > - case gdb_fpu_ip : return fpu_ip; > - case gdb_fpu_ds : return fpu_ds; > - case gdb_fpu_dp : return fpu_dp; > - case gdb_fpu_fop : return fpu_fop; > - case gdb_fpu_xmm0 : return fpu_xmm0; > - case gdb_fpu_xmm1 : return fpu_xmm1; > - case gdb_fpu_xmm2 : return fpu_xmm2; > - case gdb_fpu_xmm3 : return fpu_xmm3; > - case gdb_fpu_xmm4 : return fpu_xmm4; > - case gdb_fpu_xmm5 : return fpu_xmm5; > - case gdb_fpu_xmm6 : return fpu_xmm6; > - case gdb_fpu_xmm7 : return fpu_xmm7; > - case gdb_fpu_xmm8 : return fpu_xmm8; > - case gdb_fpu_xmm9 : return fpu_xmm9; > - case gdb_fpu_xmm10 : return fpu_xmm10; > - case gdb_fpu_xmm11 : return fpu_xmm11; > - case gdb_fpu_xmm12 : return fpu_xmm12; > - case gdb_fpu_xmm13 : return fpu_xmm13; > - case gdb_fpu_xmm14 : return fpu_xmm14; > - case gdb_fpu_xmm15 : return fpu_xmm15; > - case gdb_fpu_mxcsr : return fpu_mxcsr; > - default: > - return LLDB_INVALID_REGNUM; > - } > - } > - else if (kind == eRegisterKindLLDB) > - { > - return num; > - } > - > - return LLDB_INVALID_REGNUM; > -} > - > -bool > -RegisterContextLinux_x86_64::HardwareSingleStep(bool enable) > -{ > - enum { TRACE_BIT = 0x100 }; > - uint64_t rflags; > - > - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) > - return false; > - > - if (enable) > - { > - if (rflags & TRACE_BIT) > - return true; > - > - rflags |= TRACE_BIT; > - } > - else > - { > - if (!(rflags & TRACE_BIT)) > - return false; > - > - rflags &= ~TRACE_BIT; > - } > - > - return WriteRegisterFromUnsigned(gpr_rflags, rflags); > -} > - > -bool > -RegisterContextLinux_x86_64::ReadGPR() > -{ > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.ReadGPR(&user.regs); > -} > - > -bool > -RegisterContextLinux_x86_64::ReadFPR() > -{ > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.ReadFPR(&user.i387); > -} > - > -bool > -RegisterContextLinux_x86_64::WriteGPR() > -{ > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.WriteGPR(&user.regs); > -} > - > -bool > -RegisterContextLinux_x86_64::WriteFPR() > -{ > - ProcessMonitor &monitor = GetMonitor(); > - return monitor.WriteFPR(&user.i387); > -} > Index: source/Plugins/Process/Linux/ProcessMessage.h > =================================================================== > --- source/Plugins/Process/Linux/ProcessMessage.h (revision 147560) > +++ source/Plugins/Process/Linux/ProcessMessage.h (working copy) > @@ -1,171 +0,0 @@ > -//===-- ProcessMessage.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_ProcessMessage_H_ > -#define liblldb_ProcessMessage_H_ > - > -#include > - > -#include "lldb/lldb-defines.h" > -#include "lldb/lldb-types.h" > - > -class ProcessMessage > -{ > -public: > - > - /// The type of signal this message can correspond to. > - enum Kind > - { > - eInvalidMessage, > - eExitMessage, > - eLimboMessage, > - eSignalMessage, > - eSignalDeliveredMessage, > - eTraceMessage, > - eBreakpointMessage, > - eCrashMessage > - }; > - > - enum CrashReason > - { > - eInvalidCrashReason, > - > - // SIGSEGV crash reasons. > - eInvalidAddress, > - ePrivilegedAddress, > - > - // SIGILL crash reasons. > - eIllegalOpcode, > - eIllegalOperand, > - eIllegalAddressingMode, > - eIllegalTrap, > - ePrivilegedOpcode, > - ePrivilegedRegister, > - eCoprocessorError, > - eInternalStackError, > - > - // SIGBUS crash reasons, > - eIllegalAlignment, > - eIllegalAddress, > - eHardwareError, > - > - // SIGFPE crash reasons, > - eIntegerDivideByZero, > - eIntegerOverflow, > - eFloatDivideByZero, > - eFloatOverflow, > - eFloatUnderflow, > - eFloatInexactResult, > - eFloatInvalidOperation, > - eFloatSubscriptRange > - }; > - > - ProcessMessage() > - : m_tid(LLDB_INVALID_PROCESS_ID), > - m_kind(eInvalidMessage), > - m_crash_reason(eInvalidCrashReason), > - m_status(0), > - m_addr(0) { } > - > - Kind GetKind() const { return m_kind; } > - > - lldb::tid_t GetTID() const { return m_tid; } > - > - /// Indicates that the thread @p tid is about to exit with status @p status. > - static ProcessMessage Limbo(lldb::tid_t tid, int status) { > - return ProcessMessage(tid, eLimboMessage, status); > - } > - > - /// Indicates that the thread @p tid had the signal @p signum delivered. > - static ProcessMessage Signal(lldb::tid_t tid, int signum) { > - return ProcessMessage(tid, eSignalMessage, signum); > - } > - > - /// Indicates that a signal @p signum generated by the debugging process was > - /// delivered to the thread @p tid. > - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { > - return ProcessMessage(tid, eSignalDeliveredMessage, signum); > - } > - > - /// Indicates that the thread @p tid encountered a trace point. > - static ProcessMessage Trace(lldb::tid_t tid) { > - return ProcessMessage(tid, eTraceMessage); > - } > - > - /// Indicates that the thread @p tid encountered a break point. > - static ProcessMessage Break(lldb::tid_t tid) { > - return ProcessMessage(tid, eBreakpointMessage); > - } > - > - /// Indicates that the thread @p tid crashed. > - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, > - int signo, lldb::addr_t fault_addr) { > - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); > - message.m_crash_reason = reason; > - return message; > - } > - > - int GetExitStatus() const { > - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); > - return m_status; > - } > - > - int GetSignal() const { > - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || > - GetKind() == eSignalDeliveredMessage); > - return m_status; > - } > - > - int GetStopStatus() const { > - assert(GetKind() == eSignalMessage); > - return m_status; > - } > - > - CrashReason GetCrashReason() const { > - assert(GetKind() == eCrashMessage); > - return m_crash_reason; > - } > - > - lldb::addr_t GetFaultAddress() const { > - assert(GetKind() == eCrashMessage); > - return m_addr; > - } > - > - static const char * > - GetCrashReasonString(CrashReason reason); > - > - const char * > - PrintCrashReason() const; > - > - static const char * > - PrintCrashReason(CrashReason reason); > - > - const char * > - PrintKind() const; > - > - static const char * > - PrintKind(Kind); > - > -private: > - ProcessMessage(lldb::tid_t tid, Kind kind, > - int status = 0, lldb::addr_t addr = 0) > - : m_tid(tid), > - m_kind(kind), > - m_crash_reason(eInvalidCrashReason), > - m_status(status), > - m_addr(addr) { } > - > - lldb::tid_t m_tid; > - Kind m_kind : 8; > - CrashReason m_crash_reason : 8; > - int m_status; > - lldb::addr_t m_addr; > -}; > - > -#endif // #ifndef liblldb_ProcessMessage_H_ > Index: source/Plugins/Process/Linux/ProcessMonitor.h > =================================================================== > --- source/Plugins/Process/Linux/ProcessMonitor.h (revision 147560) > +++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy) > @@ -24,10 +24,12 @@ > class Error; > class Module; > class Scalar; > + > } // End lldb_private namespace. > > class ProcessLinux; > class Operation; > +class ProcessPOSIX; > > /// @class ProcessMonitor > /// @brief Manages communication with the inferior (debugee) process. > @@ -47,7 +49,7 @@ > > /// Launches an inferior process ready for debugging. Forms the > /// implementation of Process::DoLaunch. > - ProcessMonitor(ProcessLinux *process, > + ProcessMonitor(ProcessPOSIX *process, > lldb_private::Module *module, > char const *argv[], > char const *envp[], > @@ -56,7 +58,7 @@ > const char *stderr_path, > lldb_private::Error &error); > > - ProcessMonitor(ProcessLinux *process, > + ProcessMonitor(ProcessPOSIX *process, > lldb::pid_t pid, > lldb_private::Error &error); > > @@ -104,7 +106,7 @@ > /// > /// This method is provided for use by RegisterContextLinux derivatives. > bool > - ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value); > + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); > > /// Writes the given value to the register identified by the given > /// (architecture dependent) offset. > Index: source/Plugins/Process/Linux/Makefile > =================================================================== > --- source/Plugins/Process/Linux/Makefile (revision 147560) > +++ source/Plugins/Process/Linux/Makefile (working copy) > @@ -12,6 +12,6 @@ > BUILD_ARCHIVE = 1 > > # Extend the include path so we may locate UnwindLLDB.h > -CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility > +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility > > include $(LLDB_LEVEL)/Makefile > Index: source/Plugins/Process/Linux/LinuxThread.h > =================================================================== > --- source/Plugins/Process/Linux/LinuxThread.h (revision 147560) > +++ source/Plugins/Process/Linux/LinuxThread.h (working copy) > @@ -1,102 +0,0 @@ > -//===-- LinuxThread.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_LinuxThread_H_ > -#define liblldb_LinuxThread_H_ > - > -// C Includes > -// C++ Includes > -#include > - > -// Other libraries and framework includes > -#include "lldb/Target/Thread.h" > - > -class ProcessMessage; > -class ProcessMonitor; > -class RegisterContextLinux; > - > -//------------------------------------------------------------------------------ > -// @class LinuxThread > -// @brief Abstraction of a linux process (thread). > -class LinuxThread > - : public lldb_private::Thread > -{ > -public: > - LinuxThread(lldb_private::Process &process, lldb::tid_t tid); > - > - virtual ~LinuxThread(); > - > - void > - RefreshStateAfterStop(); > - > - bool > - WillResume(lldb::StateType resume_state); > - > - const char * > - GetInfo(); > - > - virtual lldb::RegisterContextSP > - GetRegisterContext(); > - > - virtual lldb::RegisterContextSP > - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); > - > - //-------------------------------------------------------------------------- > - // These static functions provide a mapping from the register offset > - // back to the register index or name for use in debugging or log > - // output. > - > - static unsigned > - GetRegisterIndexFromOffset(unsigned offset); > - > - static const char * > - GetRegisterName(unsigned reg); > - > - static const char * > - GetRegisterNameFromOffset(unsigned offset); > - > - //-------------------------------------------------------------------------- > - // These methods form a specialized interface to linux threads. > - // > - bool Resume(); > - > - void Notify(const ProcessMessage &message); > - > -private: > - RegisterContextLinux * > - GetRegisterContextLinux () > - { > - if (!m_reg_context_sp) > - GetRegisterContext(); > - return (RegisterContextLinux *)m_reg_context_sp.get(); > - } > - > - std::auto_ptr m_frame_ap; > - > - lldb::BreakpointSiteSP m_breakpoint; > - lldb::StopInfoSP m_stop_info; > - > - ProcessMonitor & > - GetMonitor(); > - > - lldb::StopInfoSP > - GetPrivateStopReason(); > - > - void BreakNotify(const ProcessMessage &message); > - void TraceNotify(const ProcessMessage &message); > - void LimboNotify(const ProcessMessage &message); > - void SignalNotify(const ProcessMessage &message); > - void SignalDeliveredNotify(const ProcessMessage &message); > - void CrashNotify(const ProcessMessage &message); > - > - lldb_private::Unwind * > - GetUnwinder(); > -}; > - > -#endif // #ifndef liblldb_LinuxThread_H_ > Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h > =================================================================== > --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (revision 147560) > +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (working copy) > @@ -10,67 +10,7 @@ > #ifndef liblldb_RegisterContextLinux_x86_64_H_ > #define liblldb_RegisterContextLinux_x86_64_H_ > > -#include "RegisterContextLinux.h" > - > -class ProcessMonitor; > - > -class RegisterContextLinux_x86_64 > - : public RegisterContextLinux > -{ > -public: > - RegisterContextLinux_x86_64 (lldb_private::Thread &thread, > - uint32_t concrete_frame_idx); > - > - ~RegisterContextLinux_x86_64(); > - > - void > - Invalidate(); > - > - void > - InvalidateAllRegisters(); > - > - size_t > - GetRegisterCount(); > - > - const lldb_private::RegisterInfo * > - GetRegisterInfoAtIndex(uint32_t reg); > - > - size_t > - GetRegisterSetCount(); > - > - const lldb_private::RegisterSet * > - GetRegisterSet(uint32_t set); > - > - static unsigned > - GetRegisterIndexFromOffset(unsigned offset); > - > - static const char * > - GetRegisterName(unsigned reg); > - > - virtual bool > - ReadRegister(const lldb_private::RegisterInfo *reg_info, > - lldb_private::RegisterValue &value); > - > - bool > - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); > - > - virtual bool > - WriteRegister(const lldb_private::RegisterInfo *reg_info, > - const lldb_private::RegisterValue &value); > - > - bool > - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); > - > - uint32_t > - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); > - > - bool > - HardwareSingleStep(bool enable); > - > - bool > - UpdateAfterBreakpoint(); > - > - struct GPR > + typedef struct _GPR > { > uint64_t r15; > uint64_t r14; > @@ -99,67 +39,6 @@ > uint64_t es; > uint64_t fs; > uint64_t gs; > - }; > + } GPR; > > - struct MMSReg > - { > - uint8_t bytes[10]; > - uint8_t pad[6]; > - }; > - > - struct XMMReg > - { > - uint8_t bytes[16]; > - }; > - > - struct FPU > - { > - uint16_t fcw; > - uint16_t fsw; > - uint16_t ftw; > - uint16_t fop; > - uint64_t ip; > - uint64_t dp; > - uint32_t mxcsr; > - uint32_t mxcsrmask; > - MMSReg stmm[8]; > - XMMReg xmm[16]; > - uint32_t padding[24]; > - }; > - > - struct UserArea > - { > - GPR regs; // General purpose registers. > - int32_t fpvalid; // True if FPU is being used. > - int32_t pad0; > - FPU i387; // FPU registers. > - uint64_t tsize; // Text segment size. > - uint64_t dsize; // Data segment size. > - uint64_t ssize; // Stack segment size. > - uint64_t start_code; // VM address of text. > - uint64_t start_stack; // VM address of stack bottom (top in rsp). > - int64_t signal; // Signal causing core dump. > - int32_t reserved; // Unused. > - int32_t pad1; > - uint64_t ar0; // Location of GPR's. > - FPU* fpstate; // Location of FPR's. > - uint64_t magic; // Identifier for core dumps. > - char u_comm[32]; // Command causing core dump. > - uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). > - uint64_t error_code; // CPU error code. > - uint64_t fault_address; // Control register CR3. > - }; > - > -private: > - UserArea user; > - > - ProcessMonitor &GetMonitor(); > - > - bool ReadGPR(); > - bool ReadFPR(); > - > - bool WriteGPR(); > - bool WriteFPR(); > -}; > - > -#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_ > +#endif > Index: source/Plugins/Process/POSIX/POSIXThread.h > =================================================================== > --- source/Plugins/Process/POSIX/POSIXThread.h (revision 0) > +++ source/Plugins/Process/POSIX/POSIXThread.h (revision 0) > @@ -0,0 +1,106 @@ > +//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef liblldb_POSIXThread_H_ > +#define liblldb_POSIXThread_H_ > + > +// C Includes > +// C++ Includes > +#include > + > +// Other libraries and framework includes > +#include "lldb/Target/Thread.h" > +#include "RegisterContextPOSIX.h" > + > +class ProcessMessage; > +class ProcessMonitor; > +class RegisterContextPOSIX; > + > +//------------------------------------------------------------------------------ > +// @class POSIXThread > +// @brief Abstraction of a linux process (thread). > +class POSIXThread > + : public lldb_private::Thread > +{ > +public: > + POSIXThread(lldb_private::Process &process, lldb::tid_t tid); > + > + virtual ~POSIXThread(); > + > + void > + RefreshStateAfterStop(); > + > + bool > + WillResume(lldb::StateType resume_state); > + > + const char * > + GetInfo(); > + > + virtual lldb::RegisterContextSP > + GetRegisterContext(); > + > + virtual lldb::RegisterContextSP > + CreateRegisterContextForFrame (lldb_private::StackFrame *frame); > + > + //-------------------------------------------------------------------------- > + // These static functions provide a mapping from the register offset > + // back to the register index or name for use in debugging or log > + // output. > + > + static unsigned > + GetRegisterIndexFromOffset(unsigned offset); > + > + static const char * > + GetRegisterName(unsigned reg); > + > + static const char * > + GetRegisterNameFromOffset(unsigned offset); > + > + //-------------------------------------------------------------------------- > + // These methods form a specialized interface to linux threads. > + // > + bool Resume(); > + > + void Notify(const ProcessMessage &message); > + > +private: > + RegisterContextPOSIX * > + GetRegisterContextPOSIX () > + { > + if (!m_reg_context_sp) > + m_reg_context_sp = GetRegisterContext(); > +#if 0 > + return dynamic_cast(m_reg_context_sp.get()); > +#endif > + return (RegisterContextPOSIX *)m_reg_context_sp.get(); > + } > + > + std::auto_ptr m_frame_ap; > + > + lldb::BreakpointSiteSP m_breakpoint; > + lldb::StopInfoSP m_stop_info; > + > + ProcessMonitor & > + GetMonitor(); > + > + lldb::StopInfoSP > + GetPrivateStopReason(); > + > + void BreakNotify(const ProcessMessage &message); > + void TraceNotify(const ProcessMessage &message); > + void LimboNotify(const ProcessMessage &message); > + void SignalNotify(const ProcessMessage &message); > + void SignalDeliveredNotify(const ProcessMessage &message); > + void CrashNotify(const ProcessMessage &message); > + > + lldb_private::Unwind * > + GetUnwinder(); > +}; > + > +#endif // #ifndef liblldb_POSIXThread_H_ > Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp > =================================================================== > --- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) > +++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) > @@ -0,0 +1,594 @@ > +//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +// C Includes > +#include > + > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/PluginManager.h" > +#include "lldb/Core/State.h" > +#include "lldb/Host/Host.h" > +#include "lldb/Symbol/ObjectFile.h" > +#include "lldb/Target/DynamicLoader.h" > +#include "lldb/Target/Target.h" > + > +#include "ProcessPOSIX.h" > +#include "ProcessPOSIXLog.h" > +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" > +#include "ProcessMonitor.h" > +#include "POSIXThread.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > +//------------------------------------------------------------------------------ > +// Static functions. > +#if 0 > +Process* > +ProcessPOSIX::CreateInstance(Target& target, Listener &listener) > +{ > + return new ProcessPOSIX(target, listener); > +} > + > + > +void > +ProcessPOSIX::Initialize() > +{ > + static bool g_initialized = false; > + > + if (!g_initialized) > + { > + g_initialized = true; > + PluginManager::RegisterPlugin(GetPluginNameStatic(), > + GetPluginDescriptionStatic(), > + CreateInstance); > + > + Log::Callbacks log_callbacks = { > + ProcessPOSIXLog::DisableLog, > + ProcessPOSIXLog::EnableLog, > + ProcessPOSIXLog::ListLogCategories > + }; > + > + Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks); > + } > +} > +#endif > + > +//------------------------------------------------------------------------------ > +// Constructors and destructors. > + > +ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) > + : Process(target, listener), > + m_monitor(NULL), > + m_module(NULL), > + m_in_limbo(false), > + m_exit_now(false) > +{ > + // FIXME: Putting this code in the ctor and saving the byte order in a > + // member variable is a hack to avoid const qual issues in GetByteOrder. > + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); > + m_byte_order = obj_file->GetByteOrder(); > +} > + > +ProcessPOSIX::~ProcessPOSIX() > +{ > + delete m_monitor; > +} > + > +//------------------------------------------------------------------------------ > +// Process protocol. > + > +bool > +ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) > +{ > + // For now we are just making sure the file exists for a given module > + ModuleSP exe_module_sp(target.GetExecutableModule()); > + if (exe_module_sp.get()) > + return exe_module_sp->GetFileSpec().Exists(); > + return false; > +} > + > +Error > +ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid) > +{ > + Error error; > + assert(m_monitor == NULL); > + > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID()); > + > + m_monitor = new ProcessMonitor(this, pid, error); > + > + if (!error.Success()) > + return error; > + > + SetID(pid); > + return error; > +} > + > +Error > +ProcessPOSIX::WillLaunch(Module* module) > +{ > + Error error; > + return error; > +} > + > +const char * > +ProcessPOSIX::GetFilePath( > + const lldb_private::ProcessLaunchInfo::FileAction *file_action, > + const char *default_path) > +{ > + const char *pts_name = "/dev/pts/"; > + const char *path = NULL; > + > + if (file_action) > + { > + if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) > + path = file_action->GetPath(); > + // By default the stdio paths passed in will be pseudo-terminal > + // (/dev/pts). If so, convert to using a different default path > + // instead to redirect I/O to the debugger console. This should > + // also handle user overrides to /dev/null or a different file. > + if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0) > + path = default_path; > + } > + > + return path; > +} > + > +Error > +ProcessPOSIX::DoLaunch (Module *module, > + const ProcessLaunchInfo &launch_info) > +{ > + Error error; > + assert(m_monitor == NULL); > + > + SetPrivateState(eStateLaunching); > + > + const lldb_private::ProcessLaunchInfo::FileAction *file_action; > + > + // Default of NULL will mean to use existing open file descriptors > + const char *stdin_path = NULL; > + const char *stdout_path = NULL; > + const char *stderr_path = NULL; > + > + file_action = launch_info.GetFileActionForFD (STDIN_FILENO); > + stdin_path = GetFilePath(file_action, stdin_path); > + > + file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); > + stdout_path = GetFilePath(file_action, stdout_path); > + > + file_action = launch_info.GetFileActionForFD (STDERR_FILENO); > + stderr_path = GetFilePath(file_action, stderr_path); > + > + m_monitor = new ProcessMonitor (this, > + module, > + launch_info.GetArguments().GetConstArgumentVector(), > + launch_info.GetEnvironmentEntries().GetConstArgumentVector(), > + stdin_path, > + stdout_path, > + stderr_path, > + error); > + > + m_module = module; > + > + if (!error.Success()) > + return error; > + > + SetID(m_monitor->GetPID()); > + return error; > +} > + > +void > +ProcessPOSIX::DidLaunch() > +{ > +} > + > +Error > +ProcessPOSIX::DoResume() > +{ > + StateType state = GetPrivateState(); > + > + assert(state == eStateStopped || state == eStateCrashed); > + > + // We are about to resume a thread that will cause the process to exit so > + // set our exit status now. Do not change our state if the inferior > + // crashed. > + if (state == eStateStopped) > + { > + if (m_in_limbo) > + SetExitStatus(m_exit_status, NULL); > + else > + SetPrivateState(eStateRunning); > + } > + > + bool did_resume = false; > + uint32_t thread_count = m_thread_list.GetSize(false); > + for (uint32_t i = 0; i < thread_count; ++i) > + { > + POSIXThread *thread = static_cast( > + m_thread_list.GetThreadAtIndex(i, false).get()); > + did_resume = thread->Resume() || did_resume; > + } > + assert(did_resume && "Process resume failed!"); > + > + return Error(); > +} > + > +addr_t > +ProcessPOSIX::GetImageInfoAddress() > +{ > + Target *target = &GetTarget(); > + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); > + Address addr = obj_file->GetImageInfoAddress(); > + > + if (addr.IsValid()) > + return addr.GetLoadAddress(target); > + else > + return LLDB_INVALID_ADDRESS; > +} > + > +Error > +ProcessPOSIX::DoHalt(bool &caused_stop) > +{ > + Error error; > + > + if (IsStopped()) > + { > + caused_stop = false; > + } > + else if (kill(GetID(), SIGSTOP)) > + { > + caused_stop = false; > + error.SetErrorToErrno(); > + } > + else > + { > + caused_stop = true; > + } > + > + return error; > +} > + > +Error > +ProcessPOSIX::DoDetach() > +{ > + Error error; > + > + error = m_monitor->Detach(); > + if (error.Success()) > + SetPrivateState(eStateDetached); > + > + return error; > +} > + > +Error > +ProcessPOSIX::DoSignal(int signal) > +{ > + Error error; > + > + if (kill(GetID(), signal)) > + error.SetErrorToErrno(); > + > + return error; > +} > + > +Error > +ProcessPOSIX::DoDestroy() > +{ > + Error error; > + > + if (!HasExited()) > + { > + // Drive the exit event to completion (do not keep the inferior in > + // limbo). > + m_exit_now = true; > + > + if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) > + { > + error.SetErrorToErrno(); > + return error; > + } > + > + SetPrivateState(eStateExited); > + } > + > + return error; > +} > + > +void > +ProcessPOSIX::SendMessage(const ProcessMessage &message) > +{ > + Mutex::Locker lock(m_message_mutex); > + > + switch (message.GetKind()) > + { > + default: > + assert(false && "Unexpected process message!"); > + break; > + > + case ProcessMessage::eInvalidMessage: > + return; > + > + case ProcessMessage::eLimboMessage: > + m_in_limbo = true; > + m_exit_status = message.GetExitStatus(); > + if (m_exit_now) > + { > + SetPrivateState(eStateExited); > + m_monitor->Detach(); > + } > + else > + SetPrivateState(eStateStopped); > + break; > + > + case ProcessMessage::eExitMessage: > + m_exit_status = message.GetExitStatus(); > + SetExitStatus(m_exit_status, NULL); > + break; > + > + case ProcessMessage::eTraceMessage: > + case ProcessMessage::eBreakpointMessage: > + SetPrivateState(eStateStopped); > + break; > + > + case ProcessMessage::eSignalMessage: > + case ProcessMessage::eSignalDeliveredMessage: > + SetPrivateState(eStateStopped); > + break; > + > + case ProcessMessage::eCrashMessage: > + SetPrivateState(eStateCrashed); > + break; > + } > + > + m_message_queue.push(message); > +} > + > +void > +ProcessPOSIX::RefreshStateAfterStop() > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("ProcessPOSIX::%s()", __FUNCTION__); > + > + Mutex::Locker lock(m_message_mutex); > + if (m_message_queue.empty()) > + return; > + > + ProcessMessage &message = m_message_queue.front(); > + > + // Resolve the thread this message corresponds to and pass it along. > + // FIXME: we're really dealing with the pid here. This should get > + // fixed when this code is fixed to handle multiple threads. > + lldb::tid_t tid = message.GetTID(); > + if (log) > + log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid); > + POSIXThread *thread = static_cast( > + GetThreadList().FindThreadByID(tid, false).get()); > + > + assert(thread); > + thread->Notify(message); > + > + m_message_queue.pop(); > +} > + > +bool > +ProcessPOSIX::IsAlive() > +{ > + StateType state = GetPrivateState(); > + return state != eStateDetached && state != eStateExited && state != eStateInvalid; > +} > + > +size_t > +ProcessPOSIX::DoReadMemory(addr_t vm_addr, > + void *buf, size_t size, Error &error) > +{ > + assert(m_monitor); > + return m_monitor->ReadMemory(vm_addr, buf, size, error); > +} > + > +size_t > +ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, > + Error &error) > +{ > + assert(m_monitor); > + return m_monitor->WriteMemory(vm_addr, buf, size, error); > +} > + > +addr_t > +ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, > + Error &error) > +{ > + addr_t allocated_addr = LLDB_INVALID_ADDRESS; > + > + unsigned prot = 0; > + if (permissions & lldb::ePermissionsReadable) > + prot |= eMmapProtRead; > + if (permissions & lldb::ePermissionsWritable) > + prot |= eMmapProtWrite; > + if (permissions & lldb::ePermissionsExecutable) > + prot |= eMmapProtExec; > + > + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, > + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { > + m_addr_to_mmap_size[allocated_addr] = size; > + error.Clear(); > + } else { > + allocated_addr = LLDB_INVALID_ADDRESS; > + error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); > + } > + > + return allocated_addr; > +} > + > +Error > +ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) > +{ > + Error error; > + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); > + if (pos != m_addr_to_mmap_size.end() && > + InferiorCallMunmap(this, addr, pos->second)) > + m_addr_to_mmap_size.erase (pos); > + else > + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); > + > + return error; > +} > + > +size_t > +ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) > +{ > + static const uint8_t g_i386_opcode[] = { 0xCC }; > + > + ArchSpec arch = GetTarget().GetArchitecture(); > + const uint8_t *opcode = NULL; > + size_t opcode_size = 0; > + > + switch (arch.GetCore()) > + { > + default: > + assert(false && "CPU type not supported!"); > + break; > + > + case ArchSpec::eCore_x86_32_i386: > + case ArchSpec::eCore_x86_64_x86_64: > + opcode = g_i386_opcode; > + opcode_size = sizeof(g_i386_opcode); > + break; > + } > + > + bp_site->SetTrapOpcode(opcode, opcode_size); > + return opcode_size; > +} > + > +Error > +ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site) > +{ > + return EnableSoftwareBreakpoint(bp_site); > +} > + > +Error > +ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site) > +{ > + return DisableSoftwareBreakpoint(bp_site); > +} > + > +uint32_t > +ProcessPOSIX::UpdateThreadListIfNeeded() > +{ > + // Do not allow recursive updates. > + return m_thread_list.GetSize(false); > +} > + > +uint32_t > +ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID()); > + > + // Update the process thread list with this new thread. > + // FIXME: We should be using tid, not pid. > + assert(m_monitor); > + ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); > + if (!thread_sp) > + thread_sp.reset(new POSIXThread(*this, GetID())); > + > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID()); > + new_thread_list.AddThread(thread_sp); > + > + return new_thread_list.GetSize(false); > +} > + > +ByteOrder > +ProcessPOSIX::GetByteOrder() const > +{ > + // FIXME: We should be able to extract this value directly. See comment in > + // ProcessPOSIX(). > + return m_byte_order; > +} > + > +size_t > +ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) > +{ > + ssize_t status; > + if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) > + { > + error.SetErrorToErrno(); > + return 0; > + } > + return status; > +} > + > +size_t > +ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error) > +{ > + ssize_t bytes_read; > + > + // The terminal file descriptor is always in non-block mode. > + if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) > + { > + if (errno != EAGAIN) > + error.SetErrorToErrno(); > + return 0; > + } > + return bytes_read; > +} > + > +size_t > +ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error) > +{ > + return GetSTDOUT(buf, len, error); > +} > + > +UnixSignals & > +ProcessPOSIX::GetUnixSignals() > +{ > + return m_signals; > +} > + > +//------------------------------------------------------------------------------ > +// Utility functions. > + > +bool > +ProcessPOSIX::HasExited() > +{ > + switch (GetPrivateState()) > + { > + default: > + break; > + > + case eStateDetached: > + case eStateExited: > + return true; > + } > + > + return false; > +} > + > +bool > +ProcessPOSIX::IsStopped() > +{ > + switch (GetPrivateState()) > + { > + default: > + break; > + > + case eStateStopped: > + case eStateCrashed: > + case eStateSuspended: > + return true; > + } > + > + return false; > +} > Index: source/Plugins/Process/POSIX/RegisterContext_i386.cpp > =================================================================== > --- source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) > +++ source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) > @@ -0,0 +1,643 @@ > +//===-- RegisterContextPOSIX_i386.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/Core/DataExtractor.h" > +#include "lldb/Target/Thread.h" > +#include "lldb/Host/Endian.h" > + > +#include "ProcessPOSIX.h" > +#include "ProcessPOSIXLog.h" > +#include "ProcessMonitor.h" > +#include "RegisterContext_i386.h" > + > +using namespace lldb_private; > +using namespace lldb; > + > +enum > +{ > + k_first_gpr, > + gpr_eax = k_first_gpr, > + gpr_ebx, > + gpr_ecx, > + gpr_edx, > + gpr_edi, > + gpr_esi, > + gpr_ebp, > + gpr_esp, > + gpr_ss, > + gpr_eflags, > +#ifdef __FreeBSD__ > + gpr_orig_ax, > +#endif > + gpr_eip, > + gpr_cs, > + gpr_ds, > + gpr_es, > + gpr_fs, > + gpr_gs, > + k_last_gpr = gpr_gs, > + > + k_first_fpr, > + fpu_fcw = k_first_fpr, > + fpu_fsw, > + fpu_ftw, > + fpu_fop, > + fpu_ip, > + fpu_cs, > + fpu_foo, > + fpu_fos, > + fpu_mxcsr, > + fpu_stmm0, > + fpu_stmm1, > + fpu_stmm2, > + fpu_stmm3, > + fpu_stmm4, > + fpu_stmm5, > + fpu_stmm6, > + fpu_stmm7, > + fpu_xmm0, > + fpu_xmm1, > + fpu_xmm2, > + fpu_xmm3, > + fpu_xmm4, > + fpu_xmm5, > + fpu_xmm6, > + fpu_xmm7, > + k_last_fpr = fpu_xmm7, > + > + k_num_registers, > + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, > + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 > +}; > + > +// Number of register sets provided by this context. > +enum > +{ > + k_num_register_sets = 2 > +}; > + > +enum > +{ > + gcc_eax = 0, > + gcc_ecx, > + gcc_edx, > + gcc_ebx, > + gcc_ebp, > + gcc_esp, > + gcc_esi, > + gcc_edi, > + gcc_eip, > + gcc_eflags > +}; > + > +enum > +{ > + dwarf_eax = 0, > + dwarf_ecx, > + dwarf_edx, > + dwarf_ebx, > + dwarf_esp, > + dwarf_ebp, > + dwarf_esi, > + dwarf_edi, > + dwarf_eip, > + dwarf_eflags, > + dwarf_stmm0 = 11, > + dwarf_stmm1, > + dwarf_stmm2, > + dwarf_stmm3, > + dwarf_stmm4, > + dwarf_stmm5, > + dwarf_stmm6, > + dwarf_stmm7, > + dwarf_xmm0 = 21, > + dwarf_xmm1, > + dwarf_xmm2, > + dwarf_xmm3, > + dwarf_xmm4, > + dwarf_xmm5, > + dwarf_xmm6, > + dwarf_xmm7 > +}; > + > +enum > +{ > + gdb_eax = 0, > + gdb_ecx = 1, > + gdb_edx = 2, > + gdb_ebx = 3, > + gdb_esp = 4, > + gdb_ebp = 5, > + gdb_esi = 6, > + gdb_edi = 7, > + gdb_eip = 8, > + gdb_eflags = 9, > + gdb_cs = 10, > + gdb_ss = 11, > + gdb_ds = 12, > + gdb_es = 13, > + gdb_fs = 14, > + gdb_gs = 15, > + gdb_stmm0 = 16, > + gdb_stmm1 = 17, > + gdb_stmm2 = 18, > + gdb_stmm3 = 19, > + gdb_stmm4 = 20, > + gdb_stmm5 = 21, > + gdb_stmm6 = 22, > + gdb_stmm7 = 23, > + gdb_fcw = 24, > + gdb_fsw = 25, > + gdb_ftw = 26, > + gdb_fpu_cs = 27, > + gdb_ip = 28, > + gdb_fpu_ds = 29, > + gdb_dp = 30, > + gdb_fop = 31, > + gdb_xmm0 = 32, > + gdb_xmm1 = 33, > + gdb_xmm2 = 34, > + gdb_xmm3 = 35, > + gdb_xmm4 = 36, > + gdb_xmm5 = 37, > + gdb_xmm6 = 38, > + gdb_xmm7 = 39, > + gdb_mxcsr = 40, > + gdb_mm0 = 41, > + gdb_mm1 = 42, > + gdb_mm2 = 43, > + gdb_mm3 = 44, > + gdb_mm4 = 45, > + gdb_mm5 = 46, > + gdb_mm6 = 47, > + gdb_mm7 = 48 > +}; > + > +static const > +uint32_t g_gpr_regnums[k_num_gpr_registers] = > +{ > + gpr_eax, > + gpr_ebx, > + gpr_ecx, > + gpr_edx, > + gpr_edi, > + gpr_esi, > + gpr_ebp, > + gpr_esp, > + gpr_ss, > + gpr_eflags, > +#ifdef __FreeBSD__ > + gpr_orig_ax, > +#endif > + gpr_eip, > + gpr_cs, > + gpr_ds, > + gpr_es, > + gpr_fs, > + gpr_gs, > +}; > + > +static const uint32_t > +g_fpu_regnums[k_num_fpu_registers] = > +{ > + fpu_fcw, > + fpu_fsw, > + fpu_ftw, > + fpu_fop, > + fpu_ip, > + fpu_cs, > + fpu_foo, > + fpu_fos, > + fpu_mxcsr, > + fpu_stmm0, > + fpu_stmm1, > + fpu_stmm2, > + fpu_stmm3, > + fpu_stmm4, > + fpu_stmm5, > + fpu_stmm6, > + fpu_stmm7, > + fpu_xmm0, > + fpu_xmm1, > + fpu_xmm2, > + fpu_xmm3, > + fpu_xmm4, > + fpu_xmm5, > + fpu_xmm6, > + fpu_xmm7, > +}; > + > +static const RegisterSet > +g_reg_sets[k_num_register_sets] = > +{ > + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, > + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } > +}; > + > +// Computes the offset of the given GPR in the user data area. > +#define GPR_OFFSET(regname) \ > + (offsetof(RegisterContext_i386::UserArea, regs) + \ > + offsetof(RegisterContext_i386::GPR, regname)) > + > +// Computes the offset of the given FPR in the user data area. > +#define FPR_OFFSET(regname) \ > + (offsetof(RegisterContext_i386::UserArea, i387) + \ > + offsetof(RegisterContext_i386::FPU, regname)) > + > +// Number of bytes needed to represent a GPR. > +#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) > + > +// Number of bytes needed to represent a FPR. > +#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg) > + > +// Number of bytes needed to represent the i'th FP register. > +#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes) > + > +// Number of bytes needed to represent an XMM register. > +#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg) > + > +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ > + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ > + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } > + > +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ > + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ > + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } > + > +#define DEFINE_FP(reg, i) \ > + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > + eFormatVectorOfUInt8, \ > + { dwarf_##reg##i, dwarf_##reg##i, \ > + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } > + > +#define DEFINE_XMM(reg, i) \ > + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > + eFormatVectorOfUInt8, \ > + { dwarf_##reg##i, dwarf_##reg##i, \ > + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } > + > +static RegisterInfo > +g_register_infos[k_num_registers] = > +{ > + // General purpose registers. > + DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), > + DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), > + DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), > + DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), > + DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), > + DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), > + DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), > + DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), > + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), > + DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), > + DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), > + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), > + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), > + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), > + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), > + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), > + > + // Floating point registers. > + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), > + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), > + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), > + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), > + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), > + DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), > + DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), > + DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), > + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), > + > + DEFINE_FP(stmm, 0), > + DEFINE_FP(stmm, 1), > + DEFINE_FP(stmm, 2), > + DEFINE_FP(stmm, 3), > + DEFINE_FP(stmm, 4), > + DEFINE_FP(stmm, 5), > + DEFINE_FP(stmm, 6), > + DEFINE_FP(stmm, 7), > + > + // XMM registers > + DEFINE_XMM(xmm, 0), > + DEFINE_XMM(xmm, 1), > + DEFINE_XMM(xmm, 2), > + DEFINE_XMM(xmm, 3), > + DEFINE_XMM(xmm, 4), > + DEFINE_XMM(xmm, 5), > + DEFINE_XMM(xmm, 6), > + DEFINE_XMM(xmm, 7), > + > +}; > + > +#ifndef NDEBUG > +static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); > +#endif > + > +static unsigned GetRegOffset(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register number."); > + return g_register_infos[reg].byte_offset; > +} > + > +static unsigned GetRegSize(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register number."); > + return g_register_infos[reg].byte_size; > +} > + > +RegisterContext_i386::RegisterContext_i386(Thread &thread, > + uint32_t concrete_frame_idx) > + : RegisterContextPOSIX(thread, concrete_frame_idx) > +{ > +} > + > +RegisterContext_i386::~RegisterContext_i386() > +{ > +} > + > +ProcessMonitor & > +RegisterContext_i386::GetMonitor() > +{ > + ProcessPOSIX *process = static_cast(CalculateProcess()); > + return process->GetMonitor(); > +} > + > +void > +RegisterContext_i386::Invalidate() > +{ > +} > + > +void > +RegisterContext_i386::InvalidateAllRegisters() > +{ > +} > + > +size_t > +RegisterContext_i386::GetRegisterCount() > +{ > + assert(k_num_register_infos == k_num_registers); > + return k_num_registers; > +} > + > +const RegisterInfo * > +RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg) > +{ > + assert(k_num_register_infos == k_num_registers); > + if (reg < k_num_registers) > + return &g_register_infos[reg]; > + else > + return NULL; > +} > + > +size_t > +RegisterContext_i386::GetRegisterSetCount() > +{ > + return k_num_register_sets; > +} > + > +const RegisterSet * > +RegisterContext_i386::GetRegisterSet(uint32_t set) > +{ > + if (set < k_num_register_sets) > + return &g_reg_sets[set]; > + else > + return NULL; > +} > + > +unsigned > +RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset) > +{ > + unsigned reg; > + for (reg = 0; reg < k_num_registers; reg++) > + { > + if (g_register_infos[reg].byte_offset == offset) > + break; > + } > + assert(reg < k_num_registers && "Invalid register offset."); > + return reg; > +} > + > +const char * > +RegisterContext_i386::GetRegisterName(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register offset."); > + return g_register_infos[reg].name; > +} > + > +bool > +RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info, > + RegisterValue &value) > +{ > + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); > +} > + > +bool > +RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp) > +{ > + return false; > +} > + > +bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info, > + const RegisterValue &value) > +{ > + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.WriteRegisterValue(GetRegOffset(reg), value); > +} > + > +bool > +RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data) > +{ > + return false; > +} > + > +bool > +RegisterContext_i386::UpdateAfterBreakpoint() > +{ > + // PC points one byte past the int3 responsible for the breakpoint. > + lldb::addr_t pc; > + > + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) > + return false; > + > + SetPC(pc - 1); > + return true; > +} > + > +uint32_t > +RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, > + uint32_t num) > +{ > + if (kind == eRegisterKindGeneric) > + { > + switch (num) > + { > + case LLDB_REGNUM_GENERIC_PC: return gpr_eip; > + case LLDB_REGNUM_GENERIC_SP: return gpr_esp; > + case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; > + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; > + case LLDB_REGNUM_GENERIC_RA: > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + > + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) > + { > + switch (num) > + { > + case dwarf_eax: return gpr_eax; > + case dwarf_edx: return gpr_edx; > + case dwarf_ecx: return gpr_ecx; > + case dwarf_ebx: return gpr_ebx; > + case dwarf_esi: return gpr_esi; > + case dwarf_edi: return gpr_edi; > + case dwarf_ebp: return gpr_ebp; > + case dwarf_esp: return gpr_esp; > + case dwarf_eip: return gpr_eip; > + case dwarf_xmm0: return fpu_xmm0; > + case dwarf_xmm1: return fpu_xmm1; > + case dwarf_xmm2: return fpu_xmm2; > + case dwarf_xmm3: return fpu_xmm3; > + case dwarf_xmm4: return fpu_xmm4; > + case dwarf_xmm5: return fpu_xmm5; > + case dwarf_xmm6: return fpu_xmm6; > + case dwarf_xmm7: return fpu_xmm7; > + case dwarf_stmm0: return fpu_stmm0; > + case dwarf_stmm1: return fpu_stmm1; > + case dwarf_stmm2: return fpu_stmm2; > + case dwarf_stmm3: return fpu_stmm3; > + case dwarf_stmm4: return fpu_stmm4; > + case dwarf_stmm5: return fpu_stmm5; > + case dwarf_stmm6: return fpu_stmm6; > + case dwarf_stmm7: return fpu_stmm7; > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + > + if (kind == eRegisterKindGDB) > + { > + switch (num) > + { > + case gdb_eax : return gpr_eax; > + case gdb_ebx : return gpr_ebx; > + case gdb_ecx : return gpr_ecx; > + case gdb_edx : return gpr_edx; > + case gdb_esi : return gpr_esi; > + case gdb_edi : return gpr_edi; > + case gdb_ebp : return gpr_ebp; > + case gdb_esp : return gpr_esp; > + case gdb_eip : return gpr_eip; > + case gdb_eflags : return gpr_eflags; > + case gdb_cs : return gpr_cs; > + case gdb_ss : return gpr_ss; > + case gdb_ds : return gpr_ds; > + case gdb_es : return gpr_es; > + case gdb_fs : return gpr_fs; > + case gdb_gs : return gpr_gs; > + case gdb_stmm0 : return fpu_stmm0; > + case gdb_stmm1 : return fpu_stmm1; > + case gdb_stmm2 : return fpu_stmm2; > + case gdb_stmm3 : return fpu_stmm3; > + case gdb_stmm4 : return fpu_stmm4; > + case gdb_stmm5 : return fpu_stmm5; > + case gdb_stmm6 : return fpu_stmm6; > + case gdb_stmm7 : return fpu_stmm7; > + case gdb_fcw : return fpu_fcw; > + case gdb_fsw : return fpu_fsw; > + case gdb_ftw : return fpu_ftw; > + case gdb_fpu_cs : return fpu_cs; > + case gdb_ip : return fpu_ip; > + case gdb_fpu_ds : return fpu_fos; > + case gdb_dp : return fpu_foo; > + case gdb_fop : return fpu_fop; > + case gdb_xmm0 : return fpu_xmm0; > + case gdb_xmm1 : return fpu_xmm1; > + case gdb_xmm2 : return fpu_xmm2; > + case gdb_xmm3 : return fpu_xmm3; > + case gdb_xmm4 : return fpu_xmm4; > + case gdb_xmm5 : return fpu_xmm5; > + case gdb_xmm6 : return fpu_xmm6; > + case gdb_xmm7 : return fpu_xmm7; > + case gdb_mxcsr : return fpu_mxcsr; > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + else if (kind == eRegisterKindLLDB) > + { > + return num; > + } > + > + return LLDB_INVALID_REGNUM; > +} > + > +bool > +RegisterContext_i386::HardwareSingleStep(bool enable) > +{ > + enum { TRACE_BIT = 0x100 }; > + uint64_t eflags; > + > + if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) > + return false; > + > + if (enable) > + { > + if (eflags & TRACE_BIT) > + return true; > + > + eflags |= TRACE_BIT; > + } > + else > + { > + if (!(eflags & TRACE_BIT)) > + return false; > + > + eflags &= ~TRACE_BIT; > + } > + > + return WriteRegisterFromUnsigned(gpr_eflags, eflags); > +} > + > +void > +RegisterContext_i386::LogGPR(const char *title) > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); > + if (log) > + { > + if (title) > + log->Printf ("%s", title); > + for (uint32_t i=0; i + { > + uint32_t reg = gpr_eax + i; > + log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); > + } > + } > +} > + > +bool > +RegisterContext_i386::ReadGPR() > +{ > + bool result; > + > + ProcessMonitor &monitor = GetMonitor(); > + result = monitor.ReadGPR(&user.regs); > + LogGPR("RegisterContext_i386::ReadGPR()"); > + return result; > +} > + > +bool > +RegisterContext_i386::ReadFPR() > +{ > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.ReadFPR(&user.i387); > +} > Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp > =================================================================== > --- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) > +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) > @@ -0,0 +1,195 @@ > +//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#include "ProcessPOSIXLog.h" > + > +#include "lldb/Interpreter/Args.h" > +#include "lldb/Core/StreamFile.h" > + > +#include "ProcessPOSIX.h" > +#include "ProcessPOSIXLog.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > + > +// We want to avoid global constructors where code needs to be run so here we > +// control access to our static g_log_sp by hiding it in a singleton function > +// that will construct the static g_lob_sp the first time this function is > +// called. > +static LogSP & > +GetLog () > +{ > + static LogSP g_log_sp; > + return g_log_sp; > +} > + > +LogSP > +ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) > +{ > + LogSP log(GetLog ()); > + if (log && mask) > + { > + uint32_t log_mask = log->GetMask().Get(); > + if ((log_mask & mask) != mask) > + return LogSP(); > + } > + return log; > +} > + > +void > +ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm) > +{ > + LogSP log (GetLog ()); > + if (log) > + { > + uint32_t flag_bits = 0; > + > + const size_t argc = args.GetArgumentCount (); > + if (argc > 0) > + { > + flag_bits = log->GetMask().Get(); > + for (size_t i = 0; i < argc; ++i) > + { > + const char *arg = args.GetArgumentAtIndex (i); > + > + > + if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; > + else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; > + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; > + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; > + else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; > + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; > + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; > + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; > + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; > + else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; > + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; > + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; > + else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; > + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; > + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; > + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; > + else > + { > + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); > + ListLogCategories (feedback_strm); > + } > + > + } > + } > + > + if (flag_bits == 0) > + GetLog ().reset(); > + else > + log->GetMask().Reset (flag_bits); > + } > + > + return; > +} > + > +LogSP > +ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) > +{ > + // Try see if there already is a log - that way we can reuse its settings. > + // We could reuse the log in toto, but we don't know that the stream is the same. > + uint32_t flag_bits = 0; > + LogSP log(GetLog ()); > + if (log) > + flag_bits = log->GetMask().Get(); > + > + // Now make a new log with this stream if one was provided > + if (log_stream_sp) > + { > + log = make_shared(log_stream_sp); > + GetLog () = log; > + } > + > + if (log) > + { > + bool got_unknown_category = false; > + const size_t argc = args.GetArgumentCount(); > + for (size_t i=0; i + { > + const char *arg = args.GetArgumentAtIndex(i); > + > + if (::strcasecmp (arg, "all") == 0 ) flag_bits |= POSIX_LOG_ALL; > + else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= POSIX_LOG_ASYNC; > + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS; > + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= POSIX_LOG_COMM; > + else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= POSIX_LOG_DEFAULT; > + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= POSIX_LOG_PACKETS; > + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= POSIX_LOG_MEMORY; > + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT; > + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG; > + else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= POSIX_LOG_PROCESS; > + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= POSIX_LOG_PTRACE; > + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= POSIX_LOG_REGISTERS; > + else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= POSIX_LOG_STEP; > + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= POSIX_LOG_THREAD; > + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= POSIX_LOG_VERBOSE; > + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS; > + else > + { > + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); > + if (got_unknown_category == false) > + { > + got_unknown_category = true; > + ListLogCategories (feedback_strm); > + } > + } > + } > + if (flag_bits == 0) > + flag_bits = POSIX_LOG_DEFAULT; > + log->GetMask().Reset(flag_bits); > + log->GetOptions().Reset(log_options); > + } > + return log; > +} > + > +void > +ProcessPOSIXLog::ListLogCategories (Stream *strm) > +{ > + strm->Printf ("Logging categories for '%s':\n" > + " all - turn on all available logging categories\n" > + " async - log asynchronous activity\n" > + " break - log breakpoints\n" > + " communication - log communication activity\n" > + " default - enable the default set of logging categories for liblldb\n" > + " packets - log gdb remote packets\n" > + " memory - log memory reads and writes\n" > + " data-short - log memory bytes for memory reads and writes for short transactions only\n" > + " data-long - log memory bytes for memory reads and writes for all transactions\n" > + " process - log process events and activities\n" > +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION > + " ptrace - log all calls to ptrace\n" > +#endif > + " registers - log register read/writes\n" > + " thread - log thread events and activities\n" > + " step - log step related activities\n" > + " verbose - enable verbose logging\n" > + " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); > +} > + > + > +void > +ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); > + if (log) > + { > + va_list args; > + va_start (args, format); > + log->VAPrintf (format, args); > + va_end (args); > + } > +} > + > +int ProcessPOSIXLog::m_nestinglevel; > +const char *ProcessPOSIXLog::m_pluginname = ""; > Index: source/Plugins/Process/POSIX/ProcessPOSIX.h > =================================================================== > --- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) > +++ source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) > @@ -0,0 +1,180 @@ > +//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef liblldb_ProcessPOSIX_H_ > +#define liblldb_ProcessPOSIX_H_ > + > +// C Includes > + > +// C++ Includes > +#include > + > +// Other libraries and framework includes > +#include "lldb/Target/Process.h" > +#include "lldb/Target/UnixSignals.h" > +#include "ProcessMessage.h" > + > +class ProcessMonitor; > + > +class ProcessPOSIX : > + public lldb_private::Process > +{ > +public: > + > + //------------------------------------------------------------------ > + // Constructors and destructors > + //------------------------------------------------------------------ > + ProcessPOSIX(lldb_private::Target& target, > + lldb_private::Listener &listener); > + > + virtual > + ~ProcessPOSIX(); > + > + //------------------------------------------------------------------ > + // Process protocol. > + //------------------------------------------------------------------ > + virtual bool > + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); > + > + virtual lldb_private::Error > + WillLaunch(lldb_private::Module *module); > + > + virtual lldb_private::Error > + DoAttachToProcessWithID(lldb::pid_t pid); > + > + virtual lldb_private::Error > + DoLaunch (lldb_private::Module *exe_module, > + const lldb_private::ProcessLaunchInfo &launch_info); > + > + virtual void > + DidLaunch(); > + > + virtual lldb_private::Error > + DoResume(); > + > + virtual lldb_private::Error > + DoHalt(bool &caused_stop); > + > + virtual lldb_private::Error > + DoDetach(); > + > + virtual lldb_private::Error > + DoSignal(int signal); > + > + virtual lldb_private::Error > + DoDestroy(); > + > + virtual void > + RefreshStateAfterStop(); > + > + virtual bool > + IsAlive(); > + > + virtual size_t > + DoReadMemory(lldb::addr_t vm_addr, > + void *buf, > + size_t size, > + lldb_private::Error &error); > + > + virtual size_t > + DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, > + lldb_private::Error &error); > + > + virtual lldb::addr_t > + DoAllocateMemory(size_t size, uint32_t permissions, > + lldb_private::Error &error); > + > + virtual lldb_private::Error > + DoDeallocateMemory(lldb::addr_t ptr); > + > + virtual size_t > + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); > + > + virtual lldb_private::Error > + EnableBreakpoint(lldb_private::BreakpointSite *bp_site); > + > + virtual lldb_private::Error > + DisableBreakpoint(lldb_private::BreakpointSite *bp_site); > + > + virtual uint32_t > + UpdateThreadListIfNeeded(); > + > + virtual uint32_t > + UpdateThreadList(lldb_private::ThreadList &old_thread_list, > + lldb_private::ThreadList &new_thread_list) = 0; > + > + virtual lldb::ByteOrder > + GetByteOrder() const; > + > + virtual lldb::addr_t > + GetImageInfoAddress(); > + > + virtual size_t > + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); > + > + virtual size_t > + GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); > + > + virtual size_t > + GetSTDERR(char *buf, size_t len, lldb_private::Error &error); > + > + //-------------------------------------------------------------------------- > + // ProcessPOSIX internal API. > + > + /// Registers the given message with this process. > + void SendMessage(const ProcessMessage &message); > + > + ProcessMonitor & > + GetMonitor() { assert(m_monitor); return *m_monitor; } > + > + lldb_private::UnixSignals & > + GetUnixSignals(); > + > + const char * > + GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action, > + const char *default_path); > + > +protected: > + /// Target byte order. > + lldb::ByteOrder m_byte_order; > + > + /// Process monitor; > + ProcessMonitor *m_monitor; > + > + /// The module we are executing. > + lldb_private::Module *m_module; > + > + /// Message queue notifying this instance of inferior process state changes. > + lldb_private::Mutex m_message_mutex; > + std::queue m_message_queue; > + > + /// True when the process has entered a state of "limbo". > + /// > + /// This flag qualifies eStateStopped. It lets us know that when we > + /// continue from this state the process will exit. Also, when true, > + /// Process::m_exit_status is set. > + bool m_in_limbo; > + > + /// Drive any exit events to completion. > + bool m_exit_now; > + > + /// OS-specific signal set. > + lldb_private::UnixSignals m_signals; > + > + /// Returns true if the process has exited. > + bool HasExited(); > + > + /// Returns true if the process is stopped. > + bool IsStopped(); > + > + typedef std::map MMapMap; > + MMapMap m_addr_to_mmap_size; > +}; > + > +#endif // liblldb_MacOSXProcess_H_ > Index: source/Plugins/Process/POSIX/RegisterContext_i386.h > =================================================================== > --- source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) > +++ source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) > @@ -0,0 +1,169 @@ > +//===-- RegisterContext_i386.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_RegisterContext_i386_h_ > +#define liblldb_RegisterContext_i386_h_ > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +// Project includes > +#include "lldb/Core/Log.h" > +#include "RegisterContextPOSIX.h" > + > +class RegisterContext_i386 : public RegisterContextPOSIX > +{ > +public: > + RegisterContext_i386(lldb_private::Thread &thread, > + uint32_t concreate_frame_idx); > + > + ~RegisterContext_i386(); > + > + void > + Invalidate(); > + > + void > + InvalidateAllRegisters(); > + > + size_t > + GetRegisterCount(); > + > + const lldb_private::RegisterInfo * > + GetRegisterInfoAtIndex(uint32_t reg); > + > + size_t > + GetRegisterSetCount(); > + > + const lldb_private::RegisterSet * > + GetRegisterSet(uint32_t set); > + > + static unsigned > + GetRegisterIndexFromOffset(unsigned offset); > + > + static const char * > + GetRegisterName(unsigned reg); > + > + bool > + ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); > + > + bool > + ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); > + > + virtual bool > + ReadRegister(const lldb_private::RegisterInfo *reg_info, > + lldb_private::RegisterValue &value); > + > + bool > + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); > + > + bool > + WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); > + > + bool > + WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, > + uint32_t data_offset = 0); > + > + virtual bool > + WriteRegister(const lldb_private::RegisterInfo *reg_info, > + const lldb_private::RegisterValue &value); > + > + bool > + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); > + > + uint32_t > + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); > + > + bool > + HardwareSingleStep(bool enable); > + > + bool > + UpdateAfterBreakpoint(); > + > + struct GPR > + { > + uint32_t ebx; > + uint32_t ecx; > + uint32_t edx; > + uint32_t esi; > + uint32_t edi; > + uint32_t ebp; > + uint32_t eax; > + uint32_t ds; > + uint32_t es; > + uint32_t fs; > + uint32_t gs; > + uint32_t orig_ax; > + uint32_t eip; > + uint32_t cs; > + uint32_t eflags; > + uint32_t esp; > + uint32_t ss; > + }; > + > + struct MMSReg > + { > + uint8_t bytes[8]; > + }; > + > + struct XMMReg > + { > + uint8_t bytes[16]; > + }; > + > + struct FPU > + { > + uint16_t fcw; > + uint16_t fsw; > + uint16_t ftw; > + uint16_t fop; > + uint32_t ip; > + uint32_t cs; > + uint32_t foo; > + uint32_t fos; > + uint32_t mxcsr; > + uint32_t reserved; > + MMSReg stmm[8]; > + XMMReg xmm[8]; > + uint32_t pad[56]; > + }; > + > + // A user area like this no longer exists on FreeBSD > + // making this a Linux artifact. Nonetheless, it is safe > + // leaving it here while the code is being cleaned up and generalized. > + > + struct UserArea > + { > + GPR regs; // General purpose registers. > + int32_t fpvalid; // True if FPU is being used. > + FPU i387; // FPU registers. > + uint32_t tsize; // Text segment size. > + uint32_t dsize; // Data segment size. > + uint32_t ssize; // Stack segment size. > + uint32_t start_code; // VM address of text. > + uint32_t start_stack; // VM address of stack bottom (top in rsp). > + int32_t signal; // Signal causing core dump. > + int32_t reserved; // Unused. > + uint32_t ar0; // Location of GPR's. > + FPU* fpstate; // Location of FPR's. > + uint32_t magic; // Identifier for core dumps. > + char u_comm[32]; // Command causing core dump. > + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). > + }; > +private: > + UserArea user; > + > + ProcessMonitor &GetMonitor(); > + > + void LogGPR(const char *title); > + > + bool ReadGPR(); > + bool ReadFPR(); > +}; > + > +#endif // #ifndef liblldb_RegisterContext_i386_h_ > Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp > =================================================================== > --- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) > +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) > @@ -0,0 +1,757 @@ > +//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#include > +#include > +#include > + > +#include "lldb/Core/DataBufferHeap.h" > +#include "lldb/Core/DataExtractor.h" > +#include "lldb/Core/Scalar.h" > +#include "lldb/Target/Thread.h" > +#include "lldb/Host/Endian.h" > + > +#include "ProcessPOSIX.h" > +#include "ProcessMonitor.h" > +#include "RegisterContext_x86_64.h" > + > +using namespace lldb_private; > +using namespace lldb; > + > +// Internal codes for all x86_64 registers. > +enum > +{ > + k_first_gpr, > + gpr_rax = k_first_gpr, > + gpr_rbx, > + gpr_rcx, > + gpr_rdx, > + gpr_rdi, > + gpr_rsi, > + gpr_rbp, > + gpr_rsp, > + gpr_r8, > + gpr_r9, > + gpr_r10, > + gpr_r11, > + gpr_r12, > + gpr_r13, > + gpr_r14, > + gpr_r15, > + gpr_rip, > + gpr_rflags, > + gpr_cs, > + gpr_fs, > + gpr_gs, > + gpr_ss, > + gpr_ds, > + gpr_es, > + k_last_gpr = gpr_es, > + > + k_first_fpr, > + fpu_fcw = k_first_fpr, > + fpu_fsw, > + fpu_ftw, > + fpu_fop, > + fpu_ip, > + fpu_cs, > + fpu_dp, > + fpu_ds, > + fpu_mxcsr, > + fpu_mxcsrmask, > + fpu_stmm0, > + fpu_stmm1, > + fpu_stmm2, > + fpu_stmm3, > + fpu_stmm4, > + fpu_stmm5, > + fpu_stmm6, > + fpu_stmm7, > + fpu_xmm0, > + fpu_xmm1, > + fpu_xmm2, > + fpu_xmm3, > + fpu_xmm4, > + fpu_xmm5, > + fpu_xmm6, > + fpu_xmm7, > + fpu_xmm8, > + fpu_xmm9, > + fpu_xmm10, > + fpu_xmm11, > + fpu_xmm12, > + fpu_xmm13, > + fpu_xmm14, > + fpu_xmm15, > + k_last_fpr = fpu_xmm15, > + > + k_num_registers, > + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, > + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 > +}; > + > +// Number of register sets provided by this context. > +enum > +{ > + k_num_register_sets = 2 > +}; > + > +enum gcc_dwarf_regnums > +{ > + gcc_dwarf_gpr_rax = 0, > + gcc_dwarf_gpr_rdx, > + gcc_dwarf_gpr_rcx, > + gcc_dwarf_gpr_rbx, > + gcc_dwarf_gpr_rsi, > + gcc_dwarf_gpr_rdi, > + gcc_dwarf_gpr_rbp, > + gcc_dwarf_gpr_rsp, > + gcc_dwarf_gpr_r8, > + gcc_dwarf_gpr_r9, > + gcc_dwarf_gpr_r10, > + gcc_dwarf_gpr_r11, > + gcc_dwarf_gpr_r12, > + gcc_dwarf_gpr_r13, > + gcc_dwarf_gpr_r14, > + gcc_dwarf_gpr_r15, > + gcc_dwarf_gpr_rip, > + gcc_dwarf_fpu_xmm0, > + gcc_dwarf_fpu_xmm1, > + gcc_dwarf_fpu_xmm2, > + gcc_dwarf_fpu_xmm3, > + gcc_dwarf_fpu_xmm4, > + gcc_dwarf_fpu_xmm5, > + gcc_dwarf_fpu_xmm6, > + gcc_dwarf_fpu_xmm7, > + gcc_dwarf_fpu_xmm8, > + gcc_dwarf_fpu_xmm9, > + gcc_dwarf_fpu_xmm10, > + gcc_dwarf_fpu_xmm11, > + gcc_dwarf_fpu_xmm12, > + gcc_dwarf_fpu_xmm13, > + gcc_dwarf_fpu_xmm14, > + gcc_dwarf_fpu_xmm15, > + gcc_dwarf_fpu_stmm0, > + gcc_dwarf_fpu_stmm1, > + gcc_dwarf_fpu_stmm2, > + gcc_dwarf_fpu_stmm3, > + gcc_dwarf_fpu_stmm4, > + gcc_dwarf_fpu_stmm5, > + gcc_dwarf_fpu_stmm6, > + gcc_dwarf_fpu_stmm7 > +}; > + > +enum gdb_regnums > +{ > + gdb_gpr_rax = 0, > + gdb_gpr_rbx = 1, > + gdb_gpr_rcx = 2, > + gdb_gpr_rdx = 3, > + gdb_gpr_rsi = 4, > + gdb_gpr_rdi = 5, > + gdb_gpr_rbp = 6, > + gdb_gpr_rsp = 7, > + gdb_gpr_r8 = 8, > + gdb_gpr_r9 = 9, > + gdb_gpr_r10 = 10, > + gdb_gpr_r11 = 11, > + gdb_gpr_r12 = 12, > + gdb_gpr_r13 = 13, > + gdb_gpr_r14 = 14, > + gdb_gpr_r15 = 15, > + gdb_gpr_rip = 16, > + gdb_gpr_rflags = 17, > + gdb_gpr_cs = 18, > + gdb_gpr_ss = 19, > + gdb_gpr_ds = 20, > + gdb_gpr_es = 21, > + gdb_gpr_fs = 22, > + gdb_gpr_gs = 23, > + gdb_fpu_stmm0 = 24, > + gdb_fpu_stmm1 = 25, > + gdb_fpu_stmm2 = 26, > + gdb_fpu_stmm3 = 27, > + gdb_fpu_stmm4 = 28, > + gdb_fpu_stmm5 = 29, > + gdb_fpu_stmm6 = 30, > + gdb_fpu_stmm7 = 31, > + gdb_fpu_fcw = 32, > + gdb_fpu_fsw = 33, > + gdb_fpu_ftw = 34, > + gdb_fpu_cs = 35, > + gdb_fpu_ip = 36, > + gdb_fpu_ds = 37, > + gdb_fpu_dp = 38, > + gdb_fpu_fop = 39, > + gdb_fpu_xmm0 = 40, > + gdb_fpu_xmm1 = 41, > + gdb_fpu_xmm2 = 42, > + gdb_fpu_xmm3 = 43, > + gdb_fpu_xmm4 = 44, > + gdb_fpu_xmm5 = 45, > + gdb_fpu_xmm6 = 46, > + gdb_fpu_xmm7 = 47, > + gdb_fpu_xmm8 = 48, > + gdb_fpu_xmm9 = 49, > + gdb_fpu_xmm10 = 50, > + gdb_fpu_xmm11 = 51, > + gdb_fpu_xmm12 = 52, > + gdb_fpu_xmm13 = 53, > + gdb_fpu_xmm14 = 54, > + gdb_fpu_xmm15 = 55, > + gdb_fpu_mxcsr = 56 > +}; > + > +static const > +uint32_t g_gpr_regnums[k_num_gpr_registers] = > +{ > + gpr_rax, > + gpr_rbx, > + gpr_rcx, > + gpr_rdx, > + gpr_rdi, > + gpr_rsi, > + gpr_rbp, > + gpr_rsp, > + gpr_r8, > + gpr_r9, > + gpr_r10, > + gpr_r11, > + gpr_r12, > + gpr_r13, > + gpr_r14, > + gpr_r15, > + gpr_rip, > + gpr_rflags, > + gpr_cs, > + gpr_fs, > + gpr_gs, > + gpr_ss, > + gpr_ds, > + gpr_es > +}; > + > +static const uint32_t > +g_fpu_regnums[k_num_fpu_registers] = > +{ > + fpu_fcw, > + fpu_fsw, > + fpu_ftw, > + fpu_fop, > + fpu_ip, > + fpu_cs, > + fpu_dp, > + fpu_ds, > + fpu_mxcsr, > + fpu_mxcsrmask, > + fpu_stmm0, > + fpu_stmm1, > + fpu_stmm2, > + fpu_stmm3, > + fpu_stmm4, > + fpu_stmm5, > + fpu_stmm6, > + fpu_stmm7, > + fpu_xmm0, > + fpu_xmm1, > + fpu_xmm2, > + fpu_xmm3, > + fpu_xmm4, > + fpu_xmm5, > + fpu_xmm6, > + fpu_xmm7, > + fpu_xmm8, > + fpu_xmm9, > + fpu_xmm10, > + fpu_xmm11, > + fpu_xmm12, > + fpu_xmm13, > + fpu_xmm14, > + fpu_xmm15 > +}; > + > +static const RegisterSet > +g_reg_sets[k_num_register_sets] = > +{ > + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, > + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } > +}; > + > +// Computes the offset of the given GPR in the user data area. > +#define GPR_OFFSET(regname) \ > + (offsetof(RegisterContext_x86_64::UserArea, regs) + \ > + offsetof(GPR, regname)) > + > +// Computes the offset of the given FPR in the user data area. > +#define FPR_OFFSET(regname) \ > + (offsetof(RegisterContext_x86_64::UserArea, i387) + \ > + offsetof(RegisterContext_x86_64::FPU, regname)) > + > +// Number of bytes needed to represent a GPR. > +#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg) > + > +// Number of bytes needed to represent a FPR. > +#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg) > + > +// Number of bytes needed to represent the i'th FP register. > +#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes) > + > +// Number of bytes needed to represent an XMM register. > +#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg) > + > +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ > + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ > + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } > + > +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ > + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ > + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } > + > +#define DEFINE_FP(reg, i) \ > + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > + eFormatVectorOfUInt8, \ > + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ > + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } > + > +#define DEFINE_XMM(reg, i) \ > + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ > + eFormatVectorOfUInt8, \ > + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ > + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } > + > +#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU)) > + > +static RegisterInfo > +g_register_infos[k_num_registers] = > +{ > + // General purpose registers. > + DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), > + DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), > + DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), > + DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), > + DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), > + DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), > + DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), > + DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), > + DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), > + DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), > + DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), > + DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), > + DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), > + DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), > + DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), > + DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), > + DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), > + DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), > + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), > + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), > + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), > + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), > + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), > + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), > + > + // i387 Floating point registers. > + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), > + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), > + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), > + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), > + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), > + // FIXME: Extract segment from ip. > + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), > + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), > + // FIXME: Extract segment from dp. > + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), > + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), > + DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), > + > + // FP registers. > + DEFINE_FP(stmm, 0), > + DEFINE_FP(stmm, 1), > + DEFINE_FP(stmm, 2), > + DEFINE_FP(stmm, 3), > + DEFINE_FP(stmm, 4), > + DEFINE_FP(stmm, 5), > + DEFINE_FP(stmm, 6), > + DEFINE_FP(stmm, 7), > + > + // XMM registers > + DEFINE_XMM(xmm, 0), > + DEFINE_XMM(xmm, 1), > + DEFINE_XMM(xmm, 2), > + DEFINE_XMM(xmm, 3), > + DEFINE_XMM(xmm, 4), > + DEFINE_XMM(xmm, 5), > + DEFINE_XMM(xmm, 6), > + DEFINE_XMM(xmm, 7), > + DEFINE_XMM(xmm, 8), > + DEFINE_XMM(xmm, 9), > + DEFINE_XMM(xmm, 10), > + DEFINE_XMM(xmm, 11), > + DEFINE_XMM(xmm, 12), > + DEFINE_XMM(xmm, 13), > + DEFINE_XMM(xmm, 14), > + DEFINE_XMM(xmm, 15) > +}; > + > +static unsigned GetRegOffset(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register number."); > + return g_register_infos[reg].byte_offset; > +} > + > +static unsigned GetRegSize(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register number."); > + return g_register_infos[reg].byte_size; > +} > + > +static bool IsGPR(unsigned reg) > +{ > + return reg <= k_last_gpr; // GPR's come first. > +} > + > +static bool IsFPR(unsigned reg) > +{ > + return (k_first_fpr <= reg && reg <= k_last_fpr); > +} > + > +RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread, > + uint32_t concrete_frame_idx) > + : RegisterContextPOSIX(thread, concrete_frame_idx) > +{ > +} > + > +RegisterContext_x86_64::~RegisterContext_x86_64() > +{ > +} > + > +ProcessMonitor & > +RegisterContext_x86_64::GetMonitor() > +{ > + ProcessPOSIX *process = static_cast(CalculateProcess()); > + return process->GetMonitor(); > +} > + > +void > +RegisterContext_x86_64::Invalidate() > +{ > +} > + > +void > +RegisterContext_x86_64::InvalidateAllRegisters() > +{ > +} > + > +size_t > +RegisterContext_x86_64::GetRegisterCount() > +{ > + return k_num_registers; > +} > + > +const RegisterInfo * > +RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg) > +{ > + if (reg < k_num_registers) > + return &g_register_infos[reg]; > + else > + return NULL; > +} > + > +size_t > +RegisterContext_x86_64::GetRegisterSetCount() > +{ > + return k_num_register_sets; > +} > + > +const RegisterSet * > +RegisterContext_x86_64::GetRegisterSet(uint32_t set) > +{ > + if (set < k_num_register_sets) > + return &g_reg_sets[set]; > + else > + return NULL; > +} > + > +unsigned > +RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset) > +{ > + unsigned reg; > + for (reg = 0; reg < k_num_registers; reg++) > + { > + if (g_register_infos[reg].byte_offset == offset) > + break; > + } > + assert(reg < k_num_registers && "Invalid register offset."); > + return reg; > +} > + > +const char * > +RegisterContext_x86_64::GetRegisterName(unsigned reg) > +{ > + assert(reg < k_num_registers && "Invalid register offset."); > + return g_register_infos[reg].name; > +} > + > +bool > +RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, > + RegisterValue &value) > +{ > + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); > +} > + > +bool > +RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) > +{ > + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); > + if (data_sp && ReadGPR () && ReadFPR ()) > + { > + uint8_t *dst = data_sp->GetBytes(); > + ::memcpy (dst, &user.regs, sizeof(user.regs)); > + dst += sizeof(user.regs); > + > + ::memcpy (dst, &user.i387, sizeof(user.i387)); > + return true; > + } > + return false; > +} > + > +bool > +RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, > + const lldb_private::RegisterValue &value) > +{ > + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.WriteRegisterValue(GetRegOffset(reg), value); > +} > + > +bool > +RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) > +{ > + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) > + { > + const uint8_t *src = data_sp->GetBytes(); > + ::memcpy (&user.regs, src, sizeof(user.regs)); > + src += sizeof(user.regs); > + > + ::memcpy (&user.i387, src, sizeof(user.i387)); > + return WriteGPR() & WriteFPR(); > + } > + return false; > +} > + > +bool > +RegisterContext_x86_64::UpdateAfterBreakpoint() > +{ > + // PC points one byte past the int3 responsible for the breakpoint. > + lldb::addr_t pc; > + > + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) > + return false; > + > + SetPC(pc - 1); > + return true; > +} > + > +uint32_t > +RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, > + uint32_t num) > +{ > + if (kind == eRegisterKindGeneric) > + { > + switch (num) > + { > + case LLDB_REGNUM_GENERIC_PC: return gpr_rip; > + case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; > + case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; > + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; > + case LLDB_REGNUM_GENERIC_RA: > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + > + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) > + { > + switch (num) > + { > + case gcc_dwarf_gpr_rax: return gpr_rax; > + case gcc_dwarf_gpr_rdx: return gpr_rdx; > + case gcc_dwarf_gpr_rcx: return gpr_rcx; > + case gcc_dwarf_gpr_rbx: return gpr_rbx; > + case gcc_dwarf_gpr_rsi: return gpr_rsi; > + case gcc_dwarf_gpr_rdi: return gpr_rdi; > + case gcc_dwarf_gpr_rbp: return gpr_rbp; > + case gcc_dwarf_gpr_rsp: return gpr_rsp; > + case gcc_dwarf_gpr_r8: return gpr_r8; > + case gcc_dwarf_gpr_r9: return gpr_r9; > + case gcc_dwarf_gpr_r10: return gpr_r10; > + case gcc_dwarf_gpr_r11: return gpr_r11; > + case gcc_dwarf_gpr_r12: return gpr_r12; > + case gcc_dwarf_gpr_r13: return gpr_r13; > + case gcc_dwarf_gpr_r14: return gpr_r14; > + case gcc_dwarf_gpr_r15: return gpr_r15; > + case gcc_dwarf_gpr_rip: return gpr_rip; > + case gcc_dwarf_fpu_xmm0: return fpu_xmm0; > + case gcc_dwarf_fpu_xmm1: return fpu_xmm1; > + case gcc_dwarf_fpu_xmm2: return fpu_xmm2; > + case gcc_dwarf_fpu_xmm3: return fpu_xmm3; > + case gcc_dwarf_fpu_xmm4: return fpu_xmm4; > + case gcc_dwarf_fpu_xmm5: return fpu_xmm5; > + case gcc_dwarf_fpu_xmm6: return fpu_xmm6; > + case gcc_dwarf_fpu_xmm7: return fpu_xmm7; > + case gcc_dwarf_fpu_xmm8: return fpu_xmm8; > + case gcc_dwarf_fpu_xmm9: return fpu_xmm9; > + case gcc_dwarf_fpu_xmm10: return fpu_xmm10; > + case gcc_dwarf_fpu_xmm11: return fpu_xmm11; > + case gcc_dwarf_fpu_xmm12: return fpu_xmm12; > + case gcc_dwarf_fpu_xmm13: return fpu_xmm13; > + case gcc_dwarf_fpu_xmm14: return fpu_xmm14; > + case gcc_dwarf_fpu_xmm15: return fpu_xmm15; > + case gcc_dwarf_fpu_stmm0: return fpu_stmm0; > + case gcc_dwarf_fpu_stmm1: return fpu_stmm1; > + case gcc_dwarf_fpu_stmm2: return fpu_stmm2; > + case gcc_dwarf_fpu_stmm3: return fpu_stmm3; > + case gcc_dwarf_fpu_stmm4: return fpu_stmm4; > + case gcc_dwarf_fpu_stmm5: return fpu_stmm5; > + case gcc_dwarf_fpu_stmm6: return fpu_stmm6; > + case gcc_dwarf_fpu_stmm7: return fpu_stmm7; > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + > + if (kind == eRegisterKindGDB) > + { > + switch (num) > + { > + case gdb_gpr_rax : return gpr_rax; > + case gdb_gpr_rbx : return gpr_rbx; > + case gdb_gpr_rcx : return gpr_rcx; > + case gdb_gpr_rdx : return gpr_rdx; > + case gdb_gpr_rsi : return gpr_rsi; > + case gdb_gpr_rdi : return gpr_rdi; > + case gdb_gpr_rbp : return gpr_rbp; > + case gdb_gpr_rsp : return gpr_rsp; > + case gdb_gpr_r8 : return gpr_r8; > + case gdb_gpr_r9 : return gpr_r9; > + case gdb_gpr_r10 : return gpr_r10; > + case gdb_gpr_r11 : return gpr_r11; > + case gdb_gpr_r12 : return gpr_r12; > + case gdb_gpr_r13 : return gpr_r13; > + case gdb_gpr_r14 : return gpr_r14; > + case gdb_gpr_r15 : return gpr_r15; > + case gdb_gpr_rip : return gpr_rip; > + case gdb_gpr_rflags : return gpr_rflags; > + case gdb_gpr_cs : return gpr_cs; > + case gdb_gpr_ss : return gpr_ss; > + case gdb_gpr_ds : return gpr_ds; > + case gdb_gpr_es : return gpr_es; > + case gdb_gpr_fs : return gpr_fs; > + case gdb_gpr_gs : return gpr_gs; > + case gdb_fpu_stmm0 : return fpu_stmm0; > + case gdb_fpu_stmm1 : return fpu_stmm1; > + case gdb_fpu_stmm2 : return fpu_stmm2; > + case gdb_fpu_stmm3 : return fpu_stmm3; > + case gdb_fpu_stmm4 : return fpu_stmm4; > + case gdb_fpu_stmm5 : return fpu_stmm5; > + case gdb_fpu_stmm6 : return fpu_stmm6; > + case gdb_fpu_stmm7 : return fpu_stmm7; > + case gdb_fpu_fcw : return fpu_fcw; > + case gdb_fpu_fsw : return fpu_fsw; > + case gdb_fpu_ftw : return fpu_ftw; > + case gdb_fpu_cs : return fpu_cs; > + case gdb_fpu_ip : return fpu_ip; > + case gdb_fpu_ds : return fpu_ds; > + case gdb_fpu_dp : return fpu_dp; > + case gdb_fpu_fop : return fpu_fop; > + case gdb_fpu_xmm0 : return fpu_xmm0; > + case gdb_fpu_xmm1 : return fpu_xmm1; > + case gdb_fpu_xmm2 : return fpu_xmm2; > + case gdb_fpu_xmm3 : return fpu_xmm3; > + case gdb_fpu_xmm4 : return fpu_xmm4; > + case gdb_fpu_xmm5 : return fpu_xmm5; > + case gdb_fpu_xmm6 : return fpu_xmm6; > + case gdb_fpu_xmm7 : return fpu_xmm7; > + case gdb_fpu_xmm8 : return fpu_xmm8; > + case gdb_fpu_xmm9 : return fpu_xmm9; > + case gdb_fpu_xmm10 : return fpu_xmm10; > + case gdb_fpu_xmm11 : return fpu_xmm11; > + case gdb_fpu_xmm12 : return fpu_xmm12; > + case gdb_fpu_xmm13 : return fpu_xmm13; > + case gdb_fpu_xmm14 : return fpu_xmm14; > + case gdb_fpu_xmm15 : return fpu_xmm15; > + case gdb_fpu_mxcsr : return fpu_mxcsr; > + default: > + return LLDB_INVALID_REGNUM; > + } > + } > + else if (kind == eRegisterKindLLDB) > + { > + return num; > + } > + > + return LLDB_INVALID_REGNUM; > +} > + > +bool > +RegisterContext_x86_64::HardwareSingleStep(bool enable) > +{ > + enum { TRACE_BIT = 0x100 }; > + uint64_t rflags; > + > + if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) > + return false; > + > + if (enable) > + { > + if (rflags & TRACE_BIT) > + return true; > + > + rflags |= TRACE_BIT; > + } > + else > + { > + if (!(rflags & TRACE_BIT)) > + return false; > + > + rflags &= ~TRACE_BIT; > + } > + > + return WriteRegisterFromUnsigned(gpr_rflags, rflags); > +} > + > +bool > +RegisterContext_x86_64::ReadGPR() > +{ > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.ReadGPR(&user.regs); > +} > + > +bool > +RegisterContext_x86_64::ReadFPR() > +{ > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.ReadFPR(&user.i387); > +} > + > +bool > +RegisterContext_x86_64::WriteGPR() > +{ > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.WriteGPR(&user.regs); > +} > + > +bool > +RegisterContext_x86_64::WriteFPR() > +{ > + ProcessMonitor &monitor = GetMonitor(); > + return monitor.WriteFPR(&user.i387); > +} > Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.h > =================================================================== > --- source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) > +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) > @@ -0,0 +1,106 @@ > +//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ > +#define liblldb_ProcessLinuxLog_h_ > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > + > +// Project includes > +#include "lldb/Core/Log.h" > + > +#define POSIX_LOG_VERBOSE (1u << 0) > +#define POSIX_LOG_PROCESS (1u << 1) > +#define POSIX_LOG_THREAD (1u << 2) > +#define POSIX_LOG_PACKETS (1u << 3) > +#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls > +#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes > +#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes > +#define POSIX_LOG_BREAKPOINTS (1u << 7) > +#define POSIX_LOG_WATCHPOINTS (1u << 8) > +#define POSIX_LOG_STEP (1u << 9) > +#define POSIX_LOG_COMM (1u << 10) > +#define POSIX_LOG_ASYNC (1u << 11) > +#define POSIX_LOG_PTRACE (1u << 12) > +#define POSIX_LOG_REGISTERS (1u << 13) > +#define POSIX_LOG_ALL (UINT32_MAX) > +#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS > + > +// The size which determines "short memory reads/writes". > +#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) > + > +class ProcessPOSIXLog > +{ > + static int m_nestinglevel; > + static const char *m_pluginname; > + > +public: > + static void > + RegisterPluginName(const char *pluginName) > + { > + m_pluginname = pluginName; > + } > + > + > + static lldb::LogSP > + GetLogIfAllCategoriesSet(uint32_t mask = 0); > + > + static void > + DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); > + > + static lldb::LogSP > + EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, > + lldb_private::Args &args, lldb_private::Stream *feedback_strm); > + > + static void > + ListLogCategories (lldb_private::Stream *strm); > + > + static void > + LogIf (uint32_t mask, const char *format, ...); > + > + // The following functions can be used to enable the client to limit > + // logging to only the top level function calls. This is useful for > + // recursive functions. FIXME: not thread safe! > + // Example: > + // void NestingFunc() { > + // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); > + // if (log) > + // { > + // ProcessLinuxLog::IncNestLevel(); > + // if (ProcessLinuxLog::AtTopNestLevel()) > + // log->Print(msg); > + // } > + // NestingFunc(); > + // if (log) > + // ProcessLinuxLog::DecNestLevel(); > + // } > + > + static bool > + AtTopNestLevel() > + { > + return m_nestinglevel == 1; > + } > + > + static void > + IncNestLevel() > + { > + ++m_nestinglevel; > + } > + > + static void > + DecNestLevel() > + { > + --m_nestinglevel; > + assert(m_nestinglevel >= 0); > + } > +}; > + > +#endif // liblldb_ProcessLinuxLog_h_ > Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h > =================================================================== > --- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) > +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) > @@ -0,0 +1,143 @@ > +//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef liblldb_RegisterContext_x86_64_H_ > +#define liblldb_RegisterContext_x86_64_H_ > + > +#include "lldb/Core/Log.h" > +#include "RegisterContextPOSIX.h" > + > +#ifdef __FreeBSD__ > +#include "RegisterContextFreeBSD_x86_64.h" > +#endif > + > +#ifdef __linux__ > +#include "RegisterContextLinux_x86_64.h" > +#endif > + > +class ProcessMonitor; > + > +class RegisterContext_x86_64 > + : public RegisterContextPOSIX > +{ > +public: > + RegisterContext_x86_64 (lldb_private::Thread &thread, > + uint32_t concrete_frame_idx); > + > + ~RegisterContext_x86_64(); > + > + void > + Invalidate(); > + > + void > + InvalidateAllRegisters(); > + > + size_t > + GetRegisterCount(); > + > + const lldb_private::RegisterInfo * > + GetRegisterInfoAtIndex(uint32_t reg); > + > + size_t > + GetRegisterSetCount(); > + > + const lldb_private::RegisterSet * > + GetRegisterSet(uint32_t set); > + > + static unsigned > + GetRegisterIndexFromOffset(unsigned offset); > + > + static const char * > + GetRegisterName(unsigned reg); > + > + virtual bool > + ReadRegister(const lldb_private::RegisterInfo *reg_info, > + lldb_private::RegisterValue &value); > + > + bool > + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); > + > + virtual bool > + WriteRegister(const lldb_private::RegisterInfo *reg_info, > + const lldb_private::RegisterValue &value); > + > + bool > + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); > + > + uint32_t > + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); > + > + bool > + HardwareSingleStep(bool enable); > + > + bool > + UpdateAfterBreakpoint(); > + > + struct MMSReg > + { > + uint8_t bytes[10]; > + uint8_t pad[6]; > + }; > + > + struct XMMReg > + { > + uint8_t bytes[16]; > + }; > + > + struct FPU > + { > + uint16_t fcw; > + uint16_t fsw; > + uint16_t ftw; > + uint16_t fop; > + uint64_t ip; > + uint64_t dp; > + uint32_t mxcsr; > + uint32_t mxcsrmask; > + MMSReg stmm[8]; > + XMMReg xmm[16]; > + uint32_t padding[24]; > + }; > + > + struct UserArea > + { > + GPR regs; // General purpose registers. > + int32_t fpvalid; // True if FPU is being used. > + int32_t pad0; > + FPU i387; // FPU registers. > + uint64_t tsize; // Text segment size. > + uint64_t dsize; // Data segment size. > + uint64_t ssize; // Stack segment size. > + uint64_t start_code; // VM address of text. > + uint64_t start_stack; // VM address of stack bottom (top in rsp). > + int64_t signal; // Signal causing core dump. > + int32_t reserved; // Unused. > + int32_t pad1; > + uint64_t ar0; // Location of GPR's. > + FPU* fpstate; // Location of FPR's. > + uint64_t magic; // Identifier for core dumps. > + char u_comm[32]; // Command causing core dump. > + uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). > + uint64_t error_code; // CPU error code. > + uint64_t fault_address; // Control register CR3. > + }; > + > +private: > + UserArea user; > + > + ProcessMonitor &GetMonitor(); > + > + bool ReadGPR(); > + bool ReadFPR(); > + > + bool WriteGPR(); > + bool WriteFPR(); > +}; > + > +#endif // #ifndef liblldb_RegisterContext_x86_64_H_ > Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h > =================================================================== > --- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) > +++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) > @@ -0,0 +1,40 @@ > +//===-- RegisterContextPOSIX.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_RegisterContextPOSIX_H_ > +#define liblldb_RegisterContextPOSIX_H_ > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Target/RegisterContext.h" > + > +//------------------------------------------------------------------------------ > +/// @class RegisterContextPOSIX > +/// > +/// @brief Extends RegisterClass with a few virtual operations useful on POSIX. > +class RegisterContextPOSIX > + : public lldb_private::RegisterContext > +{ > +public: > + RegisterContextPOSIX(lldb_private::Thread &thread, > + uint32_t concrete_frame_idx) > + : RegisterContext(thread, concrete_frame_idx) { } > + > + /// Updates the register state of the associated thread after hitting a > + /// breakpoint (if that make sense for the architecture). Default > + /// implementation simply returns true for architectures which do not > + /// require any update. > + /// > + /// @return > + /// True if the operation succeeded and false otherwise. > + virtual bool UpdateAfterBreakpoint() { return true; } > +}; > + > +#endif // #ifndef liblldb_RegisterContextPOSIX_H_ > Index: source/Plugins/Process/POSIX/ProcessMessage.cpp > =================================================================== > --- source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) > +++ source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) > @@ -0,0 +1,245 @@ > +//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#include "ProcessMessage.h" > + > +using namespace lldb_private; > + > +const char * > +ProcessMessage::GetCrashReasonString(CrashReason reason) > +{ > + const char *str = NULL; > + > + switch (reason) > + { > + default: > + assert(false && "invalid CrashReason"); > + break; > + > + case eInvalidAddress: > + str = "invalid address"; > + break; > + case ePrivilegedAddress: > + str = "address access protected"; > + break; > + case eIllegalOpcode: > + str = "illegal instruction"; > + break; > + case eIllegalOperand: > + str = "illegal instruction operand"; > + break; > + case eIllegalAddressingMode: > + str = "illegal addressing mode"; > + break; > + case eIllegalTrap: > + str = "illegal trap"; > + break; > + case ePrivilegedOpcode: > + str = "privileged instruction"; > + break; > + case ePrivilegedRegister: > + str = "privileged register"; > + break; > + case eCoprocessorError: > + str = "coprocessor error"; > + break; > + case eInternalStackError: > + str = "internal stack error"; > + break; > + case eIllegalAlignment: > + str = "illegal alignment"; > + break; > + case eIllegalAddress: > + str = "illegal address"; > + break; > + case eHardwareError: > + str = "hardware error"; > + break; > + case eIntegerDivideByZero: > + str = "integer divide by zero"; > + break; > + case eIntegerOverflow: > + str = "integer overflow"; > + break; > + case eFloatDivideByZero: > + str = "floating point divide by zero"; > + break; > + case eFloatOverflow: > + str = "floating point overflow"; > + break; > + case eFloatUnderflow: > + str = "floating point underflow"; > + break; > + case eFloatInexactResult: > + str = "inexact floating point result"; > + break; > + case eFloatInvalidOperation: > + str = "invalid floating point operation"; > + break; > + case eFloatSubscriptRange: > + str = "invalid floating point subscript range"; > + break; > + } > + > + return str; > +} > + > +const char * > +ProcessMessage::PrintCrashReason(CrashReason reason) > +{ > +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION > + // Just return the code in asci for integration builds. > + chcar str[8]; > + sprintf(str, "%d", reason); > +#else > + const char *str = NULL; > + > + switch (reason) > + { > + default: > + assert(false && "invalid CrashReason"); > + break; > + > + case eInvalidCrashReason: > + str = "eInvalidCrashReason"; > + break; > + > + // SIGSEGV crash reasons. > + case eInvalidAddress: > + str = "eInvalidAddress"; > + break; > + case ePrivilegedAddress: > + str = "ePrivilegedAddress"; > + break; > + > + // SIGILL crash reasons. > + case eIllegalOpcode: > + str = "eIllegalOpcode"; > + break; > + case eIllegalOperand: > + str = "eIllegalOperand"; > + break; > + case eIllegalAddressingMode: > + str = "eIllegalAddressingMode"; > + break; > + case eIllegalTrap: > + str = "eIllegalTrap"; > + break; > + case ePrivilegedOpcode: > + str = "ePrivilegedOpcode"; > + break; > + case ePrivilegedRegister: > + str = "ePrivilegedRegister"; > + break; > + case eCoprocessorError: > + str = "eCoprocessorError"; > + break; > + case eInternalStackError: > + str = "eInternalStackError"; > + break; > + > + // SIGBUS crash reasons: > + case eIllegalAlignment: > + str = "eIllegalAlignment"; > + break; > + case eIllegalAddress: > + str = "eIllegalAddress"; > + break; > + case eHardwareError: > + str = "eHardwareError"; > + break; > + > + // SIGFPE crash reasons: > + case eIntegerDivideByZero: > + str = "eIntegerDivideByZero"; > + break; > + case eIntegerOverflow: > + str = "eIntegerOverflow"; > + break; > + case eFloatDivideByZero: > + str = "eFloatDivideByZero"; > + break; > + case eFloatOverflow: > + str = "eFloatOverflow"; > + break; > + case eFloatUnderflow: > + str = "eFloatUnderflow"; > + break; > + case eFloatInexactResult: > + str = "eFloatInexactResult"; > + break; > + case eFloatInvalidOperation: > + str = "eFloatInvalidOperation"; > + break; > + case eFloatSubscriptRange: > + str = "eFloatSubscriptRange"; > + break; > + } > +#endif > + > + return str; > +} > + > +const char * > +ProcessMessage::PrintCrashReason() const > +{ > + return PrintCrashReason(m_crash_reason); > +} > + > +const char * > +ProcessMessage::PrintKind(Kind kind) > +{ > +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION > + // Just return the code in asci for integration builds. > + chcar str[8]; > + sprintf(str, "%d", reason); > +#else > + const char *str = NULL; > + > + switch (kind) > + { > + default: > + assert(false && "invalid Kind"); > + break; > + > + case eInvalidMessage: > + str = "eInvalidMessage"; > + break; > + case eExitMessage: > + str = "eExitMessage"; > + break; > + case eLimboMessage: > + str = "eLimboMessage"; > + break; > + case eSignalMessage: > + str = "eSignalMessage"; > + break; > + case eSignalDeliveredMessage: > + str = "eSignalDeliveredMessage"; > + break; > + case eTraceMessage: > + str = "eTraceMessage"; > + break; > + case eBreakpointMessage: > + str = "eBreakpointMessage"; > + break; > + case eCrashMessage: > + str = "eCrashMessage"; > + break; > + } > +#endif > + > + return str; > +} > + > +const char * > +ProcessMessage::PrintKind() const > +{ > + return PrintKind(m_kind); > +} > Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp > =================================================================== > --- source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) > +++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) > @@ -0,0 +1,60 @@ > +//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#include "POSIXStopInfo.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > + > +//===----------------------------------------------------------------------===// > +// POSIXLimboStopInfo > + > +POSIXLimboStopInfo::~POSIXLimboStopInfo() { } > + > +lldb::StopReason > +POSIXLimboStopInfo::GetStopReason() const > +{ > + return lldb::eStopReasonTrace; > +} > + > +const char * > +POSIXLimboStopInfo::GetDescription() > +{ > + return "thread exiting"; > +} > + > +bool > +POSIXLimboStopInfo::ShouldStop(Event *event_ptr) > +{ > + return true; > +} > + > +bool > +POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) > +{ > + return true; > +} > + > +//===----------------------------------------------------------------------===// > +// POSIXCrashStopInfo > + > +POSIXCrashStopInfo::~POSIXCrashStopInfo() { } > + > +lldb::StopReason > +POSIXCrashStopInfo::GetStopReason() const > +{ > + return lldb::eStopReasonException; > +} > + > +const char * > +POSIXCrashStopInfo::GetDescription() > +{ > + return ProcessMessage::GetCrashReasonString(m_crash_reason); > +} > Index: source/Plugins/Process/POSIX/ProcessMessage.h > =================================================================== > --- source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) > +++ source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) > @@ -0,0 +1,171 @@ > +//===-- ProcessMessage.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_ProcessMessage_H_ > +#define liblldb_ProcessMessage_H_ > + > +#include > + > +#include "lldb/lldb-defines.h" > +#include "lldb/lldb-types.h" > + > +class ProcessMessage > +{ > +public: > + > + /// The type of signal this message can correspond to. > + enum Kind > + { > + eInvalidMessage, > + eExitMessage, > + eLimboMessage, > + eSignalMessage, > + eSignalDeliveredMessage, > + eTraceMessage, > + eBreakpointMessage, > + eCrashMessage > + }; > + > + enum CrashReason > + { > + eInvalidCrashReason, > + > + // SIGSEGV crash reasons. > + eInvalidAddress, > + ePrivilegedAddress, > + > + // SIGILL crash reasons. > + eIllegalOpcode, > + eIllegalOperand, > + eIllegalAddressingMode, > + eIllegalTrap, > + ePrivilegedOpcode, > + ePrivilegedRegister, > + eCoprocessorError, > + eInternalStackError, > + > + // SIGBUS crash reasons, > + eIllegalAlignment, > + eIllegalAddress, > + eHardwareError, > + > + // SIGFPE crash reasons, > + eIntegerDivideByZero, > + eIntegerOverflow, > + eFloatDivideByZero, > + eFloatOverflow, > + eFloatUnderflow, > + eFloatInexactResult, > + eFloatInvalidOperation, > + eFloatSubscriptRange > + }; > + > + ProcessMessage() > + : m_tid(LLDB_INVALID_PROCESS_ID), > + m_kind(eInvalidMessage), > + m_crash_reason(eInvalidCrashReason), > + m_status(0), > + m_addr(0) { } > + > + Kind GetKind() const { return m_kind; } > + > + lldb::tid_t GetTID() const { return m_tid; } > + > + /// Indicates that the thread @p tid is about to exit with status @p status. > + static ProcessMessage Limbo(lldb::tid_t tid, int status) { > + return ProcessMessage(tid, eLimboMessage, status); > + } > + > + /// Indicates that the thread @p tid had the signal @p signum delivered. > + static ProcessMessage Signal(lldb::tid_t tid, int signum) { > + return ProcessMessage(tid, eSignalMessage, signum); > + } > + > + /// Indicates that a signal @p signum generated by the debugging process was > + /// delivered to the thread @p tid. > + static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { > + return ProcessMessage(tid, eSignalDeliveredMessage, signum); > + } > + > + /// Indicates that the thread @p tid encountered a trace point. > + static ProcessMessage Trace(lldb::tid_t tid) { > + return ProcessMessage(tid, eTraceMessage); > + } > + > + /// Indicates that the thread @p tid encountered a break point. > + static ProcessMessage Break(lldb::tid_t tid) { > + return ProcessMessage(tid, eBreakpointMessage); > + } > + > + /// Indicates that the thread @p tid crashed. > + static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, > + int signo, lldb::addr_t fault_addr) { > + ProcessMessage message(pid, eCrashMessage, signo, fault_addr); > + message.m_crash_reason = reason; > + return message; > + } > + > + int GetExitStatus() const { > + assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); > + return m_status; > + } > + > + int GetSignal() const { > + assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || > + GetKind() == eSignalDeliveredMessage); > + return m_status; > + } > + > + int GetStopStatus() const { > + assert(GetKind() == eSignalMessage); > + return m_status; > + } > + > + CrashReason GetCrashReason() const { > + assert(GetKind() == eCrashMessage); > + return m_crash_reason; > + } > + > + lldb::addr_t GetFaultAddress() const { > + assert(GetKind() == eCrashMessage); > + return m_addr; > + } > + > + static const char * > + GetCrashReasonString(CrashReason reason); > + > + const char * > + PrintCrashReason() const; > + > + static const char * > + PrintCrashReason(CrashReason reason); > + > + const char * > + PrintKind() const; > + > + static const char * > + PrintKind(Kind); > + > +private: > + ProcessMessage(lldb::tid_t tid, Kind kind, > + int status = 0, lldb::addr_t addr = 0) > + : m_tid(tid), > + m_kind(kind), > + m_crash_reason(eInvalidCrashReason), > + m_status(status), > + m_addr(addr) { } > + > + lldb::tid_t m_tid; > + Kind m_kind : 8; > + CrashReason m_crash_reason : 8; > + int m_status; > + lldb::addr_t m_addr; > +}; > + > +#endif // #ifndef liblldb_ProcessMessage_H_ > Index: source/Plugins/Process/POSIX/POSIXStopInfo.h > =================================================================== > --- source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) > +++ source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) > @@ -0,0 +1,92 @@ > +//===-- POSIXStopInfo.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_POSIXStopInfo_H_ > +#define liblldb_POSIXStopInfo_H_ > + > +// C Includes > +// C++ Includes > +// Other libraries and framework includes > +// Project includes > +#include "lldb/Target/StopInfo.h" > + > +#include "POSIXThread.h" > +#include "ProcessMessage.h" > + > +//===----------------------------------------------------------------------===// > +/// @class POSIXStopInfo > +/// @brief Simple base class for all POSIX-specific StopInfo objects. > +/// > +class POSIXStopInfo > + : public lldb_private::StopInfo > +{ > +public: > + POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) > + : StopInfo(thread, status) > + { } > +}; > + > +//===----------------------------------------------------------------------===// > +/// @class POSIXLimboStopInfo > +/// @brief Represents the stop state of a process ready to exit. > +/// > +class POSIXLimboStopInfo > + : public POSIXStopInfo > +{ > +public: > + POSIXLimboStopInfo(POSIXThread &thread) > + : POSIXStopInfo(thread, 0) > + { } > + > + ~POSIXLimboStopInfo(); > + > + lldb::StopReason > + GetStopReason() const; > + > + const char * > + GetDescription(); > + > + bool > + ShouldStop(lldb_private::Event *event_ptr); > + > + bool > + ShouldNotify(lldb_private::Event *event_ptr); > +}; > + > + > +//===----------------------------------------------------------------------===// > +/// @class POSIXCrashStopInfo > +/// @brief Represents the stop state of process that is ready to crash. > +/// > +class POSIXCrashStopInfo > + : public POSIXStopInfo > +{ > +public: > + POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, > + ProcessMessage::CrashReason reason) > + : POSIXStopInfo(thread, status), > + m_crash_reason(reason) > + { } > + > + ~POSIXCrashStopInfo(); > + > + lldb::StopReason > + GetStopReason() const; > + > + const char * > + GetDescription(); > + > + ProcessMessage::CrashReason > + GetCrashReason() const; > + > +private: > + ProcessMessage::CrashReason m_crash_reason; > +}; > + > +#endif > Index: source/Plugins/Process/POSIX/POSIXThread.cpp > =================================================================== > --- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) > +++ source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) > @@ -0,0 +1,352 @@ > +//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +// C Includes > +#include > + > +// C++ Includes > +// Other libraries and framework includes > +// Project includes > +#include "lldb/Core/Debugger.h" > +#include "lldb/Host/Host.h" > +#include "lldb/Target/Process.h" > +#include "lldb/Target/StopInfo.h" > +#include "lldb/Target/Target.h" > +#include "POSIXStopInfo.h" > +#include "POSIXThread.h" > +#include "ProcessPOSIX.h" > +#include "ProcessPOSIXLog.h" > +#include "ProcessMonitor.h" > +#include "RegisterContext_i386.h" > +#include "RegisterContext_x86_64.h" > +#include "RegisterContextPOSIX.h" > + > +#include "UnwindLLDB.h" > + > +using namespace lldb_private; > + > + > +POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) > + : Thread(process, tid), > + m_frame_ap(0) > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid); > +} > + > +POSIXThread::~POSIXThread() > +{ > + DestroyThread(); > +} > + > +ProcessMonitor & > +POSIXThread::GetMonitor() > +{ > + ProcessPOSIX &process = static_cast(GetProcess()); > + return process.GetMonitor(); > +} > + > +void > +POSIXThread::RefreshStateAfterStop() > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("POSIXThread::%s ()", __FUNCTION__); > + > + // Let all threads recover from stopping and do any clean up based > + // on the previous thread state (if any). > + ProcessPOSIX &process = static_cast(GetProcess()); > + process.GetThreadList().RefreshStateAfterStop(); > +} > + > +const char * > +POSIXThread::GetInfo() > +{ > + return NULL; > +} > + > +lldb::RegisterContextSP > +POSIXThread::GetRegisterContext() > +{ > + if (!m_reg_context_sp) > + { > + ArchSpec arch = Host::GetArchitecture(); > + > + switch (arch.GetCore()) > + { > + default: > + assert(false && "CPU type not supported!"); > + break; > + > + case ArchSpec::eCore_x86_32_i386: > + case ArchSpec::eCore_x86_32_i486: > + case ArchSpec::eCore_x86_32_i486sx: > + m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); > + break; > + > + case ArchSpec::eCore_x86_64_x86_64: > + m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0)); > + break; > + } > + } > + return m_reg_context_sp; > +} > + > +lldb::RegisterContextSP > +POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) > +{ > + lldb::RegisterContextSP reg_ctx_sp; > + uint32_t concrete_frame_idx = 0; > + > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("POSIXThread::%s ()", __FUNCTION__); > + > + if (frame) > + concrete_frame_idx = frame->GetConcreteFrameIndex(); > + > + if (concrete_frame_idx == 0) > + reg_ctx_sp = GetRegisterContext(); > + else > + { > + assert(GetUnwinder()); > + reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); > + } > + > + return reg_ctx_sp; > +} > + > +lldb::StopInfoSP > +POSIXThread::GetPrivateStopReason() > +{ > + return m_stop_info; > +} > + > +Unwind * > +POSIXThread::GetUnwinder() > +{ > + if (m_unwinder_ap.get() == NULL) > + m_unwinder_ap.reset(new UnwindLLDB(*this)); > + > + return m_unwinder_ap.get(); > +} > + > +bool > +POSIXThread::WillResume(lldb::StateType resume_state) > +{ > + SetResumeState(resume_state); > + > + ClearStackFrames(); > + if (m_unwinder_ap.get()) > + m_unwinder_ap->Clear(); > + > + return Thread::WillResume(resume_state); > +} > + > +bool > +POSIXThread::Resume() > +{ > + lldb::StateType resume_state = GetResumeState(); > + ProcessMonitor &monitor = GetMonitor(); > + bool status; > + > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) > + log->Printf ("POSIXThread::%s ()", __FUNCTION__); > + > + switch (resume_state) > + { > + default: > + assert(false && "Unexpected state for resume!"); > + status = false; > + break; > + > + case lldb::eStateRunning: > + SetState(resume_state); > + status = monitor.Resume(GetID(), GetResumeSignal()); > + break; > + > + case lldb::eStateStepping: > + SetState(resume_state); > + status = monitor.SingleStep(GetID(), GetResumeSignal()); > + break; > + } > + > + return status; > +} > + > +void > +POSIXThread::Notify(const ProcessMessage &message) > +{ > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log) > + log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); > + > + switch (message.GetKind()) > + { > + default: > + assert(false && "Unexpected message kind!"); > + break; > + > + case ProcessMessage::eLimboMessage: > + LimboNotify(message); > + break; > + > + case ProcessMessage::eSignalMessage: > + SignalNotify(message); > + break; > + > + case ProcessMessage::eSignalDeliveredMessage: > + SignalDeliveredNotify(message); > + break; > + > + case ProcessMessage::eTraceMessage: > + TraceNotify(message); > + break; > + > + case ProcessMessage::eBreakpointMessage: > + BreakNotify(message); > + break; > + > + case ProcessMessage::eCrashMessage: > + CrashNotify(message); > + break; > + } > +} > + > +void > +POSIXThread::BreakNotify(const ProcessMessage &message) > +{ > + bool status; > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + > + assert(GetRegisterContext()); > + status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); > + assert(status && "Breakpoint update failed!"); > + > + // With our register state restored, resolve the breakpoint object > + // corresponding to our current PC. > + assert(GetRegisterContext()); > + lldb::addr_t pc = GetRegisterContext()->GetPC(); > + if (log) > + log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); > + lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); > + assert(bp_site); > + lldb::break_id_t bp_id = bp_site->GetID(); > + assert(bp_site && bp_site->ValidForThisThread(this)); > + > + > + m_breakpoint = bp_site; > + m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); > +} > + > +void > +POSIXThread::TraceNotify(const ProcessMessage &message) > +{ > + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); > +} > + > +void > +POSIXThread::LimboNotify(const ProcessMessage &message) > +{ > + m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this)); > +} > + > +void > +POSIXThread::SignalNotify(const ProcessMessage &message) > +{ > + int signo = message.GetSignal(); > + > + m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); > + SetResumeSignal(signo); > +} > + > +void > +POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) > +{ > + int signo = message.GetSignal(); > + > + // Just treat debugger generated signal events like breakpoints for now. > + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); > + SetResumeSignal(signo); > +} > + > +void > +POSIXThread::CrashNotify(const ProcessMessage &message) > +{ > + int signo = message.GetSignal(); > + > + assert(message.GetKind() == ProcessMessage::eCrashMessage); > + > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); > + if (log) > + log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); > + > + m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo( > + *this, signo, message.GetCrashReason())); > + SetResumeSignal(signo); > +} > + > +unsigned > +POSIXThread::GetRegisterIndexFromOffset(unsigned offset) > +{ > + unsigned reg; > + ArchSpec arch = Host::GetArchitecture(); > + > + switch (arch.GetCore()) > + { > + default: > + assert(false && "CPU type not supported!"); > + break; > + > + case ArchSpec::eCore_x86_32_i386: > + case ArchSpec::eCore_x86_32_i486: > + case ArchSpec::eCore_x86_32_i486sx: > + reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset); > + break; > + > + case ArchSpec::eCore_x86_64_x86_64: > + reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset); > + break; > + } > + return reg; > +} > + > +const char * > +POSIXThread::GetRegisterName(unsigned reg) > +{ > + const char * name; > + ArchSpec arch = Host::GetArchitecture(); > + > + switch (arch.GetCore()) > + { > + default: > + assert(false && "CPU type not supported!"); > + break; > + > + case ArchSpec::eCore_x86_32_i386: > + case ArchSpec::eCore_x86_32_i486: > + case ArchSpec::eCore_x86_32_i486sx: > + name = RegisterContext_i386::GetRegisterName(reg); > + break; > + > + case ArchSpec::eCore_x86_64_x86_64: > + name = RegisterContext_x86_64::GetRegisterName(reg); > + break; > + } > + return name; > +} > + > +const char * > +POSIXThread::GetRegisterNameFromOffset(unsigned offset) > +{ > + return GetRegisterName(GetRegisterIndexFromOffset(offset)); > +} > + > Index: source/Plugins/Process/POSIX/Makefile > =================================================================== > --- source/Plugins/Process/POSIX/Makefile (revision 0) > +++ source/Plugins/Process/POSIX/Makefile (revision 0) > @@ -0,0 +1,28 @@ > +##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===## > +# > +# The LLVM Compiler Infrastructure > +# > +# This file is distributed under the University of Illinois Open Source > +# License. See LICENSE.TXT for details. > +# > +##===----------------------------------------------------------------------===## > + > +LLDB_LEVEL := ../../../.. > +LIBRARYNAME := lldbPluginProcessPOSIX > +BUILD_ARCHIVE = 1 > + > +include $(LLDB_LEVEL)/../../Makefile.config > + > +# Extend the include path so we may locate UnwindLLDB.h > +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility > + > +ifeq ($(HOST_OS),Linux) > +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux > +endif > + > +ifeq ($(HOST_OS),FreeBSD) > +# Extend the include path so we may locate ProcessMonitor > +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD > +endif > + > +include $(LLDB_LEVEL)/Makefile > Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.h > =================================================================== > --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) > +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) > @@ -0,0 +1,84 @@ > +//===-- ProcessFreeBSD.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_ProcessFreeBSD_H_ > +#define liblldb_ProcessFreeBSD_H_ > + > +// C Includes > + > +// C++ Includes > +#include > + > +// Other libraries and framework includes > +#include "lldb/Target/Process.h" > +#include "lldb/Target/ThreadList.h" > +#include "ProcessMessage.h" > +#include "ProcessPOSIX.h" > + > +class ProcessMonitor; > + > +class ProcessFreeBSD : > + public ProcessPOSIX > +{ > + > +public: > + //------------------------------------------------------------------ > + // Static functions. > + //------------------------------------------------------------------ > + static Process* > + CreateInstance(lldb_private::Target& target, > + lldb_private::Listener &listener); > + > + static void > + Initialize(); > + > + static void > + Terminate(); > + > + static const char * > + GetPluginNameStatic(); > + > + static const char * > + GetPluginDescriptionStatic(); > + > + //------------------------------------------------------------------ > + // Constructors and destructors > + //------------------------------------------------------------------ > + ProcessFreeBSD(lldb_private::Target& target, > + lldb_private::Listener &listener); > + > + virtual uint32_t > + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); > + > + //------------------------------------------------------------------ > + // PluginInterface protocol > + //------------------------------------------------------------------ > + virtual const char * > + GetPluginName(); > + > + virtual const char * > + GetShortPluginName(); > + > + virtual uint32_t > + GetPluginVersion(); > + > + virtual void > + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); > + > + virtual lldb_private::Error > + ExecutePluginCommand(lldb_private::Args &command, > + lldb_private::Stream *strm); > + > + virtual lldb_private::Log * > + EnablePluginLogging(lldb_private::Stream *strm, > + lldb_private::Args &command); > + > +}; > + > +#endif // liblldb_MacOSXProcess_H_ > Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp > =================================================================== > --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) > +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) > @@ -0,0 +1,1558 @@ > +//===-- ProcessMonitor.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 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/Error.h" > +#include "lldb/Core/RegisterValue.h" > +#include "lldb/Core/Scalar.h" > +#include "lldb/Host/Host.h" > +#include "lldb/Target/Thread.h" > +#include "lldb/Target/RegisterContext.h" > +#include "lldb/Utility/PseudoTerminal.h" > + > + > +#include "POSIXThread.h" > +#include "ProcessFreeBSD.h" > +#include "ProcessPOSIXLog.h" > +#include "ProcessMonitor.h" > + > +extern "C" { > + extern char ** environ; > + } > + > +using namespace lldb; > +using namespace lldb_private; > + > +// We disable the tracing of ptrace calls for integration builds to > +// avoid the additional indirection and checks. > +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION > +// Wrapper for ptrace to catch errors and log calls. > + > +const char * > +Get_PT_IO_OP(int op) > +{ > + switch (op) { > + case PIOD_READ_D: return "READ_D"; > + case PIOD_WRITE_D: return "WRITE_D"; > + case PIOD_READ_I: return "READ_I"; > + case PIOD_WRITE_I: return "WRITE_I"; > + default: return "Unknown op"; > + } > +} > + > +extern long > +PtraceWrapper(int req, ::pid_t pid, void *addr, int data, > + const char* reqName, const char* file, int line) > +{ > + long int result; > + > + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); > + > + if (log) { > + log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d", > + reqName, pid, addr, data, file, line); > + if (req == PT_IO) { > + struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; > + > + log->Printf("PT_IO: op=%s offs=%zx size=%ld", > + Get_PT_IO_OP(pi->piod_op), pi->piod_offs, pi->piod_len); > + } > + } > + > + //PtraceDisplayBytes(req, data); > + > + errno = 0; > + result = ptrace(req, pid, (caddr_t) addr, data); > + > + //PtraceDisplayBytes(req, data); > + > + if (log && (result == -1 || errno != 0)) > + { > + const char* str; > + switch (errno) > + { > + case ESRCH: str = "ESRCH"; break; > + case EINVAL: str = "EINVAL"; break; > + case EBUSY: str = "EBUSY"; break; > + case EPERM: str = "EPERM"; break; > + default: str = ""; > + } > + log->Printf("ptrace() failed; errno=%d (%s)", errno, str); > + } > + > + if (log) { > + if (req == PT_GETREGS) { > + struct reg *r = (struct reg *) addr; > + > + log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip); > + log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp); > + log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); > + log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); > + } > + } > + > + return result; > +} > + > +#define PTRACE(req, pid, addr, data) \ > + PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) > +#else > +#define PTRACE ptrace > +#endif > + > +//------------------------------------------------------------------------------ > +// Static implementations of ProcessMonitor::ReadMemory and > +// ProcessMonitor::WriteMemory. This enables mutual recursion between these > +// functions without needed to go thru the thread funnel. > + > +static size_t > +DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, > + Error &error) > +{ > + struct ptrace_io_desc pi_desc; > + > + pi_desc.piod_op = PIOD_READ_D; > + pi_desc.piod_offs = (void *)vm_addr; > + pi_desc.piod_addr = buf; > + pi_desc.piod_len = size; > + > + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) > + error.SetErrorToErrno(); > + return pi_desc.piod_len; > +} > + > +static size_t > +DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, > + size_t size, Error &error) > +{ > + struct ptrace_io_desc pi_desc; > + > + pi_desc.piod_op = PIOD_WRITE_D; > + pi_desc.piod_offs = (void *)vm_addr; > + pi_desc.piod_addr = (void *)buf; > + pi_desc.piod_len = size; > + > + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) > + error.SetErrorToErrno(); > + return pi_desc.piod_len; > +} > + > +// Simple helper function to ensure flags are enabled on the given file > +// descriptor. > +static bool > +EnsureFDFlags(int fd, int flags, Error &error) > +{ > + int status; > + > + if ((status = fcntl(fd, F_GETFL)) == -1) > + { > + error.SetErrorToErrno(); > + return false; > + } > + > + if (fcntl(fd, F_SETFL, status | flags) == -1) > + { > + error.SetErrorToErrno(); > + return false; > + } > + > + return true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class Operation > +/// @brief Represents a ProcessMonitor operation. > +/// > +/// Under FreeBSD, it is not possible to ptrace() from any other thread but the > +/// one that spawned or attached to the process from the start. Therefore, when > +/// a ProcessMonitor is asked to deliver or change the state of an inferior > +/// process the operation must be "funneled" to a specific thread to perform the > +/// task. The Operation class provides an abstract base for all services the > +/// ProcessMonitor must perform via the single virtual function Execute, thus > +/// encapsulating the code that needs to run in the privileged context. > +class Operation > +{ > +public: > + virtual void Execute(ProcessMonitor *monitor) = 0; > +}; > + > +//------------------------------------------------------------------------------ > +/// @class ReadOperation > +/// @brief Implements ProcessMonitor::ReadMemory. > +class ReadOperation : public Operation > +{ > +public: > + ReadOperation(lldb::addr_t addr, void *buff, size_t size, > + Error &error, size_t &result) > + : m_addr(addr), m_buff(buff), m_size(size), > + m_error(error), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::addr_t m_addr; > + void *m_buff; > + size_t m_size; > + Error &m_error; > + size_t &m_result; > +}; > + > +void > +ReadOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + > + m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); > +} > + > +//------------------------------------------------------------------------------ > +/// @class ReadOperation > +/// @brief Implements ProcessMonitor::WriteMemory. > +class WriteOperation : public Operation > +{ > +public: > + WriteOperation(lldb::addr_t addr, const void *buff, size_t size, > + Error &error, size_t &result) > + : m_addr(addr), m_buff(buff), m_size(size), > + m_error(error), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::addr_t m_addr; > + const void *m_buff; > + size_t m_size; > + Error &m_error; > + size_t &m_result; > +}; > + > +void > +WriteOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + > + m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); > +} > + > +//------------------------------------------------------------------------------ > +/// @class ReadRegOperation > +/// @brief Implements ProcessMonitor::ReadRegisterValue. > +class ReadRegOperation : public Operation > +{ > +public: > + ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result) > + : m_offset(offset), m_size(size), m_value(value), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + unsigned m_offset; > + unsigned m_size; > + RegisterValue &m_value; > + bool &m_result; > +}; > + > +void > +ReadRegOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + struct reg regs; > + int rc; > + > + if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0)) < 0) { > + m_result = false; > + } else { > + if (m_size == sizeof(uintptr_t)) > + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); > + else > + memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); > + m_result = true; > + } > +} > + > +//------------------------------------------------------------------------------ > +/// @class WriteRegOperation > +/// @brief Implements ProcessMonitor::WriteRegisterValue. > +class WriteRegOperation : public Operation > +{ > +public: > + WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result) > + : m_offset(offset), m_value(value), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + unsigned m_offset; > + const RegisterValue &m_value; > + bool &m_result; > +}; > + > +void > +WriteRegOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + struct reg regs; > + > + if (PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0) < 0) { > + m_result = false; > + return; > + } > + *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); > + if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 0) < 0) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class ReadGPROperation > +/// @brief Implements ProcessMonitor::ReadGPR. > +class ReadGPROperation : public Operation > +{ > +public: > + ReadGPROperation(void *buf, bool &result) > + : m_buf(buf), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + void *m_buf; > + bool &m_result; > +}; > + > +void > +ReadGPROperation::Execute(ProcessMonitor *monitor) > +{ > + int rc; > + > + errno = 0; > + rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0); > + if (errno != 0) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class ReadFPROperation > +/// @brief Implements ProcessMonitor::ReadFPR. > +class ReadFPROperation : public Operation > +{ > +public: > + ReadFPROperation(void *buf, bool &result) > + : m_buf(buf), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + void *m_buf; > + bool &m_result; > +}; > + > +void > +ReadFPROperation::Execute(ProcessMonitor *monitor) > +{ > + if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class WriteGPROperation > +/// @brief Implements ProcessMonitor::WriteGPR. > +class WriteGPROperation : public Operation > +{ > +public: > + WriteGPROperation(void *buf, bool &result) > + : m_buf(buf), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + void *m_buf; > + bool &m_result; > +}; > + > +void > +WriteGPROperation::Execute(ProcessMonitor *monitor) > +{ > + if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class WriteFPROperation > +/// @brief Implements ProcessMonitor::WriteFPR. > +class WriteFPROperation : public Operation > +{ > +public: > + WriteFPROperation(void *buf, bool &result) > + : m_buf(buf), m_result(result) > + { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + void *m_buf; > + bool &m_result; > +}; > + > +void > +WriteFPROperation::Execute(ProcessMonitor *monitor) > +{ > + if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class ResumeOperation > +/// @brief Implements ProcessMonitor::Resume. > +class ResumeOperation : public Operation > +{ > +public: > + ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : > + m_tid(tid), m_signo(signo), m_result(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::tid_t m_tid; > + uint32_t m_signo; > + bool &m_result; > +}; > + > +void > +ResumeOperation::Execute(ProcessMonitor *monitor) > +{ > + int data = 0; > + > + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) > + data = m_signo; > + > + if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data)) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class ResumeOperation > +/// @brief Implements ProcessMonitor::SingleStep. > +class SingleStepOperation : public Operation > +{ > +public: > + SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) > + : m_tid(tid), m_signo(signo), m_result(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::tid_t m_tid; > + uint32_t m_signo; > + bool &m_result; > +}; > + > +void > +SingleStepOperation::Execute(ProcessMonitor *monitor) > +{ > + int data = 0; > + > + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) > + data = m_signo; > + > + if (PTRACE(PT_STEP, m_tid, NULL, data)) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class SiginfoOperation > +/// @brief Implements ProcessMonitor::GetSignalInfo. > +class SiginfoOperation : public Operation > +{ > +public: > + SiginfoOperation(lldb::tid_t tid, void *info, bool &result) > + : m_tid(tid), m_info(info), m_result(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::tid_t m_tid; > + void *m_info; > + bool &m_result; > +}; > + > +void > +SiginfoOperation::Execute(ProcessMonitor *monitor) > +{ > + struct ptrace_lwpinfo plwp; > + > + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) > + m_result = false; > + else { > + memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t)); > + m_result = true; > + } > +} > + > +//------------------------------------------------------------------------------ > +/// @class EventMessageOperation > +/// @brief Implements ProcessMonitor::GetEventMessage. > +class EventMessageOperation : public Operation > +{ > +public: > + EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) > + : m_tid(tid), m_message(message), m_result(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + lldb::tid_t m_tid; > + unsigned long *m_message; > + bool &m_result; > +}; > + > +void > +EventMessageOperation::Execute(ProcessMonitor *monitor) > +{ > + struct ptrace_lwpinfo plwp; > + > + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) > + m_result = false; > + else { > + if (plwp.pl_flags & PL_FLAG_FORKED) { > + m_message = (unsigned long *)plwp.pl_child_pid; > + m_result = true; > + } else > + m_result = false; > + } > +} > + > +//------------------------------------------------------------------------------ > +/// @class KillOperation > +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. > +class KillOperation : public Operation > +{ > +public: > + KillOperation(bool &result) : m_result(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + bool &m_result; > +}; > + > +void > +KillOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + > + if (PTRACE(PT_KILL, pid, NULL, 0)) > + m_result = false; > + else > + m_result = true; > +} > + > +//------------------------------------------------------------------------------ > +/// @class KillOperation > +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. > +class DetachOperation : public Operation > +{ > +public: > + DetachOperation(Error &result) : m_error(result) { } > + > + void Execute(ProcessMonitor *monitor); > + > +private: > + Error &m_error; > +}; > + > +void > +DetachOperation::Execute(ProcessMonitor *monitor) > +{ > + lldb::pid_t pid = monitor->GetPID(); > + > + if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) > + m_error.SetErrorToErrno(); > + > +} > + > +ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) > + : m_monitor(monitor) > +{ > + sem_init(&m_semaphore, 0, 0); > +} > + > +ProcessMonitor::OperationArgs::~OperationArgs() > +{ > + sem_destroy(&m_semaphore); > +} > + > +ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, > + lldb_private::Module *module, > + char const **argv, > + char const **envp, > + const char *stdin_path, > + const char *stdout_path, > + const char *stderr_path) > + : OperationArgs(monitor), > + m_module(module), > + m_argv(argv), > + m_envp(envp), > + m_stdin_path(stdin_path), > + m_stdout_path(stdout_path), > + m_stderr_path(stderr_path) { } > + > +ProcessMonitor::LaunchArgs::~LaunchArgs() > +{ } > + > +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, > + lldb::pid_t pid) > + : OperationArgs(monitor), m_pid(pid) { } > + > +ProcessMonitor::AttachArgs::~AttachArgs() > +{ } > + > +//------------------------------------------------------------------------------ > +/// The basic design of the ProcessMonitor is built around two threads. > +/// > +/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking > +/// for changes in the debugee state. When a change is detected a > +/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread > +/// "drives" state changes in the debugger. > +/// > +/// The second thread (@see OperationThread) is responsible for two things 1) > +/// launching or attaching to the inferior process, and then 2) servicing > +/// operations such as register reads/writes, stepping, etc. See the comments > +/// on the Operation class for more info as to why this is needed. > +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, > + Module *module, > + const char *argv[], > + const char *envp[], > + const char *stdin_path, > + const char *stdout_path, > + const char *stderr_path, > + lldb_private::Error &error) > + : m_process(static_cast(process)), > + m_operation_thread(LLDB_INVALID_HOST_THREAD), > + m_monitor_thread(LLDB_INVALID_HOST_THREAD), > + m_pid(LLDB_INVALID_PROCESS_ID), > + m_server_mutex(Mutex::eMutexTypeRecursive), > + m_terminal_fd(-1), > + m_client_fd(-1), > + m_server_fd(-1) > +{ > + std::auto_ptr args; > + > + args.reset(new LaunchArgs(this, module, argv, envp, > + stdin_path, stdout_path, stderr_path)); > + > + > + // Server/client descriptors. > + if (!EnableIPC()) > + { > + error.SetErrorToGenericError(); > + error.SetErrorString("Monitor failed to initialize."); > + } > + > + StartLaunchOpThread(args.get(), error); > + if (!error.Success()) > + return; > + > +WAIT_AGAIN: > + // Wait for the operation thread to initialize. > + if (sem_wait(&args->m_semaphore)) > + { > + if (errno == EINTR) > + goto WAIT_AGAIN; > + else > + { > + error.SetErrorToErrno(); > + return; > + } > + } > + > + // Check that the launch was a success. > + if (!args->m_error.Success()) > + { > + StopLaunchOpThread(); > + error = args->m_error; > + return; > + } > + > + // Finally, start monitoring the child process for change in state. > + m_monitor_thread = Host::StartMonitoringChildProcess( > + ProcessMonitor::MonitorCallback, this, GetPID(), true); > + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) > + { > + error.SetErrorToGenericError(); > + error.SetErrorString("Process launch failed."); > + return; > + } > +} > + > +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, > + lldb::pid_t pid, > + lldb_private::Error &error) > + : m_process(static_cast(process)), > + m_operation_thread(LLDB_INVALID_HOST_THREAD), > + m_monitor_thread(LLDB_INVALID_HOST_THREAD), > + m_pid(pid), > + m_server_mutex(Mutex::eMutexTypeRecursive), > + m_terminal_fd(-1), > + m_client_fd(-1), > + m_server_fd(-1) > +{ > + std::auto_ptr args; > + > + args.reset(new AttachArgs(this, pid)); > + > + // Server/client descriptors. > + if (!EnableIPC()) > + { > + error.SetErrorToGenericError(); > + error.SetErrorString("Monitor failed to initialize."); > + } > + > + StartAttachOpThread(args.get(), error); > + if (!error.Success()) > + return; > + > +WAIT_AGAIN: > + // Wait for the operation thread to initialize. > + if (sem_wait(&args->m_semaphore)) > + { > + if (errno == EINTR) > + goto WAIT_AGAIN; > + else > + { > + error.SetErrorToErrno(); > + return; > + } > + } > + > + // Check that the launch was a success. > + if (!args->m_error.Success()) > + { > + StopAttachOpThread(); > + error = args->m_error; > + return; > + } > + > + // Finally, start monitoring the child process for change in state. > + m_monitor_thread = Host::StartMonitoringChildProcess( > + ProcessMonitor::MonitorCallback, this, GetPID(), true); > + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) > + { > + error.SetErrorToGenericError(); > + error.SetErrorString("Process attach failed."); > + return; > + } > +} > + > +ProcessMonitor::~ProcessMonitor() > +{ > + StopMonitor(); > +} > + > +//------------------------------------------------------------------------------ > +// Thread setup and tear down. > +void > +ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) > +{ > + static const char *g_thread_name = "lldb.process.freebsd.operation"; > + > + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) > + return; > + > + m_operation_thread = > + Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error); > +} > + > +void > +ProcessMonitor::StopLaunchOpThread() > +{ > + lldb::thread_result_t result; > + > + if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) > + return; > + > + Host::ThreadCancel(m_operation_thread, NULL); > + Host::ThreadJoin(m_operation_thread, &result, NULL); > +} > + > +void * > +ProcessMonitor::LaunchOpThread(void *arg) > +{ > + LaunchArgs *args = static_cast(arg); > + > + if (!Launch(args)) { > + sem_post(&args->m_semaphore); > + return NULL; > + } > + > + ServeOperation(args); > + return NULL; > +} > + > +bool > +ProcessMonitor::Launch(LaunchArgs *args) > +{ > + ProcessMonitor *monitor = args->m_monitor; > + ProcessFreeBSD &process = monitor->GetProcess(); > + const char **argv = args->m_argv; > + const char **envp = args->m_envp; > + const char *stdin_path = args->m_stdin_path; > + const char *stdout_path = args->m_stdout_path; > + const char *stderr_path = args->m_stderr_path; > + lldb::pid_t pid; > + > + lldb::ThreadSP inferior; > + > + // Propagate the environment if one is not supplied. > + if (envp == NULL || envp[0] == NULL) > + envp = const_cast(environ); > + > + // Recognized child exit status codes. > + enum { > + ePtraceFailed = 1, > + eDupStdinFailed, > + eDupStdoutFailed, > + eDupStderrFailed, > + eExecFailed > + }; > + > + pid = fork(); > + > + // Child process. > + if (pid == 0) > + { > + // Trace this process. > + if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) > + exit(ePtraceFailed); > + > + // Do not inherit setgid powers. > + setgid(getgid()); > + > + // Let us have our own process group. > + setpgid(0, 0); > + > + // Dup file descriptors if needed. > + // > + // FIXME: If two or more of the paths are the same we needlessly open > + // the same file multiple times. > + if (stdin_path != NULL && stdin_path[0]) > + if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY)) > + exit(eDupStdinFailed); > + > + if (stdout_path != NULL && stdout_path[0]) > + if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT)) > + exit(eDupStdoutFailed); > + > + if (stderr_path != NULL && stderr_path[0]) > + if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT)) > + exit(eDupStderrFailed); > + > + // Execute. We should never return. > + execve(argv[0], > + const_cast(argv), > + const_cast(envp)); > + exit(eExecFailed); > + } > + > + // Wait for the child process to to trap on its call to execve. > + ::pid_t wpid; > + int status; > + if ((wpid = waitpid(pid, &status, 0)) < 0) > + { > + args->m_error.SetErrorToErrno(); > + goto FINISH; > + } > + else if (WIFEXITED(status)) > + { > + // open, dup or execve likely failed for some reason. > + args->m_error.SetErrorToGenericError(); > + switch (WEXITSTATUS(status)) > + { > + case ePtraceFailed: > + args->m_error.SetErrorString("Child ptrace failed."); > + break; > + case eDupStdinFailed: > + args->m_error.SetErrorString("Child open stdin failed."); > + break; > + case eDupStdoutFailed: > + args->m_error.SetErrorString("Child open stdout failed."); > + break; > + case eDupStderrFailed: > + args->m_error.SetErrorString("Child open stderr failed."); > + break; > + case eExecFailed: > + args->m_error.SetErrorString("Child exec failed."); > + break; > + default: > + args->m_error.SetErrorString("Child returned unknown exit status."); > + break; > + } > + goto FINISH; > + } > + assert(WIFSTOPPED(status) && wpid == pid && > + "Could not sync with inferior process."); > + > +#ifdef notyet > + // Have the child raise an event on exit. This is used to keep the child in > + // limbo until it is destroyed. > + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) > + { > + args->m_error.SetErrorToErrno(); > + goto FINISH; > + } > +#endif > + // XXX - Release the master terminal descriptor and pass it off to the > + // XXX - ProcessMonitor instance. Similarly stash the inferior pid. > + // For now just use stdin fd > + monitor->m_terminal_fd = STDIN_FILENO; > + monitor->m_pid = pid; > + > + // Set the terminal fd to be in non blocking mode (it simplifies the > + // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking > + // descriptor to read from). > + if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) > + goto FINISH; > + > + // Update the process thread list with this new thread. > + inferior.reset(new POSIXThread(process, pid)); > + process.GetThreadList().AddThread(inferior); > + > + // Let our process instance know the thread has stopped. > + process.SendMessage(ProcessMessage::Trace(pid)); > + > +FINISH: > + return args->m_error.Success(); > +} > + > +bool > +ProcessMonitor::EnableIPC() > +{ > + int fd[2]; > + > + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) > + return false; > + > + m_client_fd = fd[0]; > + m_server_fd = fd[1]; > + return true; > +} > + > +void > +ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) > +{ > + static const char *g_thread_name = "lldb.process.freebsd.operation"; > + > + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) > + return; > + > + m_operation_thread = > + Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error); > +} > + > +void > +ProcessMonitor::StopAttachOpThread() > +{ > + assert(!"Not implemented yet!!!"); > +} > + > +void * > +ProcessMonitor::AttachOpThread(void *arg) > +{ > + AttachArgs *args = static_cast(arg); > + > + if (!Attach(args)) > + return NULL; > + > + ServeOperation(args); > + return NULL; > +} > + > +bool > +ProcessMonitor::Attach(AttachArgs *args) > +{ > + lldb::pid_t pid = args->m_pid; > + > + ProcessMonitor *monitor = args->m_monitor; > + ProcessFreeBSD &process = monitor->GetProcess(); > + ThreadList &tl = process.GetThreadList(); > + lldb::ThreadSP inferior; > + > + if (pid <= 1) > + { > + args->m_error.SetErrorToGenericError(); > + args->m_error.SetErrorString("Attaching to process 1 is not allowed."); > + goto FINISH; > + } > + > + // Attach to the requested process. > + if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) > + { > + args->m_error.SetErrorToErrno(); > + goto FINISH; > + } > + > + int status; > + if ((status = waitpid(pid, NULL, 0)) < 0) > + { > + args->m_error.SetErrorToErrno(); > + goto FINISH; > + } > + > + // Update the process thread list with the attached thread. > + inferior.reset(new POSIXThread(process, pid)); > + tl.AddThread(inferior); > + > + // Let our process instance know the thread has stopped. > + process.SendMessage(ProcessMessage::Trace(pid)); > + > + FINISH: > + return args->m_error.Success(); > +} > + > +bool > +ProcessMonitor::MonitorCallback(void *callback_baton, > + lldb::pid_t pid, > + bool exited, > + int signal, > + int status) > +{ > + ProcessMessage message; > + ProcessMonitor *monitor = static_cast(callback_baton); > + ProcessFreeBSD *process = monitor->m_process; > + bool stop_monitoring; > + siginfo_t info; > + > + if (!monitor->GetSignalInfo(pid, &info)) > + stop_monitoring = true; // pid is gone. Bail. > + else { > + switch (info.si_signo) > + { > + case SIGTRAP: > + message = MonitorSIGTRAP(monitor, &info, pid); > + break; > + > + default: > + message = MonitorSignal(monitor, &info, pid); > + break; > + } > + > + process->SendMessage(message); > + stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; > + } > + > + return stop_monitoring; > +} > + > +ProcessMessage > +ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, > + const siginfo_t *info, lldb::pid_t pid) > +{ > + ProcessMessage message; > + > + assert(info->si_signo == SIGTRAP && "Unexpected child signal!"); > + > + switch (info->si_code) > + { > + default: > + assert(false && "Unexpected SIGTRAP code!"); > + break; > + > + case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): > + { > + // The inferior process is about to exit. Maintain the process in a > + // state of "limbo" until we are explicitly commanded to detach, > + // destroy, resume, etc. > + unsigned long data = 0; > + if (!monitor->GetEventMessage(pid, &data)) > + data = -1; > + message = ProcessMessage::Limbo(pid, (data >> 8)); > + break; > + } > + > + case 0: > + case TRAP_TRACE: > + message = ProcessMessage::Trace(pid); > + break; > + > + case SI_KERNEL: > + case TRAP_BRKPT: > + message = ProcessMessage::Break(pid); > + break; > + } > + > + return message; > +} > + > +ProcessMessage > +ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, > + const siginfo_t *info, lldb::pid_t pid) > +{ > + ProcessMessage message; > + int signo = info->si_signo; > + > + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, > + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a > + // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. > + // > + // IOW, user generated signals never generate what we consider to be a > + // "crash". > + // > + // Similarly, ACK signals generated by this monitor. > + if (info->si_code == SI_USER) > + { > + if (info->si_pid == getpid()) > + return ProcessMessage::SignalDelivered(pid, signo); > + else > + return ProcessMessage::Signal(pid, signo); > + } > + > + if (signo == SIGSEGV) { > + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); > + ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); > + return ProcessMessage::Crash(pid, reason, signo, fault_addr); > + } > + > + if (signo == SIGILL) { > + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); > + ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); > + return ProcessMessage::Crash(pid, reason, signo, fault_addr); > + } > + > + if (signo == SIGFPE) { > + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); > + ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); > + return ProcessMessage::Crash(pid, reason, signo, fault_addr); > + } > + > + if (signo == SIGBUS) { > + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); > + ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); > + return ProcessMessage::Crash(pid, reason, signo, fault_addr); > + } > + > + // Everything else is "normal" and does not require any special action on > + // our part. > + return ProcessMessage::Signal(pid, signo); > +} > + > +ProcessMessage::CrashReason > +ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) > +{ > + ProcessMessage::CrashReason reason; > + assert(info->si_signo == SIGSEGV); > + > + reason = ProcessMessage::eInvalidCrashReason; > + > + switch (info->si_code) > + { > + default: > + assert(false && "unexpected si_code for SIGSEGV"); > + break; > + case SEGV_MAPERR: > + reason = ProcessMessage::eInvalidAddress; > + break; > + case SEGV_ACCERR: > + reason = ProcessMessage::ePrivilegedAddress; > + break; > + } > + > + return reason; > +} > + > +ProcessMessage::CrashReason > +ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) > +{ > + ProcessMessage::CrashReason reason; > + assert(info->si_signo == SIGILL); > + > + reason = ProcessMessage::eInvalidCrashReason; > + > + switch (info->si_code) > + { > + default: > + assert(false && "unexpected si_code for SIGILL"); > + break; > + case ILL_ILLOPC: > + reason = ProcessMessage::eIllegalOpcode; > + break; > + case ILL_ILLOPN: > + reason = ProcessMessage::eIllegalOperand; > + break; > + case ILL_ILLADR: > + reason = ProcessMessage::eIllegalAddressingMode; > + break; > + case ILL_ILLTRP: > + reason = ProcessMessage::eIllegalTrap; > + break; > + case ILL_PRVOPC: > + reason = ProcessMessage::ePrivilegedOpcode; > + break; > + case ILL_PRVREG: > + reason = ProcessMessage::ePrivilegedRegister; > + break; > + case ILL_COPROC: > + reason = ProcessMessage::eCoprocessorError; > + break; > + case ILL_BADSTK: > + reason = ProcessMessage::eInternalStackError; > + break; > + } > + > + return reason; > +} > + > +ProcessMessage::CrashReason > +ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) > +{ > + ProcessMessage::CrashReason reason; > + assert(info->si_signo == SIGFPE); > + > + reason = ProcessMessage::eInvalidCrashReason; > + > + switch (info->si_code) > + { > + default: > + assert(false && "unexpected si_code for SIGFPE"); > + break; > + case FPE_INTDIV: > + reason = ProcessMessage::eIntegerDivideByZero; > + break; > + case FPE_INTOVF: > + reason = ProcessMessage::eIntegerOverflow; > + break; > + case FPE_FLTDIV: > + reason = ProcessMessage::eFloatDivideByZero; > + break; > + case FPE_FLTOVF: > + reason = ProcessMessage::eFloatOverflow; > + break; > + case FPE_FLTUND: > + reason = ProcessMessage::eFloatUnderflow; > + break; > + case FPE_FLTRES: > + reason = ProcessMessage::eFloatInexactResult; > + break; > + case FPE_FLTINV: > + reason = ProcessMessage::eFloatInvalidOperation; > + break; > + case FPE_FLTSUB: > + reason = ProcessMessage::eFloatSubscriptRange; > + break; > + } > + > + return reason; > +} > + > +ProcessMessage::CrashReason > +ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) > +{ > + ProcessMessage::CrashReason reason; > + assert(info->si_signo == SIGBUS); > + > + reason = ProcessMessage::eInvalidCrashReason; > + > + switch (info->si_code) > + { > + default: > + assert(false && "unexpected si_code for SIGBUS"); > + break; > + case BUS_ADRALN: > + reason = ProcessMessage::eIllegalAlignment; > + break; > + case BUS_ADRERR: > + reason = ProcessMessage::eIllegalAddress; > + break; > + case BUS_OBJERR: > + reason = ProcessMessage::eHardwareError; > + break; > + } > + > + return reason; > +} > + > +void > +ProcessMonitor::ServeOperation(OperationArgs *args) > +{ > + int status; > + pollfd fdset; > + > + ProcessMonitor *monitor = args->m_monitor; > + > + fdset.fd = monitor->m_server_fd; > + fdset.events = POLLIN | POLLPRI; > + fdset.revents = 0; > + > + // We are finised with the arguments and are ready to go. Sync with the > + // parent thread and start serving operations on the inferior. > + sem_post(&args->m_semaphore); > + > + for (;;) > + { > + if ((status = poll(&fdset, 1, -1)) < 0) > + { > + switch (errno) > + { > + default: > + assert(false && "Unexpected poll() failure!"); > + continue; > + > + case EINTR: continue; // Just poll again. > + case EBADF: return; // Connection terminated. > + } > + } > + > + assert(status == 1 && "Too many descriptors!"); > + > + if (fdset.revents & POLLIN) > + { > + Operation *op = NULL; > + > + READ_AGAIN: > + if ((status = read(fdset.fd, &op, sizeof(op))) < 0) > + { > + // There is only one acceptable failure. > + assert(errno == EINTR); > + goto READ_AGAIN; > + } > + > + assert(status == sizeof(op)); > + op->Execute(monitor); > + write(fdset.fd, &op, sizeof(op)); > + } > + } > +} > + > +void > +ProcessMonitor::DoOperation(Operation *op) > +{ > + int status; > + Operation *ack = NULL; > + Mutex::Locker lock(m_server_mutex); > + > + // FIXME: Do proper error checking here. > + write(m_client_fd, &op, sizeof(op)); > + > +READ_AGAIN: > + if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0) > + { > + // If interrupted by a signal handler try again. Otherwise the monitor > + // thread probably died and we have a stale file descriptor -- abort the > + // operation. > + if (errno == EINTR) > + goto READ_AGAIN; > + return; > + } > + > + assert(status == sizeof(ack)); > + assert(ack == op && "Invalid monitor thread response!"); > +} > + > +size_t > +ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, > + Error &error) > +{ > + size_t result; > + ReadOperation op(vm_addr, buf, size, error, result); > + DoOperation(&op); > + return result; > +} > + > +size_t > +ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, > + lldb_private::Error &error) > +{ > + size_t result; > + WriteOperation op(vm_addr, buf, size, error, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) > +{ > + bool result; > + ReadRegOperation op(offset, size, value, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value) > +{ > + bool result; > + WriteRegOperation op(offset, value, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::ReadGPR(void *buf) > +{ > + bool result; > + ReadGPROperation op(buf, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::ReadFPR(void *buf) > +{ > + bool result; > + ReadFPROperation op(buf, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::WriteGPR(void *buf) > +{ > + bool result; > + WriteGPROperation op(buf, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::WriteFPR(void *buf) > +{ > + bool result; > + WriteFPROperation op(buf, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) > +{ > + bool result; > + ResumeOperation op(tid, signo, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo) > +{ > + bool result; > + SingleStepOperation op(tid, signo, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::BringProcessIntoLimbo() > +{ > + bool result; > + KillOperation op(result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo) > +{ > + bool result; > + SiginfoOperation op(tid, siginfo, result); > + DoOperation(&op); > + return result; > +} > + > +bool > +ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) > +{ > + bool result; > + EventMessageOperation op(tid, message, result); > + DoOperation(&op); > + return result; > +} > + > +Error > +ProcessMonitor::Detach() > +{ > + Error result; > + DetachOperation op(result); > + DoOperation(&op); > + StopMonitor(); > + return result; > +} > + > +bool > +ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) > +{ > + int target_fd = open(path, flags, 0666); > + > + if (target_fd == -1) > + return false; > + > + return (dup2(target_fd, fd) == -1) ? false : true; > +} > + > +void > +ProcessMonitor::StopMonitoringChildProcess() > +{ > + lldb::thread_result_t thread_result; > + > + if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) > + { > + Host::ThreadCancel(m_monitor_thread, NULL); > + Host::ThreadJoin(m_monitor_thread, &thread_result, NULL); > + m_monitor_thread = LLDB_INVALID_HOST_THREAD; > + } > +} > + > +void > +ProcessMonitor::StopMonitor() > +{ > + StopMonitoringChildProcess(); > + StopLaunchOpThread(); > + CloseFD(m_terminal_fd); > + CloseFD(m_client_fd); > + CloseFD(m_server_fd); > +} > + > +void > +ProcessMonitor::CloseFD(int &fd) > +{ > + if (fd != -1) > + { > + close(fd); > + fd = -1; > + } > +} > Index: source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h > =================================================================== > --- source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) > +++ source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) > @@ -0,0 +1,43 @@ > +//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > + > +#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ > +#define liblldb_RegisterContextFreeBSD_x86_64_H_ > + > + typedef struct _GPR > + { > + uint64_t r15; > + uint64_t r14; > + uint64_t r13; > + uint64_t r12; > + uint64_t r11; > + uint64_t r10; > + uint64_t r9; > + uint64_t r8; > + uint64_t rdi; > + uint64_t rsi; > + uint64_t rbp; > + uint64_t rbx; > + uint64_t rdx; > + uint64_t rcx; > + uint64_t rax; > + uint32_t trapno; > + uint16_t fs; > + uint16_t gs; > + uint32_t err; > + uint16_t es; > + uint16_t ds; > + uint64_t rip; > + uint64_t cs; > + uint64_t rflags; > + uint64_t rsp; > + uint64_t ss; > + } GPR; > + > +#endif > Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp > =================================================================== > --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) > +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) > @@ -0,0 +1,136 @@ > +//===-- ProcessFreeBSD.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 > + > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/Core/PluginManager.h" > +#include "lldb/Core/State.h" > +#include "lldb/Host/Host.h" > +#include "lldb/Symbol/ObjectFile.h" > +#include "lldb/Target/DynamicLoader.h" > +#include "lldb/Target/Target.h" > + > +#include "ProcessFreeBSD.h" > +#include "ProcessPOSIXLog.h" > +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" > +#include "ProcessMonitor.h" > +#include "POSIXThread.h" > + > +using namespace lldb; > +using namespace lldb_private; > + > +//------------------------------------------------------------------------------ > +// Static functions. > + > +Process* > +ProcessFreeBSD::CreateInstance(Target& target, Listener &listener) > +{ > + return new ProcessFreeBSD(target, listener); > +} > + > +void > +ProcessFreeBSD::Initialize() > +{ > + static bool g_initialized = false; > + > + if (!g_initialized) > + { > + PluginManager::RegisterPlugin(GetPluginNameStatic(), > + GetPluginDescriptionStatic(), > + CreateInstance); > + Log::Callbacks log_callbacks = { > + ProcessPOSIXLog::DisableLog, > + ProcessPOSIXLog::EnableLog, > + ProcessPOSIXLog::ListLogCategories > + }; > + > + Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks); > + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); > + g_initialized = true; > + } > +} > + > +const char * > +ProcessFreeBSD::GetPluginNameStatic() > +{ > + return "freebsd"; > +} > + > +const char * > +ProcessFreeBSD::GetPluginDescriptionStatic() > +{ > + return "Process plugin for FreeBSD"; > +} > + > +//------------------------------------------------------------------------------ > +// ProcessInterface protocol. > + > +const char * > +ProcessFreeBSD::GetPluginName() > +{ > + return "process.freebsd"; > +} > + > +const char * > +ProcessFreeBSD::GetShortPluginName() > +{ > + return "process.freebsd"; > +} > + > +uint32_t > +ProcessFreeBSD::GetPluginVersion() > +{ > + return 1; > +} > + > +void > +ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) > +{ > +} > + > +Error > +ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) > +{ > + return Error(1, eErrorTypeGeneric); > +} > + > +Log * > +ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) > +{ > + return NULL; > +} > + > +//------------------------------------------------------------------------------ > +// Constructors and destructors. > + > +ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) > + : ProcessPOSIX(target, listener) > +{ > + // FIXME: Putting this code in the ctor and saving the byte order in a > + // member variable is a hack to avoid const qual issues in GetByteOrder. > + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); > + m_byte_order = obj_file->GetByteOrder(); > +} > + > +void > +ProcessFreeBSD::Terminate() > +{ > +} > + > +uint32_t > +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) > +{ > + // XXX haxx > + new_thread_list = old_thread_list; > + > + return 0; > +} > Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h > =================================================================== > --- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) > +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) > @@ -0,0 +1,292 @@ > +//===-- ProcessMonitor.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_ProcessMonitor_H_ > +#define liblldb_ProcessMonitor_H_ > + > +// C Includes > +#include > +#include > + > +// C++ Includes > +// Other libraries and framework includes > +#include "lldb/lldb-types.h" > +#include "lldb/Host/Mutex.h" > + > +namespace lldb_private > +{ > +class Error; > +class Module; > +class Scalar; > +} // End lldb_private namespace. > + > +class ProcessFreeBSD; > +class Operation; > + > +/// @class ProcessMonitor > +/// @brief Manages communication with the inferior (debugee) process. > +/// > +/// Upon construction, this class prepares and launches an inferior process for > +/// debugging. > +/// > +/// Changes in the inferior process state are propagated to the associated > +/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the > +/// appropriate ProcessMessage events. > +/// > +/// A purposely minimal set of operations are provided to interrogate and change > +/// the inferior process state. > +class ProcessMonitor > +{ > +public: > + > + /// Launches an inferior process ready for debugging. Forms the > + /// implementation of Process::DoLaunch. > + ProcessMonitor(ProcessPOSIX *process, > + lldb_private::Module *module, > + char const *argv[], > + char const *envp[], > + const char *stdin_path, > + const char *stdout_path, > + const char *stderr_path, > + lldb_private::Error &error); > + > + ProcessMonitor(ProcessPOSIX *process, > + lldb::pid_t pid, > + lldb_private::Error &error); > + > + ~ProcessMonitor(); > + > + /// Provides the process number of debugee. > + lldb::pid_t > + GetPID() const { return m_pid; } > + > + /// Returns the process associated with this ProcessMonitor. > + ProcessFreeBSD & > + GetProcess() { return *m_process; } > + > + /// Returns a file descriptor to the controlling terminal of the inferior > + /// process. > + /// > + /// Reads from this file descriptor yield both the standard output and > + /// standard error of this debugee. Even if stderr and stdout were > + /// redirected on launch it may still happen that data is available on this > + /// descriptor (if the inferior process opens /dev/tty, for example). > + /// > + /// If this monitor was attached to an existing process this method returns > + /// -1. > + int > + GetTerminalFD() const { return m_terminal_fd; } > + > + /// Reads @p size bytes from address @vm_adder in the inferior process > + /// address space. > + /// > + /// This method is provided to implement Process::DoReadMemory. > + size_t > + ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, > + lldb_private::Error &error); > + > + /// Writes @p size bytes from address @p vm_adder in the inferior process > + /// address space. > + /// > + /// This method is provided to implement Process::DoWriteMemory. > + size_t > + WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, > + lldb_private::Error &error); > + > + /// Reads the contents from the register identified by the given (architecture > + /// dependent) offset. > + /// > + /// This method is provided for use by RegisterContextFreeBSD derivatives. > + bool > + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); > + > + /// Writes the given value to the register identified by the given > + /// (architecture dependent) offset. > + /// > + /// This method is provided for use by RegisterContextFreeBSD derivatives. > + bool > + WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value); > + > + /// Reads all general purpose registers into the specified buffer. > + bool > + ReadGPR(void *buf); > + > + /// Reads all floating point registers into the specified buffer. > + bool > + ReadFPR(void *buf); > + > + /// Writes all general purpose registers into the specified buffer. > + bool > + WriteGPR(void *buf); > + > + /// Writes all floating point registers into the specified buffer. > + bool > + WriteFPR(void *buf); > + > + /// Writes a siginfo_t structure corresponding to the given thread ID to the > + /// memory region pointed to by @p siginfo. > + bool > + GetSignalInfo(lldb::tid_t tid, void *siginfo); > + > + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) > + /// corresponding to the given thread IDto the memory pointed to by @p > + /// message. > + bool > + GetEventMessage(lldb::tid_t tid, unsigned long *message); > + > + /// Resumes the given thread. If @p signo is anything but > + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. > + bool > + Resume(lldb::tid_t tid, uint32_t signo); > + > + /// Single steps the given thread. If @p signo is anything but > + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. > + bool > + SingleStep(lldb::tid_t tid, uint32_t signo); > + > + /// Sends the inferior process a PTRACE_KILL signal. The inferior will > + /// still exists and can be interrogated. Once resumed it will exit as > + /// though it received a SIGKILL. > + bool > + BringProcessIntoLimbo(); > + > + lldb_private::Error > + Detach(); > + > + > +private: > + ProcessFreeBSD *m_process; > + > + lldb::thread_t m_operation_thread; > + lldb::thread_t m_monitor_thread; > + lldb::pid_t m_pid; > + > + > + lldb_private::Mutex m_server_mutex; > + int m_terminal_fd; > + int m_client_fd; > + int m_server_fd; > + > + struct OperationArgs > + { > + OperationArgs(ProcessMonitor *monitor); > + > + ~OperationArgs(); > + > + ProcessMonitor *m_monitor; // The monitor performing the attach. > + sem_t m_semaphore; // Posted to once operation complete. > + lldb_private::Error m_error; // Set if process operation failed. > + }; > + > + /// @class LauchArgs > + /// > + /// @brief Simple structure to pass data to the thread responsible for > + /// launching a child process. > + struct LaunchArgs : OperationArgs > + { > + LaunchArgs(ProcessMonitor *monitor, > + lldb_private::Module *module, > + char const **argv, > + char const **envp, > + const char *stdin_path, > + const char *stdout_path, > + const char *stderr_path); > + > + ~LaunchArgs(); > + > + lldb_private::Module *m_module; // The executable image to launch. > + char const **m_argv; // Process arguments. > + char const **m_envp; // Process environment. > + const char *m_stdin_path; // Redirect stdin or NULL. > + const char *m_stdout_path; // Redirect stdout or NULL. > + const char *m_stderr_path; // Redirect stderr or NULL. > + }; > + > + void > + StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); > + > + void > + StopLaunchOpThread(); > + > + static void * > + LaunchOpThread(void *arg); > + > + static bool > + Launch(LaunchArgs *args); > + > + bool > + EnableIPC(); > + > + struct AttachArgs : OperationArgs > + { > + AttachArgs(ProcessMonitor *monitor, > + lldb::pid_t pid); > + > + ~AttachArgs(); > + > + lldb::pid_t m_pid; // pid of the process to be attached. > + }; > + > + void > + StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); > + > + void > + StopAttachOpThread(); > + > + static void * > + AttachOpThread(void *args); > + > + static bool > + Attach(AttachArgs *args); > + > + static void > + ServeOperation(OperationArgs *args); > + > + static bool > + DupDescriptor(const char *path, int fd, int flags); > + > + static bool > + MonitorCallback(void *callback_baton, > + lldb::pid_t pid, bool exited, int signal, int status); > + > + static ProcessMessage > + MonitorSIGTRAP(ProcessMonitor *monitor, > + const siginfo_t *info, lldb::pid_t pid); > + > + static ProcessMessage > + MonitorSignal(ProcessMonitor *monitor, > + const siginfo_t *info, lldb::pid_t pid); > + > + static ProcessMessage::CrashReason > + GetCrashReasonForSIGSEGV(const siginfo_t *info); > + > + static ProcessMessage::CrashReason > + GetCrashReasonForSIGILL(const siginfo_t *info); > + > + static ProcessMessage::CrashReason > + GetCrashReasonForSIGFPE(const siginfo_t *info); > + > + static ProcessMessage::CrashReason > + GetCrashReasonForSIGBUS(const siginfo_t *info); > + > + void > + DoOperation(Operation *op); > + > + /// Stops the child monitor thread. > + void > + StopMonitoringChildProcess(); > + > + void > + StopMonitor(); > + > + void > + CloseFD(int &fd); > +}; > + > +#endif // #ifndef liblldb_ProcessMonitor_H_ > Index: source/Plugins/Process/FreeBSD/Makefile > =================================================================== > --- source/Plugins/Process/FreeBSD/Makefile (revision 0) > +++ source/Plugins/Process/FreeBSD/Makefile (revision 0) > @@ -0,0 +1,17 @@ > +##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===## > +# > +# The LLVM Compiler Infrastructure > +# > +# This file is distributed under the University of Illinois Open Source > +# License. See LICENSE.TXT for details. > +# > +##===----------------------------------------------------------------------===## > + > +LLDB_LEVEL := ../../../.. > +LIBRARYNAME := lldbPluginProcessFreeBSD > +BUILD_ARCHIVE = 1 > + > +# Extend the include path so we may locate UnwindLLDB.h > +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility > + > +include $(LLDB_LEVEL)/Makefile > Index: source/Host/linux/Host.cpp > =================================================================== > --- source/Host/linux/Host.cpp (revision 147560) > +++ source/Host/linux/Host.cpp (working copy) > @@ -10,12 +10,20 @@ > // C Includes > #include > #include > +#include > +#include > +#include > > + > // C++ Includes > // Other libraries and framework includes > // Project includes > #include "lldb/Core/Error.h" > +#include "lldb/Target/Process.h" > + > #include "lldb/Host/Host.h" > +#include "lldb/Core/DataBufferHeap.h" > +#include "lldb/Core/DataExtractor.h" > > using namespace lldb; > using namespace lldb_private; > @@ -43,3 +51,48 @@ > return error; > } > > +lldb::DataBufferSP > +Host::GetAuxvData(lldb_private::Process *process) > +{ > + static const size_t path_size = 128; > + static char path[path_size]; > + lldb::DataBufferSP buf_sp; > + > + int fd; > + > + // Ideally, we would simply create a FileSpec and call ReadFileContents. > + // However, files in procfs have zero size (since they are, in general, > + // dynamically generated by the kernel) which is incompatible with the > + // current ReadFileContents implementation. Therefore we simply stream the > + // data into a DataBuffer ourselves. > + if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0) > + return buf_sp; > + > + if ((fd = open(path, O_RDONLY, 0)) < 0) > + return buf_sp; > + > + size_t bytes_read = 0; > + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); > + for (;;) > + { > + size_t avail = buf_ap->GetByteSize() - bytes_read; > + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); > + > + if (status < 0) > + break; > + > + bytes_read += status; > + > + if (status == 0) > + { > + buf_ap->SetByteSize(bytes_read); > + buf_sp.reset(buf_ap.release()); > + break; > + } > + > + if (avail - status == 0) > + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); > + } > + > + return buf_sp; > +} > Index: source/Host/freebsd/Host.cpp > =================================================================== > --- source/Host/freebsd/Host.cpp (revision 147560) > +++ source/Host/freebsd/Host.cpp (working copy) > @@ -9,12 +9,18 @@ > > // C Includes > #include > +#include > #include > #include > #include > #include > #include > > +#include > +#include > +#include > + > + > // C++ Includes > // Other libraries and framework includes > // Project includes > @@ -26,15 +32,19 @@ > #include "lldb/Core/StreamString.h" > #include "lldb/Target/Process.h" > > +#include "lldb/Core/DataBufferHeap.h" > +#include "lldb/Core/DataExtractor.h" > #include "llvm/Support/Host.h" > > + > extern "C" { > - char **environ; > + extern char **environ; > } > > using namespace lldb; > using namespace lldb_private; > > + > class FreeBSDThread > { > public: > @@ -77,7 +87,7 @@ > std::vector frame_buffer (max_frames, NULL); > int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); > ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); > - > + > const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); > > if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) > @@ -101,7 +111,7 @@ > { > char *v; > char **var = environ; > - for (var = environ; var != NULL; ++var) { > + for (; var != NULL && *var != NULL; ++var) { > v = strchr(*var, (int)'-'); > if (v == NULL) > continue; > @@ -168,49 +178,47 @@ > ProcessInstanceInfo &process_info) > { > if (process_info.ProcessIDIsValid()) { > - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; > + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; > > char arg_data[8192]; > size_t arg_data_size = sizeof(arg_data); > - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) > + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) > { > DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); > uint32_t offset = 0; > - uint32_t start_offset; > - uint32_t argc = data.GetU32 (&offset); > const char *cstr; > - > + > cstr = data.GetCStr (&offset); > if (cstr) > { > process_info.GetExecutableFile().SetFile(cstr, false); > > - if (match_info_ptr == NULL || > + if (!(match_info_ptr == NULL || > NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), > match_info_ptr->GetNameMatchType(), > - match_info_ptr->GetProcessInfo().GetName())) > + match_info_ptr->GetProcessInfo().GetName()))) > + return false; > + > + Args &proc_args = process_info.GetArguments(); > + while (1) > { > - // Skip NULLs > - while (1) > + const uint8_t *p = data.PeekData(offset, 1); > + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) > { > - const uint8_t *p = data.PeekData(offset, 1); > - if ((p == NULL) || (*p != '\0')) > - break; > ++offset; > + p = data.PeekData(offset, 1); > } > - // Now extract all arguments > - Args &proc_args = process_info.GetArguments(); > - for (int i=0; i - { > - start_offset = offset; > - cstr = data.GetCStr(&offset); > - if (cstr) > - proc_args.AppendArgument(cstr); > - } > - return true; > + if (p == NULL || offset >= arg_data_size) > + return true; > + > + cstr = data.GetCStr(&offset); > + if (cstr) > + proc_args.AppendArgument(cstr); > + else > + return true; > } > } > - } > + } > } > return false; > } > @@ -219,8 +227,8 @@ > GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) > { > if (process_info.ProcessIDIsValid()) { > - // TODO: This > - // return true; > + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); > + return true; > } > process_info.GetArchitecture().Clear(); > return false; > @@ -249,7 +257,7 @@ > if (proc_kinfo.ki_ngroups > 0) > process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); > else > - process_info.SetEffectiveGroupID (UINT32_MAX); > + process_info.SetEffectiveGroupID (UINT32_MAX); > return true; > } > } > @@ -258,7 +266,7 @@ > process_info.SetUserID (UINT32_MAX); > process_info.SetGroupID (UINT32_MAX); > process_info.SetEffectiveUserID (UINT32_MAX); > - process_info.SetEffectiveGroupID (UINT32_MAX); > + process_info.SetEffectiveGroupID (UINT32_MAX); > return false; > } > > @@ -275,3 +283,46 @@ > process_info.Clear(); > return false; > } > + > +lldb::DataBufferSP > +Host::GetAuxvData(lldb_private::Process *process) > +{ > + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; > + void *ps_strings_addr, *auxv_addr; > + size_t ps_strings_size = sizeof(void *); > + Elf_Auxinfo aux_info[AT_COUNT]; > + struct ps_strings ps_strings; > + struct ptrace_io_desc pid; > + DataBufferSP buf_sp; > + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); > + > + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { > + pid.piod_op = PIOD_READ_D; > + pid.piod_addr = &ps_strings; > + pid.piod_offs = ps_strings_addr; > + pid.piod_len = sizeof(ps_strings); > + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { > + perror("failed to fetch ps_strings"); > + buf_ap.release(); > + goto done; > + } > + > + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; > + > + pid.piod_addr = aux_info; > + pid.piod_offs = auxv_addr; > + pid.piod_len = sizeof(aux_info); > + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { > + perror("failed to fetch aux_info"); > + buf_ap.release(); > + goto done; > + } > + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); > + buf_sp.reset(buf_ap.release()); > + } else { > + perror("sysctl failed on ps_strings"); > + } > + > + done: > + return buf_sp; > +} > Index: source/lldb.cpp > =================================================================== > --- source/lldb.cpp (revision 147560) > +++ source/lldb.cpp (working copy) > @@ -52,13 +52,16 @@ > #endif > > #if defined (__linux__) > -#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h" > +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" > #include "Plugins/Platform/Linux/PlatformLinux.h" > #include "Plugins/Process/Linux/ProcessLinux.h" > #endif > > #if defined (__FreeBSD__) > +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" > #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" > +#include "Plugins/Process/POSIX/ProcessPOSIX.h" > +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" > #endif > > #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" > @@ -120,10 +123,12 @@ > //---------------------------------------------------------------------- > PlatformLinux::Initialize(); > ProcessLinux::Initialize(); > - DynamicLoaderLinuxDYLD::Initialize(); > + DynamicLoaderPOSIXDYLD::Initialize(); > #endif > #if defined (__FreeBSD__) > - PlatformFreeBSD::Initialize(); > + PlatformFreeBSD::Initialize(); > + ProcessFreeBSD::Initialize(); > + DynamicLoaderPOSIXDYLD::Initialize(); > #endif > //---------------------------------------------------------------------- > // Platform agnostic plugins > @@ -190,11 +195,13 @@ > #if defined (__linux__) > PlatformLinux::Terminate(); > ProcessLinux::Terminate(); > - DynamicLoaderLinuxDYLD::Terminate(); > + DynamicLoaderPOSIXDYLD::Terminate(); > #endif > > #if defined (__FreeBSD__) > - PlatformFreeBSD::Terminate(); > + PlatformFreeBSD::Terminate(); > + ProcessFreeBSD::Terminate(); > + DynamicLoaderPOSIXDYLD::Terminate(); > #endif > > DynamicLoaderStatic::Terminate(); > Index: tools/driver/Makefile > =================================================================== > --- tools/driver/Makefile (revision 147560) > +++ tools/driver/Makefile (working copy) > @@ -25,7 +25,6 @@ > > ifeq ($(HOST_OS),FreeBSD) > CPP.Flags += -I/usr/include/edit #-v > - LD.Flags += -lEnhancedDisassembly > LD.Flags += -Wl,-rpath,$(LibDir) > endif > > Index: lib/Makefile > =================================================================== > --- lib/Makefile (revision 147560) > +++ lib/Makefile (working copy) > @@ -81,15 +81,19 @@ > endif > > ifeq ($(HOST_OS),Linux) > - USEDLIBS += lldbPluginProcessLinux.a \ > - lldbPluginDynamicLoaderLinux.a \ > + USEDLIBS += lldbPluginProcessPOSIX.a \ > + lldbPluginProcessLinux.a \ > + lldbPluginDynamicLoaderPOSIX.a \ > lldbPluginPlatformLinux.a \ > lldbHostLinux.a > endif > > ifeq ($(HOST_OS),FreeBSD) > USEDLIBS += lldbHostFreeBSD.a \ > - lldbPluginPlatformFreeBSD.a > + lldbPluginDynamicLoaderPOSIX.a \ > + lldbPluginProcessPOSIX.a \ > + lldbPluginProcessFreeBSD.a \ > + lldbPluginPlatformFreeBSD.a > endif > > include $(LEVEL)/Makefile.common > @@ -130,8 +134,8 @@ > # Include everything from the .a's into the shared library. > ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \ > -Wl,--no-whole-archive > - # Don't allow unresolved symbols. > - LLVMLibsOptions += -Wl,--no-undefined > + # Allow unresolved symbols. > + LLVMLibsOptions += -Wl,--allow-shlib-undefined > # Link in python > LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo > endif > Index: Makefile > =================================================================== > --- Makefile (revision 147560) > +++ Makefile (working copy) > @@ -39,6 +39,7 @@ > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility > +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX > ifeq ($(HOST_OS),Darwin) > CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks > endif > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits From gclayton at apple.com Wed Jan 4 21:58:00 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 05 Jan 2012 03:58:00 -0000 Subject: [Lldb-commits] [lldb] r147596 - in /lldb/trunk: include/lldb/Core/ include/lldb/Host/ include/lldb/Symbol/ source/Core/ source/Host/common/ source/Host/macosx/ source/Plugins/DynamicLoader/Darwin-Kernel/ source/Plugins/DynamicLoader/MacOSX-DYLD/ source/Plugins/ObjectFile/Mach-O/ source/Plugins/SymbolFile/DWARF/ source/Symbol/ Message-ID: <20120105035801.0B2171BE003@llvm.org> Author: gclayton Date: Wed Jan 4 21:57:59 2012 New Revision: 147596 URL: http://llvm.org/viewvc/llvm-project?rev=147596&view=rev Log: Added code in the Host layer that can report system log messages so that we don't have "fprintf (stderr, ...)" calls sprinkled everywhere. Changed all needed locations over to using this. For non-darwin, we log to stderr only. On darwin, we log to stderr _and_ to ASL (Apple System Log facility). This will allow GUI apps to have a place for these error and warning messages to go, and also allows the command line apps to log directly to the terminal. Modified: lldb/trunk/include/lldb/Core/Module.h lldb/trunk/include/lldb/Host/Host.h lldb/trunk/include/lldb/Symbol/SymbolFile.h lldb/trunk/source/Core/Module.cpp lldb/trunk/source/Core/ModuleList.cpp lldb/trunk/source/Host/common/Host.cpp lldb/trunk/source/Host/macosx/Host.mm lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp lldb/trunk/source/Symbol/Function.cpp lldb/trunk/source/Symbol/SymbolContext.cpp lldb/trunk/source/Symbol/SymbolFile.cpp Modified: lldb/trunk/include/lldb/Core/Module.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Module.h (original) +++ lldb/trunk/include/lldb/Core/Module.h Wed Jan 4 21:57:59 2012 @@ -678,6 +678,17 @@ void ReportError (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + // Only report an error once when the module is first detected to be modified + // so we don't spam the console with many messages. + void + ReportErrorIfModifyDetected (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + bool + GetModified (bool use_cached_only); + + bool + SetModified (bool b); + protected: //------------------------------------------------------------------ // Member Variables @@ -697,7 +708,8 @@ m_did_load_symbol_vendor:1, m_did_parse_uuid:1, m_did_init_ast:1, - m_is_dynamic_loader_module:1; + m_is_dynamic_loader_module:1, + m_was_modified:1; /// See if the module was modified after it was initially opened. //------------------------------------------------------------------ /// Resolve a file or load virtual address. Modified: lldb/trunk/include/lldb/Host/Host.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Host.h?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/include/lldb/Host/Host.h (original) +++ lldb/trunk/include/lldb/Host/Host.h Wed Jan 4 21:57:59 2012 @@ -116,7 +116,19 @@ static const char * GetGroupName (uint32_t gid, std::string &group_name); - + + enum SystemLogType + { + eSystemLogWarning, + eSystemLogError + }; + + static void + SystemLog (SystemLogType type, const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + static void + SystemLog (SystemLogType type, const char *format, va_list args); + //------------------------------------------------------------------ /// Gets the host architecture. /// Modified: lldb/trunk/include/lldb/Symbol/SymbolFile.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolFile.h?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/SymbolFile.h (original) +++ lldb/trunk/include/lldb/Symbol/SymbolFile.h Wed Jan 4 21:57:59 2012 @@ -148,13 +148,6 @@ ObjectFile* GetObjectFile() { return m_obj_file; } const ObjectFile* GetObjectFile() const { return m_obj_file; } - // Special error functions that can do printf style formatting that will prepend the message with - // something appropriate for this symbol file (like the architecture, path and object name). This - // centralizes code so that everyone doesn't need to format their error and log messages on their - // own and keeps the output a bit more consistent. - void LogMessage (Log *log, const char *format, ...) __attribute__ ((format (printf, 3, 4))); - void ReportWarning (const char *format, ...) __attribute__ ((format (printf, 2, 3))); - void ReportError (const char *format, ...) __attribute__ ((format (printf, 2, 3))); protected: ObjectFile* m_obj_file; // The object file that symbols can be extracted from. uint32_t m_abilities; Modified: lldb/trunk/source/Core/Module.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Core/Module.cpp (original) +++ lldb/trunk/source/Core/Module.cpp Wed Jan 4 21:57:59 2012 @@ -13,6 +13,7 @@ #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" #include "lldb/lldb-private-log.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -85,7 +86,8 @@ m_did_load_symbol_vendor (false), m_did_parse_uuid (false), m_did_init_ast (false), - m_is_dynamic_loader_module (false) + m_is_dynamic_loader_module (false), + m_was_modified (false) { // Scope for locker below... { @@ -613,27 +615,82 @@ void Module::ReportError (const char *format, ...) { - StreamString module_description; - GetDescription(&module_description, lldb::eDescriptionLevelBrief); - ::fprintf (stderr, "error: %s ", module_description.GetString().c_str()); - - va_list args; - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); + if (format && format[0]) + { + StreamString strm; + strm.PutCString("error: "); + GetDescription(&strm, lldb::eDescriptionLevelBrief); + + va_list args; + va_start (args, format); + strm.PrintfVarArg(format, args); + va_end (args); + + const int format_len = strlen(format); + if (format_len > 0) + { + const char last_char = format[format_len-1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); + } + Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); + + } +} + +void +Module::ReportErrorIfModifyDetected (const char *format, ...) +{ + if (!GetModified(true) && GetModified(false)) + { + if (format) + { + StreamString strm; + strm.PutCString("error: the object file "); + GetDescription(&strm, lldb::eDescriptionLevelFull); + strm.PutCString (" has been modified\n"); + + va_list args; + va_start (args, format); + strm.PrintfVarArg(format, args); + va_end (args); + + const int format_len = strlen(format); + if (format_len > 0) + { + const char last_char = format[format_len-1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); + } + strm.PutCString("The debug session should be aborted as the original debug information has been overwritten.\n"); + Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); + } + } } void Module::ReportWarning (const char *format, ...) { - StreamString module_description; - GetDescription(&module_description, lldb::eDescriptionLevelBrief); - ::fprintf (stderr, "warning: %s ", module_description.GetString().c_str()); - - va_list args; - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); + if (format && format[0]) + { + StreamString strm; + strm.PutCString("warning: "); + GetDescription(&strm, lldb::eDescriptionLevelBrief); + + va_list args; + va_start (args, format); + strm.PrintfVarArg(format, args); + va_end (args); + + const int format_len = strlen(format); + if (format_len > 0) + { + const char last_char = format[format_len-1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); + } + Host::SystemLog (Host::eSystemLogWarning, "%s", strm.GetString().c_str()); + } } void @@ -652,6 +709,26 @@ } } +bool +Module::GetModified (bool use_cached_only) +{ + if (m_was_modified == false && use_cached_only == false) + { + TimeValue curr_mod_time (m_file.GetModificationTime()); + m_was_modified = curr_mod_time != m_mod_time; + } + return m_was_modified; +} + +bool +Module::SetModified (bool b) +{ + const bool prev_value = m_was_modified; + m_was_modified = b; + return prev_value; +} + + void Module::Dump(Stream *s) { Modified: lldb/trunk/source/Core/ModuleList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ModuleList.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Core/ModuleList.cpp (original) +++ lldb/trunk/source/Core/ModuleList.cpp Wed Jan 4 21:57:59 2012 @@ -15,6 +15,7 @@ // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Host/Host.h" #include "lldb/Host/Symbols.h" #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/ObjectFile.h" @@ -700,11 +701,12 @@ char uuid_cstr[256]; const_cast(module_ptr)->GetUUID().GetAsCString (uuid_cstr, sizeof(uuid_cstr)); const FileSpec &module_file_spec = module_ptr->GetFileSpec(); - fprintf (stderr, "warning: module not in shared module list: %s (%s) \"%s/%s\"\n", - uuid_cstr, - module_ptr->GetArchitecture().GetArchitectureName(), - module_file_spec.GetDirectory().GetCString(), - module_file_spec.GetFilename().GetCString()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: module not in shared module list: %s (%s) \"%s/%s\"\n", + uuid_cstr, + module_ptr->GetArchitecture().GetArchitectureName(), + module_file_spec.GetDirectory().GetCString(), + module_file_spec.GetFilename().GetCString()); } } return module_sp; Modified: lldb/trunk/source/Host/common/Host.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Host.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Host/common/Host.cpp (original) +++ lldb/trunk/source/Host/common/Host.cpp Wed Jan 4 21:57:59 2012 @@ -231,8 +231,24 @@ return NULL; } + +void +Host::SystemLog (SystemLogType type, const char *format, va_list args) +{ + vfprintf (stderr, format, args); +} + #endif // #if !defined (__APPLE__) +void +Host::SystemLog (SystemLogType type, const char *format, ...) +{ + va_list args; + va_start (args, format); + SystemLog (type, format, args); + va_end (args); +} + size_t Host::GetPageSize() { Modified: lldb/trunk/source/Host/macosx/Host.mm URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Host.mm?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Host/macosx/Host.mm (original) +++ lldb/trunk/source/Host/macosx/Host.mm Wed Jan 4 21:57:59 2012 @@ -9,6 +9,7 @@ #include "lldb/Host/Host.h" +#include #include #include #include @@ -1515,3 +1516,45 @@ } return thread; } + +//---------------------------------------------------------------------- +// Log to both stderr and to ASL Logging when running on MacOSX. +//---------------------------------------------------------------------- +void +Host::SystemLog (SystemLogType type, const char *format, va_list args) +{ + if (format && format[0]) + { + static aslmsg g_aslmsg = NULL; + if (g_aslmsg == NULL) + { + g_aslmsg = ::asl_new (ASL_TYPE_MSG); + char asl_key_sender[PATH_MAX]; + snprintf(asl_key_sender, sizeof(asl_key_sender), "com.apple.LLDB.framework"); + ::asl_set (g_aslmsg, ASL_KEY_SENDER, asl_key_sender); + } + + // Copy the va_list so we can log this message twice + va_list copy_args; + va_copy (copy_args, args); + // Log to stderr + ::vfprintf (stderr, format, copy_args); + va_end (copy_args); + + int asl_level; + switch (type) + { + default: + case eSystemLogError: + asl_level = ASL_LEVEL_ERR; + break; + + case eSystemLogWarning: + asl_level = ASL_LEVEL_WARNING; + break; + } + + // Log to ASL + ::asl_vlog (NULL, g_aslmsg, asl_level, format, args); + } +} Modified: lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp Wed Jan 4 21:57:59 2012 @@ -326,12 +326,11 @@ } else { - fprintf (stderr, - "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - (uint64_t)new_section_load_addr, - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); + Host::SystemLog (Host::eSystemLogWarning, "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + (uint64_t)new_section_load_addr, + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); } } else @@ -389,11 +388,11 @@ } else { - fprintf (stderr, - "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); } } } Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Wed Jan 4 21:57:59 2012 @@ -419,12 +419,12 @@ } else { - fprintf (stderr, - "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - (uint64_t)new_section_load_addr, - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + (uint64_t)new_section_load_addr, + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); } } } @@ -461,11 +461,11 @@ } else { - fprintf (stderr, - "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - image_object_file->GetFileSpec().GetDirectory().AsCString(), - image_object_file->GetFileSpec().GetFilename().AsCString()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); } } } Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Wed Jan 4 21:57:59 2012 @@ -14,7 +14,6 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" -#include "lldb/Host/FileSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -23,6 +22,8 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/UUID.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangNamespaceDecl.h" #include "lldb/Symbol/ObjectFile.h" @@ -705,7 +706,7 @@ } else { - fprintf (stderr, "error: unable to find section for section %u\n", n_sect); + Host::SystemLog (Host::eSystemLogError, "error: unable to find section for section %u\n", n_sect); } } if (m_section_infos[n_sect].vm_range.Contains(file_addr)) @@ -893,12 +894,12 @@ // No symbol should be NULL, even the symbols with no // string values should have an offset zero which points // to an empty C-string - fprintf (stderr, - "error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n", - nlist_idx, - nlist.n_strx, - m_module->GetFileSpec().GetDirectory().GetCString(), - m_module->GetFileSpec().GetFilename().GetCString()); + Host::SystemLog (Host::eSystemLogError, + "error: symbol[%u] has invalid string table offset 0x%x in %s/%s, ignoring symbol\n", + nlist_idx, + nlist.n_strx, + m_module->GetFileSpec().GetDirectory().GetCString(), + m_module->GetFileSpec().GetFilename().GetCString()); continue; } const char *symbol_name = &strtab_data[nlist.n_strx]; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp Wed Jan 4 21:57:59 2012 @@ -170,9 +170,9 @@ LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) { - m_dwarf2Data->LogMessage (log.get(), - "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]", - GetOffset()); + m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log.get(), + "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]", + GetOffset()); } } @@ -266,9 +266,9 @@ // unit header). if (offset > next_cu_offset) { - m_dwarf2Data->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x\n", - GetOffset(), - offset); + m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x\n", + GetOffset(), + offset); } // Since std::vector objects will double their size, we really need to @@ -404,9 +404,9 @@ if (log) { - m_dwarf2Data->LogMessage (log.get(), - "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]", - GetOffset()); + m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log.get(), + "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]", + GetOffset()); } DIE()->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); const bool minimize = false; @@ -577,9 +577,9 @@ if (log) { - m_dwarf2Data->LogMessage (log.get(), - "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", - GetOffset()); + m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log.get(), + "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", + GetOffset()); } DWARFDebugInfoEntry::const_iterator pos; @@ -765,8 +765,7 @@ { if (specification_die_offset != DW_INVALID_OFFSET) { - const DWARFDebugInfoEntry *specification_die - = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); + const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); if (specification_die) { parent = specification_die->GetParent(); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp Wed Jan 4 21:57:59 2012 @@ -13,6 +13,7 @@ #include +#include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" @@ -138,9 +139,9 @@ if (abbrevDecl == NULL) { - cu->GetSymbolFileDWARF ()->ReportError ("{0x%8.8x}: invalid abbreviation code %u, please file a bug and attach the file at the start of this error message", - m_offset, - (unsigned)abbr_idx); + cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid abbreviation code %u, please file a bug and attach the file at the start of this error message", + m_offset, + (unsigned)abbr_idx); // WE can't parse anymore if the DWARF is borked... *offset_ptr = UINT32_MAX; return false; @@ -2082,11 +2083,13 @@ if (abbrev_decl->Code() == abbrev_code) return abbrev_decl; - - dwarf2Data->ReportError ("0x%8.8x: the DWARF debug info has been modified (abbrev code was %u, and is now %u)", - GetOffset(), - (uint32_t)abbrev_decl->Code(), - (uint32_t)abbrev_code); + + // Only log if we are the one to figure out that the module was modified + // which is indicated by SetModified() returning false. + dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", + GetOffset(), + (uint32_t)abbrev_decl->Code(), + (uint32_t)abbrev_code); } offset = DW_INVALID_OFFSET; return NULL; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp Wed Jan 4 21:57:59 2012 @@ -15,6 +15,7 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Log.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/Host.h" #include "SymbolFileDWARF.h" #include "LogChannelDWARF.h" @@ -456,8 +457,11 @@ if (*offset_ptr != end_prologue_offset) { - fprintf (stderr, "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8x\n", - prologue_offset, end_prologue_offset, *offset_ptr); + Host::SystemLog (Host::eSystemLogWarning, + "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8x\n", + prologue_offset, + end_prologue_offset, + *offset_ptr); } return end_prologue_offset; } @@ -539,8 +543,11 @@ if (offset != end_prologue_offset) { - fprintf (stderr, "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8x\n", - stmt_list, end_prologue_offset, offset); + Host::SystemLog (Host::eSystemLogError, + "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8x\n", + stmt_list, + end_prologue_offset, + offset); } return end_prologue_offset; } Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jan 4 21:57:59 2012 @@ -1452,14 +1452,14 @@ else { if (name) - ReportError ("0x%8.8llx: DW_TAG_member '%s' refers to type 0x%8.8llx which was unable to be parsed", - MakeUserID(die->GetOffset()), - name, - encoding_uid); + GetObjectFile()->GetModule()->ReportError ("0x%8.8llx: DW_TAG_member '%s' refers to type 0x%8.8llx which was unable to be parsed", + MakeUserID(die->GetOffset()), + name, + encoding_uid); else - ReportError ("0x%8.8llx: DW_TAG_member refers to type 0x%8.8llx which was unable to be parsed", - MakeUserID(die->GetOffset()), - encoding_uid); + GetObjectFile()->GetModule()->ReportError ("0x%8.8llx: DW_TAG_member refers to type 0x%8.8llx which was unable to be parsed", + MakeUserID(die->GetOffset()), + encoding_uid); } if (prop_name != NULL) @@ -1633,10 +1633,11 @@ { LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) - LogMessage (log.get(), "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, cu)); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, cu)); // We might be coming in in the middle of a type tree (a class // withing a class, an enum within a class), so parse any needed @@ -1650,21 +1651,23 @@ { // Get the type, which could be a forward declaration if (log) - LogMessage (log.get(), "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, cu), - decl_ctx_die->GetOffset()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, cu), + decl_ctx_die->GetOffset()); Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed); if (DW_TAG_is_function_tag(die->Tag())) { if (log) - LogMessage (log.get(), "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function", - die->GetOffset(), - DW_TAG_value_to_name(die->Tag()), - die->GetName(this, cu), - decl_ctx_die->GetOffset()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function", + die->GetOffset(), + DW_TAG_value_to_name(die->Tag()), + die->GetName(this, cu), + decl_ctx_die->GetOffset()); // Ask the type to complete itself if it already hasn't since if we // want a function (method or static) from a class, the class must // create itself and add it's own methods and class functions. @@ -1725,11 +1728,11 @@ LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) - LogMessage (log.get(), - "0x%8.8llx: %s '%s' resolving forward declaration...\n", - MakeUserID(die->GetOffset()), - DW_TAG_value_to_name(tag), - type->GetName().AsCString()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "0x%8.8llx: %s '%s' resolving forward declaration...\n", + MakeUserID(die->GetOffset()), + DW_TAG_value_to_name(tag), + type->GetName().AsCString()); assert (clang_type); DWARFDebugInfoEntry::Attributes attributes; @@ -1832,8 +1835,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_objc accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, class_str.c_str()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, class_str.c_str()); } } } @@ -2258,7 +2261,7 @@ LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); if (log) - LogMessage(log.get(), "Valid namespace does not match symbol file"); + GetObjectFile()->GetModule()->LogMessage(log.get(), "Valid namespace does not match symbol file"); return false; } @@ -2284,7 +2287,7 @@ if (decl_ctx_die->Tag() != DW_TAG_namespace) { if (log) - LogMessage(log.get(), "Found a match, but its parent is not a namespace"); + GetObjectFile()->GetModule()->LogMessage(log.get(), "Found a match, but its parent is not a namespace"); return false; } @@ -2293,7 +2296,7 @@ if (pos == m_decl_ctx_to_die.end()) { if (log) - LogMessage(log.get(), "Found a match in a namespace, but its parent is not the requested namespace"); + GetObjectFile()->GetModule()->LogMessage(log.get(), "Found a match in a namespace, but its parent is not the requested namespace"); return false; } @@ -2312,7 +2315,7 @@ } if (log) - LogMessage(log.get(), "Found a match, but its parent doesn't exist"); + GetObjectFile()->GetModule()->LogMessage(log.get(), "Found a match, but its parent doesn't exist"); return false; } @@ -2323,12 +2326,12 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)", - name.GetCString(), - namespace_decl, - append, - max_matches); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)", + name.GetCString(), + namespace_decl, + append, + max_matches); } if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl)) @@ -2403,8 +2406,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_names accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name.GetCString()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, name.GetCString()); } } } @@ -2421,11 +2424,11 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)", - regex.GetText(), - append, - max_matches); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)", + regex.GetText(), + append, + max_matches); } DWARFDebugInfo* info = DebugInfo(); @@ -2488,8 +2491,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_names accelerator table had bad die 0x%8.8x for regex '%s'\n", - die_offset, regex.GetText()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n", + die_offset, regex.GetText()); } } } @@ -2696,11 +2699,11 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list)", - name.GetCString(), - name_type_mask, - append); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list)", + name.GetCString(), + name_type_mask, + append); } // If we aren't appending the results to this list, then clear the list @@ -2798,8 +2801,8 @@ } else { - ReportError (".apple_names accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name_cstr); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", + die_offset, name_cstr); } } } @@ -2826,8 +2829,8 @@ } else { - ReportError (".apple_names accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name_cstr); + GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", + die_offset, name_cstr); } } die_offsets.clear(); @@ -2870,8 +2873,8 @@ } else { - ReportError (".apple_names accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name_cstr); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", + die_offset, name_cstr); } } die_offsets.clear(); @@ -2970,10 +2973,10 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", - regex.GetText(), - append); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", + regex.GetText(), + append); } @@ -3021,11 +3024,11 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindTypes (sc, name=\"%s\", append=%u, max_matches=%u, type_list)", - name.GetCString(), - append, - max_matches); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindTypes (sc, name=\"%s\", append=%u, max_matches=%u, type_list)", + name.GetCString(), + append, + max_matches); } // If we aren't appending the results to this list, then clear the list @@ -3084,8 +3087,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_types accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name.GetCString()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, name.GetCString()); } } @@ -3105,9 +3108,9 @@ if (log) { - LogMessage (log.get(), - "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", - name.GetCString()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", + name.GetCString()); } if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl)) @@ -3165,8 +3168,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_namespaces accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, name.GetCString()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, name.GetCString()); } } @@ -3658,22 +3661,22 @@ { if (namespace_name) { - LogMessage (log.get(), - "ASTContext => %p: 0x%8.8llx: DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", - GetClangASTContext().getASTContext(), - MakeUserID(die->GetOffset()), - namespace_name, - namespace_decl, - namespace_decl->getOriginalNamespace()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "ASTContext => %p: 0x%8.8llx: DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)", + GetClangASTContext().getASTContext(), + MakeUserID(die->GetOffset()), + namespace_name, + namespace_decl, + namespace_decl->getOriginalNamespace()); } else { - LogMessage (log.get(), - "ASTContext => %p: 0x%8.8llx: DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", - GetClangASTContext().getASTContext(), - MakeUserID(die->GetOffset()), - namespace_decl, - namespace_decl->getOriginalNamespace()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "ASTContext => %p: 0x%8.8llx: DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)", + GetClangASTContext().getASTContext(), + MakeUserID(die->GetOffset()), + namespace_decl, + namespace_decl->getOriginalNamespace()); } } @@ -3703,7 +3706,7 @@ LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) - LogMessage(log.get(), "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu)); + GetObjectFile()->GetModule()->LogMessage(log.get(), "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu)); // This is the DIE we want. Parse it, then query our map. bool assert_not_being_parsed = true; ResolveTypeUID (cu, die, assert_not_being_parsed); @@ -3950,8 +3953,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_types accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, type_name.GetCString()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, type_name.GetCString()); } } @@ -4075,8 +4078,8 @@ { if (m_using_apple_tables) { - ReportError (".apple_types accelerator table had bad die 0x%8.8x for '%s'\n", - die_offset, type_name.GetCString()); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n", + die_offset, type_name.GetCString()); } } @@ -4098,7 +4101,7 @@ { LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) - LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s'", + GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, dwarf_cu)); @@ -4108,7 +4111,7 @@ // { // StreamString s; // die->DumpLocation (this, dwarf_cu, s); -// LogMessage (log.get(), "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); +// GetObjectFile()->GetModule()->LogMessage (log.get(), "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData()); // // } @@ -4432,13 +4435,13 @@ { if (log) { - LogMessage (log.get(), - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8llx", - this, - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr, - type_sp->GetID()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8llx", + this, + die->GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr, + type_sp->GetID()); } // We found a real definition for this type elsewhere @@ -4460,12 +4463,12 @@ // DWARF. If this fails, we need to look elsewhere... if (log) { - LogMessage (log.get(), - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", - this, - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", + this, + die->GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr); } type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str); @@ -4482,13 +4485,13 @@ { if (log) { - LogMessage (log.get(), - "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8llx", - this, - die->GetOffset(), - DW_TAG_value_to_name(tag), - type_name_cstr, - type_sp->GetID()); + GetObjectFile()->GetModule()->LogMessage (log.get(), + "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8llx", + this, + die->GetOffset(), + DW_TAG_value_to_name(tag), + type_name_cstr, + type_sp->GetID()); } // We found a real definition for this type elsewhere @@ -4914,9 +4917,9 @@ } else { - ReportWarning ("0x%8.8llx: DW_AT_specification(0x%8.8x) has no decl\n", - MakeUserID(die->GetOffset()), - specification_die_offset); + GetObjectFile()->GetModule()->ReportWarning ("0x%8.8llx: DW_AT_specification(0x%8.8x) has no decl\n", + MakeUserID(die->GetOffset()), + specification_die_offset); } type_handled = true; } @@ -4937,9 +4940,9 @@ } else { - ReportWarning ("0x%8.8llx: DW_AT_abstract_origin(0x%8.8x) has no decl\n", - MakeUserID(die->GetOffset()), - abstract_origin_die_offset); + GetObjectFile()->GetModule()->ReportWarning ("0x%8.8llx: DW_AT_abstract_origin(0x%8.8x) has no decl\n", + MakeUserID(die->GetOffset()), + abstract_origin_die_offset); } type_handled = true; } @@ -5353,14 +5356,14 @@ const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID()); dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, DW_INVALID_ADDRESS); - assert (func_lo_pc != DW_INVALID_ADDRESS); - - const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true); + if (func_lo_pc != DW_INVALID_ADDRESS) + { + const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true); - // Let all blocks know they have parse all their variables - sc.function->GetBlock (false).SetDidParseVariables (true, true); - - return num_variables; + // Let all blocks know they have parse all their variables + sc.function->GetBlock (false).SetDidParseVariables (true, true); + return num_variables; + } } else if (sc.comp_unit) { @@ -5421,7 +5424,7 @@ { if (m_using_apple_tables) { - ReportError (".apple_names accelerator table had bad die 0x%8.8x\n", die_offset); + GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset); } } @@ -5563,7 +5566,7 @@ { StreamString strm; location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL); - ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str()); + GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str()); } } @@ -5824,11 +5827,11 @@ } else { - ReportError ("parent 0x%8.8llx %s with no valid compile unit in symbol context for 0x%8.8llx %s.\n", - MakeUserID(sc_parent_die->GetOffset()), - DW_TAG_value_to_name (parent_tag), - MakeUserID(orig_die->GetOffset()), - DW_TAG_value_to_name (orig_die->Tag())); + GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8llx %s with no valid compile unit in symbol context for 0x%8.8llx %s.\n", + MakeUserID(sc_parent_die->GetOffset()), + DW_TAG_value_to_name (parent_tag), + MakeUserID(orig_die->GetOffset()), + DW_TAG_value_to_name (orig_die->Tag())); } break; @@ -5868,9 +5871,9 @@ break; default: - ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8llx %s.\n", - MakeUserID(orig_die->GetOffset()), - DW_TAG_value_to_name (orig_die->Tag())); + GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8llx %s.\n", + MakeUserID(orig_die->GetOffset()), + DW_TAG_value_to_name (orig_die->Tag())); break; } } Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Wed Jan 4 21:57:59 2012 @@ -908,11 +908,11 @@ // to fix any issues we run into. if (type_name) { - fprintf (stderr, "error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u\n", type_name, dw_ate, bit_size); + Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type '%s' encoded with DW_ATE = 0x%x, bit_size = %u\n", type_name, dw_ate, bit_size); } else { - fprintf (stderr, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size); + Host::SystemLog (Host::eSystemLogError, "error: need to add support for DW_TAG_base_type encoded with DW_ATE = 0x%x, bit_size = %u\n", dw_ate, bit_size); } return NULL; } Modified: lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp (original) +++ lldb/trunk/source/Symbol/DWARFCallFrameInfo.cpp Wed Jan 4 21:57:59 2012 @@ -14,14 +14,15 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Section.h" -#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/RegisterContext.h" -#include "lldb/Core/Section.h" #include "lldb/Target/Thread.h" -#include "lldb/Symbol/UnwindPlan.h" using namespace lldb; using namespace lldb_private; @@ -146,7 +147,7 @@ if (i == CFI_AUG_MAX_SIZE && cie_sp->augmentation[CFI_AUG_MAX_SIZE-1] != '\0') { - fprintf(stderr, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE); + Host::SystemLog (Host::eSystemLogError, "CIE parse error: CIE augmentation string was too large for the fixed sized buffer of %d bytes.\n", CFI_AUG_MAX_SIZE); return cie_sp; } cie_sp->code_align = (uint32_t)m_cfi_data.GetULEB128(&offset); @@ -330,11 +331,11 @@ } else { - fprintf (stderr, - "error: unable to find CIE at 0x%8.8x for cie_id = 0x%8.8x for entry at 0x%8.8x.\n", - cie_offset, - cie_id, - current_entry); + Host::SystemLog (Host::eSystemLogError, + "error: unable to find CIE at 0x%8.8x for cie_id = 0x%8.8x for entry at 0x%8.8x.\n", + cie_offset, + cie_id, + current_entry); } offset = next_entry; } Modified: lldb/trunk/source/Symbol/Function.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Function.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Function.cpp (original) +++ lldb/trunk/source/Symbol/Function.cpp Wed Jan 4 21:57:59 2012 @@ -10,6 +10,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Host/Host.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" @@ -313,12 +314,12 @@ } else { - ::fprintf (stderr, - "unable to find module shared pointer for function '%s' in %s%s%s\n", - GetName().GetCString(), - m_comp_unit->GetDirectory().GetCString(), - m_comp_unit->GetDirectory() ? "/" : "", - m_comp_unit->GetFilename().GetCString()); + Host::SystemLog (Host::eSystemLogError, + "error: unable to find module shared pointer for function '%s' in %s%s%s\n", + GetName().GetCString(), + m_comp_unit->GetDirectory().GetCString(), + m_comp_unit->GetDirectory() ? "/" : "", + m_comp_unit->GetFilename().GetCString()); } m_block.SetBlockInfoHasBeenParsed (true, true); } Modified: lldb/trunk/source/Symbol/SymbolContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Symbol/SymbolContext.cpp (original) +++ lldb/trunk/source/Symbol/SymbolContext.cpp Wed Jan 4 21:57:59 2012 @@ -11,6 +11,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Host/Host.h" #include "lldb/Interpreter/Args.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/ObjectFile.h" @@ -519,16 +520,19 @@ } if (objfile) { - fprintf (stderr, "warning: inlined block 0x%8.8llx doesn't have a range that contains file address 0x%llx in %s/%s\n", - curr_inlined_block->GetID(), - curr_frame_pc.GetFileAddress(), - objfile->GetFileSpec().GetDirectory().GetCString(), - objfile->GetFileSpec().GetFilename().GetCString()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: inlined block 0x%8.8llx doesn't have a range that contains file address 0x%llx in %s/%s\n", + curr_inlined_block->GetID(), + curr_frame_pc.GetFileAddress(), + objfile->GetFileSpec().GetDirectory().GetCString(), + objfile->GetFileSpec().GetFilename().GetCString()); } else { - fprintf (stderr, "warning: inlined block 0x%8.8llx doesn't have a range that contains file address 0x%llx\n", - curr_inlined_block->GetID(), curr_frame_pc.GetFileAddress()); + Host::SystemLog (Host::eSystemLogWarning, + "warning: inlined block 0x%8.8llx doesn't have a range that contains file address 0x%llx\n", + curr_inlined_block->GetID(), + curr_frame_pc.GetFileAddress()); } } #endif Modified: lldb/trunk/source/Symbol/SymbolFile.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolFile.cpp?rev=147596&r1=147595&r2=147596&view=diff ============================================================================== --- lldb/trunk/source/Symbol/SymbolFile.cpp (original) +++ lldb/trunk/source/Symbol/SymbolFile.cpp Wed Jan 4 21:57:59 2012 @@ -70,46 +70,3 @@ { return m_obj_file->GetModule()->GetClangASTContext(); } - - -void -SymbolFile::ReportError (const char *format, ...) -{ - StreamString module_description; - m_obj_file->GetModule()->GetDescription (&module_description, lldb::eDescriptionLevelBrief); - ::fprintf (stderr, "error: %s ", module_description.GetString().c_str()); - - va_list args; - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); -} - -void -SymbolFile::ReportWarning (const char *format, ...) -{ - StreamString module_description; - m_obj_file->GetModule()->GetDescription (&module_description, lldb::eDescriptionLevelBrief); - ::fprintf (stderr, "warning: %s ", module_description.GetString().c_str()); - - va_list args; - va_start (args, format); - vfprintf (stderr, format, args); - va_end (args); -} - -void -SymbolFile::LogMessage (Log *log, const char *format, ...) -{ - if (log) - { - StreamString log_message; - m_obj_file->GetModule()->GetDescription (&log_message, lldb::eDescriptionLevelBrief); - log_message.PutChar(' '); - va_list args; - va_start (args, format); - log_message.PrintfVarArg (format, args); - va_end (args); - log->PutCString (log_message.GetString().c_str()); - } -} From gclayton at apple.com Wed Jan 4 22:00:49 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 05 Jan 2012 04:00:49 -0000 Subject: [Lldb-commits] [lldb] r147597 - in /lldb/trunk: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist tools/debugserver/debugserver.xcodeproj/project.pbxproj Message-ID: <20120105040049.4BFFD2A6C12C@llvm.org> Author: gclayton Date: Wed Jan 4 22:00:49 2012 New Revision: 147597 URL: http://llvm.org/viewvc/llvm-project?rev=147597&view=rev Log: Bumped Xcode project versions for lldb-101 and debugserver-160. Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/resources/LLDB-Info.plist lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=147597&r1=147596&r2=147597&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jan 4 22:00:49 2012 @@ -3733,9 +3733,9 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 100; + DYLIB_CURRENT_VERSION = 101; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3793,10 +3793,10 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 100; + DYLIB_CURRENT_VERSION = 101; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3852,8 +3852,8 @@ 2689FFD513353D7A00698AC0 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 100; - DYLIB_CURRENT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; + DYLIB_CURRENT_VERSION = 101; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3881,8 +3881,8 @@ 2689FFD613353D7A00698AC0 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 100; - DYLIB_CURRENT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; + DYLIB_CURRENT_VERSION = 101; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3910,8 +3910,8 @@ 2689FFD713353D7A00698AC0 /* BuildAndIntegration */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 100; - DYLIB_CURRENT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; + DYLIB_CURRENT_VERSION = 101; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3991,7 +3991,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4022,10 +4022,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; DEAD_CODE_STRIPPING = YES; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 100; + DYLIB_CURRENT_VERSION = 101; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -4269,7 +4269,7 @@ 26F5C26C10F3D9A5009D5894 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", @@ -4299,7 +4299,7 @@ 26F5C26D10F3D9A5009D5894 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 100; + CURRENT_PROJECT_VERSION = 101; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"", Modified: lldb/trunk/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=147597&r1=147596&r2=147597&view=diff ============================================================================== --- lldb/trunk/resources/LLDB-Info.plist (original) +++ lldb/trunk/resources/LLDB-Info.plist Wed Jan 4 22:00:49 2012 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 100 + 101 CFBundleName ${EXECUTABLE_NAME} Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=147597&r1=147596&r2=147597&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original) +++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Wed Jan 4 22:00:49 2012 @@ -475,7 +475,7 @@ i386, ); COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = ""; @@ -494,7 +494,7 @@ x86_64, i386, ); - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; DEAD_CODE_STRIPPING = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -515,7 +515,7 @@ x86_64, i386, ); - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; DEAD_CODE_STRIPPING = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; @@ -534,7 +534,7 @@ "ARCHS[sdk=iphoneos*]" = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( @@ -577,7 +577,7 @@ "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( "$(SDKROOT)/System/Library/PrivateFrameworks", @@ -620,7 +620,7 @@ "CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]" = "source/debugserver-entitlements.plist"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = lldb_codesign; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 159; + CURRENT_PROJECT_VERSION = 160; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = $SDKROOT/System/Library/PrivateFrameworks; "FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*][arch=*]" = ( From gclayton at apple.com Wed Jan 4 22:01:21 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 05 Jan 2012 04:01:21 -0000 Subject: [Lldb-commits] [lldb] r147598 - /lldb/tags/lldb-101/ Message-ID: <20120105040121.C3A3E2A6C12C@llvm.org> Author: gclayton Date: Wed Jan 4 22:01:21 2012 New Revision: 147598 URL: http://llvm.org/viewvc/llvm-project?rev=147598&view=rev Log: lldb-101 Added: lldb/tags/lldb-101/ - copied from r147597, lldb/trunk/ From dawn at burble.org Wed Jan 4 23:25:39 2012 From: dawn at burble.org (dawn at burble.org) Date: Wed, 4 Jan 2012 21:25:39 -0800 Subject: [Lldb-commits] TargetList.cpp changes from [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120105020417.GA31220@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> <20120105011113.GA30805@bloodbath.burble.org> <20120105020417.GA31220@bloodbath.burble.org> Message-ID: <20120105052539.GA1545@bloodbath.burble.org> Here's some background for why the changes to TargetList.cpp were needed. On Wed, Jan 04, 2012 at 06:04:17PM -0800, dawn at burble.org wrote: > lldb_svnR147560_POSIX_TargetList.patch - changes to TargetList.cpp separated out. > > The changes to TargetList.cpp are needed by both BSD and Linux in order for > Attach() to work. I spent a lot of time debugging this one, and the BSD folks > came to the same conclusion. I'll dig through my notes and try to write up my > findings - should this be discussed here or on lldb-dev? Perhaps the BSD folks can add more based on their experience, but here's what I remember the problem being: When attaching, TargetList::CreateTarget() is called with file = 0 since it's not known yet. So in the nested call to TargetList::CreateTarget() we do target_sp.reset(new Target(debugger, arch, platform_sp)); (around line TargetList.cpp:155). This causes Target to be created with an invalid arch, and things head downhill from there. We do have a default arch set in platform_sp however from: platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); (around line TargetList.cpp:73). giving us m_selected_platform_sp.m_system_arch.m_triple.Data = "i386-pc-linux-gnu". But no where is this default copied to the target. What's supposed to happen here? As a work-around, could we add code like if (!arch.IsValid()) arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); before the call to target_sp.reset(new Target(debugger, arch, platform_sp)); (around line TargetList.cpp:155)? Thanks for any help, -Dawn From gclayton at apple.com Thu Jan 5 12:48:59 2012 From: gclayton at apple.com (Greg Clayton) Date: Thu, 05 Jan 2012 10:48:59 -0800 Subject: [Lldb-commits] TargetList.cpp changes from [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120105052539.GA1545@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> <20120105011113.GA30805@bloodbath.burble.org> <20120105020417.GA31220@bloodbath.burble.org> <20120105052539.GA1545@bloodbath.burble.org> Message-ID: <19FC5893-CC5D-4BB4-B29A-F9C8F69EB025@apple.com> On Jan 4, 2012, at 9:25 PM, dawn at burble.org wrote: > Here's some background for why the changes to TargetList.cpp were needed. > > On Wed, Jan 04, 2012 at 06:04:17PM -0800, dawn at burble.org wrote: >> lldb_svnR147560_POSIX_TargetList.patch - changes to TargetList.cpp separated out. >> >> The changes to TargetList.cpp are needed by both BSD and Linux in order for >> Attach() to work. I spent a lot of time debugging this one, and the BSD folks >> came to the same conclusion. I'll dig through my notes and try to write up my >> findings - should this be discussed here or on lldb-dev? > > Perhaps the BSD folks can add more based on their experience, but > here's what I remember the problem being: > > When attaching, TargetList::CreateTarget() is called with > file = 0 since it's not known yet. > So in the nested call to TargetList::CreateTarget() we do > target_sp.reset(new Target(debugger, arch, platform_sp)); > (around line TargetList.cpp:155). > This causes Target to be created with an invalid arch, and > things head downhill from there. The DynamicLoader plug-in is not doing everything that it needs to do on linux is my guess here. It is the job of the dynamic loader to figure out what you have attached to and figure out the architecture and the executable file. On darwin this is done in the "DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(...)" function, take a look and see how it sets the executable. The dynamic loader has to be able to set the executable on the target because you might do something like: /usr/bin/lldb (lldb) process attach --pid 123 Just setting the target architecture to the current host default is the wrong thing to do, because what if we had done this: /usr/bin/lldb (lldb) platform select remote-ios (lldb) platform connect .... (lldb) process attach --pid 123 Now you will have a target with "x86_64" as the architecture and you will try to attach to a remote ARM process which is bad. When a target's executable is set it will grab the architecture from the executable module if it already hasn't bee set (see "Target::SetExecutableModule(...)"). > We do have a default arch set in platform_sp however from: > platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); > (around line TargetList.cpp:73). > giving us m_selected_platform_sp.m_system_arch.m_triple.Data > = "i386-pc-linux-gnu". > But no where is this default copied to the target. > What's supposed to happen here? The DynamicLoader needs to do its job as stated above. It should be ok for the target to have an invalid architecture until the dynamic loader has detected the architecture and set the executable. The other issue that you could run into, and the reason you want your dynamic loader to change the executable is what if you did this: /usr/bin/lldb (lldb) target create --arch x86_64-apple-darwin /bin/ls (lldb) process attach --pid 123 And what if pid "123" is actually "/bin/cat". And even worse, what if the architecture is different? (this won't happen on linux because linux is a single arch OS AFAIK, but on darwin we can run both 32 and 64 bit version of a binary, so we can actually run into this: /usr/bin/lldb (lldb) target create --arch i386-apple-darwin /bin/ls (lldb) process attach --pid 123 Where pid 123 is /bin/ls, but it is actually the x86_64 slice.... > As a work-around, could we add code like > if (!arch.IsValid()) > arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); Try the above approach and see how that works for you. The work around above will cause problems for remote debugging. > before the call to > target_sp.reset(new Target(debugger, arch, platform_sp)); > (around line TargetList.cpp:155)? > > > Thanks for any help, > -Dawn Let me know if anything above doesn't make sense. And there is no documentation on this stuff yet, so its not like anyone would just know this information, so this is our fault for not documenting the expected behavior... Sorry about that. Greg Clayton > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits From johnny.chen at apple.com Thu Jan 5 12:57:13 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 05 Jan 2012 10:57:13 -0800 Subject: [Lldb-commits] [PATCH] Merge of Linux and FreeBSD In-Reply-To: <20120105032530.GA32500@bloodbath.burble.org> References: <20120104232604.GA29483@bloodbath.burble.org> <61C1A32A-16A6-4DA1-BB75-9887214B2756@apple.com> <20120105011113.GA30805@bloodbath.burble.org> <20120105020417.GA31220@bloodbath.burble.org> <20120105032530.GA32500@bloodbath.burble.org> Message-ID: <6C81627F-F607-404E-B0D2-10CF91CE530E@apple.com> Hi Dawn, I will commit the POSIX patch for you in a moment. Thanks. On Jan 4, 2012, at 7:25 PM, dawn at burble.org wrote: > The commit failed with: > > svn: Commit failed (details follow): > svn: Server sent unexpected return value (400 Bad Request) in response to MKACTIVITY request for '/svn/llvm-project/!svn/act/171a3442-2c78-47b3-89ac-63b98af59774' > svn: Your commit message was left in a temporary file: > svn: '/home/dawn/dev/llvm_svnR146622/tools/lldb/svn-commit.tmp' > > I tried checking out the tree with: > svn co https://llvm.org/svn/llvm-project > but that gave me: > svn: access to '/svn/llvm-project/!svn/vcc/default' forbidden > > Please commit lldb_svnR147560_POSIX.patch for me? > Commit message is: > > This patch combines common code from Linux and FreeBSD into > a new POSIX platform. It also contains fixes for 64bit FreeBSD. > > The patch is based on changes by Mark Peek and > "K. Macy" in their github repo located at > https://github.com/fbsd/lldb. > > Thanks, > -Dawn > > On Wed, Jan 04, 2012 at 06:04:17PM -0800, dawn at burble.org wrote: >> Looks like only source/Target/Platform.cpp had left-overs from the >> bad git patch, so we're good now. >> >> New patches attached: >> lldb_svnR147560_POSIX_TargetList.patch - changes to TargetList.cpp separated out. >> lldb_svnR147560_POSIX.patch - changes sans Platform.cpp and TargetList.cpp >> >> The changes to TargetList.cpp are needed by both BSD and Linux in order for >> Attach() to work. I spent a lot of time debugging this one, and the BSD folks >> came to the same conclusion. I'll dig through my notes and try to write up my >> findings - should this be discussed here or on lldb-dev? >> >> So I should go ahead and commit the rest of the patch? I've commited to clang >> but never lldb - I can give it a try... >> >> Thanks, >> -Dawn >> >> On Wed, Jan 04, 2012 at 05:11:13PM -0800, dawn at burble.org wrote: >>> On Wed, Jan 04, 2012 at 04:41:08PM -0800, Johnny Chen wrote: >>>> Hi Dawn, >>>> >>>> The patch looks good. I have a couple of questions on source/Target/Platform.cpp and source/Target/TargetList.cpp, though. >>>> Please commit the patch except the two files. >>>> >>>> Here are my questions: >>>> >>>> The Platform.cpp patch looks wrong? >>> >>> Sorry - you're right. That was a left over from a mis-applied git patch >>> that I thought I had reverted. I will fix ASAP and resubmit. >>> >>> Thanks for catching this!!! >>> >>> ...stay tuned... >>> >>>> Index: source/Target/Platform.cpp >>>> =================================================================== >>>> --- source/Target/Platform.cpp (revision 147560) >>>> +++ source/Target/Platform.cpp (working copy) >>>> @@ -572,6 +572,16 @@ >>>> Error &error) >>>> { >>>> ProcessSP process_sp; >>>> + >>>> + launch_info.GetFlags ().Set (eLaunchFlagDebug); >>>> + const char *plugin_name = launch_info.GetProcessPluginName(); >>>> + process_sp = target->CreateProcess (listener, plugin_name).get(); >>>> + error = process_sp->Launch (launch_info); >>>> + return process_sp; >>>> + >>>> + >>>> +#if 0 >>>> + ProcessSP process_sp; >>>> // Make sure we stop at the entry point >>>> launch_info.GetFlags ().Set (eLaunchFlagDebug); >>>> error = LaunchProcess (launch_info); >>>> @@ -602,4 +612,5 @@ >>>> } >>>> } >>>> return process_sp; >>>> +#endif >>>> } >>>> >>>> Also, I'll ask Greg to review the TargetList.cpp question you have. >>>> Please don't commit it for the time being. >>>> >>>> Index: source/Target/TargetList.cpp >>>> =================================================================== >>>> --- source/Target/TargetList.cpp (revision 147560) >>>> +++ source/Target/TargetList.cpp (working copy) >>>> @@ -72,7 +72,8 @@ >>>> if (!platform_sp) >>>> platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); >>>> >>>> - ArchSpec arch; >>>> + // Unclear why I need to init this and others don't >>>> + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); >>>> >>>> if (triple_cstr) >>>> { >>>> @@ -83,6 +84,7 @@ >>>> return error; >>>> } >>>> } >>>> + >>>> error = TargetList::CreateTarget (debugger, >>>> file, >>>> arch, >>>> >>>> On Jan 4, 2012, at 3:26 PM, dawn at burble.org wrote: >>>> >>>>> >>>>> This patch combines common code from Linux and FreeBSD into >>>>> a new POSIX platform. It also contains fixes for 64bit FreeBSD. >>>>> >>>>> The patch is based on changes by Mark Peek and >>>>> "K. Macy" in their >>>>> github repo located at https://github.com/fbsd/lldb. >>>>> >>>>> Ok to commit? >>>>> Thanks! >>>>> -Dawn >>>>> _______________________________________________ >>>>> lldb-commits mailing list >>>>> lldb-commits at cs.uiuc.edu >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits >>> _______________________________________________ >>> lldb-commits mailing list >>> lldb-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > >> Index: source/Target/TargetList.cpp >> =================================================================== >> --- source/Target/TargetList.cpp (revision 147560) >> +++ source/Target/TargetList.cpp (working copy) >> @@ -72,7 +72,8 @@ >> if (!platform_sp) >> platform_sp = debugger.GetPlatformList().GetSelectedPlatform (); >> >> - ArchSpec arch; >> + // Unclear why I need to init this and others don't >> + ArchSpec arch = Host::GetArchitecture(Host::eSystemDefaultArchitecture); >> >> if (triple_cstr) >> { >> @@ -83,6 +84,7 @@ >> return error; >> } >> } >> + >> error = TargetList::CreateTarget (debugger, >> file, >> arch, > >> Index: include/lldb/Host/Host.h >> =================================================================== >> --- include/lldb/Host/Host.h (revision 147560) >> +++ include/lldb/Host/Host.h (working copy) >> @@ -355,7 +355,10 @@ >> >> static Error >> LaunchProcess (ProcessLaunchInfo &launch_info); >> - >> + >> + static lldb::DataBufferSP >> + GetAuxvData (lldb_private::Process *process); >> + >> static lldb::TargetSP >> GetDummyTarget (Debugger &debugger); >> >> Index: source/Plugins/Platform/Linux/PlatformLinux.h >> =================================================================== >> --- source/Plugins/Platform/Linux/PlatformLinux.h (revision 147560) >> +++ source/Plugins/Platform/Linux/PlatformLinux.h (working copy) >> @@ -104,6 +104,7 @@ >> Attach(ProcessAttachInfo &attach_info, Debugger &debugger, >> Target *target, Listener &listener, Error &error); >> >> + // Linux processes can not be launched by spawning and attaching. >> virtual bool >> CanDebugProcess () >> { >> Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp >> =================================================================== >> --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (revision 147560) >> +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (working copy) >> @@ -27,16 +27,13 @@ >> Platform * >> PlatformFreeBSD::CreateInstance () >> { >> - // The only time we create an instance is when we are creating a remote >> - // freebsd platform >> - const bool is_host = false; >> - return new PlatformFreeBSD (is_host); >> + return new PlatformFreeBSD (true); >> } >> >> const char * >> PlatformFreeBSD::GetPluginNameStatic() >> { >> - return "PlatformFreeBSD"; >> + return "plugin.platform.freebsd"; >> } >> >> const char * >> @@ -66,7 +63,7 @@ >> { >> #if defined (__FreeBSD__) >> PlatformSP default_platform_sp (CreateInstance()); >> - //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); >> + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); >> Platform::SetDefaultPlatform (default_platform_sp); >> #endif >> PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false), >> @@ -79,7 +76,7 @@ >> void >> PlatformFreeBSD::Terminate () >> { >> - PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); >> + PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); >> } >> >> //------------------------------------------------------------------ >> @@ -385,17 +382,16 @@ >> bool >> PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) >> { >> - bool sucess = false; >> + bool success = false; >> if (IsHost()) >> { >> - sucess = Platform::GetProcessInfo (pid, process_info); >> + success = Platform::GetProcessInfo (pid, process_info); >> } >> - else >> + else if (m_remote_platform_sp) >> { >> - if (m_remote_platform_sp) >> - sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); >> + success = m_remote_platform_sp->GetProcessInfo (pid, process_info); >> } >> - return sucess; >> + return success; >> } >> >> >> @@ -438,11 +434,11 @@ >> } >> >> lldb::ProcessSP >> -PlatformFreeBSD::Attach(lldb::pid_t pid, >> - Debugger &debugger, >> - Target *target, >> - Listener &listener, >> - Error &error) >> +PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, >> + Debugger &debugger, >> + Target *target, >> + Listener &listener, >> + Error &error) >> { >> lldb::ProcessSP process_sp; >> if (IsHost()) >> @@ -457,6 +453,7 @@ >> emptyFileSpec, >> emptyArchSpec, >> false, >> + m_remote_platform_sp, >> new_target_sp); >> target = new_target_sp.get(); >> } >> @@ -472,13 +469,13 @@ >> process_sp = target->CreateProcess (listener, "gdb-remote"); >> >> if (process_sp) >> - error = process_sp->Attach (pid); >> + error = process_sp->Attach (attach_info); >> } >> } >> else >> { >> if (m_remote_platform_sp) >> - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); >> + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); >> else >> error.SetErrorString ("the platform is not currently connected"); >> } >> Index: source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h >> =================================================================== >> --- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (revision 147560) >> +++ source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (working copy) >> @@ -132,12 +132,16 @@ >> LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); >> >> virtual lldb::ProcessSP >> - Attach(lldb::pid_t pid, >> + Attach(lldb_private::ProcessAttachInfo &attach_info, >> lldb_private::Debugger &debugger, >> lldb_private::Target *target, >> lldb_private::Listener &listener, >> lldb_private::Error &error); >> >> + // FreeBSD processes can not be launched by spawning and attaching. >> + virtual bool >> + CanDebugProcess () { return false; } >> + >> // Only on PlatformMacOSX: >> virtual lldb_private::Error >> GetFile (const lldb_private::FileSpec &platform_file, >> Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (working copy) >> @@ -1,191 +0,0 @@ >> -//===-- AuxVector.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 >> -#include >> -#include >> - >> -// C++ Includes >> -// Other libraries and framework includes >> -#include "lldb/Core/DataBufferHeap.h" >> -#include "lldb/Core/DataExtractor.h" >> -#include "lldb/Core/Log.h" >> -#include "lldb/Target/Process.h" >> - >> -#include "AuxVector.h" >> - >> -using namespace lldb; >> -using namespace lldb_private; >> - >> -static bool >> -GetMaxU64(DataExtractor &data, >> - uint32_t *offset, uint64_t *value, unsigned int byte_size) >> -{ >> - uint32_t saved_offset = *offset; >> - *value = data.GetMaxU64(offset, byte_size); >> - return *offset != saved_offset; >> -} >> - >> -static bool >> -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, >> - uint32_t *offset, unsigned int byte_size) >> -{ >> - if (!GetMaxU64(data, offset, &entry.type, byte_size)) >> - return false; >> - >> - if (!GetMaxU64(data, offset, &entry.value, byte_size)) >> - return false; >> - >> - return true; >> -} >> - >> -DataBufferSP >> -AuxVector::GetAuxvData() >> -{ >> - static const size_t path_size = 128; >> - static char path[path_size]; >> - DataBufferSP buf_sp; >> - int fd; >> - >> - // Ideally, we would simply create a FileSpec and call ReadFileContents. >> - // However, files in procfs have zero size (since they are, in general, >> - // dynamically generated by the kernel) which is incompatible with the >> - // current ReadFileContents implementation. Therefore we simply stream the >> - // data into a DataBuffer ourselves. >> - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) >> - return buf_sp; >> - >> - if ((fd = open(path, O_RDONLY, 0)) < 0) >> - return buf_sp; >> - >> - size_t bytes_read = 0; >> - std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); >> - for (;;) >> - { >> - size_t avail = buf_ap->GetByteSize() - bytes_read; >> - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); >> - >> - if (status < 0) >> - break; >> - >> - bytes_read += status; >> - >> - if (status == 0) >> - { >> - buf_ap->SetByteSize(bytes_read); >> - buf_sp.reset(buf_ap.release()); >> - break; >> - } >> - >> - if (avail - status == 0) >> - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); >> - } >> - >> - return buf_sp; >> -} >> - >> -void >> -AuxVector::ParseAuxv(DataExtractor &data) >> -{ >> - const unsigned int byte_size = m_process->GetAddressByteSize(); >> - uint32_t offset = 0; >> - >> - for (;;) >> - { >> - Entry entry; >> - >> - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) >> - break; >> - >> - if (entry.type == AT_NULL) >> - break; >> - >> - if (entry.type == AT_IGNORE) >> - continue; >> - >> - m_auxv.push_back(entry); >> - } >> -} >> - >> -AuxVector::AuxVector(Process *process) >> - : m_process(process) >> -{ >> - DataExtractor data; >> - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); >> - >> - data.SetData(GetAuxvData()); >> - data.SetByteOrder(m_process->GetByteOrder()); >> - data.SetAddressByteSize(m_process->GetAddressByteSize()); >> - >> - ParseAuxv(data); >> - >> - if (log) >> - DumpToLog(log); >> -} >> - >> -AuxVector::iterator >> -AuxVector::FindEntry(EntryType type) const >> -{ >> - for (iterator I = begin(); I != end(); ++I) >> - { >> - if (I->type == static_cast(type)) >> - return I; >> - } >> - >> - return end(); >> -} >> - >> -void >> -AuxVector::DumpToLog(LogSP log) const >> -{ >> - if (!log) >> - return; >> - >> - log->PutCString("AuxVector: "); >> - for (iterator I = begin(); I != end(); ++I) >> - { >> - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); >> - } >> -} >> - >> -const char * >> -AuxVector::GetEntryName(EntryType type) >> -{ >> - const char *name; >> - >> -#define ENTRY_NAME(_type) _type: name = #_type >> - switch (type) >> - { >> - default: >> - name = "unkown"; >> - break; >> - >> - case ENTRY_NAME(AT_NULL); break; >> - case ENTRY_NAME(AT_IGNORE); break; >> - case ENTRY_NAME(AT_EXECFD); break; >> - case ENTRY_NAME(AT_PHDR); break; >> - case ENTRY_NAME(AT_PHENT); break; >> - case ENTRY_NAME(AT_PHNUM); break; >> - case ENTRY_NAME(AT_PAGESZ); break; >> - case ENTRY_NAME(AT_BASE); break; >> - case ENTRY_NAME(AT_FLAGS); break; >> - case ENTRY_NAME(AT_ENTRY); break; >> - case ENTRY_NAME(AT_NOTELF); break; >> - case ENTRY_NAME(AT_UID); break; >> - case ENTRY_NAME(AT_EUID); break; >> - case ENTRY_NAME(AT_GID); break; >> - case ENTRY_NAME(AT_EGID); break; >> - case ENTRY_NAME(AT_CLKTCK); break; >> - } >> -#undef ENTRY_NAME >> - >> - return name; >> -} >> - >> Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (working copy) >> @@ -1,322 +0,0 @@ >> -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -#include "lldb/Core/ArchSpec.h" >> -#include "lldb/Core/Error.h" >> -#include "lldb/Core/Log.h" >> -#include "lldb/Target/Process.h" >> -#include "lldb/Target/Target.h" >> - >> -#include "DYLDRendezvous.h" >> - >> -using namespace lldb; >> -using namespace lldb_private; >> - >> -/// Locates the address of the rendezvous structure. Returns the address on >> -/// success and LLDB_INVALID_ADDRESS on failure. >> -static addr_t >> -ResolveRendezvousAddress(Process *process) >> -{ >> - addr_t info_location; >> - addr_t info_addr; >> - Error error; >> - size_t size; >> - >> - info_location = process->GetImageInfoAddress(); >> - >> - if (info_location == LLDB_INVALID_ADDRESS) >> - return LLDB_INVALID_ADDRESS; >> - >> - info_addr = 0; >> - size = process->DoReadMemory(info_location, &info_addr, >> - process->GetAddressByteSize(), error); >> - if (size != process->GetAddressByteSize() || error.Fail()) >> - return LLDB_INVALID_ADDRESS; >> - >> - if (info_addr == 0) >> - return LLDB_INVALID_ADDRESS; >> - >> - return info_addr; >> -} >> - >> -DYLDRendezvous::DYLDRendezvous(Process *process) >> - : m_process(process), >> - m_rendezvous_addr(LLDB_INVALID_ADDRESS), >> - m_current(), >> - m_previous(), >> - m_soentries(), >> - m_added_soentries(), >> - m_removed_soentries() >> -{ >> -} >> - >> -bool >> -DYLDRendezvous::Resolve() >> -{ >> - const size_t word_size = 4; >> - Rendezvous info; >> - size_t address_size; >> - size_t padding; >> - addr_t info_addr; >> - addr_t cursor; >> - >> - address_size = m_process->GetAddressByteSize(); >> - padding = address_size - word_size; >> - >> - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) >> - cursor = info_addr = ResolveRendezvousAddress(m_process); >> - else >> - cursor = info_addr = m_rendezvous_addr; >> - >> - if (cursor == LLDB_INVALID_ADDRESS) >> - return false; >> - >> - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) >> - return false; >> - >> - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) >> - return false; >> - >> - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) >> - return false; >> - >> - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) >> - return false; >> - >> - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) >> - return false; >> - >> - // The rendezvous was successfully read. Update our internal state. >> - m_rendezvous_addr = info_addr; >> - m_previous = m_current; >> - m_current = info; >> - >> - return UpdateSOEntries(); >> -} >> - >> -bool >> -DYLDRendezvous::IsValid() >> -{ >> - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; >> -} >> - >> -bool >> -DYLDRendezvous::UpdateSOEntries() >> -{ >> - SOEntry entry; >> - >> - if (m_current.map_addr == 0) >> - return false; >> - >> - // When the previous and current states are consistent this is the first >> - // time we have been asked to update. Just take a snapshot of the currently >> - // loaded modules. >> - if (m_previous.state == eConsistent && m_current.state == eConsistent) >> - return TakeSnapshot(m_soentries); >> - >> - // If we are about to add or remove a shared object clear out the current >> - // state and take a snapshot of the currently loaded images. >> - if (m_current.state == eAdd || m_current.state == eDelete) >> - { >> - assert(m_previous.state == eConsistent); >> - m_soentries.clear(); >> - m_added_soentries.clear(); >> - m_removed_soentries.clear(); >> - return TakeSnapshot(m_soentries); >> - } >> - assert(m_current.state == eConsistent); >> - >> - // Otherwise check the previous state to determine what to expect and update >> - // accordingly. >> - if (m_previous.state == eAdd) >> - return UpdateSOEntriesForAddition(); >> - else if (m_previous.state == eDelete) >> - return UpdateSOEntriesForDeletion(); >> - >> - return false; >> -} >> - >> -bool >> -DYLDRendezvous::UpdateSOEntriesForAddition() >> -{ >> - SOEntry entry; >> - iterator pos; >> - >> - assert(m_previous.state == eAdd); >> - >> - if (m_current.map_addr == 0) >> - return false; >> - >> - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) >> - { >> - if (!ReadSOEntryFromMemory(cursor, entry)) >> - return false; >> - >> - if (entry.path.empty()) >> - continue; >> - >> - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); >> - if (pos == m_soentries.end()) >> - { >> - m_soentries.push_back(entry); >> - m_added_soentries.push_back(entry); >> - } >> - } >> - >> - return true; >> -} >> - >> -bool >> -DYLDRendezvous::UpdateSOEntriesForDeletion() >> -{ >> - SOEntryList entry_list; >> - iterator pos; >> - >> - assert(m_previous.state == eDelete); >> - >> - if (!TakeSnapshot(entry_list)) >> - return false; >> - >> - for (iterator I = begin(); I != end(); ++I) >> - { >> - pos = std::find(entry_list.begin(), entry_list.end(), *I); >> - if (pos == entry_list.end()) >> - m_removed_soentries.push_back(*I); >> - } >> - >> - m_soentries = entry_list; >> - return true; >> -} >> - >> -bool >> -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) >> -{ >> - SOEntry entry; >> - >> - if (m_current.map_addr == 0) >> - return false; >> - >> - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) >> - { >> - if (!ReadSOEntryFromMemory(cursor, entry)) >> - return false; >> - >> - if (entry.path.empty()) >> - continue; >> - >> - entry_list.push_back(entry); >> - } >> - >> - return true; >> -} >> - >> -addr_t >> -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) >> -{ >> - size_t bytes_read; >> - Error error; >> - >> - bytes_read = m_process->DoReadMemory(addr, dst, size, error); >> - if (bytes_read != size || error.Fail()) >> - return 0; >> - >> - return addr + bytes_read; >> -} >> - >> -std::string >> -DYLDRendezvous::ReadStringFromMemory(addr_t addr) >> -{ >> - std::string str; >> - Error error; >> - size_t size; >> - char c; >> - >> - if (addr == LLDB_INVALID_ADDRESS) >> - return std::string(); >> - >> - for (;;) { >> - size = m_process->DoReadMemory(addr, &c, 1, error); >> - if (size != 1 || error.Fail()) >> - return std::string(); >> - if (c == 0) >> - break; >> - else { >> - str.push_back(c); >> - addr++; >> - } >> - } >> - >> - return str; >> -} >> - >> -bool >> -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) >> -{ >> - size_t address_size = m_process->GetAddressByteSize(); >> - >> - entry.clear(); >> - >> - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) >> - return false; >> - >> - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) >> - return false; >> - >> - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) >> - return false; >> - >> - if (!(addr = ReadMemory(addr, &entry.next, address_size))) >> - return false; >> - >> - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) >> - return false; >> - >> - entry.path = ReadStringFromMemory(entry.path_addr); >> - >> - return true; >> -} >> - >> -void >> -DYLDRendezvous::DumpToLog(LogSP log) const >> -{ >> - int state = GetState(); >> - >> - if (!log) >> - return; >> - >> - log->PutCString("DYLDRendezvous:"); >> - log->Printf(" Address: %lx", GetRendezvousAddress()); >> - log->Printf(" Version: %d", GetVersion()); >> - log->Printf(" Link : %lx", GetLinkMapAddress()); >> - log->Printf(" Break : %lx", GetBreakAddress()); >> - log->Printf(" LDBase : %lx", GetLDBase()); >> - log->Printf(" State : %s", >> - (state == eConsistent) ? "consistent" : >> - (state == eAdd) ? "add" : >> - (state == eDelete) ? "delete" : "unknown"); >> - >> - iterator I = begin(); >> - iterator E = end(); >> - >> - if (I != E) >> - log->PutCString("DYLDRendezvous SOEntries:"); >> - >> - for (int i = 1; I != E; ++I, ++i) >> - { >> - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); >> - log->Printf(" Base : %lx", I->base_addr); >> - log->Printf(" Path : %lx", I->path_addr); >> - log->Printf(" Dyn : %lx", I->dyn_addr); >> - log->Printf(" Next : %lx", I->next); >> - log->Printf(" Prev : %lx", I->prev); >> - } >> -} >> Index: source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (working copy) >> @@ -1,97 +0,0 @@ >> -//===-- AuxVector.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_AuxVector_H_ >> -#define liblldb_AuxVector_H_ >> - >> -// C Includes >> -// C++ Includes >> -#include >> - >> -// Other libraries and framework includes >> -#include "lldb/lldb-forward-rtti.h" >> - >> -namespace lldb_private { >> -class DataExtractor; >> -} >> - >> -/// @class AuxVector >> -/// @brief Represents a processes auxiliary vector. >> -/// >> -/// When a process is loaded on Linux a vector of values is placed onto the >> -/// stack communicating operating system specific information. On construction >> -/// this class locates and parses this information and provides a simple >> -/// read-only interface to the entries found. >> -class AuxVector { >> - >> -public: >> - AuxVector(lldb_private::Process *process); >> - >> - struct Entry { >> - uint64_t type; >> - uint64_t value; >> - >> - Entry() : type(0), value(0) { } >> - }; >> - >> - /// Constants describing the type of entry. >> - enum EntryType { >> - AT_NULL = 0, ///< End of auxv. >> - AT_IGNORE = 1, ///< Ignore entry. >> - AT_EXECFD = 2, ///< File descriptor of program. >> - AT_PHDR = 3, ///< Program headers. >> - AT_PHENT = 4, ///< Size of program header. >> - AT_PHNUM = 5, ///< Number of program headers. >> - AT_PAGESZ = 6, ///< Page size. >> - AT_BASE = 7, ///< Interpreter base address. >> - AT_FLAGS = 8, ///< Flags. >> - AT_ENTRY = 9, ///< Program entry point. >> - AT_NOTELF = 10, ///< Set if program is not an ELF. >> - AT_UID = 11, ///< UID. >> - AT_EUID = 12, ///< Effective UID. >> - AT_GID = 13, ///< GID. >> - AT_EGID = 14, ///< Effective GID. >> - AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). >> - }; >> - >> -private: >> - typedef std::vector EntryVector; >> - >> -public: >> - typedef EntryVector::const_iterator iterator; >> - >> - iterator begin() const { return m_auxv.begin(); } >> - iterator end() const { return m_auxv.end(); } >> - >> - iterator >> - FindEntry(EntryType type) const; >> - >> - static const char * >> - GetEntryName(const Entry &entry) { >> - return GetEntryName(static_cast(entry.type)); >> - } >> - >> - static const char * >> - GetEntryName(EntryType type); >> - >> - void >> - DumpToLog(lldb::LogSP log) const; >> - >> -private: >> - lldb_private::Process *m_process; >> - EntryVector m_auxv; >> - >> - lldb::DataBufferSP >> - GetAuxvData(); >> - >> - void >> - ParseAuxv(lldb_private::DataExtractor &data); >> -}; >> - >> -#endif >> Index: source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (working copy) >> @@ -1,227 +0,0 @@ >> -//===-- DYLDRendezvous.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_Rendezvous_H_ >> -#define liblldb_Rendezvous_H_ >> - >> -// C Includes >> -// C++ Includes >> -#include >> -#include >> - >> -// Other libraries and framework includes >> -#include "lldb/lldb-defines.h" >> -#include "lldb/lldb-types.h" >> - >> -namespace lldb_private { >> -class Process; >> -} >> - >> -/// @class DYLDRendezvous >> -/// @brief Interface to the runtime linker. >> -/// >> -/// A structure is present in a processes memory space which is updated by the >> -/// runtime liker each time a module is loaded or unloaded. This class provides >> -/// an interface to this structure and maintains a consistent snapshot of the >> -/// currently loaded modules. >> -class DYLDRendezvous { >> - >> - // This structure is used to hold the contents of the debug rendezvous >> - // information (struct r_debug) as found in the inferiors memory. Note that >> - // the layout of this struct is not binary compatible, it is simply large >> - // enough to hold the information on both 32 and 64 bit platforms. >> - struct Rendezvous { >> - uint64_t version; >> - lldb::addr_t map_addr; >> - lldb::addr_t brk; >> - uint64_t state; >> - lldb::addr_t ldbase; >> - >> - Rendezvous() >> - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } >> - }; >> - >> -public: >> - DYLDRendezvous(lldb_private::Process *process); >> - >> - /// Update the internal snapshot of runtime linker rendezvous and recompute >> - /// the currently loaded modules. >> - /// >> - /// This method should be called once one start up, then once each time the >> - /// runtime linker enters the function given by GetBreakAddress(). >> - /// >> - /// @returns true on success and false on failure. >> - /// >> - /// @see GetBreakAddress(). >> - bool >> - Resolve(); >> - >> - /// @returns true if this rendezvous has been located in the inferiors >> - /// address space and false otherwise. >> - bool >> - IsValid(); >> - >> - /// @returns the address of the rendezvous structure in the inferiors >> - /// address space. >> - lldb::addr_t >> - GetRendezvousAddress() const { return m_rendezvous_addr; } >> - >> - /// @returns the version of the rendezvous protocol being used. >> - int >> - GetVersion() const { return m_current.version; } >> - >> - /// @returns address in the inferiors address space containing the linked >> - /// list of shared object descriptors. >> - lldb::addr_t >> - GetLinkMapAddress() const { return m_current.map_addr; } >> - >> - /// A breakpoint should be set at this address and Resolve called on each >> - /// hit. >> - /// >> - /// @returns the address of a function called by the runtime linker each >> - /// time a module is loaded/unloaded, or about to be loaded/unloaded. >> - /// >> - /// @see Resolve() >> - lldb::addr_t >> - GetBreakAddress() const { return m_current.brk; } >> - >> - /// Returns the current state of the rendezvous structure. >> - int >> - GetState() const { return m_current.state; } >> - >> - /// @returns the base address of the runtime linker in the inferiors address >> - /// space. >> - lldb::addr_t >> - GetLDBase() const { return m_current.ldbase; } >> - >> - /// @returns true if modules have been loaded into the inferior since the >> - /// last call to Resolve(). >> - bool >> - ModulesDidLoad() const { return !m_added_soentries.empty(); } >> - >> - /// @returns true if modules have been unloaded from the inferior since the >> - /// last call to Resolve(). >> - bool >> - ModulesDidUnload() const { return !m_removed_soentries.empty(); } >> - >> - void >> - DumpToLog(lldb::LogSP log) const; >> - >> - /// @brief Constants describing the state of the rendezvous. >> - /// >> - /// @see GetState(). >> - enum RendezvousState { >> - eConsistent, >> - eAdd, >> - eDelete >> - }; >> - >> - /// @brief Structure representing the shared objects currently loaded into >> - /// the inferior process. >> - /// >> - /// This object is a rough analogue to the struct link_map object which >> - /// actually lives in the inferiors memory. >> - struct SOEntry { >> - lldb::addr_t base_addr; ///< Base address of the loaded object. >> - lldb::addr_t path_addr; ///< String naming the shared object. >> - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. >> - lldb::addr_t next; ///< Address of next so_entry. >> - lldb::addr_t prev; ///< Address of previous so_entry. >> - std::string path; ///< File name of shared object. >> - >> - SOEntry() { clear(); } >> - >> - bool operator ==(const SOEntry &entry) { >> - return this->path == entry.path; >> - } >> - >> - void clear() { >> - base_addr = 0; >> - path_addr = 0; >> - dyn_addr = 0; >> - next = 0; >> - prev = 0; >> - path.clear(); >> - } >> - }; >> - >> -protected: >> - typedef std::list SOEntryList; >> - >> -public: >> - typedef SOEntryList::const_iterator iterator; >> - >> - /// Iterators over all currently loaded modules. >> - iterator begin() const { return m_soentries.begin(); } >> - iterator end() const { return m_soentries.end(); } >> - >> - /// Iterators over all modules loaded into the inferior since the last call >> - /// to Resolve(). >> - iterator loaded_begin() const { return m_added_soentries.begin(); } >> - iterator loaded_end() const { return m_added_soentries.end(); } >> - >> - /// Iterators over all modules unloaded from the inferior since the last >> - /// call to Resolve(). >> - iterator unloaded_begin() const { return m_removed_soentries.begin(); } >> - iterator unloaded_end() const { return m_removed_soentries.end(); } >> - >> -protected: >> - lldb_private::Process *m_process; >> - >> - /// Location of the r_debug structure in the inferiors address space. >> - lldb::addr_t m_rendezvous_addr; >> - >> - /// Current and previous snapshots of the rendezvous structure. >> - Rendezvous m_current; >> - Rendezvous m_previous; >> - >> - /// List of SOEntry objects corresponding to the current link map state. >> - SOEntryList m_soentries; >> - >> - /// List of SOEntry's added to the link map since the last call to Resolve(). >> - SOEntryList m_added_soentries; >> - >> - /// List of SOEntry's removed from the link map since the last call to >> - /// Resolve(). >> - SOEntryList m_removed_soentries; >> - >> - /// Reads @p size bytes from the inferiors address space starting at @p >> - /// addr. >> - /// >> - /// @returns addr + size if the read was successful and false otherwise. >> - lldb::addr_t >> - ReadMemory(lldb::addr_t addr, void *dst, size_t size); >> - >> - /// Reads a null-terminated C string from the memory location starting at @p >> - /// addr. >> - std::string >> - ReadStringFromMemory(lldb::addr_t addr); >> - >> - /// Reads an SOEntry starting at @p addr. >> - bool >> - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); >> - >> - /// Updates the current set of SOEntries, the set of added entries, and the >> - /// set of removed entries. >> - bool >> - UpdateSOEntries(); >> - >> - bool >> - UpdateSOEntriesForAddition(); >> - >> - bool >> - UpdateSOEntriesForDeletion(); >> - >> - /// Reads the current list of shared objects according to the link map >> - /// supplied by the runtime linker. >> - bool >> - TakeSnapshot(SOEntryList &entry_list); >> -}; >> - >> -#endif >> Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (working copy) >> @@ -1,423 +0,0 @@ >> -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -#include "lldb/Core/PluginManager.h" >> -#include "lldb/Core/Log.h" >> -#include "lldb/Target/Process.h" >> -#include "lldb/Target/Target.h" >> -#include "lldb/Target/Thread.h" >> -#include "lldb/Target/ThreadPlanRunToAddress.h" >> - >> -#include "AuxVector.h" >> -#include "DynamicLoaderLinuxDYLD.h" >> - >> -using namespace lldb; >> -using namespace lldb_private; >> - >> -void >> -DynamicLoaderLinuxDYLD::Initialize() >> -{ >> - PluginManager::RegisterPlugin(GetPluginNameStatic(), >> - GetPluginDescriptionStatic(), >> - CreateInstance); >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::Terminate() >> -{ >> -} >> - >> -const char * >> -DynamicLoaderLinuxDYLD::GetPluginName() >> -{ >> - return "DynamicLoaderLinuxDYLD"; >> -} >> - >> -const char * >> -DynamicLoaderLinuxDYLD::GetShortPluginName() >> -{ >> - return "linux-dyld"; >> -} >> - >> -const char * >> -DynamicLoaderLinuxDYLD::GetPluginNameStatic() >> -{ >> - return "dynamic-loader.linux-dyld"; >> -} >> - >> -const char * >> -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() >> -{ >> - return "Dynamic loader plug-in that watches for shared library " >> - "loads/unloads in Linux processes."; >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) >> -{ >> -} >> - >> -uint32_t >> -DynamicLoaderLinuxDYLD::GetPluginVersion() >> -{ >> - return 1; >> -} >> - >> -DynamicLoader * >> -DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force) >> -{ >> - bool create = force; >> - if (!create) >> - { >> - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); >> - if (triple_ref.getOS() == llvm::Triple::Linux) >> - create = true; >> - } >> - >> - if (create) >> - return new DynamicLoaderLinuxDYLD (process); >> - return NULL; >> -} >> - >> -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) >> - : DynamicLoader(process), >> - m_rendezvous(process), >> - m_load_offset(LLDB_INVALID_ADDRESS), >> - m_entry_point(LLDB_INVALID_ADDRESS), >> - m_auxv(NULL) >> -{ >> -} >> - >> -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() >> -{ >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::DidAttach() >> -{ >> - ModuleSP executable; >> - addr_t load_offset; >> - >> - m_auxv.reset(new AuxVector(m_process)); >> - >> - executable = m_process->GetTarget().GetExecutableModule(); >> - load_offset = ComputeLoadOffset(); >> - >> - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) >> - { >> - ModuleList module_list; >> - module_list.Append(executable); >> - UpdateLoadedSections(executable, load_offset); >> - m_process->GetTarget().ModulesDidLoad(module_list); >> - } >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::DidLaunch() >> -{ >> - ModuleSP executable; >> - addr_t load_offset; >> - >> - m_auxv.reset(new AuxVector(m_process)); >> - >> - executable = m_process->GetTarget().GetExecutableModule(); >> - load_offset = ComputeLoadOffset(); >> - >> - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) >> - { >> - ModuleList module_list; >> - module_list.Append(executable); >> - UpdateLoadedSections(executable, load_offset); >> - ProbeEntry(); >> - m_process->GetTarget().ModulesDidLoad(module_list); >> - } >> -} >> - >> -Error >> -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) >> -{ >> - return Error(); >> -} >> - >> -Log * >> -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) >> -{ >> - return NULL; >> -} >> - >> -Error >> -DynamicLoaderLinuxDYLD::CanLoadImage() >> -{ >> - return Error(); >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) >> -{ >> - ObjectFile *obj_file = module->GetObjectFile(); >> - SectionList *sections = obj_file->GetSectionList(); >> - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); >> - const size_t num_sections = sections->GetSize(); >> - >> - for (unsigned i = 0; i < num_sections; ++i) >> - { >> - Section *section = sections->GetSectionAtIndex(i).get(); >> - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; >> - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); >> - >> - // If the file address of the section is zero then this is not an >> - // allocatable/loadable section (property of ELF sh_addr). Skip it. >> - if (new_load_addr == base_addr) >> - continue; >> - >> - if (old_load_addr == LLDB_INVALID_ADDRESS || >> - old_load_addr != new_load_addr) >> - load_list.SetSectionLoadAddress(section, new_load_addr); >> - } >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::ProbeEntry() >> -{ >> - Breakpoint *entry_break; >> - addr_t entry; >> - >> - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) >> - return; >> - >> - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); >> - entry_break->SetCallback(EntryBreakpointHit, this, true); >> -} >> - >> -// The runtime linker has run and initialized the rendezvous structure once the >> -// process has hit its entry point. When we hit the corresponding breakpoint we >> -// interrogate the rendezvous structure to get the load addresses of all >> -// dependent modules for the process. Similarly, we can discover the runtime >> -// linker function and setup a breakpoint to notify us of any dynamically loaded >> -// modules (via dlopen). >> -bool >> -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, >> - StoppointCallbackContext *context, >> - user_id_t break_id, >> - user_id_t break_loc_id) >> -{ >> - DynamicLoaderLinuxDYLD* dyld_instance; >> - >> - dyld_instance = static_cast(baton); >> - dyld_instance->LoadAllCurrentModules(); >> - dyld_instance->SetRendezvousBreakpoint(); >> - return false; // Continue running. >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() >> -{ >> - Breakpoint *dyld_break; >> - addr_t break_addr; >> - >> - break_addr = m_rendezvous.GetBreakAddress(); >> - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); >> - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); >> -} >> - >> -bool >> -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, >> - StoppointCallbackContext *context, >> - user_id_t break_id, >> - user_id_t break_loc_id) >> -{ >> - DynamicLoaderLinuxDYLD* dyld_instance; >> - >> - dyld_instance = static_cast(baton); >> - dyld_instance->RefreshModules(); >> - >> - // Return true to stop the target, false to just let the target run. >> - return dyld_instance->GetStopWhenImagesChange(); >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::RefreshModules() >> -{ >> - if (!m_rendezvous.Resolve()) >> - return; >> - >> - DYLDRendezvous::iterator I; >> - DYLDRendezvous::iterator E; >> - >> - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); >> - >> - if (m_rendezvous.ModulesDidLoad()) >> - { >> - ModuleList new_modules; >> - >> - E = m_rendezvous.loaded_end(); >> - for (I = m_rendezvous.loaded_begin(); I != E; ++I) >> - { >> - FileSpec file(I->path.c_str(), true); >> - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); >> - if (module_sp.get()) >> - new_modules.Append(module_sp); >> - } >> - m_process->GetTarget().ModulesDidLoad(new_modules); >> - } >> - >> - if (m_rendezvous.ModulesDidUnload()) >> - { >> - ModuleList old_modules; >> - >> - E = m_rendezvous.unloaded_end(); >> - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) >> - { >> - FileSpec file(I->path.c_str(), true); >> - ModuleSP module_sp = >> - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); >> - if (module_sp.get()) >> - old_modules.Append(module_sp); >> - } >> - m_process->GetTarget().ModulesDidUnload(old_modules); >> - } >> -} >> - >> -ThreadPlanSP >> -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) >> -{ >> - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); >> - ThreadPlanSP thread_plan_sp; >> - >> - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); >> - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); >> - Symbol *sym = context.symbol; >> - >> - if (sym == NULL || !sym->IsTrampoline()) >> - return thread_plan_sp; >> - >> - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); >> - if (!sym_name) >> - return thread_plan_sp; >> - >> - SymbolContextList target_symbols; >> - Target &target = thread.GetProcess().GetTarget(); >> - ModuleList &images = target.GetImages(); >> - >> - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); >> - size_t num_targets = target_symbols.GetSize(); >> - if (!num_targets) >> - return thread_plan_sp; >> - >> - typedef std::vector AddressVector; >> - AddressVector addrs; >> - for (size_t i = 0; i < num_targets; ++i) >> - { >> - SymbolContext context; >> - AddressRange range; >> - if (target_symbols.GetContextAtIndex(i, context)) >> - { >> - context.GetAddressRange(eSymbolContextEverything, 0, false, range); >> - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); >> - if (addr != LLDB_INVALID_ADDRESS) >> - addrs.push_back(addr); >> - } >> - } >> - >> - if (addrs.size() > 0) >> - { >> - AddressVector::iterator start = addrs.begin(); >> - AddressVector::iterator end = addrs.end(); >> - >> - std::sort(start, end); >> - addrs.erase(std::unique(start, end), end); >> - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); >> - } >> - >> - return thread_plan_sp; >> -} >> - >> -void >> -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() >> -{ >> - DYLDRendezvous::iterator I; >> - DYLDRendezvous::iterator E; >> - ModuleList module_list; >> - >> - if (!m_rendezvous.Resolve()) >> - return; >> - >> - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) >> - { >> - FileSpec file(I->path.c_str(), false); >> - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); >> - if (module_sp.get()) >> - module_list.Append(module_sp); >> - } >> - >> - m_process->GetTarget().ModulesDidLoad(module_list); >> -} >> - >> -ModuleSP >> -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) >> -{ >> - Target &target = m_process->GetTarget(); >> - ModuleList &modules = target.GetImages(); >> - ModuleSP module_sp; >> - >> - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) >> - { >> - UpdateLoadedSections(module_sp, base_addr); >> - } >> - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) >> - { >> - UpdateLoadedSections(module_sp, base_addr); >> - modules.Append(module_sp); >> - } >> - >> - return module_sp; >> -} >> - >> -addr_t >> -DynamicLoaderLinuxDYLD::ComputeLoadOffset() >> -{ >> - addr_t virt_entry; >> - >> - if (m_load_offset != LLDB_INVALID_ADDRESS) >> - return m_load_offset; >> - >> - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) >> - return LLDB_INVALID_ADDRESS; >> - >> - ModuleSP module = m_process->GetTarget().GetExecutableModule(); >> - ObjectFile *exe = module->GetObjectFile(); >> - Address file_entry = exe->GetEntryPointAddress(); >> - >> - if (!file_entry.IsValid()) >> - return LLDB_INVALID_ADDRESS; >> - >> - m_load_offset = virt_entry - file_entry.GetFileAddress(); >> - return m_load_offset; >> -} >> - >> -addr_t >> -DynamicLoaderLinuxDYLD::GetEntryPoint() >> -{ >> - if (m_entry_point != LLDB_INVALID_ADDRESS) >> - return m_entry_point; >> - >> - if (m_auxv.get() == NULL) >> - return LLDB_INVALID_ADDRESS; >> - >> - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); >> - >> - if (I == m_auxv->end()) >> - return LLDB_INVALID_ADDRESS; >> - >> - m_entry_point = static_cast(I->value); >> - return m_entry_point; >> -} >> Index: source/Plugins/DynamicLoader/Linux-DYLD/Makefile >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/Makefile (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/Makefile (working copy) >> @@ -1,14 +0,0 @@ >> -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## >> -# >> -# The LLVM Compiler Infrastructure >> -# >> -# This file is distributed under the University of Illinois Open Source >> -# License. See LICENSE.TXT for details. >> -# >> -##===----------------------------------------------------------------------===## >> - >> -LLDB_LEVEL := ../../../.. >> -LIBRARYNAME := lldbPluginDynamicLoaderLinux >> -BUILD_ARCHIVE = 1 >> - >> -include $(LLDB_LEVEL)/Makefile >> Index: source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h >> =================================================================== >> --- source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (revision 147560) >> +++ source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (working copy) >> @@ -1,165 +0,0 @@ >> -//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_ >> -#define liblldb_DynamicLoaderLinux_H_ >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -#include "lldb/Breakpoint/StoppointCallbackContext.h" >> -#include "lldb/Target/DynamicLoader.h" >> - >> -#include "DYLDRendezvous.h" >> - >> -class AuxVector; >> - >> -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader >> -{ >> -public: >> - >> - static void >> - Initialize(); >> - >> - static void >> - Terminate(); >> - >> - static const char * >> - GetPluginNameStatic(); >> - >> - static const char * >> - GetPluginDescriptionStatic(); >> - >> - static lldb_private::DynamicLoader * >> - CreateInstance(lldb_private::Process *process, bool force); >> - >> - DynamicLoaderLinuxDYLD(lldb_private::Process *process); >> - >> - virtual >> - ~DynamicLoaderLinuxDYLD(); >> - >> - //------------------------------------------------------------------ >> - // DynamicLoader protocol >> - //------------------------------------------------------------------ >> - >> - virtual void >> - DidAttach(); >> - >> - virtual void >> - DidLaunch(); >> - >> - virtual lldb::ThreadPlanSP >> - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, >> - bool stop_others); >> - >> - virtual lldb_private::Error >> - CanLoadImage(); >> - >> - //------------------------------------------------------------------ >> - // PluginInterface protocol >> - //------------------------------------------------------------------ >> - virtual const char * >> - GetPluginName(); >> - >> - virtual const char * >> - GetShortPluginName(); >> - >> - virtual uint32_t >> - GetPluginVersion(); >> - >> - virtual void >> - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); >> - >> - virtual lldb_private::Error >> - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); >> - >> - virtual lldb_private::Log * >> - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); >> - >> -protected: >> - /// Runtime linker rendezvous structure. >> - DYLDRendezvous m_rendezvous; >> - >> - /// Virtual load address of the inferior process. >> - lldb::addr_t m_load_offset; >> - >> - /// Virtual entry address of the inferior process. >> - lldb::addr_t m_entry_point; >> - >> - /// Auxiliary vector of the inferior process. >> - std::auto_ptr m_auxv; >> - >> - /// Enables a breakpoint on a function called by the runtime >> - /// linker each time a module is loaded or unloaded. >> - void >> - SetRendezvousBreakpoint(); >> - >> - /// Callback routine which updates the current list of loaded modules based >> - /// on the information supplied by the runtime linker. >> - static bool >> - RendezvousBreakpointHit(void *baton, >> - lldb_private::StoppointCallbackContext *context, >> - lldb::user_id_t break_id, >> - lldb::user_id_t break_loc_id); >> - >> - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set >> - /// of loaded modules. >> - void >> - RefreshModules(); >> - >> - /// Updates the load address of every allocatable section in @p module. >> - /// >> - /// @param module The module to traverse. >> - /// >> - /// @param base_addr The virtual base address @p module is loaded at. >> - void >> - UpdateLoadedSections(lldb::ModuleSP module, >> - lldb::addr_t base_addr = 0); >> - >> - /// Locates or creates a module given by @p file and updates/loads the >> - /// resulting module at the virtual base address @p base_addr. >> - lldb::ModuleSP >> - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); >> - >> - /// Resolves the entry point for the current inferior process and sets a >> - /// breakpoint at that address. >> - void >> - ProbeEntry(); >> - >> - /// Callback routine invoked when we hit the breakpoint on process entry. >> - /// >> - /// This routine is responsible for resolving the load addresses of all >> - /// dependent modules required by the inferior and setting up the rendezvous >> - /// breakpoint. >> - static bool >> - EntryBreakpointHit(void *baton, >> - lldb_private::StoppointCallbackContext *context, >> - lldb::user_id_t break_id, >> - lldb::user_id_t break_loc_id); >> - >> - /// Helper for the entry breakpoint callback. Resolves the load addresses >> - /// of all dependent modules. >> - void >> - LoadAllCurrentModules(); >> - >> - /// Computes a value for m_load_offset returning the computed address on >> - /// success and LLDB_INVALID_ADDRESS on failure. >> - lldb::addr_t >> - ComputeLoadOffset(); >> - >> - /// Computes a value for m_entry_point returning the computed address on >> - /// success and LLDB_INVALID_ADDRESS on failure. >> - lldb::addr_t >> - GetEntryPoint(); >> - >> -private: >> - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); >> -}; >> - >> -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h (revision 0) >> @@ -0,0 +1,165 @@ >> +//===-- DynamicLoaderPOSIX.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_DynamicLoaderPOSIX_H_ >> +#define liblldb_DynamicLoaderPOSIX_H_ >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Breakpoint/StoppointCallbackContext.h" >> +#include "lldb/Target/DynamicLoader.h" >> + >> +#include "DYLDRendezvous.h" >> + >> +class AuxVector; >> + >> +class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader >> +{ >> +public: >> + >> + static void >> + Initialize(); >> + >> + static void >> + Terminate(); >> + >> + static const char * >> + GetPluginNameStatic(); >> + >> + static const char * >> + GetPluginDescriptionStatic(); >> + >> + static lldb_private::DynamicLoader * >> + CreateInstance(lldb_private::Process *process, bool force); >> + >> + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); >> + >> + virtual >> + ~DynamicLoaderPOSIXDYLD(); >> + >> + //------------------------------------------------------------------ >> + // DynamicLoader protocol >> + //------------------------------------------------------------------ >> + >> + virtual void >> + DidAttach(); >> + >> + virtual void >> + DidLaunch(); >> + >> + virtual lldb::ThreadPlanSP >> + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, >> + bool stop_others); >> + >> + virtual lldb_private::Error >> + CanLoadImage(); >> + >> + //------------------------------------------------------------------ >> + // PluginInterface protocol >> + //------------------------------------------------------------------ >> + virtual const char * >> + GetPluginName(); >> + >> + virtual const char * >> + GetShortPluginName(); >> + >> + virtual uint32_t >> + GetPluginVersion(); >> + >> + virtual void >> + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); >> + >> + virtual lldb_private::Error >> + ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); >> + >> + virtual lldb_private::Log * >> + EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); >> + >> +protected: >> + /// Runtime linker rendezvous structure. >> + DYLDRendezvous m_rendezvous; >> + >> + /// Virtual load address of the inferior process. >> + lldb::addr_t m_load_offset; >> + >> + /// Virtual entry address of the inferior process. >> + lldb::addr_t m_entry_point; >> + >> + /// Auxiliary vector of the inferior process. >> + std::auto_ptr m_auxv; >> + >> + /// Enables a breakpoint on a function called by the runtime >> + /// linker each time a module is loaded or unloaded. >> + void >> + SetRendezvousBreakpoint(); >> + >> + /// Callback routine which updates the current list of loaded modules based >> + /// on the information supplied by the runtime linker. >> + static bool >> + RendezvousBreakpointHit(void *baton, >> + lldb_private::StoppointCallbackContext *context, >> + lldb::user_id_t break_id, >> + lldb::user_id_t break_loc_id); >> + >> + /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set >> + /// of loaded modules. >> + void >> + RefreshModules(); >> + >> + /// Updates the load address of every allocatable section in @p module. >> + /// >> + /// @param module The module to traverse. >> + /// >> + /// @param base_addr The virtual base address @p module is loaded at. >> + void >> + UpdateLoadedSections(lldb::ModuleSP module, >> + lldb::addr_t base_addr = 0); >> + >> + /// Locates or creates a module given by @p file and updates/loads the >> + /// resulting module at the virtual base address @p base_addr. >> + lldb::ModuleSP >> + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); >> + >> + /// Resolves the entry point for the current inferior process and sets a >> + /// breakpoint at that address. >> + void >> + ProbeEntry(); >> + >> + /// Callback routine invoked when we hit the breakpoint on process entry. >> + /// >> + /// This routine is responsible for resolving the load addresses of all >> + /// dependent modules required by the inferior and setting up the rendezvous >> + /// breakpoint. >> + static bool >> + EntryBreakpointHit(void *baton, >> + lldb_private::StoppointCallbackContext *context, >> + lldb::user_id_t break_id, >> + lldb::user_id_t break_loc_id); >> + >> + /// Helper for the entry breakpoint callback. Resolves the load addresses >> + /// of all dependent modules. >> + void >> + LoadAllCurrentModules(); >> + >> + /// Computes a value for m_load_offset returning the computed address on >> + /// success and LLDB_INVALID_ADDRESS on failure. >> + lldb::addr_t >> + ComputeLoadOffset(); >> + >> + /// Computes a value for m_entry_point returning the computed address on >> + /// success and LLDB_INVALID_ADDRESS on failure. >> + lldb::addr_t >> + GetEntryPoint(); >> + >> +private: >> + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); >> +}; >> + >> +#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (revision 0) >> @@ -0,0 +1,153 @@ >> +//===-- AuxVector.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 >> +#include >> +#include >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/DataBufferHeap.h" >> +#include "lldb/Core/DataExtractor.h" >> +#include "lldb/Core/Log.h" >> +#include "lldb/Target/Process.h" >> + >> +#include "AuxVector.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +static bool >> +GetMaxU64(DataExtractor &data, >> + uint32_t *offset, uint64_t *value, unsigned int byte_size) >> +{ >> + uint32_t saved_offset = *offset; >> + *value = data.GetMaxU64(offset, byte_size); >> + return *offset != saved_offset; >> +} >> + >> +static bool >> +ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, >> + uint32_t *offset, unsigned int byte_size) >> +{ >> + if (!GetMaxU64(data, offset, &entry.type, byte_size)) >> + return false; >> + >> + if (!GetMaxU64(data, offset, &entry.value, byte_size)) >> + return false; >> + >> + return true; >> +} >> + >> +DataBufferSP >> +AuxVector::GetAuxvData() >> +{ >> + >> + return lldb_private::Host::GetAuxvData(m_process); >> +} >> + >> +void >> +AuxVector::ParseAuxv(DataExtractor &data) >> +{ >> + const unsigned int byte_size = m_process->GetAddressByteSize(); >> + uint32_t offset = 0; >> + >> + for (;;) >> + { >> + Entry entry; >> + >> + if (!ParseAuxvEntry(data, entry, &offset, byte_size)) >> + break; >> + >> + if (entry.type == AT_NULL) >> + break; >> + >> + if (entry.type == AT_IGNORE) >> + continue; >> + >> + m_auxv.push_back(entry); >> + } >> +} >> + >> +AuxVector::AuxVector(Process *process) >> + : m_process(process) >> +{ >> + DataExtractor data; >> + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); >> + >> + data.SetData(GetAuxvData()); >> + data.SetByteOrder(m_process->GetByteOrder()); >> + data.SetAddressByteSize(m_process->GetAddressByteSize()); >> + >> + ParseAuxv(data); >> + >> + if (log) >> + DumpToLog(log); >> +} >> + >> +AuxVector::iterator >> +AuxVector::FindEntry(EntryType type) const >> +{ >> + for (iterator I = begin(); I != end(); ++I) >> + { >> + if (I->type == static_cast(type)) >> + return I; >> + } >> + >> + return end(); >> +} >> + >> +void >> +AuxVector::DumpToLog(LogSP log) const >> +{ >> + if (!log) >> + return; >> + >> + log->PutCString("AuxVector: "); >> + for (iterator I = begin(); I != end(); ++I) >> + { >> + log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); >> + } >> +} >> + >> +const char * >> +AuxVector::GetEntryName(EntryType type) >> +{ >> + const char *name; >> + >> +#define ENTRY_NAME(_type) _type: name = #_type >> + switch (type) >> + { >> + default: >> + name = "unkown"; >> + break; >> + >> + case ENTRY_NAME(AT_NULL); break; >> + case ENTRY_NAME(AT_IGNORE); break; >> + case ENTRY_NAME(AT_EXECFD); break; >> + case ENTRY_NAME(AT_PHDR); break; >> + case ENTRY_NAME(AT_PHENT); break; >> + case ENTRY_NAME(AT_PHNUM); break; >> + case ENTRY_NAME(AT_PAGESZ); break; >> + case ENTRY_NAME(AT_BASE); break; >> + case ENTRY_NAME(AT_FLAGS); break; >> + case ENTRY_NAME(AT_ENTRY); break; >> + case ENTRY_NAME(AT_NOTELF); break; >> + case ENTRY_NAME(AT_UID); break; >> + case ENTRY_NAME(AT_EUID); break; >> + case ENTRY_NAME(AT_GID); break; >> + case ENTRY_NAME(AT_EGID); break; >> + case ENTRY_NAME(AT_CLKTCK); break; >> + } >> +#undef ENTRY_NAME >> + >> + return name; >> +} >> + >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp (revision 0) >> @@ -0,0 +1,330 @@ >> +//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/ArchSpec.h" >> +#include "lldb/Core/Error.h" >> +#include "lldb/Core/Log.h" >> +#include "lldb/Target/Process.h" >> +#include "lldb/Target/Target.h" >> + >> +#include "DYLDRendezvous.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +/// Locates the address of the rendezvous structure. Returns the address on >> +/// success and LLDB_INVALID_ADDRESS on failure. >> +static addr_t >> +ResolveRendezvousAddress(Process *process) >> +{ >> + addr_t info_location; >> + addr_t info_addr; >> + Error error; >> + size_t size; >> + >> + info_location = process->GetImageInfoAddress(); >> + >> + if (info_location == LLDB_INVALID_ADDRESS) >> + return LLDB_INVALID_ADDRESS; >> + >> + info_addr = 0; >> + size = process->DoReadMemory(info_location, &info_addr, >> + process->GetAddressByteSize(), error); >> + if (size != process->GetAddressByteSize() || error.Fail()) >> + return LLDB_INVALID_ADDRESS; >> + >> + if (info_addr == 0) >> + return LLDB_INVALID_ADDRESS; >> + >> + return info_addr; >> +} >> + >> +DYLDRendezvous::DYLDRendezvous(Process *process) >> + : m_process(process), >> + m_rendezvous_addr(LLDB_INVALID_ADDRESS), >> + m_current(), >> + m_previous(), >> + m_soentries(), >> + m_added_soentries(), >> + m_removed_soentries() >> +{ >> + // Cache a copy of the executable path >> + m_process->GetTarget().GetExecutableModule().get()->GetFileSpec().GetPath(m_exe_path, PATH_MAX); >> +} >> + >> +bool >> +DYLDRendezvous::Resolve() >> +{ >> + const size_t word_size = 4; >> + Rendezvous info; >> + size_t address_size; >> + size_t padding; >> + addr_t info_addr; >> + addr_t cursor; >> + >> + address_size = m_process->GetAddressByteSize(); >> + padding = address_size - word_size; >> + >> + if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) >> + cursor = info_addr = ResolveRendezvousAddress(m_process); >> + else >> + cursor = info_addr = m_rendezvous_addr; >> + >> + if (cursor == LLDB_INVALID_ADDRESS) >> + return false; >> + >> + if (!(cursor = ReadMemory(cursor, &info.version, word_size))) >> + return false; >> + >> + if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) >> + return false; >> + >> + if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) >> + return false; >> + >> + if (!(cursor = ReadMemory(cursor, &info.state, word_size))) >> + return false; >> + >> + if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) >> + return false; >> + >> + // The rendezvous was successfully read. Update our internal state. >> + m_rendezvous_addr = info_addr; >> + m_previous = m_current; >> + m_current = info; >> + >> + return UpdateSOEntries(); >> +} >> + >> +bool >> +DYLDRendezvous::IsValid() >> +{ >> + return m_rendezvous_addr != LLDB_INVALID_ADDRESS; >> +} >> + >> +bool >> +DYLDRendezvous::UpdateSOEntries() >> +{ >> + SOEntry entry; >> + >> + if (m_current.map_addr == 0) >> + return false; >> + >> + // When the previous and current states are consistent this is the first >> + // time we have been asked to update. Just take a snapshot of the currently >> + // loaded modules. >> + if (m_previous.state == eConsistent && m_current.state == eConsistent) >> + return TakeSnapshot(m_soentries); >> + >> + // If we are about to add or remove a shared object clear out the current >> + // state and take a snapshot of the currently loaded images. >> + if (m_current.state == eAdd || m_current.state == eDelete) >> + { >> + assert(m_previous.state == eConsistent); >> + m_soentries.clear(); >> + m_added_soentries.clear(); >> + m_removed_soentries.clear(); >> + return TakeSnapshot(m_soentries); >> + } >> + assert(m_current.state == eConsistent); >> + >> + // Otherwise check the previous state to determine what to expect and update >> + // accordingly. >> + if (m_previous.state == eAdd) >> + return UpdateSOEntriesForAddition(); >> + else if (m_previous.state == eDelete) >> + return UpdateSOEntriesForDeletion(); >> + >> + return false; >> +} >> + >> +bool >> +DYLDRendezvous::UpdateSOEntriesForAddition() >> +{ >> + SOEntry entry; >> + iterator pos; >> + >> + assert(m_previous.state == eAdd); >> + >> + if (m_current.map_addr == 0) >> + return false; >> + >> + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) >> + { >> + if (!ReadSOEntryFromMemory(cursor, entry)) >> + return false; >> + >> + // Only add shared libraries and not the executable. >> + // On Linux this is indicated by an empty path in the entry. >> + // On FreeBSD it is the name of the executable. >> + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) >> + continue; >> + >> + pos = std::find(m_soentries.begin(), m_soentries.end(), entry); >> + if (pos == m_soentries.end()) >> + { >> + m_soentries.push_back(entry); >> + m_added_soentries.push_back(entry); >> + } >> + } >> + >> + return true; >> +} >> + >> +bool >> +DYLDRendezvous::UpdateSOEntriesForDeletion() >> +{ >> + SOEntryList entry_list; >> + iterator pos; >> + >> + assert(m_previous.state == eDelete); >> + >> + if (!TakeSnapshot(entry_list)) >> + return false; >> + >> + for (iterator I = begin(); I != end(); ++I) >> + { >> + pos = std::find(entry_list.begin(), entry_list.end(), *I); >> + if (pos == entry_list.end()) >> + m_removed_soentries.push_back(*I); >> + } >> + >> + m_soentries = entry_list; >> + return true; >> +} >> + >> +bool >> +DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) >> +{ >> + SOEntry entry; >> + >> + if (m_current.map_addr == 0) >> + return false; >> + >> + for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) >> + { >> + if (!ReadSOEntryFromMemory(cursor, entry)) >> + return false; >> + >> + // Only add shared libraries and not the executable. >> + // On Linux this is indicated by an empty path in the entry. >> + // On FreeBSD it is the name of the executable. >> + if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0) >> + continue; >> + >> + entry_list.push_back(entry); >> + } >> + >> + return true; >> +} >> + >> +addr_t >> +DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) >> +{ >> + size_t bytes_read; >> + Error error; >> + >> + bytes_read = m_process->DoReadMemory(addr, dst, size, error); >> + if (bytes_read != size || error.Fail()) >> + return 0; >> + >> + return addr + bytes_read; >> +} >> + >> +std::string >> +DYLDRendezvous::ReadStringFromMemory(addr_t addr) >> +{ >> + std::string str; >> + Error error; >> + size_t size; >> + char c; >> + >> + if (addr == LLDB_INVALID_ADDRESS) >> + return std::string(); >> + >> + for (;;) { >> + size = m_process->DoReadMemory(addr, &c, 1, error); >> + if (size != 1 || error.Fail()) >> + return std::string(); >> + if (c == 0) >> + break; >> + else { >> + str.push_back(c); >> + addr++; >> + } >> + } >> + >> + return str; >> +} >> + >> +bool >> +DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) >> +{ >> + size_t address_size = m_process->GetAddressByteSize(); >> + >> + entry.clear(); >> + >> + if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) >> + return false; >> + >> + if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) >> + return false; >> + >> + if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) >> + return false; >> + >> + if (!(addr = ReadMemory(addr, &entry.next, address_size))) >> + return false; >> + >> + if (!(addr = ReadMemory(addr, &entry.prev, address_size))) >> + return false; >> + >> + entry.path = ReadStringFromMemory(entry.path_addr); >> + >> + return true; >> +} >> + >> +void >> +DYLDRendezvous::DumpToLog(LogSP log) const >> +{ >> + int state = GetState(); >> + >> + if (!log) >> + return; >> + >> + log->PutCString("DYLDRendezvous:"); >> + log->Printf(" Address: %lx", GetRendezvousAddress()); >> + log->Printf(" Version: %d", GetVersion()); >> + log->Printf(" Link : %lx", GetLinkMapAddress()); >> + log->Printf(" Break : %lx", GetBreakAddress()); >> + log->Printf(" LDBase : %lx", GetLDBase()); >> + log->Printf(" State : %s", >> + (state == eConsistent) ? "consistent" : >> + (state == eAdd) ? "add" : >> + (state == eDelete) ? "delete" : "unknown"); >> + >> + iterator I = begin(); >> + iterator E = end(); >> + >> + if (I != E) >> + log->PutCString("DYLDRendezvous SOEntries:"); >> + >> + for (int i = 1; I != E; ++I, ++i) >> + { >> + log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); >> + log->Printf(" Base : %lx", I->base_addr); >> + log->Printf(" Path : %lx", I->path_addr); >> + log->Printf(" Dyn : %lx", I->dyn_addr); >> + log->Printf(" Next : %lx", I->next); >> + log->Printf(" Prev : %lx", I->prev); >> + } >> +} >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h (revision 0) >> @@ -0,0 +1,97 @@ >> +//===-- AuxVector.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_AuxVector_H_ >> +#define liblldb_AuxVector_H_ >> + >> +// C Includes >> +// C++ Includes >> +#include >> + >> +// Other libraries and framework includes >> +#include "lldb/lldb-forward-rtti.h" >> + >> +namespace lldb_private { >> +class DataExtractor; >> +} >> + >> +/// @class AuxVector >> +/// @brief Represents a processes auxiliary vector. >> +/// >> +/// When a process is loaded on Linux a vector of values is placed onto the >> +/// stack communicating operating system specific information. On construction >> +/// this class locates and parses this information and provides a simple >> +/// read-only interface to the entries found. >> +class AuxVector { >> + >> +public: >> + AuxVector(lldb_private::Process *process); >> + >> + struct Entry { >> + uint64_t type; >> + uint64_t value; >> + >> + Entry() : type(0), value(0) { } >> + }; >> + >> + /// Constants describing the type of entry. >> + enum EntryType { >> + AT_NULL = 0, ///< End of auxv. >> + AT_IGNORE = 1, ///< Ignore entry. >> + AT_EXECFD = 2, ///< File descriptor of program. >> + AT_PHDR = 3, ///< Program headers. >> + AT_PHENT = 4, ///< Size of program header. >> + AT_PHNUM = 5, ///< Number of program headers. >> + AT_PAGESZ = 6, ///< Page size. >> + AT_BASE = 7, ///< Interpreter base address. >> + AT_FLAGS = 8, ///< Flags. >> + AT_ENTRY = 9, ///< Program entry point. >> + AT_NOTELF = 10, ///< Set if program is not an ELF. >> + AT_UID = 11, ///< UID. >> + AT_EUID = 12, ///< Effective UID. >> + AT_GID = 13, ///< GID. >> + AT_EGID = 14, ///< Effective GID. >> + AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). >> + }; >> + >> +private: >> + typedef std::vector EntryVector; >> + >> +public: >> + typedef EntryVector::const_iterator iterator; >> + >> + iterator begin() const { return m_auxv.begin(); } >> + iterator end() const { return m_auxv.end(); } >> + >> + iterator >> + FindEntry(EntryType type) const; >> + >> + static const char * >> + GetEntryName(const Entry &entry) { >> + return GetEntryName(static_cast(entry.type)); >> + } >> + >> + static const char * >> + GetEntryName(EntryType type); >> + >> + void >> + DumpToLog(lldb::LogSP log) const; >> + >> +private: >> + lldb_private::Process *m_process; >> + EntryVector m_auxv; >> + >> + lldb::DataBufferSP >> + GetAuxvData(); >> + >> + void >> + ParseAuxv(lldb_private::DataExtractor &data); >> +}; >> + >> +#endif >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h (revision 0) >> @@ -0,0 +1,230 @@ >> +//===-- DYLDRendezvous.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_Rendezvous_H_ >> +#define liblldb_Rendezvous_H_ >> + >> +// C Includes >> +// C++ Includes >> +#include >> +#include >> + >> +// Other libraries and framework includes >> +#include "lldb/lldb-defines.h" >> +#include "lldb/lldb-types.h" >> + >> +namespace lldb_private { >> +class Process; >> +} >> + >> +/// @class DYLDRendezvous >> +/// @brief Interface to the runtime linker. >> +/// >> +/// A structure is present in a processes memory space which is updated by the >> +/// runtime liker each time a module is loaded or unloaded. This class provides >> +/// an interface to this structure and maintains a consistent snapshot of the >> +/// currently loaded modules. >> +class DYLDRendezvous { >> + >> + // This structure is used to hold the contents of the debug rendezvous >> + // information (struct r_debug) as found in the inferiors memory. Note that >> + // the layout of this struct is not binary compatible, it is simply large >> + // enough to hold the information on both 32 and 64 bit platforms. >> + struct Rendezvous { >> + uint64_t version; >> + lldb::addr_t map_addr; >> + lldb::addr_t brk; >> + uint64_t state; >> + lldb::addr_t ldbase; >> + >> + Rendezvous() >> + : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } >> + }; >> + >> +public: >> + DYLDRendezvous(lldb_private::Process *process); >> + >> + /// Update the internal snapshot of runtime linker rendezvous and recompute >> + /// the currently loaded modules. >> + /// >> + /// This method should be called once one start up, then once each time the >> + /// runtime linker enters the function given by GetBreakAddress(). >> + /// >> + /// @returns true on success and false on failure. >> + /// >> + /// @see GetBreakAddress(). >> + bool >> + Resolve(); >> + >> + /// @returns true if this rendezvous has been located in the inferiors >> + /// address space and false otherwise. >> + bool >> + IsValid(); >> + >> + /// @returns the address of the rendezvous structure in the inferiors >> + /// address space. >> + lldb::addr_t >> + GetRendezvousAddress() const { return m_rendezvous_addr; } >> + >> + /// @returns the version of the rendezvous protocol being used. >> + int >> + GetVersion() const { return m_current.version; } >> + >> + /// @returns address in the inferiors address space containing the linked >> + /// list of shared object descriptors. >> + lldb::addr_t >> + GetLinkMapAddress() const { return m_current.map_addr; } >> + >> + /// A breakpoint should be set at this address and Resolve called on each >> + /// hit. >> + /// >> + /// @returns the address of a function called by the runtime linker each >> + /// time a module is loaded/unloaded, or about to be loaded/unloaded. >> + /// >> + /// @see Resolve() >> + lldb::addr_t >> + GetBreakAddress() const { return m_current.brk; } >> + >> + /// Returns the current state of the rendezvous structure. >> + int >> + GetState() const { return m_current.state; } >> + >> + /// @returns the base address of the runtime linker in the inferiors address >> + /// space. >> + lldb::addr_t >> + GetLDBase() const { return m_current.ldbase; } >> + >> + /// @returns true if modules have been loaded into the inferior since the >> + /// last call to Resolve(). >> + bool >> + ModulesDidLoad() const { return !m_added_soentries.empty(); } >> + >> + /// @returns true if modules have been unloaded from the inferior since the >> + /// last call to Resolve(). >> + bool >> + ModulesDidUnload() const { return !m_removed_soentries.empty(); } >> + >> + void >> + DumpToLog(lldb::LogSP log) const; >> + >> + /// @brief Constants describing the state of the rendezvous. >> + /// >> + /// @see GetState(). >> + enum RendezvousState { >> + eConsistent, >> + eAdd, >> + eDelete >> + }; >> + >> + /// @brief Structure representing the shared objects currently loaded into >> + /// the inferior process. >> + /// >> + /// This object is a rough analogue to the struct link_map object which >> + /// actually lives in the inferiors memory. >> + struct SOEntry { >> + lldb::addr_t base_addr; ///< Base address of the loaded object. >> + lldb::addr_t path_addr; ///< String naming the shared object. >> + lldb::addr_t dyn_addr; ///< Dynamic section of shared object. >> + lldb::addr_t next; ///< Address of next so_entry. >> + lldb::addr_t prev; ///< Address of previous so_entry. >> + std::string path; ///< File name of shared object. >> + >> + SOEntry() { clear(); } >> + >> + bool operator ==(const SOEntry &entry) { >> + return this->path == entry.path; >> + } >> + >> + void clear() { >> + base_addr = 0; >> + path_addr = 0; >> + dyn_addr = 0; >> + next = 0; >> + prev = 0; >> + path.clear(); >> + } >> + }; >> + >> +protected: >> + typedef std::list SOEntryList; >> + >> +public: >> + typedef SOEntryList::const_iterator iterator; >> + >> + /// Iterators over all currently loaded modules. >> + iterator begin() const { return m_soentries.begin(); } >> + iterator end() const { return m_soentries.end(); } >> + >> + /// Iterators over all modules loaded into the inferior since the last call >> + /// to Resolve(). >> + iterator loaded_begin() const { return m_added_soentries.begin(); } >> + iterator loaded_end() const { return m_added_soentries.end(); } >> + >> + /// Iterators over all modules unloaded from the inferior since the last >> + /// call to Resolve(). >> + iterator unloaded_begin() const { return m_removed_soentries.begin(); } >> + iterator unloaded_end() const { return m_removed_soentries.end(); } >> + >> +protected: >> + lldb_private::Process *m_process; >> + >> + // Cached copy of executable pathname >> + char m_exe_path[PATH_MAX]; >> + >> + /// Location of the r_debug structure in the inferiors address space. >> + lldb::addr_t m_rendezvous_addr; >> + >> + /// Current and previous snapshots of the rendezvous structure. >> + Rendezvous m_current; >> + Rendezvous m_previous; >> + >> + /// List of SOEntry objects corresponding to the current link map state. >> + SOEntryList m_soentries; >> + >> + /// List of SOEntry's added to the link map since the last call to Resolve(). >> + SOEntryList m_added_soentries; >> + >> + /// List of SOEntry's removed from the link map since the last call to >> + /// Resolve(). >> + SOEntryList m_removed_soentries; >> + >> + /// Reads @p size bytes from the inferiors address space starting at @p >> + /// addr. >> + /// >> + /// @returns addr + size if the read was successful and false otherwise. >> + lldb::addr_t >> + ReadMemory(lldb::addr_t addr, void *dst, size_t size); >> + >> + /// Reads a null-terminated C string from the memory location starting at @p >> + /// addr. >> + std::string >> + ReadStringFromMemory(lldb::addr_t addr); >> + >> + /// Reads an SOEntry starting at @p addr. >> + bool >> + ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); >> + >> + /// Updates the current set of SOEntries, the set of added entries, and the >> + /// set of removed entries. >> + bool >> + UpdateSOEntries(); >> + >> + bool >> + UpdateSOEntriesForAddition(); >> + >> + bool >> + UpdateSOEntriesForDeletion(); >> + >> + /// Reads the current list of shared objects according to the link map >> + /// supplied by the runtime linker. >> + bool >> + TakeSnapshot(SOEntryList &entry_list); >> +}; >> + >> +#endif >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (revision 0) >> @@ -0,0 +1,425 @@ >> +//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/PluginManager.h" >> +#include "lldb/Core/Log.h" >> +#include "lldb/Target/Process.h" >> +#include "lldb/Target/Target.h" >> +#include "lldb/Target/Thread.h" >> +#include "lldb/Target/ThreadPlanRunToAddress.h" >> + >> +#include "AuxVector.h" >> +#include "DynamicLoaderPOSIXDYLD.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +void >> +DynamicLoaderPOSIXDYLD::Initialize() >> +{ >> + PluginManager::RegisterPlugin(GetPluginNameStatic(), >> + GetPluginDescriptionStatic(), >> + CreateInstance); >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::Terminate() >> +{ >> +} >> + >> +const char * >> +DynamicLoaderPOSIXDYLD::GetPluginName() >> +{ >> + return "DynamicLoaderPOSIXDYLD"; >> +} >> + >> +const char * >> +DynamicLoaderPOSIXDYLD::GetShortPluginName() >> +{ >> + return "linux-dyld"; >> +} >> + >> +const char * >> +DynamicLoaderPOSIXDYLD::GetPluginNameStatic() >> +{ >> + return "dynamic-loader.linux-dyld"; >> +} >> + >> +const char * >> +DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() >> +{ >> + return "Dynamic loader plug-in that watches for shared library " >> + "loads/unloads in POSIX processes."; >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) >> +{ >> +} >> + >> +uint32_t >> +DynamicLoaderPOSIXDYLD::GetPluginVersion() >> +{ >> + return 1; >> +} >> + >> +DynamicLoader * >> +DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force) >> +{ >> + bool create = force; >> + if (!create) >> + { >> + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); >> + if (triple_ref.getOS() == llvm::Triple::Linux || >> + triple_ref.getOS() == llvm::Triple::FreeBSD) >> + create = true; >> + } >> + >> + if (create) >> + return new DynamicLoaderPOSIXDYLD (process); >> + return NULL; >> +} >> + >> +DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) >> + : DynamicLoader(process), >> + m_rendezvous(process), >> + m_load_offset(LLDB_INVALID_ADDRESS), >> + m_entry_point(LLDB_INVALID_ADDRESS), >> + m_auxv(NULL) >> +{ >> +} >> + >> +DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() >> +{ >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::DidAttach() >> +{ >> + ModuleSP executable; >> + addr_t load_offset; >> + >> + m_auxv.reset(new AuxVector(m_process)); >> + >> + executable = m_process->GetTarget().GetExecutableModule(); >> + load_offset = ComputeLoadOffset(); >> + >> + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) >> + { >> + ModuleList module_list; >> + module_list.Append(executable); >> + UpdateLoadedSections(executable, load_offset); >> + LoadAllCurrentModules(); >> + m_process->GetTarget().ModulesDidLoad(module_list); >> + } >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::DidLaunch() >> +{ >> + ModuleSP executable; >> + addr_t load_offset; >> + >> + m_auxv.reset(new AuxVector(m_process)); >> + >> + executable = m_process->GetTarget().GetExecutableModule(); >> + load_offset = ComputeLoadOffset(); >> + >> + if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) >> + { >> + ModuleList module_list; >> + module_list.Append(executable); >> + UpdateLoadedSections(executable, load_offset); >> + ProbeEntry(); >> + m_process->GetTarget().ModulesDidLoad(module_list); >> + } >> +} >> + >> +Error >> +DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) >> +{ >> + return Error(); >> +} >> + >> +Log * >> +DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) >> +{ >> + return NULL; >> +} >> + >> +Error >> +DynamicLoaderPOSIXDYLD::CanLoadImage() >> +{ >> + return Error(); >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) >> +{ >> + ObjectFile *obj_file = module->GetObjectFile(); >> + SectionList *sections = obj_file->GetSectionList(); >> + SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); >> + const size_t num_sections = sections->GetSize(); >> + >> + for (unsigned i = 0; i < num_sections; ++i) >> + { >> + Section *section = sections->GetSectionAtIndex(i).get(); >> + lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; >> + lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); >> + >> + // If the file address of the section is zero then this is not an >> + // allocatable/loadable section (property of ELF sh_addr). Skip it. >> + if (new_load_addr == base_addr) >> + continue; >> + >> + if (old_load_addr == LLDB_INVALID_ADDRESS || >> + old_load_addr != new_load_addr) >> + load_list.SetSectionLoadAddress(section, new_load_addr); >> + } >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::ProbeEntry() >> +{ >> + Breakpoint *entry_break; >> + addr_t entry; >> + >> + if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) >> + return; >> + >> + entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); >> + entry_break->SetCallback(EntryBreakpointHit, this, true); >> +} >> + >> +// The runtime linker has run and initialized the rendezvous structure once the >> +// process has hit its entry point. When we hit the corresponding breakpoint we >> +// interrogate the rendezvous structure to get the load addresses of all >> +// dependent modules for the process. Similarly, we can discover the runtime >> +// linker function and setup a breakpoint to notify us of any dynamically loaded >> +// modules (via dlopen). >> +bool >> +DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, >> + StoppointCallbackContext *context, >> + user_id_t break_id, >> + user_id_t break_loc_id) >> +{ >> + DynamicLoaderPOSIXDYLD* dyld_instance; >> + >> + dyld_instance = static_cast(baton); >> + dyld_instance->LoadAllCurrentModules(); >> + dyld_instance->SetRendezvousBreakpoint(); >> + return false; // Continue running. >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() >> +{ >> + Breakpoint *dyld_break; >> + addr_t break_addr; >> + >> + break_addr = m_rendezvous.GetBreakAddress(); >> + dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); >> + dyld_break->SetCallback(RendezvousBreakpointHit, this, true); >> +} >> + >> +bool >> +DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, >> + StoppointCallbackContext *context, >> + user_id_t break_id, >> + user_id_t break_loc_id) >> +{ >> + DynamicLoaderPOSIXDYLD* dyld_instance; >> + >> + dyld_instance = static_cast(baton); >> + dyld_instance->RefreshModules(); >> + >> + // Return true to stop the target, false to just let the target run. >> + return dyld_instance->GetStopWhenImagesChange(); >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::RefreshModules() >> +{ >> + if (!m_rendezvous.Resolve()) >> + return; >> + >> + DYLDRendezvous::iterator I; >> + DYLDRendezvous::iterator E; >> + >> + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); >> + >> + if (m_rendezvous.ModulesDidLoad()) >> + { >> + ModuleList new_modules; >> + >> + E = m_rendezvous.loaded_end(); >> + for (I = m_rendezvous.loaded_begin(); I != E; ++I) >> + { >> + FileSpec file(I->path.c_str(), true); >> + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); >> + if (module_sp.get()) >> + new_modules.Append(module_sp); >> + } >> + m_process->GetTarget().ModulesDidLoad(new_modules); >> + } >> + >> + if (m_rendezvous.ModulesDidUnload()) >> + { >> + ModuleList old_modules; >> + >> + E = m_rendezvous.unloaded_end(); >> + for (I = m_rendezvous.unloaded_begin(); I != E; ++I) >> + { >> + FileSpec file(I->path.c_str(), true); >> + ModuleSP module_sp = >> + loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); >> + if (module_sp.get()) >> + old_modules.Append(module_sp); >> + } >> + m_process->GetTarget().ModulesDidUnload(old_modules); >> + } >> +} >> + >> +ThreadPlanSP >> +DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) >> +{ >> + LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); >> + ThreadPlanSP thread_plan_sp; >> + >> + StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); >> + const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); >> + Symbol *sym = context.symbol; >> + >> + if (sym == NULL || !sym->IsTrampoline()) >> + return thread_plan_sp; >> + >> + const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); >> + if (!sym_name) >> + return thread_plan_sp; >> + >> + SymbolContextList target_symbols; >> + Target &target = thread.GetProcess().GetTarget(); >> + ModuleList &images = target.GetImages(); >> + >> + images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); >> + size_t num_targets = target_symbols.GetSize(); >> + if (!num_targets) >> + return thread_plan_sp; >> + >> + typedef std::vector AddressVector; >> + AddressVector addrs; >> + for (size_t i = 0; i < num_targets; ++i) >> + { >> + SymbolContext context; >> + AddressRange range; >> + if (target_symbols.GetContextAtIndex(i, context)) >> + { >> + context.GetAddressRange(eSymbolContextEverything, 0, false, range); >> + lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); >> + if (addr != LLDB_INVALID_ADDRESS) >> + addrs.push_back(addr); >> + } >> + } >> + >> + if (addrs.size() > 0) >> + { >> + AddressVector::iterator start = addrs.begin(); >> + AddressVector::iterator end = addrs.end(); >> + >> + std::sort(start, end); >> + addrs.erase(std::unique(start, end), end); >> + thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); >> + } >> + >> + return thread_plan_sp; >> +} >> + >> +void >> +DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() >> +{ >> + DYLDRendezvous::iterator I; >> + DYLDRendezvous::iterator E; >> + ModuleList module_list; >> + >> + if (!m_rendezvous.Resolve()) >> + return; >> + >> + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) >> + { >> + FileSpec file(I->path.c_str(), false); >> + ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); >> + if (module_sp.get()) >> + module_list.Append(module_sp); >> + } >> + >> + m_process->GetTarget().ModulesDidLoad(module_list); >> +} >> + >> +ModuleSP >> +DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) >> +{ >> + Target &target = m_process->GetTarget(); >> + ModuleList &modules = target.GetImages(); >> + ModuleSP module_sp; >> + >> + if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) >> + { >> + UpdateLoadedSections(module_sp, base_addr); >> + } >> + else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) >> + { >> + UpdateLoadedSections(module_sp, base_addr); >> + modules.Append(module_sp); >> + } >> + >> + return module_sp; >> +} >> + >> +addr_t >> +DynamicLoaderPOSIXDYLD::ComputeLoadOffset() >> +{ >> + addr_t virt_entry; >> + >> + if (m_load_offset != LLDB_INVALID_ADDRESS) >> + return m_load_offset; >> + >> + if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) >> + return LLDB_INVALID_ADDRESS; >> + >> + ModuleSP module = m_process->GetTarget().GetExecutableModule(); >> + ObjectFile *exe = module->GetObjectFile(); >> + Address file_entry = exe->GetEntryPointAddress(); >> + >> + if (!file_entry.IsValid()) >> + return LLDB_INVALID_ADDRESS; >> + >> + m_load_offset = virt_entry - file_entry.GetFileAddress(); >> + return m_load_offset; >> +} >> + >> +addr_t >> +DynamicLoaderPOSIXDYLD::GetEntryPoint() >> +{ >> + if (m_entry_point != LLDB_INVALID_ADDRESS) >> + return m_entry_point; >> + >> + if (m_auxv.get() == NULL) >> + return LLDB_INVALID_ADDRESS; >> + >> + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); >> + >> + if (I == m_auxv->end()) >> + return LLDB_INVALID_ADDRESS; >> + >> + m_entry_point = static_cast(I->value); >> + return m_entry_point; >> +} >> Index: source/Plugins/DynamicLoader/POSIX-DYLD/Makefile >> =================================================================== >> --- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) >> +++ source/Plugins/DynamicLoader/POSIX-DYLD/Makefile (revision 0) >> @@ -0,0 +1,14 @@ >> +##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===## >> +# >> +# The LLVM Compiler Infrastructure >> +# >> +# This file is distributed under the University of Illinois Open Source >> +# License. See LICENSE.TXT for details. >> +# >> +##===----------------------------------------------------------------------===## >> + >> +LLDB_LEVEL := ../../../.. >> +LIBRARYNAME := lldbPluginDynamicLoaderPOSIX >> +BUILD_ARCHIVE = 1 >> + >> +include $(LLDB_LEVEL)/Makefile >> Index: source/Plugins/Makefile >> =================================================================== >> --- source/Plugins/Makefile (revision 147560) >> +++ source/Plugins/Makefile (working copy) >> @@ -30,7 +30,11 @@ >> endif >> >> ifeq ($(HOST_OS),Linux) >> -DIRS += Process/Linux DynamicLoader/Linux-DYLD >> +DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD >> endif >> >> +ifeq ($(HOST_OS),FreeBSD) >> +DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD >> +endif >> + >> include $(LLDB_LEVEL)/Makefile >> Index: source/Plugins/Process/Linux/ProcessLinux.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy) >> @@ -20,10 +20,10 @@ >> #include "lldb/Target/Target.h" >> >> #include "ProcessLinux.h" >> -#include "ProcessLinuxLog.h" >> +#include "ProcessPOSIXLog.h" >> #include "Plugins/Process/Utility/InferiorCallPOSIX.h" >> #include "ProcessMonitor.h" >> -#include "LinuxThread.h" >> +#include "POSIXThread.h" >> >> using namespace lldb; >> using namespace lldb_private; >> @@ -50,42 +50,21 @@ >> CreateInstance); >> >> Log::Callbacks log_callbacks = { >> - ProcessLinuxLog::DisableLog, >> - ProcessLinuxLog::EnableLog, >> - ProcessLinuxLog::ListLogCategories >> + ProcessPOSIXLog::DisableLog, >> + ProcessPOSIXLog::EnableLog, >> + ProcessPOSIXLog::ListLogCategories >> }; >> >> Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); >> + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); >> } >> } >> >> -void >> -ProcessLinux::Terminate() >> -{ >> -} >> - >> -const char * >> -ProcessLinux::GetPluginNameStatic() >> -{ >> - return "plugin.process.linux"; >> -} >> - >> -const char * >> -ProcessLinux::GetPluginDescriptionStatic() >> -{ >> - return "Process plugin for Linux"; >> -} >> - >> - >> //------------------------------------------------------------------------------ >> // Constructors and destructors. >> >> ProcessLinux::ProcessLinux(Target& target, Listener &listener) >> - : Process(target, listener), >> - m_monitor(NULL), >> - m_module(NULL), >> - m_in_limbo(false), >> - m_exit_now(false) >> + : ProcessPOSIX(target, listener) >> { >> #if 0 >> // FIXME: Putting this code in the ctor and saving the byte order in a >> @@ -98,409 +77,28 @@ >> #endif >> } >> >> -ProcessLinux::~ProcessLinux() >> -{ >> - delete m_monitor; >> -} >> - >> -//------------------------------------------------------------------------------ >> -// Process protocol. >> - >> -bool >> -ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) >> -{ >> - // For now we are just making sure the file exists for a given module >> - ModuleSP exe_module_sp(target.GetExecutableModule()); >> - if (exe_module_sp.get()) >> - return exe_module_sp->GetFileSpec().Exists(); >> - return false; >> -} >> - >> -Error >> -ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid) >> -{ >> - Error error; >> - assert(m_monitor == NULL); >> - >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID()); >> - >> - m_monitor = new ProcessMonitor(this, pid, error); >> - >> - if (!error.Success()) >> - return error; >> - >> - SetID(pid); >> - return error; >> -} >> - >> -Error >> -ProcessLinux::WillLaunch(Module* module) >> -{ >> - Error error; >> - return error; >> -} >> - >> -Error >> -ProcessLinux::DoLaunch (Module *module, >> - const ProcessLaunchInfo &launch_info) >> -{ >> - Error error; >> - assert(m_monitor == NULL); >> - >> - SetPrivateState(eStateLaunching); >> - >> - const char *stdin_path = NULL; >> - const char *stdout_path = NULL; >> - const char *stderr_path = NULL; >> - const char *working_dir = launch_info.GetWorkingDirectory(); >> - >> - const ProcessLaunchInfo::FileAction *file_action; >> - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); >> - if (file_action) >> - { >> - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) >> - stdin_path = file_action->GetPath(); >> - } >> - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); >> - if (file_action) >> - { >> - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) >> - stdout_path = file_action->GetPath(); >> - } >> - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); >> - if (file_action) >> - { >> - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) >> - stderr_path = file_action->GetPath(); >> - } >> - >> - m_monitor = new ProcessMonitor (this, >> - module, >> - launch_info.GetArguments().GetConstArgumentVector(), >> - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), >> - stdin_path, >> - stdout_path, >> - stderr_path, >> - error); >> - >> - m_module = module; >> - >> - if (!error.Success()) >> - return error; >> - >> - SetID(m_monitor->GetPID()); >> - return error; >> -} >> - >> void >> -ProcessLinux::DidLaunch() >> +ProcessLinux::Terminate() >> { >> } >> - >> -Error >> -ProcessLinux::DoResume() >> +const char * >> +ProcessLinux::GetPluginNameStatic() >> { >> - StateType state = GetPrivateState(); >> - >> - assert(state == eStateStopped || state == eStateCrashed); >> - >> - // We are about to resume a thread that will cause the process to exit so >> - // set our exit status now. Do not change our state if the inferior >> - // crashed. >> - if (state == eStateStopped) >> - { >> - if (m_in_limbo) >> - SetExitStatus(m_exit_status, NULL); >> - else >> - SetPrivateState(eStateRunning); >> - } >> - >> - bool did_resume = false; >> - uint32_t thread_count = m_thread_list.GetSize(false); >> - for (uint32_t i = 0; i < thread_count; ++i) >> - { >> - LinuxThread *thread = static_cast( >> - m_thread_list.GetThreadAtIndex(i, false).get()); >> - did_resume = thread->Resume() || did_resume; >> - } >> - assert(did_resume && "Process resume failed!"); >> - >> - return Error(); >> + return "linux"; >> } >> >> -addr_t >> -ProcessLinux::GetImageInfoAddress() >> +const char * >> +ProcessLinux::GetPluginDescriptionStatic() >> { >> - Target *target = &GetTarget(); >> - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); >> - Address addr = obj_file->GetImageInfoAddress(); >> - >> - if (addr.IsValid()) >> - return addr.GetLoadAddress(target); >> - else >> - return LLDB_INVALID_ADDRESS; >> + return "Process plugin for Linux"; >> } >> >> -Error >> -ProcessLinux::DoHalt(bool &caused_stop) >> -{ >> - Error error; >> >> - if (IsStopped()) >> - { >> - caused_stop = false; >> - } >> - else if (kill(GetID(), SIGSTOP)) >> - { >> - caused_stop = false; >> - error.SetErrorToErrno(); >> - } >> - else >> - { >> - caused_stop = true; >> - } >> - >> - return error; >> -} >> - >> -Error >> -ProcessLinux::DoDetach() >> -{ >> - Error error; >> - >> - error = m_monitor->Detach(); >> - if (error.Success()) >> - SetPrivateState(eStateDetached); >> - >> - return error; >> -} >> - >> -Error >> -ProcessLinux::DoSignal(int signal) >> -{ >> - Error error; >> - >> - if (kill(GetID(), signal)) >> - error.SetErrorToErrno(); >> - >> - return error; >> -} >> - >> -Error >> -ProcessLinux::DoDestroy() >> -{ >> - Error error; >> - >> - if (!HasExited()) >> - { >> - // Drive the exit event to completion (do not keep the inferior in >> - // limbo). >> - m_exit_now = true; >> - >> - if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) >> - { >> - error.SetErrorToErrno(); >> - return error; >> - } >> - >> - SetPrivateState(eStateExited); >> - } >> - >> - return error; >> -} >> - >> -void >> -ProcessLinux::SendMessage(const ProcessMessage &message) >> -{ >> - Mutex::Locker lock(m_message_mutex); >> - >> - switch (message.GetKind()) >> - { >> - default: >> - assert(false && "Unexpected process message!"); >> - break; >> - >> - case ProcessMessage::eInvalidMessage: >> - return; >> - >> - case ProcessMessage::eLimboMessage: >> - m_in_limbo = true; >> - m_exit_status = message.GetExitStatus(); >> - if (m_exit_now) >> - { >> - SetPrivateState(eStateExited); >> - m_monitor->Detach(); >> - } >> - else >> - SetPrivateState(eStateStopped); >> - break; >> - >> - case ProcessMessage::eExitMessage: >> - m_exit_status = message.GetExitStatus(); >> - SetExitStatus(m_exit_status, NULL); >> - break; >> - >> - case ProcessMessage::eTraceMessage: >> - case ProcessMessage::eBreakpointMessage: >> - SetPrivateState(eStateStopped); >> - break; >> - >> - case ProcessMessage::eSignalMessage: >> - case ProcessMessage::eSignalDeliveredMessage: >> - SetPrivateState(eStateStopped); >> - break; >> - >> - case ProcessMessage::eCrashMessage: >> - SetPrivateState(eStateCrashed); >> - break; >> - } >> - >> - m_message_queue.push(message); >> -} >> - >> -void >> -ProcessLinux::RefreshStateAfterStop() >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("ProcessLinux::%s()", __FUNCTION__); >> - >> - Mutex::Locker lock(m_message_mutex); >> - if (m_message_queue.empty()) >> - return; >> - >> - ProcessMessage &message = m_message_queue.front(); >> - >> - // Resolve the thread this message corresponds to and pass it along. >> - // FIXME: we're really dealing with the pid here. This should get >> - // fixed when this code is fixed to handle multiple threads. >> - lldb::tid_t tid = message.GetTID(); >> - if (log) >> - log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid); >> - LinuxThread *thread = static_cast( >> - GetThreadList().FindThreadByID(tid, false).get()); >> - >> - assert(thread); >> - thread->Notify(message); >> - >> - m_message_queue.pop(); >> -} >> - >> -bool >> -ProcessLinux::IsAlive() >> -{ >> - StateType state = GetPrivateState(); >> - return state != eStateDetached && state != eStateExited && state != eStateInvalid; >> -} >> - >> -size_t >> -ProcessLinux::DoReadMemory(addr_t vm_addr, >> - void *buf, size_t size, Error &error) >> -{ >> - assert(m_monitor); >> - return m_monitor->ReadMemory(vm_addr, buf, size, error); >> -} >> - >> -size_t >> -ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, >> - Error &error) >> -{ >> - assert(m_monitor); >> - return m_monitor->WriteMemory(vm_addr, buf, size, error); >> -} >> - >> -addr_t >> -ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions, >> - Error &error) >> -{ >> - addr_t allocated_addr = LLDB_INVALID_ADDRESS; >> - >> - unsigned prot = 0; >> - if (permissions & lldb::ePermissionsReadable) >> - prot |= eMmapProtRead; >> - if (permissions & lldb::ePermissionsWritable) >> - prot |= eMmapProtWrite; >> - if (permissions & lldb::ePermissionsExecutable) >> - prot |= eMmapProtExec; >> - >> - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, >> - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { >> - m_addr_to_mmap_size[allocated_addr] = size; >> - error.Clear(); >> - } else { >> - allocated_addr = LLDB_INVALID_ADDRESS; >> - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); >> - } >> - >> - return allocated_addr; >> -} >> - >> -Error >> -ProcessLinux::DoDeallocateMemory(lldb::addr_t addr) >> -{ >> - Error error; >> - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); >> - if (pos != m_addr_to_mmap_size.end() && >> - InferiorCallMunmap(this, addr, pos->second)) >> - m_addr_to_mmap_size.erase (pos); >> - else >> - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); >> - >> - return error; >> -} >> - >> -size_t >> -ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) >> -{ >> - static const uint8_t g_i386_opcode[] = { 0xCC }; >> - >> - ArchSpec arch = GetTarget().GetArchitecture(); >> - const uint8_t *opcode = NULL; >> - size_t opcode_size = 0; >> - >> - switch (arch.GetCore()) >> - { >> - default: >> - assert(false && "CPU type not supported!"); >> - break; >> - >> - case ArchSpec::eCore_x86_32_i386: >> - case ArchSpec::eCore_x86_64_x86_64: >> - opcode = g_i386_opcode; >> - opcode_size = sizeof(g_i386_opcode); >> - break; >> - } >> - >> - bp_site->SetTrapOpcode(opcode, opcode_size); >> - return opcode_size; >> -} >> - >> -Error >> -ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site) >> -{ >> - return EnableSoftwareBreakpoint(bp_site); >> -} >> - >> -Error >> -ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site) >> -{ >> - return DisableSoftwareBreakpoint(bp_site); >> -} >> - >> uint32_t >> -ProcessLinux::UpdateThreadListIfNeeded() >> -{ >> - // Do not allow recursive updates. >> - return m_thread_list.GetSize(false); >> -} >> - >> -uint32_t >> ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) >> { >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID()); >> >> // Update the process thread list with this new thread. >> @@ -508,62 +106,16 @@ >> assert(m_monitor); >> ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); >> if (!thread_sp) >> - thread_sp.reset(new LinuxThread(*this, GetID())); >> + thread_sp.reset(new POSIXThread(*this, GetID())); >> >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID()); >> new_thread_list.AddThread(thread_sp); >> >> return new_thread_list.GetSize(false); >> } >> >> -ByteOrder >> -ProcessLinux::GetByteOrder() const >> -{ >> - // FIXME: We should be able to extract this value directly. See comment in >> - // ProcessLinux(). >> - return m_byte_order; >> -} >> >> -size_t >> -ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error) >> -{ >> - ssize_t status; >> - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) >> - { >> - error.SetErrorToErrno(); >> - return 0; >> - } >> - return status; >> -} >> - >> -size_t >> -ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error) >> -{ >> - ssize_t bytes_read; >> - >> - // The terminal file descriptor is always in non-block mode. >> - if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) >> - { >> - if (errno != EAGAIN) >> - error.SetErrorToErrno(); >> - return 0; >> - } >> - return bytes_read; >> -} >> - >> -size_t >> -ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error) >> -{ >> - return GetSTDOUT(buf, len, error); >> -} >> - >> -UnixSignals & >> -ProcessLinux::GetUnixSignals() >> -{ >> - return m_linux_signals; >> -} >> - >> //------------------------------------------------------------------------------ >> // ProcessInterface protocol. >> >> @@ -601,39 +153,3 @@ >> { >> return NULL; >> } >> - >> -//------------------------------------------------------------------------------ >> -// Utility functions. >> - >> -bool >> -ProcessLinux::HasExited() >> -{ >> - switch (GetPrivateState()) >> - { >> - default: >> - break; >> - >> - case eStateDetached: >> - case eStateExited: >> - return true; >> - } >> - >> - return false; >> -} >> - >> -bool >> -ProcessLinux::IsStopped() >> -{ >> - switch (GetPrivateState()) >> - { >> - default: >> - break; >> - >> - case eStateStopped: >> - case eStateCrashed: >> - case eStateSuspended: >> - return true; >> - } >> - >> - return false; >> -} >> Index: source/Plugins/Process/Linux/ProcessLinuxLog.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessLinuxLog.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessLinuxLog.cpp (working copy) >> @@ -1,193 +0,0 @@ >> -//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -#include "ProcessLinuxLog.h" >> - >> -#include "lldb/Interpreter/Args.h" >> -#include "lldb/Core/StreamFile.h" >> - >> -#include "ProcessLinux.h" >> - >> -using namespace lldb; >> -using namespace lldb_private; >> - >> - >> -// We want to avoid global constructors where code needs to be run so here we >> -// control access to our static g_log_sp by hiding it in a singleton function >> -// that will construct the static g_lob_sp the first time this function is >> -// called. >> -static LogSP & >> -GetLog () >> -{ >> - static LogSP g_log_sp; >> - return g_log_sp; >> -} >> - >> -LogSP >> -ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask) >> -{ >> - LogSP log(GetLog ()); >> - if (log && mask) >> - { >> - uint32_t log_mask = log->GetMask().Get(); >> - if ((log_mask & mask) != mask) >> - return LogSP(); >> - } >> - return log; >> -} >> - >> -void >> -ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm) >> -{ >> - LogSP log (GetLog ()); >> - if (log) >> - { >> - uint32_t flag_bits = 0; >> - >> - const size_t argc = args.GetArgumentCount (); >> - if (argc > 0) >> - { >> - flag_bits = log->GetMask().Get(); >> - for (size_t i = 0; i < argc; ++i) >> - { >> - const char *arg = args.GetArgumentAtIndex (i); >> - >> - >> - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL; >> - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC; >> - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS; >> - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM; >> - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT; >> - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS; >> - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY; >> - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT; >> - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG; >> - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS; >> - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE; >> - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS; >> - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP; >> - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD; >> - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE; >> - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS; >> - else >> - { >> - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); >> - ListLogCategories (feedback_strm); >> - } >> - >> - } >> - } >> - >> - if (flag_bits == 0) >> - GetLog ().reset(); >> - else >> - log->GetMask().Reset (flag_bits); >> - } >> - >> - return; >> -} >> - >> -LogSP >> -ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) >> -{ >> - // Try see if there already is a log - that way we can reuse its settings. >> - // We could reuse the log in toto, but we don't know that the stream is the same. >> - uint32_t flag_bits = 0; >> - LogSP log(GetLog ()); >> - if (log) >> - flag_bits = log->GetMask().Get(); >> - >> - // Now make a new log with this stream if one was provided >> - if (log_stream_sp) >> - { >> - log = make_shared(log_stream_sp); >> - GetLog () = log; >> - } >> - >> - if (log) >> - { >> - bool got_unknown_category = false; >> - const size_t argc = args.GetArgumentCount(); >> - for (size_t i=0; i> - { >> - const char *arg = args.GetArgumentAtIndex(i); >> - >> - if (::strcasecmp (arg, "all") == 0 ) flag_bits |= LINUX_LOG_ALL; >> - else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= LINUX_LOG_ASYNC; >> - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= LINUX_LOG_BREAKPOINTS; >> - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= LINUX_LOG_COMM; >> - else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= LINUX_LOG_DEFAULT; >> - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= LINUX_LOG_PACKETS; >> - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= LINUX_LOG_MEMORY; >> - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_SHORT; >> - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= LINUX_LOG_MEMORY_DATA_LONG; >> - else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= LINUX_LOG_PROCESS; >> - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= LINUX_LOG_PTRACE; >> - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= LINUX_LOG_REGISTERS; >> - else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= LINUX_LOG_STEP; >> - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= LINUX_LOG_THREAD; >> - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= LINUX_LOG_VERBOSE; >> - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= LINUX_LOG_WATCHPOINTS; >> - else >> - { >> - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); >> - if (got_unknown_category == false) >> - { >> - got_unknown_category = true; >> - ListLogCategories (feedback_strm); >> - } >> - } >> - } >> - if (flag_bits == 0) >> - flag_bits = LINUX_LOG_DEFAULT; >> - log->GetMask().Reset(flag_bits); >> - log->GetOptions().Reset(log_options); >> - } >> - return log; >> -} >> - >> -void >> -ProcessLinuxLog::ListLogCategories (Stream *strm) >> -{ >> - strm->Printf ("Logging categories for '%s':\n" >> - " all - turn on all available logging categories\n" >> - " async - log asynchronous activity\n" >> - " break - log breakpoints\n" >> - " communication - log communication activity\n" >> - " default - enable the default set of logging categories for liblldb\n" >> - " packets - log gdb remote packets\n" >> - " memory - log memory reads and writes\n" >> - " data-short - log memory bytes for memory reads and writes for short transactions only\n" >> - " data-long - log memory bytes for memory reads and writes for all transactions\n" >> - " process - log process events and activities\n" >> -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> - " ptrace - log all calls to ptrace\n" >> -#endif >> - " registers - log register read/writes\n" >> - " thread - log thread events and activities\n" >> - " step - log step related activities\n" >> - " verbose - enable verbose logging\n" >> - " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic()); >> -} >> - >> - >> -void >> -ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...) >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask)); >> - if (log) >> - { >> - va_list args; >> - va_start (args, format); >> - log->VAPrintf (format, args); >> - va_end (args); >> - } >> -} >> - >> -int ProcessLinuxLog::m_nestinglevel; >> Index: source/Plugins/Process/Linux/ProcessLinux.h >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessLinux.h (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessLinux.h (working copy) >> @@ -19,11 +19,12 @@ >> #include "lldb/Target/Process.h" >> #include "LinuxSignals.h" >> #include "ProcessMessage.h" >> +#include "ProcessPOSIX.h" >> >> class ProcessMonitor; >> >> class ProcessLinux : >> - public lldb_private::Process >> + public ProcessPOSIX >> { >> public: >> //------------------------------------------------------------------ >> @@ -51,97 +52,8 @@ >> ProcessLinux(lldb_private::Target& target, >> lldb_private::Listener &listener); >> >> - virtual >> - ~ProcessLinux(); >> - >> - //------------------------------------------------------------------ >> - // Process protocol. >> - //------------------------------------------------------------------ >> - virtual bool >> - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); >> - >> - virtual lldb_private::Error >> - WillLaunch(lldb_private::Module *module); >> - >> - virtual lldb_private::Error >> - DoAttachToProcessWithID(lldb::pid_t pid); >> - >> - virtual lldb_private::Error >> - DoLaunch (lldb_private::Module *exe_module, >> - const lldb_private::ProcessLaunchInfo &launch_info); >> - >> - virtual void >> - DidLaunch(); >> - >> - virtual lldb_private::Error >> - DoResume(); >> - >> - virtual lldb_private::Error >> - DoHalt(bool &caused_stop); >> - >> - virtual lldb_private::Error >> - DoDetach(); >> - >> - virtual lldb_private::Error >> - DoSignal(int signal); >> - >> - virtual lldb_private::Error >> - DoDestroy(); >> - >> - virtual void >> - RefreshStateAfterStop(); >> - >> - virtual bool >> - IsAlive(); >> - >> - virtual size_t >> - DoReadMemory(lldb::addr_t vm_addr, >> - void *buf, >> - size_t size, >> - lldb_private::Error &error); >> - >> - virtual size_t >> - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, >> - lldb_private::Error &error); >> - >> - virtual lldb::addr_t >> - DoAllocateMemory(size_t size, uint32_t permissions, >> - lldb_private::Error &error); >> - >> - virtual lldb_private::Error >> - DoDeallocateMemory(lldb::addr_t ptr); >> - >> - virtual size_t >> - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); >> - >> - virtual lldb_private::Error >> - EnableBreakpoint(lldb_private::BreakpointSite *bp_site); >> - >> - virtual lldb_private::Error >> - DisableBreakpoint(lldb_private::BreakpointSite *bp_site); >> - >> virtual uint32_t >> - UpdateThreadListIfNeeded(); >> - >> - uint32_t >> - UpdateThreadList(lldb_private::ThreadList &old_thread_list, >> - lldb_private::ThreadList &new_thread_list); >> - >> - virtual lldb::ByteOrder >> - GetByteOrder() const; >> - >> - virtual lldb::addr_t >> - GetImageInfoAddress(); >> - >> - virtual size_t >> - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); >> - >> - virtual size_t >> - GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); >> - >> - virtual size_t >> - GetSTDERR(char *buf, size_t len, lldb_private::Error &error); >> - >> + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); >> //------------------------------------------------------------------ >> // PluginInterface protocol >> //------------------------------------------------------------------ >> @@ -165,59 +77,11 @@ >> EnablePluginLogging(lldb_private::Stream *strm, >> lldb_private::Args &command); >> >> - //-------------------------------------------------------------------------- >> - // ProcessLinux internal API. >> - >> - /// Registers the given message with this process. >> - void SendMessage(const ProcessMessage &message); >> - >> - ProcessMonitor & >> - GetMonitor() { assert(m_monitor); return *m_monitor; } >> - >> - lldb_private::UnixSignals & >> - GetUnixSignals(); >> - >> private: >> - /// Target byte order. >> - lldb::ByteOrder m_byte_order; >> >> - /// Process monitor; >> - ProcessMonitor *m_monitor; >> - >> - /// The module we are executing. >> - lldb_private::Module *m_module; >> - >> - /// Message queue notifying this instance of inferior process state changes. >> - lldb_private::Mutex m_message_mutex; >> - std::queue m_message_queue; >> - >> - /// True when the process has entered a state of "limbo". >> - /// >> - /// This flag qualifies eStateStopped. It lets us know that when we >> - /// continue from this state the process will exit. Also, when true, >> - /// Process::m_exit_status is set. >> - bool m_in_limbo; >> - >> - /// Drive any exit events to completion. >> - bool m_exit_now; >> - >> /// Linux-specific signal set. >> LinuxSignals m_linux_signals; >> >> - /// Updates the loaded sections provided by the executable. >> - /// >> - /// FIXME: It would probably be better to delegate this task to the >> - /// DynamicLoader plugin, when we have one. >> - void UpdateLoadedSections(); >> - >> - /// Returns true if the process has exited. >> - bool HasExited(); >> - >> - /// Returns true if the process is stopped. >> - bool IsStopped(); >> - >> - typedef std::map MMapMap; >> - MMapMap m_addr_to_mmap_size; >> }; >> >> #endif // liblldb_MacOSXProcess_H_ >> Index: source/Plugins/Process/Linux/ProcessLinuxLog.h >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessLinuxLog.h (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessLinuxLog.h (working copy) >> @@ -1,98 +0,0 @@ >> -//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ >> -#define liblldb_ProcessLinuxLog_h_ >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> - >> -// Project includes >> -#include "lldb/Core/Log.h" >> - >> -#define LINUX_LOG_VERBOSE (1u << 0) >> -#define LINUX_LOG_PROCESS (1u << 1) >> -#define LINUX_LOG_THREAD (1u << 2) >> -#define LINUX_LOG_PACKETS (1u << 3) >> -#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls >> -#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes >> -#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes >> -#define LINUX_LOG_BREAKPOINTS (1u << 7) >> -#define LINUX_LOG_WATCHPOINTS (1u << 8) >> -#define LINUX_LOG_STEP (1u << 9) >> -#define LINUX_LOG_COMM (1u << 10) >> -#define LINUX_LOG_ASYNC (1u << 11) >> -#define LINUX_LOG_PTRACE (1u << 12) >> -#define LINUX_LOG_REGISTERS (1u << 13) >> -#define LINUX_LOG_ALL (UINT32_MAX) >> -#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS >> - >> -// The size which determines "short memory reads/writes". >> -#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) >> - >> -class ProcessLinuxLog >> -{ >> - static int m_nestinglevel; >> - >> -public: >> - static lldb::LogSP >> - GetLogIfAllCategoriesSet(uint32_t mask = 0); >> - >> - static void >> - DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); >> - >> - static lldb::LogSP >> - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, >> - lldb_private::Args &args, lldb_private::Stream *feedback_strm); >> - >> - static void >> - ListLogCategories (lldb_private::Stream *strm); >> - >> - static void >> - LogIf (uint32_t mask, const char *format, ...); >> - >> - // The following functions can be used to enable the client to limit >> - // logging to only the top level function calls. This is useful for >> - // recursive functions. FIXME: not thread safe! >> - // Example: >> - // void NestingFunc() { >> - // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL)); >> - // if (log) >> - // { >> - // ProcessLinuxLog::IncNestLevel(); >> - // if (ProcessLinuxLog::AtTopNestLevel()) >> - // log->Print(msg); >> - // } >> - // NestingFunc(); >> - // if (log) >> - // ProcessLinuxLog::DecNestLevel(); >> - // } >> - >> - static bool >> - AtTopNestLevel() >> - { >> - return m_nestinglevel == 1; >> - } >> - >> - static void >> - IncNestLevel() >> - { >> - ++m_nestinglevel; >> - } >> - >> - static void >> - DecNestLevel() >> - { >> - --m_nestinglevel; >> - assert(m_nestinglevel >= 0); >> - } >> -}; >> - >> -#endif // liblldb_ProcessLinuxLog_h_ >> Index: source/Plugins/Process/Linux/RegisterContextLinux.h >> =================================================================== >> --- source/Plugins/Process/Linux/RegisterContextLinux.h (revision 147560) >> +++ source/Plugins/Process/Linux/RegisterContextLinux.h (working copy) >> @@ -1,40 +0,0 @@ >> -//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -#ifndef liblldb_RegisterContextLinux_H_ >> -#define liblldb_RegisterContextLinux_H_ >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -#include "lldb/Target/RegisterContext.h" >> - >> -//------------------------------------------------------------------------------ >> -/// @class RegisterContextLinux >> -/// >> -/// @brief Extends RegisterClass with a few virtual operations useful on Linux. >> -class RegisterContextLinux >> - : public lldb_private::RegisterContext >> -{ >> -public: >> - RegisterContextLinux(lldb_private::Thread &thread, >> - uint32_t concrete_frame_idx) >> - : RegisterContext(thread, concrete_frame_idx) { } >> - >> - /// Updates the register state of the associated thread after hitting a >> - /// breakpoint (if that make sense for the architecture). Default >> - /// implementation simply returns true for architectures which do not >> - /// require any update. >> - /// >> - /// @return >> - /// True if the operation succeeded and false otherwise. >> - virtual bool UpdateAfterBreakpoint() { return true; } >> -}; >> - >> -#endif // #ifndef liblldb_RegisterContextLinux_H_ >> Index: source/Plugins/Process/Linux/LinuxStopInfo.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/LinuxStopInfo.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/LinuxStopInfo.cpp (working copy) >> @@ -1,60 +0,0 @@ >> -//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -#include "LinuxStopInfo.h" >> - >> -using namespace lldb; >> -using namespace lldb_private; >> - >> - >> -//===----------------------------------------------------------------------===// >> -// LinuxLimboStopInfo >> - >> -LinuxLimboStopInfo::~LinuxLimboStopInfo() { } >> - >> -lldb::StopReason >> -LinuxLimboStopInfo::GetStopReason() const >> -{ >> - return lldb::eStopReasonTrace; >> -} >> - >> -const char * >> -LinuxLimboStopInfo::GetDescription() >> -{ >> - return "thread exiting"; >> -} >> - >> -bool >> -LinuxLimboStopInfo::ShouldStop(Event *event_ptr) >> -{ >> - return true; >> -} >> - >> -bool >> -LinuxLimboStopInfo::ShouldNotify(Event *event_ptr) >> -{ >> - return true; >> -} >> - >> -//===----------------------------------------------------------------------===// >> -// LinuxCrashStopInfo >> - >> -LinuxCrashStopInfo::~LinuxCrashStopInfo() { } >> - >> -lldb::StopReason >> -LinuxCrashStopInfo::GetStopReason() const >> -{ >> - return lldb::eStopReasonException; >> -} >> - >> -const char * >> -LinuxCrashStopInfo::GetDescription() >> -{ >> - return ProcessMessage::GetCrashReasonString(m_crash_reason); >> -} >> Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (working copy) >> @@ -1,650 +0,0 @@ >> -//===-- RegisterContextLinux_i386.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/Core/DataExtractor.h" >> -#include "lldb/Target/Thread.h" >> -#include "lldb/Host/Endian.h" >> - >> -#include "ProcessLinux.h" >> -#include "ProcessLinuxLog.h" >> -#include "ProcessMonitor.h" >> -#include "RegisterContextLinux_i386.h" >> - >> -using namespace lldb_private; >> -using namespace lldb; >> - >> -enum >> -{ >> - k_first_gpr, >> - gpr_eax = k_first_gpr, >> - gpr_ebx, >> - gpr_ecx, >> - gpr_edx, >> - gpr_edi, >> - gpr_esi, >> - gpr_ebp, >> - gpr_esp, >> - gpr_ss, >> - gpr_eflags, >> - gpr_eip, >> - gpr_cs, >> - gpr_ds, >> - gpr_es, >> - gpr_fs, >> - gpr_gs, >> - k_last_gpr = gpr_gs, >> - >> - k_first_fpr, >> - fpu_fcw = k_first_fpr, >> - fpu_fsw, >> - fpu_ftw, >> - fpu_fop, >> - fpu_ip, >> - fpu_cs, >> - fpu_foo, >> - fpu_fos, >> - fpu_mxcsr, >> - fpu_stmm0, >> - fpu_stmm1, >> - fpu_stmm2, >> - fpu_stmm3, >> - fpu_stmm4, >> - fpu_stmm5, >> - fpu_stmm6, >> - fpu_stmm7, >> - fpu_xmm0, >> - fpu_xmm1, >> - fpu_xmm2, >> - fpu_xmm3, >> - fpu_xmm4, >> - fpu_xmm5, >> - fpu_xmm6, >> - fpu_xmm7, >> - k_last_fpr = fpu_xmm7, >> - >> - k_num_registers, >> - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, >> - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 >> -}; >> - >> -// Number of register sets provided by this context. >> -enum >> -{ >> - k_num_register_sets = 2 >> -}; >> - >> -enum >> -{ >> - gcc_eax = 0, >> - gcc_ecx, >> - gcc_edx, >> - gcc_ebx, >> - gcc_ebp, >> - gcc_esp, >> - gcc_esi, >> - gcc_edi, >> - gcc_eip, >> - gcc_eflags >> -}; >> - >> -enum >> -{ >> - dwarf_eax = 0, >> - dwarf_ecx, >> - dwarf_edx, >> - dwarf_ebx, >> - dwarf_esp, >> - dwarf_ebp, >> - dwarf_esi, >> - dwarf_edi, >> - dwarf_eip, >> - dwarf_eflags, >> - dwarf_stmm0 = 11, >> - dwarf_stmm1, >> - dwarf_stmm2, >> - dwarf_stmm3, >> - dwarf_stmm4, >> - dwarf_stmm5, >> - dwarf_stmm6, >> - dwarf_stmm7, >> - dwarf_xmm0 = 21, >> - dwarf_xmm1, >> - dwarf_xmm2, >> - dwarf_xmm3, >> - dwarf_xmm4, >> - dwarf_xmm5, >> - dwarf_xmm6, >> - dwarf_xmm7 >> -}; >> - >> -enum >> -{ >> - gdb_eax = 0, >> - gdb_ecx = 1, >> - gdb_edx = 2, >> - gdb_ebx = 3, >> - gdb_esp = 4, >> - gdb_ebp = 5, >> - gdb_esi = 6, >> - gdb_edi = 7, >> - gdb_eip = 8, >> - gdb_eflags = 9, >> - gdb_cs = 10, >> - gdb_ss = 11, >> - gdb_ds = 12, >> - gdb_es = 13, >> - gdb_fs = 14, >> - gdb_gs = 15, >> - gdb_stmm0 = 16, >> - gdb_stmm1 = 17, >> - gdb_stmm2 = 18, >> - gdb_stmm3 = 19, >> - gdb_stmm4 = 20, >> - gdb_stmm5 = 21, >> - gdb_stmm6 = 22, >> - gdb_stmm7 = 23, >> - gdb_fcw = 24, >> - gdb_fsw = 25, >> - gdb_ftw = 26, >> - gdb_fpu_cs = 27, >> - gdb_ip = 28, >> - gdb_fpu_ds = 29, >> - gdb_dp = 30, >> - gdb_fop = 31, >> - gdb_xmm0 = 32, >> - gdb_xmm1 = 33, >> - gdb_xmm2 = 34, >> - gdb_xmm3 = 35, >> - gdb_xmm4 = 36, >> - gdb_xmm5 = 37, >> - gdb_xmm6 = 38, >> - gdb_xmm7 = 39, >> - gdb_mxcsr = 40, >> - gdb_mm0 = 41, >> - gdb_mm1 = 42, >> - gdb_mm2 = 43, >> - gdb_mm3 = 44, >> - gdb_mm4 = 45, >> - gdb_mm5 = 46, >> - gdb_mm6 = 47, >> - gdb_mm7 = 48 >> -}; >> - >> -static const >> -uint32_t g_gpr_regnums[k_num_gpr_registers] = >> -{ >> - gpr_eax, >> - gpr_ebx, >> - gpr_ecx, >> - gpr_edx, >> - gpr_edi, >> - gpr_esi, >> - gpr_ebp, >> - gpr_esp, >> - gpr_ss, >> - gpr_eflags, >> - gpr_eip, >> - gpr_cs, >> - gpr_ds, >> - gpr_es, >> - gpr_fs, >> - gpr_gs, >> -}; >> - >> -static const uint32_t >> -g_fpu_regnums[k_num_fpu_registers] = >> -{ >> - fpu_fcw, >> - fpu_fsw, >> - fpu_ftw, >> - fpu_fop, >> - fpu_ip, >> - fpu_cs, >> - fpu_foo, >> - fpu_fos, >> - fpu_mxcsr, >> - fpu_stmm0, >> - fpu_stmm1, >> - fpu_stmm2, >> - fpu_stmm3, >> - fpu_stmm4, >> - fpu_stmm5, >> - fpu_stmm6, >> - fpu_stmm7, >> - fpu_xmm0, >> - fpu_xmm1, >> - fpu_xmm2, >> - fpu_xmm3, >> - fpu_xmm4, >> - fpu_xmm5, >> - fpu_xmm6, >> - fpu_xmm7, >> -}; >> - >> -static const RegisterSet >> -g_reg_sets[k_num_register_sets] = >> -{ >> - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, >> - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } >> -}; >> - >> -// Computes the offset of the given GPR in the user data area. >> -#define GPR_OFFSET(regname) \ >> - (offsetof(RegisterContextLinux_i386::UserArea, regs) + \ >> - offsetof(RegisterContextLinux_i386::GPR, regname)) >> - >> -// Computes the offset of the given FPR in the user data area. >> -#define FPR_OFFSET(regname) \ >> - (offsetof(RegisterContextLinux_i386::UserArea, i387) + \ >> - offsetof(RegisterContextLinux_i386::FPU, regname)) >> - >> -// Number of bytes needed to represent a GPR. >> -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg) >> - >> -// Number of bytes needed to represent a FPR. >> -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg) >> - >> -// Number of bytes needed to represent the i'th FP register. >> -#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes) >> - >> -// Number of bytes needed to represent an XMM register. >> -#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg) >> - >> -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ >> - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ >> - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } >> - >> -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ >> - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ >> - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } >> - >> -#define DEFINE_FP(reg, i) \ >> - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> - eFormatVectorOfUInt8, \ >> - { dwarf_##reg##i, dwarf_##reg##i, \ >> - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } >> - >> -#define DEFINE_XMM(reg, i) \ >> - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> - eFormatVectorOfUInt8, \ >> - { dwarf_##reg##i, dwarf_##reg##i, \ >> - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } >> - >> -static RegisterInfo >> -g_register_infos[k_num_registers] = >> -{ >> - // General purpose registers. >> - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), >> - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), >> - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), >> - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), >> - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), >> - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), >> - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), >> - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), >> - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), >> - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), >> - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), >> - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), >> - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), >> - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), >> - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), >> - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), >> - >> - // Floating point registers. >> - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), >> - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), >> - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), >> - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), >> - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), >> - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), >> - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), >> - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), >> - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), >> - >> - DEFINE_FP(stmm, 0), >> - DEFINE_FP(stmm, 1), >> - DEFINE_FP(stmm, 2), >> - DEFINE_FP(stmm, 3), >> - DEFINE_FP(stmm, 4), >> - DEFINE_FP(stmm, 5), >> - DEFINE_FP(stmm, 6), >> - DEFINE_FP(stmm, 7), >> - >> - // XMM registers >> - DEFINE_XMM(xmm, 0), >> - DEFINE_XMM(xmm, 1), >> - DEFINE_XMM(xmm, 2), >> - DEFINE_XMM(xmm, 3), >> - DEFINE_XMM(xmm, 4), >> - DEFINE_XMM(xmm, 5), >> - DEFINE_XMM(xmm, 6), >> - DEFINE_XMM(xmm, 7), >> - >> -}; >> - >> -#ifndef NDEBUG >> -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); >> -#endif >> - >> -static unsigned GetRegOffset(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register number."); >> - return g_register_infos[reg].byte_offset; >> -} >> - >> -#if 0 // These functions are currently not in use. >> -static unsigned GetRegSize(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register number."); >> - return g_register_infos[reg].byte_size; >> -} >> - >> -static bool IsGPR(unsigned reg) >> -{ >> - return reg <= k_last_gpr; // GPR's come first. >> -} >> - >> -static bool IsFPR(unsigned reg) >> -{ >> - return (k_first_fpr <= reg && reg <= k_last_fpr); >> -} >> -#endif >> - >> - >> -RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread, >> - uint32_t concrete_frame_idx) >> - : RegisterContextLinux(thread, concrete_frame_idx) >> -{ >> -} >> - >> -RegisterContextLinux_i386::~RegisterContextLinux_i386() >> -{ >> -} >> - >> -ProcessMonitor & >> -RegisterContextLinux_i386::GetMonitor() >> -{ >> - ProcessLinux *process = static_cast(CalculateProcess()); >> - return process->GetMonitor(); >> -} >> - >> -void >> -RegisterContextLinux_i386::Invalidate() >> -{ >> -} >> - >> -void >> -RegisterContextLinux_i386::InvalidateAllRegisters() >> -{ >> -} >> - >> -size_t >> -RegisterContextLinux_i386::GetRegisterCount() >> -{ >> - assert(k_num_register_infos == k_num_registers); >> - return k_num_registers; >> -} >> - >> -const RegisterInfo * >> -RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg) >> -{ >> - assert(k_num_register_infos == k_num_registers); >> - if (reg < k_num_registers) >> - return &g_register_infos[reg]; >> - else >> - return NULL; >> -} >> - >> -size_t >> -RegisterContextLinux_i386::GetRegisterSetCount() >> -{ >> - return k_num_register_sets; >> -} >> - >> -const RegisterSet * >> -RegisterContextLinux_i386::GetRegisterSet(uint32_t set) >> -{ >> - if (set < k_num_register_sets) >> - return &g_reg_sets[set]; >> - else >> - return NULL; >> -} >> - >> -unsigned >> -RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset) >> -{ >> - unsigned reg; >> - for (reg = 0; reg < k_num_registers; reg++) >> - { >> - if (g_register_infos[reg].byte_offset == offset) >> - break; >> - } >> - assert(reg < k_num_registers && "Invalid register offset."); >> - return reg; >> -} >> - >> -const char * >> -RegisterContextLinux_i386::GetRegisterName(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register offset."); >> - return g_register_infos[reg].name; >> -} >> - >> -bool >> -RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info, >> - RegisterValue &value) >> -{ >> - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.ReadRegisterValue(GetRegOffset(reg), value); >> -} >> - >> -bool >> -RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp) >> -{ >> - return false; >> -} >> - >> -bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info, >> - const RegisterValue &value) >> -{ >> - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.WriteRegisterValue(GetRegOffset(reg), value); >> -} >> - >> -bool >> -RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data) >> -{ >> - return false; >> -} >> - >> -bool >> -RegisterContextLinux_i386::UpdateAfterBreakpoint() >> -{ >> - // PC points one byte past the int3 responsible for the breakpoint. >> - lldb::addr_t pc; >> - >> - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) >> - return false; >> - >> - SetPC(pc - 1); >> - return true; >> -} >> - >> -uint32_t >> -RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, >> - uint32_t num) >> -{ >> - if (kind == eRegisterKindGeneric) >> - { >> - switch (num) >> - { >> - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; >> - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; >> - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; >> - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; >> - case LLDB_REGNUM_GENERIC_RA: >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - >> - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) >> - { >> - switch (num) >> - { >> - case dwarf_eax: return gpr_eax; >> - case dwarf_edx: return gpr_edx; >> - case dwarf_ecx: return gpr_ecx; >> - case dwarf_ebx: return gpr_ebx; >> - case dwarf_esi: return gpr_esi; >> - case dwarf_edi: return gpr_edi; >> - case dwarf_ebp: return gpr_ebp; >> - case dwarf_esp: return gpr_esp; >> - case dwarf_eip: return gpr_eip; >> - case dwarf_xmm0: return fpu_xmm0; >> - case dwarf_xmm1: return fpu_xmm1; >> - case dwarf_xmm2: return fpu_xmm2; >> - case dwarf_xmm3: return fpu_xmm3; >> - case dwarf_xmm4: return fpu_xmm4; >> - case dwarf_xmm5: return fpu_xmm5; >> - case dwarf_xmm6: return fpu_xmm6; >> - case dwarf_xmm7: return fpu_xmm7; >> - case dwarf_stmm0: return fpu_stmm0; >> - case dwarf_stmm1: return fpu_stmm1; >> - case dwarf_stmm2: return fpu_stmm2; >> - case dwarf_stmm3: return fpu_stmm3; >> - case dwarf_stmm4: return fpu_stmm4; >> - case dwarf_stmm5: return fpu_stmm5; >> - case dwarf_stmm6: return fpu_stmm6; >> - case dwarf_stmm7: return fpu_stmm7; >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - >> - if (kind == eRegisterKindGDB) >> - { >> - switch (num) >> - { >> - case gdb_eax : return gpr_eax; >> - case gdb_ebx : return gpr_ebx; >> - case gdb_ecx : return gpr_ecx; >> - case gdb_edx : return gpr_edx; >> - case gdb_esi : return gpr_esi; >> - case gdb_edi : return gpr_edi; >> - case gdb_ebp : return gpr_ebp; >> - case gdb_esp : return gpr_esp; >> - case gdb_eip : return gpr_eip; >> - case gdb_eflags : return gpr_eflags; >> - case gdb_cs : return gpr_cs; >> - case gdb_ss : return gpr_ss; >> - case gdb_ds : return gpr_ds; >> - case gdb_es : return gpr_es; >> - case gdb_fs : return gpr_fs; >> - case gdb_gs : return gpr_gs; >> - case gdb_stmm0 : return fpu_stmm0; >> - case gdb_stmm1 : return fpu_stmm1; >> - case gdb_stmm2 : return fpu_stmm2; >> - case gdb_stmm3 : return fpu_stmm3; >> - case gdb_stmm4 : return fpu_stmm4; >> - case gdb_stmm5 : return fpu_stmm5; >> - case gdb_stmm6 : return fpu_stmm6; >> - case gdb_stmm7 : return fpu_stmm7; >> - case gdb_fcw : return fpu_fcw; >> - case gdb_fsw : return fpu_fsw; >> - case gdb_ftw : return fpu_ftw; >> - case gdb_fpu_cs : return fpu_cs; >> - case gdb_ip : return fpu_ip; >> - case gdb_fpu_ds : return fpu_fos; >> - case gdb_dp : return fpu_foo; >> - case gdb_fop : return fpu_fop; >> - case gdb_xmm0 : return fpu_xmm0; >> - case gdb_xmm1 : return fpu_xmm1; >> - case gdb_xmm2 : return fpu_xmm2; >> - case gdb_xmm3 : return fpu_xmm3; >> - case gdb_xmm4 : return fpu_xmm4; >> - case gdb_xmm5 : return fpu_xmm5; >> - case gdb_xmm6 : return fpu_xmm6; >> - case gdb_xmm7 : return fpu_xmm7; >> - case gdb_mxcsr : return fpu_mxcsr; >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - else if (kind == eRegisterKindLLDB) >> - { >> - return num; >> - } >> - >> - return LLDB_INVALID_REGNUM; >> -} >> - >> -bool >> -RegisterContextLinux_i386::HardwareSingleStep(bool enable) >> -{ >> - enum { TRACE_BIT = 0x100 }; >> - uint64_t eflags; >> - >> - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) >> - return false; >> - >> - if (enable) >> - { >> - if (eflags & TRACE_BIT) >> - return true; >> - >> - eflags |= TRACE_BIT; >> - } >> - else >> - { >> - if (!(eflags & TRACE_BIT)) >> - return false; >> - >> - eflags &= ~TRACE_BIT; >> - } >> - >> - return WriteRegisterFromUnsigned(gpr_eflags, eflags); >> -} >> - >> -void >> -RegisterContextLinux_i386::LogGPR(const char *title) >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); >> - if (log) >> - { >> - if (title) >> - log->Printf ("%s", title); >> - for (uint32_t i=0; i> - { >> - uint32_t reg = gpr_eax + i; >> - log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); >> - } >> - } >> -} >> - >> -bool >> -RegisterContextLinux_i386::ReadGPR() >> -{ >> - bool result; >> - >> - ProcessMonitor &monitor = GetMonitor(); >> - result = monitor.ReadGPR(&user.regs); >> - LogGPR("RegisterContextLinux_i386::ReadGPR()"); >> - return result; >> -} >> - >> -bool >> -RegisterContextLinux_i386::ReadFPR() >> -{ >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.ReadFPR(&user.i387); >> -} >> Index: source/Plugins/Process/Linux/ProcessMessage.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessMessage.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessMessage.cpp (working copy) >> @@ -1,245 +0,0 @@ >> -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -#include "ProcessMessage.h" >> - >> -using namespace lldb_private; >> - >> -const char * >> -ProcessMessage::GetCrashReasonString(CrashReason reason) >> -{ >> - const char *str = NULL; >> - >> - switch (reason) >> - { >> - default: >> - assert(false && "invalid CrashReason"); >> - break; >> - >> - case eInvalidAddress: >> - str = "invalid address"; >> - break; >> - case ePrivilegedAddress: >> - str = "address access protected"; >> - break; >> - case eIllegalOpcode: >> - str = "illegal instruction"; >> - break; >> - case eIllegalOperand: >> - str = "illegal instruction operand"; >> - break; >> - case eIllegalAddressingMode: >> - str = "illegal addressing mode"; >> - break; >> - case eIllegalTrap: >> - str = "illegal trap"; >> - break; >> - case ePrivilegedOpcode: >> - str = "privileged instruction"; >> - break; >> - case ePrivilegedRegister: >> - str = "privileged register"; >> - break; >> - case eCoprocessorError: >> - str = "coprocessor error"; >> - break; >> - case eInternalStackError: >> - str = "internal stack error"; >> - break; >> - case eIllegalAlignment: >> - str = "illegal alignment"; >> - break; >> - case eIllegalAddress: >> - str = "illegal address"; >> - break; >> - case eHardwareError: >> - str = "hardware error"; >> - break; >> - case eIntegerDivideByZero: >> - str = "integer divide by zero"; >> - break; >> - case eIntegerOverflow: >> - str = "integer overflow"; >> - break; >> - case eFloatDivideByZero: >> - str = "floating point divide by zero"; >> - break; >> - case eFloatOverflow: >> - str = "floating point overflow"; >> - break; >> - case eFloatUnderflow: >> - str = "floating point underflow"; >> - break; >> - case eFloatInexactResult: >> - str = "inexact floating point result"; >> - break; >> - case eFloatInvalidOperation: >> - str = "invalid floating point operation"; >> - break; >> - case eFloatSubscriptRange: >> - str = "invalid floating point subscript range"; >> - break; >> - } >> - >> - return str; >> -} >> - >> -const char * >> -ProcessMessage::PrintCrashReason(CrashReason reason) >> -{ >> -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> - // Just return the code in asci for integration builds. >> - chcar str[8]; >> - sprintf(str, "%d", reason); >> -#else >> - const char *str = NULL; >> - >> - switch (reason) >> - { >> - default: >> - assert(false && "invalid CrashReason"); >> - break; >> - >> - case eInvalidCrashReason: >> - str = "eInvalidCrashReason"; >> - break; >> - >> - // SIGSEGV crash rcase easons. >> - case eInvalidAddress: >> - str = "eInvalidAddress"; >> - break; >> - case ePrivilegedAddress: >> - str = "ePrivilegedAddress"; >> - break; >> - >> - // SIGILL crash rcase easons. >> - case eIllegalOpcode: >> - str = "eIllegalOpcode"; >> - break; >> - case eIllegalOperand: >> - str = "eIllegalOperand"; >> - break; >> - case eIllegalAddressingMode: >> - str = "eIllegalAddressingMode"; >> - break; >> - case eIllegalTrap: >> - str = "eIllegalTrap"; >> - break; >> - case ePrivilegedOpcode: >> - str = "ePrivilegedOpcode"; >> - break; >> - case ePrivilegedRegister: >> - str = "ePrivilegedRegister"; >> - break; >> - case eCoprocessorError: >> - str = "eCoprocessorError"; >> - break; >> - case eInternalStackError: >> - str = "eInternalStackError"; >> - break; >> - >> - // SIGBUS crash rcase easons: >> - case eIllegalAlignment: >> - str = "eIllegalAlignment"; >> - break; >> - case eIllegalAddress: >> - str = "eIllegalAddress"; >> - break; >> - case eHardwareError: >> - str = "eHardwareError"; >> - break; >> - >> - // SIGFPE crash rcase easons: >> - case eIntegerDivideByZero: >> - str = "eIntegerDivideByZero"; >> - break; >> - case eIntegerOverflow: >> - str = "eIntegerOverflow"; >> - break; >> - case eFloatDivideByZero: >> - str = "eFloatDivideByZero"; >> - break; >> - case eFloatOverflow: >> - str = "eFloatOverflow"; >> - break; >> - case eFloatUnderflow: >> - str = "eFloatUnderflow"; >> - break; >> - case eFloatInexactResult: >> - str = "eFloatInexactResult"; >> - break; >> - case eFloatInvalidOperation: >> - str = "eFloatInvalidOperation"; >> - break; >> - case eFloatSubscriptRange: >> - str = "eFloatSubscriptRange"; >> - break; >> - } >> -#endif >> - >> - return str; >> -} >> - >> -const char * >> -ProcessMessage::PrintCrashReason() const >> -{ >> - return PrintCrashReason(m_crash_reason); >> -} >> - >> -const char * >> -ProcessMessage::PrintKind(Kind kind) >> -{ >> -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> - // Just return the code in asci for integration builds. >> - chcar str[8]; >> - sprintf(str, "%d", reason); >> -#else >> - const char *str = NULL; >> - >> - switch (kind) >> - { >> - default: >> - assert(false && "invalid Kind"); >> - break; >> - >> - case eInvalidMessage: >> - str = "eInvalidMessage"; >> - break; >> - case eExitMessage: >> - str = "eExitMessage"; >> - break; >> - case eLimboMessage: >> - str = "eLimboMessage"; >> - break; >> - case eSignalMessage: >> - str = "eSignalMessage"; >> - break; >> - case eSignalDeliveredMessage: >> - str = "eSignalDeliveredMessage"; >> - break; >> - case eTraceMessage: >> - str = "eTraceMessage"; >> - break; >> - case eBreakpointMessage: >> - str = "eBreakpointMessage"; >> - break; >> - case eCrashMessage: >> - str = "eCrashMessage"; >> - break; >> - } >> -#endif >> - >> - return str; >> -} >> - >> -const char * >> -ProcessMessage::PrintKind() const >> -{ >> - return PrintKind(m_kind); >> -} >> Index: source/Plugins/Process/Linux/ProcessMonitor.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy) >> @@ -28,9 +28,9 @@ >> #include "lldb/Target/RegisterContext.h" >> #include "lldb/Utility/PseudoTerminal.h" >> >> -#include "LinuxThread.h" >> +#include "POSIXThread.h" >> #include "ProcessLinux.h" >> -#include "ProcessLinuxLog.h" >> +#include "ProcessPOSIXLog.h" >> #include "ProcessMonitor.h" >> >> >> @@ -63,8 +63,8 @@ >> static void PtraceDisplayBytes(__ptrace_request &req, void *data) >> { >> StreamString buf; >> - LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet ( >> - LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE)); >> + LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( >> + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); >> >> if (verbose_log) >> { >> @@ -120,7 +120,7 @@ >> { >> long int result; >> >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); >> >> if (log) >> log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d", >> @@ -170,10 +170,10 @@ >> size_t remainder; >> long data; >> >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); >> if (log) >> - ProcessLinuxLog::IncNestLevel(); >> - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) >> + ProcessPOSIXLog::IncNestLevel(); >> + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) >> log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, >> pid, word_size, (void*)vm_addr, buf, size); >> >> @@ -187,7 +187,7 @@ >> { >> error.SetErrorToErrno(); >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_read; >> } >> >> @@ -200,10 +200,10 @@ >> for (unsigned i = 0; i < remainder; ++i) >> dst[i] = ((data >> i*8) & 0xFF); >> >> - if (log && ProcessLinuxLog::AtTopNestLevel() && >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && >> - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) >> + if (log && ProcessPOSIXLog::AtTopNestLevel() && >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && >> + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) >> log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, >> (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data); >> >> @@ -212,7 +212,7 @@ >> } >> >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_read; >> } >> >> @@ -224,10 +224,10 @@ >> size_t bytes_written = 0; >> size_t remainder; >> >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); >> if (log) >> - ProcessLinuxLog::IncNestLevel(); >> - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) >> + ProcessPOSIXLog::IncNestLevel(); >> + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) >> log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, >> pid, word_size, (void*)vm_addr, buf, size); >> >> @@ -244,10 +244,10 @@ >> for (unsigned i = 0; i < word_size; ++i) >> data |= (unsigned long)src[i] << i*8; >> >> - if (log && ProcessLinuxLog::AtTopNestLevel() && >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && >> - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) >> + if (log && ProcessPOSIXLog::AtTopNestLevel() && >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && >> + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) >> log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, >> (void*)vm_addr, *(unsigned long*)src, data); >> >> @@ -255,7 +255,7 @@ >> { >> error.SetErrorToErrno(); >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_written; >> } >> } >> @@ -266,7 +266,7 @@ >> buff, word_size, error) != word_size) >> { >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_written; >> } >> >> @@ -276,14 +276,14 @@ >> buff, word_size, error) != word_size) >> { >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_written; >> } >> >> - if (log && ProcessLinuxLog::AtTopNestLevel() && >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || >> - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && >> - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) >> + if (log && ProcessPOSIXLog::AtTopNestLevel() && >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || >> + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && >> + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) >> log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, >> (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); >> } >> @@ -292,7 +292,7 @@ >> src += word_size; >> } >> if (log) >> - ProcessLinuxLog::DecNestLevel(); >> + ProcessPOSIXLog::DecNestLevel(); >> return bytes_written; >> } >> >> @@ -420,7 +420,7 @@ >> ReadRegOperation::Execute(ProcessMonitor *monitor) >> { >> lldb::pid_t pid = monitor->GetPID(); >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); >> >> // Set errno to zero so that we can detect a failed peek. >> errno = 0; >> @@ -434,7 +434,7 @@ >> } >> if (log) >> log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__, >> - LinuxThread::GetRegisterNameFromOffset(m_offset), data); >> + POSIXThread::GetRegisterNameFromOffset(m_offset), data); >> } >> >> //------------------------------------------------------------------------------ >> @@ -460,7 +460,7 @@ >> { >> void* buf; >> lldb::pid_t pid = monitor->GetPID(); >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); >> >> if (sizeof(void*) == sizeof(uint64_t)) >> buf = (void*) m_value.GetAsUInt64(); >> @@ -472,7 +472,7 @@ >> >> if (log) >> log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, >> - LinuxThread::GetRegisterNameFromOffset(m_offset), buf); >> + POSIXThread::GetRegisterNameFromOffset(m_offset), buf); >> if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf)) >> m_result = false; >> else >> @@ -794,7 +794,7 @@ >> /// launching or attaching to the inferior process, and then 2) servicing >> /// operations such as register reads/writes, stepping, etc. See the comments >> /// on the Operation class for more info as to why this is needed. >> -ProcessMonitor::ProcessMonitor(ProcessLinux *process, >> +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, >> Module *module, >> const char *argv[], >> const char *envp[], >> @@ -802,7 +802,7 @@ >> const char *stdout_path, >> const char *stderr_path, >> lldb_private::Error &error) >> - : m_process(process), >> + : m_process(static_cast(process)), >> m_operation_thread(LLDB_INVALID_HOST_THREAD), >> m_pid(LLDB_INVALID_PROCESS_ID), >> m_terminal_fd(-1), >> @@ -858,10 +858,10 @@ >> } >> } >> >> -ProcessMonitor::ProcessMonitor(ProcessLinux *process, >> +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, >> lldb::pid_t pid, >> lldb_private::Error &error) >> - : m_process(process), >> + : m_process(static_cast(process)), >> m_operation_thread(LLDB_INVALID_HOST_THREAD), >> m_pid(LLDB_INVALID_PROCESS_ID), >> m_terminal_fd(-1), >> @@ -978,7 +978,7 @@ >> lldb::pid_t pid; >> >> lldb::ThreadSP inferior; >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); >> >> // Propagate the environment if one is not supplied. >> if (envp == NULL || envp[0] == NULL) >> @@ -1101,11 +1101,10 @@ >> if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) >> goto FINISH; >> >> - // Update the process thread list with this new thread and mark it as >> - // current. >> + // Update the process thread list with this new thread. >> // FIXME: should we be letting UpdateThreadList handle this? >> // FIXME: by using pids instead of tids, we can only support one thread. >> - inferior.reset(new LinuxThread(process, pid)); >> + inferior.reset(new POSIXThread(process, pid)); >> if (log) >> log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid); >> process.GetThreadList().AddThread(inferior); >> @@ -1167,9 +1166,8 @@ >> >> ProcessMonitor *monitor = args->m_monitor; >> ProcessLinux &process = monitor->GetProcess(); >> - >> lldb::ThreadSP inferior; >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); >> >> if (pid <= 1) >> { >> @@ -1192,13 +1190,11 @@ >> goto FINISH; >> } >> >> - // Update the process thread list with the attached thread and >> - // mark it as current. >> - inferior.reset(new LinuxThread(process, pid)); >> + // Update the process thread list with the attached thread. >> + inferior.reset(new POSIXThread(process, pid)); >> if (log) >> log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid); >> process.GetThreadList().AddThread(inferior); >> - process.GetThreadList().SetSelectedThreadByID(pid); >> >> // Let our process instance know the thread has stopped. >> process.SendMessage(ProcessMessage::Trace(pid)); >> @@ -1568,7 +1564,7 @@ >> } >> >> bool >> -ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value) >> +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) >> { >> bool result; >> ReadRegOperation op(offset, value, result); >> Index: source/Plugins/Process/Linux/LinuxStopInfo.h >> =================================================================== >> --- source/Plugins/Process/Linux/LinuxStopInfo.h (revision 147560) >> +++ source/Plugins/Process/Linux/LinuxStopInfo.h (working copy) >> @@ -1,92 +0,0 @@ >> -//===-- LinuxStopInfo.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_LinuxStopInfo_H_ >> -#define liblldb_LinuxStopInfo_H_ >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -// Project includes >> -#include "lldb/Target/StopInfo.h" >> - >> -#include "LinuxThread.h" >> -#include "ProcessMessage.h" >> - >> -//===----------------------------------------------------------------------===// >> -/// @class LinuxStopInfo >> -/// @brief Simple base class for all Linux-specific StopInfo objects. >> -/// >> -class LinuxStopInfo >> - : public lldb_private::StopInfo >> -{ >> -public: >> - LinuxStopInfo(lldb_private::Thread &thread, uint32_t status) >> - : StopInfo(thread, status) >> - { } >> -}; >> - >> -//===----------------------------------------------------------------------===// >> -/// @class LinuxLimboStopInfo >> -/// @brief Represents the stop state of a process ready to exit. >> -/// >> -class LinuxLimboStopInfo >> - : public LinuxStopInfo >> -{ >> -public: >> - LinuxLimboStopInfo(LinuxThread &thread) >> - : LinuxStopInfo(thread, 0) >> - { } >> - >> - ~LinuxLimboStopInfo(); >> - >> - lldb::StopReason >> - GetStopReason() const; >> - >> - const char * >> - GetDescription(); >> - >> - bool >> - ShouldStop(lldb_private::Event *event_ptr); >> - >> - bool >> - ShouldNotify(lldb_private::Event *event_ptr); >> -}; >> - >> - >> -//===----------------------------------------------------------------------===// >> -/// @class LinuxCrashStopInfo >> -/// @brief Represents the stop state of process that is ready to crash. >> -/// >> -class LinuxCrashStopInfo >> - : public LinuxStopInfo >> -{ >> -public: >> - LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, >> - ProcessMessage::CrashReason reason) >> - : LinuxStopInfo(thread, status), >> - m_crash_reason(reason) >> - { } >> - >> - ~LinuxCrashStopInfo(); >> - >> - lldb::StopReason >> - GetStopReason() const; >> - >> - const char * >> - GetDescription(); >> - >> - ProcessMessage::CrashReason >> - GetCrashReason() const; >> - >> -private: >> - ProcessMessage::CrashReason m_crash_reason; >> -}; >> - >> -#endif >> Index: source/Plugins/Process/Linux/LinuxThread.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/LinuxThread.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/LinuxThread.cpp (working copy) >> @@ -1,350 +0,0 @@ >> -//===-- LinuxThread.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 >> - >> -// C++ Includes >> -// Other libraries and framework includes >> -// Project includes >> -#include "lldb/Core/Debugger.h" >> -#include "lldb/Host/Host.h" >> -#include "lldb/Target/Process.h" >> -#include "lldb/Target/StopInfo.h" >> -#include "lldb/Target/Target.h" >> -#include "LinuxStopInfo.h" >> -#include "LinuxThread.h" >> -#include "ProcessLinux.h" >> -#include "ProcessLinuxLog.h" >> -#include "ProcessMonitor.h" >> -#include "RegisterContextLinux_i386.h" >> -#include "RegisterContextLinux_x86_64.h" >> -#include "UnwindLLDB.h" >> - >> -using namespace lldb_private; >> - >> - >> -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) >> - : Thread(process, tid), >> - m_frame_ap(0) >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid); >> -} >> - >> -LinuxThread::~LinuxThread() >> -{ >> - DestroyThread(); >> -} >> - >> -ProcessMonitor & >> -LinuxThread::GetMonitor() >> -{ >> - ProcessLinux &process = static_cast(GetProcess()); >> - return process.GetMonitor(); >> -} >> - >> -void >> -LinuxThread::RefreshStateAfterStop() >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("LinuxThread::%s ()", __FUNCTION__); >> - >> - // Let all threads recover from stopping and do any clean up based >> - // on the previous thread state (if any). >> - ProcessLinux &process = static_cast(GetProcess()); >> - process.GetThreadList().RefreshStateAfterStop(); >> -} >> - >> -const char * >> -LinuxThread::GetInfo() >> -{ >> - return NULL; >> -} >> - >> -lldb::RegisterContextSP >> -LinuxThread::GetRegisterContext() >> -{ >> - if (!m_reg_context_sp) >> - { >> - ArchSpec arch = Host::GetArchitecture(); >> - >> - switch (arch.GetCore()) >> - { >> - default: >> - assert(false && "CPU type not supported!"); >> - break; >> - >> - case ArchSpec::eCore_x86_32_i386: >> - case ArchSpec::eCore_x86_32_i486: >> - case ArchSpec::eCore_x86_32_i486sx: >> - m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); >> - break; >> - >> - case ArchSpec::eCore_x86_64_x86_64: >> - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); >> - break; >> - } >> - } >> - return m_reg_context_sp; >> -} >> - >> -lldb::RegisterContextSP >> -LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) >> -{ >> - lldb::RegisterContextSP reg_ctx_sp; >> - uint32_t concrete_frame_idx = 0; >> - >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("LinuxThread::%s ()", __FUNCTION__); >> - >> - if (frame) >> - concrete_frame_idx = frame->GetConcreteFrameIndex(); >> - >> - if (concrete_frame_idx == 0) >> - reg_ctx_sp = GetRegisterContext(); >> - else >> - { >> - assert(GetUnwinder()); >> - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); >> - } >> - >> - return reg_ctx_sp; >> -} >> - >> -lldb::StopInfoSP >> -LinuxThread::GetPrivateStopReason() >> -{ >> - return m_stop_info; >> -} >> - >> -Unwind * >> -LinuxThread::GetUnwinder() >> -{ >> - if (m_unwinder_ap.get() == NULL) >> - m_unwinder_ap.reset(new UnwindLLDB(*this)); >> - >> - return m_unwinder_ap.get(); >> -} >> - >> -bool >> -LinuxThread::WillResume(lldb::StateType resume_state) >> -{ >> - SetResumeState(resume_state); >> - >> - ClearStackFrames(); >> - if (m_unwinder_ap.get()) >> - m_unwinder_ap->Clear(); >> - >> - return Thread::WillResume(resume_state); >> -} >> - >> -bool >> -LinuxThread::Resume() >> -{ >> - lldb::StateType resume_state = GetResumeState(); >> - ProcessMonitor &monitor = GetMonitor(); >> - bool status; >> - >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) >> - log->Printf ("LinuxThread::%s ()", __FUNCTION__); >> - >> - switch (resume_state) >> - { >> - default: >> - assert(false && "Unexpected state for resume!"); >> - status = false; >> - break; >> - >> - case lldb::eStateRunning: >> - SetState(resume_state); >> - status = monitor.Resume(GetID(), GetResumeSignal()); >> - break; >> - >> - case lldb::eStateStepping: >> - SetState(resume_state); >> - status = monitor.SingleStep(GetID(), GetResumeSignal()); >> - break; >> - } >> - >> - return status; >> -} >> - >> -void >> -LinuxThread::Notify(const ProcessMessage &message) >> -{ >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log) >> - log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); >> - >> - switch (message.GetKind()) >> - { >> - default: >> - assert(false && "Unexpected message kind!"); >> - break; >> - >> - case ProcessMessage::eLimboMessage: >> - LimboNotify(message); >> - break; >> - >> - case ProcessMessage::eSignalMessage: >> - SignalNotify(message); >> - break; >> - >> - case ProcessMessage::eSignalDeliveredMessage: >> - SignalDeliveredNotify(message); >> - break; >> - >> - case ProcessMessage::eTraceMessage: >> - TraceNotify(message); >> - break; >> - >> - case ProcessMessage::eBreakpointMessage: >> - BreakNotify(message); >> - break; >> - >> - case ProcessMessage::eCrashMessage: >> - CrashNotify(message); >> - break; >> - } >> -} >> - >> -void >> -LinuxThread::BreakNotify(const ProcessMessage &message) >> -{ >> - bool status; >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - >> - assert(GetRegisterContextLinux()); >> - status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); >> - assert(status && "Breakpoint update failed!"); >> - >> - // With our register state restored, resolve the breakpoint object >> - // corresponding to our current PC. >> - assert(GetRegisterContext()); >> - lldb::addr_t pc = GetRegisterContext()->GetPC(); >> - if (log) >> - log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); >> - lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); >> - assert(bp_site); >> - lldb::break_id_t bp_id = bp_site->GetID(); >> - assert(bp_site && bp_site->ValidForThisThread(this)); >> - >> - >> - m_breakpoint = bp_site; >> - m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); >> -} >> - >> -void >> -LinuxThread::TraceNotify(const ProcessMessage &message) >> -{ >> - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); >> -} >> - >> -void >> -LinuxThread::LimboNotify(const ProcessMessage &message) >> -{ >> - m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this)); >> -} >> - >> -void >> -LinuxThread::SignalNotify(const ProcessMessage &message) >> -{ >> - int signo = message.GetSignal(); >> - >> - m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); >> - SetResumeSignal(signo); >> -} >> - >> -void >> -LinuxThread::SignalDeliveredNotify(const ProcessMessage &message) >> -{ >> - int signo = message.GetSignal(); >> - >> - // Just treat debugger generated signal events like breakpoints for now. >> - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); >> - SetResumeSignal(signo); >> -} >> - >> -void >> -LinuxThread::CrashNotify(const ProcessMessage &message) >> -{ >> - int signo = message.GetSignal(); >> - >> - assert(message.GetKind() == ProcessMessage::eCrashMessage); >> - >> - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); >> - if (log) >> - log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); >> - >> - m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo( >> - *this, signo, message.GetCrashReason())); >> - SetResumeSignal(signo); >> -} >> - >> -unsigned >> -LinuxThread::GetRegisterIndexFromOffset(unsigned offset) >> -{ >> - unsigned reg; >> - ArchSpec arch = Host::GetArchitecture(); >> - >> - switch (arch.GetCore()) >> - { >> - default: >> - assert(false && "CPU type not supported!"); >> - break; >> - >> - case ArchSpec::eCore_x86_32_i386: >> - case ArchSpec::eCore_x86_32_i486: >> - case ArchSpec::eCore_x86_32_i486sx: >> - reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset); >> - break; >> - >> - case ArchSpec::eCore_x86_64_x86_64: >> - reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset); >> - break; >> - } >> - return reg; >> -} >> - >> -const char * >> -LinuxThread::GetRegisterName(unsigned reg) >> -{ >> - const char * name; >> - ArchSpec arch = Host::GetArchitecture(); >> - >> - switch (arch.GetCore()) >> - { >> - default: >> - assert(false && "CPU type not supported!"); >> - break; >> - >> - case ArchSpec::eCore_x86_32_i386: >> - case ArchSpec::eCore_x86_32_i486: >> - case ArchSpec::eCore_x86_32_i486sx: >> - name = RegisterContextLinux_i386::GetRegisterName(reg); >> - break; >> - >> - case ArchSpec::eCore_x86_64_x86_64: >> - name = RegisterContextLinux_x86_64::GetRegisterName(reg); >> - break; >> - } >> - return name; >> -} >> - >> -const char * >> -LinuxThread::GetRegisterNameFromOffset(unsigned offset) >> -{ >> - return GetRegisterName(GetRegisterIndexFromOffset(offset)); >> -} >> - >> Index: source/Plugins/Process/Linux/RegisterContextLinux_i386.h >> =================================================================== >> --- source/Plugins/Process/Linux/RegisterContextLinux_i386.h (revision 147560) >> +++ source/Plugins/Process/Linux/RegisterContextLinux_i386.h (working copy) >> @@ -1,169 +0,0 @@ >> -//===-- RegisterContextLinux_i386.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_RegisterContextLinux_i386_h_ >> -#define liblldb_RegisterContextLinux_i386_h_ >> - >> -// C Includes >> -// C++ Includes >> -// Other libraries and framework includes >> -// Project includes >> -#include "lldb/Core/Log.h" >> -#include "RegisterContextLinux.h" >> - >> -class RegisterContextLinux_i386 : public RegisterContextLinux >> -{ >> -public: >> - RegisterContextLinux_i386(lldb_private::Thread &thread, >> - uint32_t concreate_frame_idx); >> - >> - ~RegisterContextLinux_i386(); >> - >> - void >> - Invalidate(); >> - >> - void >> - InvalidateAllRegisters(); >> - >> - size_t >> - GetRegisterCount(); >> - >> - const lldb_private::RegisterInfo * >> - GetRegisterInfoAtIndex(uint32_t reg); >> - >> - size_t >> - GetRegisterSetCount(); >> - >> - const lldb_private::RegisterSet * >> - GetRegisterSet(uint32_t set); >> - >> - static unsigned >> - GetRegisterIndexFromOffset(unsigned offset); >> - >> - static const char * >> - GetRegisterName(unsigned reg); >> - >> -#if 0 >> - bool >> - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); >> - >> - bool >> - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); >> -#endif >> - >> - virtual bool >> - ReadRegister(const lldb_private::RegisterInfo *reg_info, >> - lldb_private::RegisterValue &value); >> - >> - bool >> - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); >> - >> -#if 0 >> - bool >> - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); >> - >> - bool >> - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, >> - uint32_t data_offset = 0); >> -#endif >> - >> - virtual bool >> - WriteRegister(const lldb_private::RegisterInfo *reg_info, >> - const lldb_private::RegisterValue &value); >> - >> - bool >> - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); >> - >> - uint32_t >> - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); >> - >> - bool >> - HardwareSingleStep(bool enable); >> - >> - bool >> - UpdateAfterBreakpoint(); >> - >> - struct GPR >> - { >> - uint32_t ebx; >> - uint32_t ecx; >> - uint32_t edx; >> - uint32_t esi; >> - uint32_t edi; >> - uint32_t ebp; >> - uint32_t eax; >> - uint32_t ds; >> - uint32_t es; >> - uint32_t fs; >> - uint32_t gs; >> - uint32_t orig_ax; >> - uint32_t eip; >> - uint32_t cs; >> - uint32_t eflags; >> - uint32_t esp; >> - uint32_t ss; >> - }; >> - >> - struct MMSReg >> - { >> - uint8_t bytes[8]; >> - }; >> - >> - struct XMMReg >> - { >> - uint8_t bytes[16]; >> - }; >> - >> - struct FPU >> - { >> - uint16_t fcw; >> - uint16_t fsw; >> - uint16_t ftw; >> - uint16_t fop; >> - uint32_t ip; >> - uint32_t cs; >> - uint32_t foo; >> - uint32_t fos; >> - uint32_t mxcsr; >> - uint32_t reserved; >> - MMSReg stmm[8]; >> - XMMReg xmm[8]; >> - uint32_t pad[56]; >> - }; >> - >> - struct UserArea >> - { >> - GPR regs; // General purpose registers. >> - int32_t fpvalid; // True if FPU is being used. >> - FPU i387; // FPU registers. >> - uint32_t tsize; // Text segment size. >> - uint32_t dsize; // Data segment size. >> - uint32_t ssize; // Stack segment size. >> - uint32_t start_code; // VM address of text. >> - uint32_t start_stack; // VM address of stack bottom (top in rsp). >> - int32_t signal; // Signal causing core dump. >> - int32_t reserved; // Unused. >> - uint32_t ar0; // Location of GPR's. >> - FPU* fpstate; // Location of FPR's. >> - uint32_t magic; // Identifier for core dumps. >> - char u_comm[32]; // Command causing core dump. >> - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). >> - }; >> -private: >> - UserArea user; >> - >> - ProcessMonitor &GetMonitor(); >> - >> - void LogGPR(const char *title); >> - >> - bool ReadGPR(); >> - bool ReadFPR(); >> -}; >> - >> -#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ >> Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp >> =================================================================== >> --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (revision 147560) >> +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (working copy) >> @@ -1,759 +0,0 @@ >> -//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===// >> -// >> -// The LLVM Compiler Infrastructure >> -// >> -// This file is distributed under the University of Illinois Open Source >> -// License. See LICENSE.TXT for details. >> -// >> -//===----------------------------------------------------------------------===// >> - >> -#include >> -#include >> -#include >> - >> -#include "lldb/Core/DataBufferHeap.h" >> -#include "lldb/Core/DataExtractor.h" >> -#include "lldb/Core/Scalar.h" >> -#include "lldb/Target/Thread.h" >> -#include "lldb/Host/Endian.h" >> - >> -#include "ProcessLinux.h" >> -#include "ProcessMonitor.h" >> -#include "RegisterContextLinux_x86_64.h" >> - >> -using namespace lldb_private; >> -using namespace lldb; >> - >> -// Internal codes for all x86_64 registers. >> -enum >> -{ >> - k_first_gpr, >> - gpr_rax = k_first_gpr, >> - gpr_rbx, >> - gpr_rcx, >> - gpr_rdx, >> - gpr_rdi, >> - gpr_rsi, >> - gpr_rbp, >> - gpr_rsp, >> - gpr_r8, >> - gpr_r9, >> - gpr_r10, >> - gpr_r11, >> - gpr_r12, >> - gpr_r13, >> - gpr_r14, >> - gpr_r15, >> - gpr_rip, >> - gpr_rflags, >> - gpr_cs, >> - gpr_fs, >> - gpr_gs, >> - gpr_ss, >> - gpr_ds, >> - gpr_es, >> - k_last_gpr = gpr_es, >> - >> - k_first_fpr, >> - fpu_fcw = k_first_fpr, >> - fpu_fsw, >> - fpu_ftw, >> - fpu_fop, >> - fpu_ip, >> - fpu_cs, >> - fpu_dp, >> - fpu_ds, >> - fpu_mxcsr, >> - fpu_mxcsrmask, >> - fpu_stmm0, >> - fpu_stmm1, >> - fpu_stmm2, >> - fpu_stmm3, >> - fpu_stmm4, >> - fpu_stmm5, >> - fpu_stmm6, >> - fpu_stmm7, >> - fpu_xmm0, >> - fpu_xmm1, >> - fpu_xmm2, >> - fpu_xmm3, >> - fpu_xmm4, >> - fpu_xmm5, >> - fpu_xmm6, >> - fpu_xmm7, >> - fpu_xmm8, >> - fpu_xmm9, >> - fpu_xmm10, >> - fpu_xmm11, >> - fpu_xmm12, >> - fpu_xmm13, >> - fpu_xmm14, >> - fpu_xmm15, >> - k_last_fpr = fpu_xmm15, >> - >> - k_num_registers, >> - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, >> - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 >> -}; >> - >> -// Number of register sets provided by this context. >> -enum >> -{ >> - k_num_register_sets = 2 >> -}; >> - >> -enum gcc_dwarf_regnums >> -{ >> - gcc_dwarf_gpr_rax = 0, >> - gcc_dwarf_gpr_rdx, >> - gcc_dwarf_gpr_rcx, >> - gcc_dwarf_gpr_rbx, >> - gcc_dwarf_gpr_rsi, >> - gcc_dwarf_gpr_rdi, >> - gcc_dwarf_gpr_rbp, >> - gcc_dwarf_gpr_rsp, >> - gcc_dwarf_gpr_r8, >> - gcc_dwarf_gpr_r9, >> - gcc_dwarf_gpr_r10, >> - gcc_dwarf_gpr_r11, >> - gcc_dwarf_gpr_r12, >> - gcc_dwarf_gpr_r13, >> - gcc_dwarf_gpr_r14, >> - gcc_dwarf_gpr_r15, >> - gcc_dwarf_gpr_rip, >> - gcc_dwarf_fpu_xmm0, >> - gcc_dwarf_fpu_xmm1, >> - gcc_dwarf_fpu_xmm2, >> - gcc_dwarf_fpu_xmm3, >> - gcc_dwarf_fpu_xmm4, >> - gcc_dwarf_fpu_xmm5, >> - gcc_dwarf_fpu_xmm6, >> - gcc_dwarf_fpu_xmm7, >> - gcc_dwarf_fpu_xmm8, >> - gcc_dwarf_fpu_xmm9, >> - gcc_dwarf_fpu_xmm10, >> - gcc_dwarf_fpu_xmm11, >> - gcc_dwarf_fpu_xmm12, >> - gcc_dwarf_fpu_xmm13, >> - gcc_dwarf_fpu_xmm14, >> - gcc_dwarf_fpu_xmm15, >> - gcc_dwarf_fpu_stmm0, >> - gcc_dwarf_fpu_stmm1, >> - gcc_dwarf_fpu_stmm2, >> - gcc_dwarf_fpu_stmm3, >> - gcc_dwarf_fpu_stmm4, >> - gcc_dwarf_fpu_stmm5, >> - gcc_dwarf_fpu_stmm6, >> - gcc_dwarf_fpu_stmm7 >> -}; >> - >> -enum gdb_regnums >> -{ >> - gdb_gpr_rax = 0, >> - gdb_gpr_rbx = 1, >> - gdb_gpr_rcx = 2, >> - gdb_gpr_rdx = 3, >> - gdb_gpr_rsi = 4, >> - gdb_gpr_rdi = 5, >> - gdb_gpr_rbp = 6, >> - gdb_gpr_rsp = 7, >> - gdb_gpr_r8 = 8, >> - gdb_gpr_r9 = 9, >> - gdb_gpr_r10 = 10, >> - gdb_gpr_r11 = 11, >> - gdb_gpr_r12 = 12, >> - gdb_gpr_r13 = 13, >> - gdb_gpr_r14 = 14, >> - gdb_gpr_r15 = 15, >> - gdb_gpr_rip = 16, >> - gdb_gpr_rflags = 17, >> - gdb_gpr_cs = 18, >> - gdb_gpr_ss = 19, >> - gdb_gpr_ds = 20, >> - gdb_gpr_es = 21, >> - gdb_gpr_fs = 22, >> - gdb_gpr_gs = 23, >> - gdb_fpu_stmm0 = 24, >> - gdb_fpu_stmm1 = 25, >> - gdb_fpu_stmm2 = 26, >> - gdb_fpu_stmm3 = 27, >> - gdb_fpu_stmm4 = 28, >> - gdb_fpu_stmm5 = 29, >> - gdb_fpu_stmm6 = 30, >> - gdb_fpu_stmm7 = 31, >> - gdb_fpu_fcw = 32, >> - gdb_fpu_fsw = 33, >> - gdb_fpu_ftw = 34, >> - gdb_fpu_cs = 35, >> - gdb_fpu_ip = 36, >> - gdb_fpu_ds = 37, >> - gdb_fpu_dp = 38, >> - gdb_fpu_fop = 39, >> - gdb_fpu_xmm0 = 40, >> - gdb_fpu_xmm1 = 41, >> - gdb_fpu_xmm2 = 42, >> - gdb_fpu_xmm3 = 43, >> - gdb_fpu_xmm4 = 44, >> - gdb_fpu_xmm5 = 45, >> - gdb_fpu_xmm6 = 46, >> - gdb_fpu_xmm7 = 47, >> - gdb_fpu_xmm8 = 48, >> - gdb_fpu_xmm9 = 49, >> - gdb_fpu_xmm10 = 50, >> - gdb_fpu_xmm11 = 51, >> - gdb_fpu_xmm12 = 52, >> - gdb_fpu_xmm13 = 53, >> - gdb_fpu_xmm14 = 54, >> - gdb_fpu_xmm15 = 55, >> - gdb_fpu_mxcsr = 56 >> -}; >> - >> -static const >> -uint32_t g_gpr_regnums[k_num_gpr_registers] = >> -{ >> - gpr_rax, >> - gpr_rbx, >> - gpr_rcx, >> - gpr_rdx, >> - gpr_rdi, >> - gpr_rsi, >> - gpr_rbp, >> - gpr_rsp, >> - gpr_r8, >> - gpr_r9, >> - gpr_r10, >> - gpr_r11, >> - gpr_r12, >> - gpr_r13, >> - gpr_r14, >> - gpr_r15, >> - gpr_rip, >> - gpr_rflags, >> - gpr_cs, >> - gpr_fs, >> - gpr_gs, >> - gpr_ss, >> - gpr_ds, >> - gpr_es >> -}; >> - >> -static const uint32_t >> -g_fpu_regnums[k_num_fpu_registers] = >> -{ >> - fpu_fcw, >> - fpu_fsw, >> - fpu_ftw, >> - fpu_fop, >> - fpu_ip, >> - fpu_cs, >> - fpu_dp, >> - fpu_ds, >> - fpu_mxcsr, >> - fpu_mxcsrmask, >> - fpu_stmm0, >> - fpu_stmm1, >> - fpu_stmm2, >> - fpu_stmm3, >> - fpu_stmm4, >> - fpu_stmm5, >> - fpu_stmm6, >> - fpu_stmm7, >> - fpu_xmm0, >> - fpu_xmm1, >> - fpu_xmm2, >> - fpu_xmm3, >> - fpu_xmm4, >> - fpu_xmm5, >> - fpu_xmm6, >> - fpu_xmm7, >> - fpu_xmm8, >> - fpu_xmm9, >> - fpu_xmm10, >> - fpu_xmm11, >> - fpu_xmm12, >> - fpu_xmm13, >> - fpu_xmm14, >> - fpu_xmm15 >> -}; >> - >> -static const RegisterSet >> -g_reg_sets[k_num_register_sets] = >> -{ >> - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, >> - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } >> -}; >> - >> -// Computes the offset of the given GPR in the user data area. >> -#define GPR_OFFSET(regname) \ >> - (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \ >> - offsetof(RegisterContextLinux_x86_64::GPR, regname)) >> - >> -// Computes the offset of the given FPR in the user data area. >> -#define FPR_OFFSET(regname) \ >> - (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \ >> - offsetof(RegisterContextLinux_x86_64::FPU, regname)) >> - >> -// Number of bytes needed to represent a GPR. >> -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg) >> - >> -// Number of bytes needed to represent a FPR. >> -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg) >> - >> -// Number of bytes needed to represent the i'th FP register. >> -#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes) >> - >> -// Number of bytes needed to represent an XMM register. >> -#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg) >> - >> -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ >> - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ >> - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } >> - >> -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ >> - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ >> - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } >> - >> -#define DEFINE_FP(reg, i) \ >> - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> - eFormatVectorOfUInt8, \ >> - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ >> - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } >> - >> -#define DEFINE_XMM(reg, i) \ >> - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> - eFormatVectorOfUInt8, \ >> - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ >> - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } >> - >> -#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU)) >> - >> -static RegisterInfo >> -g_register_infos[k_num_registers] = >> -{ >> - // General purpose registers. >> - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), >> - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), >> - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), >> - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), >> - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), >> - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), >> - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), >> - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), >> - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), >> - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), >> - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), >> - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), >> - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), >> - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), >> - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), >> - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), >> - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), >> - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), >> - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), >> - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), >> - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), >> - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), >> - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), >> - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), >> - >> - // i387 Floating point registers. >> - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), >> - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), >> - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), >> - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), >> - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), >> - // FIXME: Extract segment from ip. >> - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), >> - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), >> - // FIXME: Extract segment from dp. >> - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), >> - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), >> - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), >> - >> - // FP registers. >> - DEFINE_FP(stmm, 0), >> - DEFINE_FP(stmm, 1), >> - DEFINE_FP(stmm, 2), >> - DEFINE_FP(stmm, 3), >> - DEFINE_FP(stmm, 4), >> - DEFINE_FP(stmm, 5), >> - DEFINE_FP(stmm, 6), >> - DEFINE_FP(stmm, 7), >> - >> - // XMM registers >> - DEFINE_XMM(xmm, 0), >> - DEFINE_XMM(xmm, 1), >> - DEFINE_XMM(xmm, 2), >> - DEFINE_XMM(xmm, 3), >> - DEFINE_XMM(xmm, 4), >> - DEFINE_XMM(xmm, 5), >> - DEFINE_XMM(xmm, 6), >> - DEFINE_XMM(xmm, 7), >> - DEFINE_XMM(xmm, 8), >> - DEFINE_XMM(xmm, 9), >> - DEFINE_XMM(xmm, 10), >> - DEFINE_XMM(xmm, 11), >> - DEFINE_XMM(xmm, 12), >> - DEFINE_XMM(xmm, 13), >> - DEFINE_XMM(xmm, 14), >> - DEFINE_XMM(xmm, 15) >> -}; >> - >> -static unsigned GetRegOffset(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register number."); >> - return g_register_infos[reg].byte_offset; >> -} >> - >> -#if 0 // These functions are currently not being used. >> -static unsigned GetRegSize(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register number."); >> - return g_register_infos[reg].byte_size; >> -} >> - >> -static bool IsGPR(unsigned reg) >> -{ >> - return reg <= k_last_gpr; // GPR's come first. >> -} >> - >> -static bool IsFPR(unsigned reg) >> -{ >> - return (k_first_fpr <= reg && reg <= k_last_fpr); >> -} >> -#endif >> - >> -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, >> - uint32_t concrete_frame_idx) >> - : RegisterContextLinux(thread, concrete_frame_idx) >> -{ >> -} >> - >> -RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() >> -{ >> -} >> - >> -ProcessMonitor & >> -RegisterContextLinux_x86_64::GetMonitor() >> -{ >> - ProcessLinux *process = static_cast(CalculateProcess()); >> - return process->GetMonitor(); >> -} >> - >> -void >> -RegisterContextLinux_x86_64::Invalidate() >> -{ >> -} >> - >> -void >> -RegisterContextLinux_x86_64::InvalidateAllRegisters() >> -{ >> -} >> - >> -size_t >> -RegisterContextLinux_x86_64::GetRegisterCount() >> -{ >> - return k_num_registers; >> -} >> - >> -const RegisterInfo * >> -RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg) >> -{ >> - if (reg < k_num_registers) >> - return &g_register_infos[reg]; >> - else >> - return NULL; >> -} >> - >> -size_t >> -RegisterContextLinux_x86_64::GetRegisterSetCount() >> -{ >> - return k_num_register_sets; >> -} >> - >> -const RegisterSet * >> -RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set) >> -{ >> - if (set < k_num_register_sets) >> - return &g_reg_sets[set]; >> - else >> - return NULL; >> -} >> - >> -unsigned >> -RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset) >> -{ >> - unsigned reg; >> - for (reg = 0; reg < k_num_registers; reg++) >> - { >> - if (g_register_infos[reg].byte_offset == offset) >> - break; >> - } >> - assert(reg < k_num_registers && "Invalid register offset."); >> - return reg; >> -} >> - >> -const char * >> -RegisterContextLinux_x86_64::GetRegisterName(unsigned reg) >> -{ >> - assert(reg < k_num_registers && "Invalid register offset."); >> - return g_register_infos[reg].name; >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, >> - RegisterValue &value) >> -{ >> - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.ReadRegisterValue(GetRegOffset(reg), value); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) >> -{ >> - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); >> - if (data_sp && ReadGPR () && ReadFPR ()) >> - { >> - uint8_t *dst = data_sp->GetBytes(); >> - ::memcpy (dst, &user.regs, sizeof(user.regs)); >> - dst += sizeof(user.regs); >> - >> - ::memcpy (dst, &user.i387, sizeof(user.i387)); >> - return true; >> - } >> - return false; >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, >> - const lldb_private::RegisterValue &value) >> -{ >> - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.WriteRegisterValue(GetRegOffset(reg), value); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) >> -{ >> - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) >> - { >> - const uint8_t *src = data_sp->GetBytes(); >> - ::memcpy (&user.regs, src, sizeof(user.regs)); >> - src += sizeof(user.regs); >> - >> - ::memcpy (&user.i387, src, sizeof(user.i387)); >> - return WriteGPR() & WriteFPR(); >> - } >> - return false; >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::UpdateAfterBreakpoint() >> -{ >> - // PC points one byte past the int3 responsible for the breakpoint. >> - lldb::addr_t pc; >> - >> - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) >> - return false; >> - >> - SetPC(pc - 1); >> - return true; >> -} >> - >> -uint32_t >> -RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, >> - uint32_t num) >> -{ >> - if (kind == eRegisterKindGeneric) >> - { >> - switch (num) >> - { >> - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; >> - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; >> - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; >> - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; >> - case LLDB_REGNUM_GENERIC_RA: >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - >> - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) >> - { >> - switch (num) >> - { >> - case gcc_dwarf_gpr_rax: return gpr_rax; >> - case gcc_dwarf_gpr_rdx: return gpr_rdx; >> - case gcc_dwarf_gpr_rcx: return gpr_rcx; >> - case gcc_dwarf_gpr_rbx: return gpr_rbx; >> - case gcc_dwarf_gpr_rsi: return gpr_rsi; >> - case gcc_dwarf_gpr_rdi: return gpr_rdi; >> - case gcc_dwarf_gpr_rbp: return gpr_rbp; >> - case gcc_dwarf_gpr_rsp: return gpr_rsp; >> - case gcc_dwarf_gpr_r8: return gpr_r8; >> - case gcc_dwarf_gpr_r9: return gpr_r9; >> - case gcc_dwarf_gpr_r10: return gpr_r10; >> - case gcc_dwarf_gpr_r11: return gpr_r11; >> - case gcc_dwarf_gpr_r12: return gpr_r12; >> - case gcc_dwarf_gpr_r13: return gpr_r13; >> - case gcc_dwarf_gpr_r14: return gpr_r14; >> - case gcc_dwarf_gpr_r15: return gpr_r15; >> - case gcc_dwarf_gpr_rip: return gpr_rip; >> - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; >> - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; >> - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; >> - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; >> - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; >> - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; >> - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; >> - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; >> - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; >> - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; >> - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; >> - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; >> - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; >> - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; >> - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; >> - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; >> - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; >> - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; >> - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; >> - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; >> - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; >> - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; >> - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; >> - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - >> - if (kind == eRegisterKindGDB) >> - { >> - switch (num) >> - { >> - case gdb_gpr_rax : return gpr_rax; >> - case gdb_gpr_rbx : return gpr_rbx; >> - case gdb_gpr_rcx : return gpr_rcx; >> - case gdb_gpr_rdx : return gpr_rdx; >> - case gdb_gpr_rsi : return gpr_rsi; >> - case gdb_gpr_rdi : return gpr_rdi; >> - case gdb_gpr_rbp : return gpr_rbp; >> - case gdb_gpr_rsp : return gpr_rsp; >> - case gdb_gpr_r8 : return gpr_r8; >> - case gdb_gpr_r9 : return gpr_r9; >> - case gdb_gpr_r10 : return gpr_r10; >> - case gdb_gpr_r11 : return gpr_r11; >> - case gdb_gpr_r12 : return gpr_r12; >> - case gdb_gpr_r13 : return gpr_r13; >> - case gdb_gpr_r14 : return gpr_r14; >> - case gdb_gpr_r15 : return gpr_r15; >> - case gdb_gpr_rip : return gpr_rip; >> - case gdb_gpr_rflags : return gpr_rflags; >> - case gdb_gpr_cs : return gpr_cs; >> - case gdb_gpr_ss : return gpr_ss; >> - case gdb_gpr_ds : return gpr_ds; >> - case gdb_gpr_es : return gpr_es; >> - case gdb_gpr_fs : return gpr_fs; >> - case gdb_gpr_gs : return gpr_gs; >> - case gdb_fpu_stmm0 : return fpu_stmm0; >> - case gdb_fpu_stmm1 : return fpu_stmm1; >> - case gdb_fpu_stmm2 : return fpu_stmm2; >> - case gdb_fpu_stmm3 : return fpu_stmm3; >> - case gdb_fpu_stmm4 : return fpu_stmm4; >> - case gdb_fpu_stmm5 : return fpu_stmm5; >> - case gdb_fpu_stmm6 : return fpu_stmm6; >> - case gdb_fpu_stmm7 : return fpu_stmm7; >> - case gdb_fpu_fcw : return fpu_fcw; >> - case gdb_fpu_fsw : return fpu_fsw; >> - case gdb_fpu_ftw : return fpu_ftw; >> - case gdb_fpu_cs : return fpu_cs; >> - case gdb_fpu_ip : return fpu_ip; >> - case gdb_fpu_ds : return fpu_ds; >> - case gdb_fpu_dp : return fpu_dp; >> - case gdb_fpu_fop : return fpu_fop; >> - case gdb_fpu_xmm0 : return fpu_xmm0; >> - case gdb_fpu_xmm1 : return fpu_xmm1; >> - case gdb_fpu_xmm2 : return fpu_xmm2; >> - case gdb_fpu_xmm3 : return fpu_xmm3; >> - case gdb_fpu_xmm4 : return fpu_xmm4; >> - case gdb_fpu_xmm5 : return fpu_xmm5; >> - case gdb_fpu_xmm6 : return fpu_xmm6; >> - case gdb_fpu_xmm7 : return fpu_xmm7; >> - case gdb_fpu_xmm8 : return fpu_xmm8; >> - case gdb_fpu_xmm9 : return fpu_xmm9; >> - case gdb_fpu_xmm10 : return fpu_xmm10; >> - case gdb_fpu_xmm11 : return fpu_xmm11; >> - case gdb_fpu_xmm12 : return fpu_xmm12; >> - case gdb_fpu_xmm13 : return fpu_xmm13; >> - case gdb_fpu_xmm14 : return fpu_xmm14; >> - case gdb_fpu_xmm15 : return fpu_xmm15; >> - case gdb_fpu_mxcsr : return fpu_mxcsr; >> - default: >> - return LLDB_INVALID_REGNUM; >> - } >> - } >> - else if (kind == eRegisterKindLLDB) >> - { >> - return num; >> - } >> - >> - return LLDB_INVALID_REGNUM; >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::HardwareSingleStep(bool enable) >> -{ >> - enum { TRACE_BIT = 0x100 }; >> - uint64_t rflags; >> - >> - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) >> - return false; >> - >> - if (enable) >> - { >> - if (rflags & TRACE_BIT) >> - return true; >> - >> - rflags |= TRACE_BIT; >> - } >> - else >> - { >> - if (!(rflags & TRACE_BIT)) >> - return false; >> - >> - rflags &= ~TRACE_BIT; >> - } >> - >> - return WriteRegisterFromUnsigned(gpr_rflags, rflags); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::ReadGPR() >> -{ >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.ReadGPR(&user.regs); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::ReadFPR() >> -{ >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.ReadFPR(&user.i387); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::WriteGPR() >> -{ >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.WriteGPR(&user.regs); >> -} >> - >> -bool >> -RegisterContextLinux_x86_64::WriteFPR() >> -{ >> - ProcessMonitor &monitor = GetMonitor(); >> - return monitor.WriteFPR(&user.i387); >> -} >> Index: source/Plugins/Process/Linux/ProcessMessage.h >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessMessage.h (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessMessage.h (working copy) >> @@ -1,171 +0,0 @@ >> -//===-- ProcessMessage.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_ProcessMessage_H_ >> -#define liblldb_ProcessMessage_H_ >> - >> -#include >> - >> -#include "lldb/lldb-defines.h" >> -#include "lldb/lldb-types.h" >> - >> -class ProcessMessage >> -{ >> -public: >> - >> - /// The type of signal this message can correspond to. >> - enum Kind >> - { >> - eInvalidMessage, >> - eExitMessage, >> - eLimboMessage, >> - eSignalMessage, >> - eSignalDeliveredMessage, >> - eTraceMessage, >> - eBreakpointMessage, >> - eCrashMessage >> - }; >> - >> - enum CrashReason >> - { >> - eInvalidCrashReason, >> - >> - // SIGSEGV crash reasons. >> - eInvalidAddress, >> - ePrivilegedAddress, >> - >> - // SIGILL crash reasons. >> - eIllegalOpcode, >> - eIllegalOperand, >> - eIllegalAddressingMode, >> - eIllegalTrap, >> - ePrivilegedOpcode, >> - ePrivilegedRegister, >> - eCoprocessorError, >> - eInternalStackError, >> - >> - // SIGBUS crash reasons, >> - eIllegalAlignment, >> - eIllegalAddress, >> - eHardwareError, >> - >> - // SIGFPE crash reasons, >> - eIntegerDivideByZero, >> - eIntegerOverflow, >> - eFloatDivideByZero, >> - eFloatOverflow, >> - eFloatUnderflow, >> - eFloatInexactResult, >> - eFloatInvalidOperation, >> - eFloatSubscriptRange >> - }; >> - >> - ProcessMessage() >> - : m_tid(LLDB_INVALID_PROCESS_ID), >> - m_kind(eInvalidMessage), >> - m_crash_reason(eInvalidCrashReason), >> - m_status(0), >> - m_addr(0) { } >> - >> - Kind GetKind() const { return m_kind; } >> - >> - lldb::tid_t GetTID() const { return m_tid; } >> - >> - /// Indicates that the thread @p tid is about to exit with status @p status. >> - static ProcessMessage Limbo(lldb::tid_t tid, int status) { >> - return ProcessMessage(tid, eLimboMessage, status); >> - } >> - >> - /// Indicates that the thread @p tid had the signal @p signum delivered. >> - static ProcessMessage Signal(lldb::tid_t tid, int signum) { >> - return ProcessMessage(tid, eSignalMessage, signum); >> - } >> - >> - /// Indicates that a signal @p signum generated by the debugging process was >> - /// delivered to the thread @p tid. >> - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { >> - return ProcessMessage(tid, eSignalDeliveredMessage, signum); >> - } >> - >> - /// Indicates that the thread @p tid encountered a trace point. >> - static ProcessMessage Trace(lldb::tid_t tid) { >> - return ProcessMessage(tid, eTraceMessage); >> - } >> - >> - /// Indicates that the thread @p tid encountered a break point. >> - static ProcessMessage Break(lldb::tid_t tid) { >> - return ProcessMessage(tid, eBreakpointMessage); >> - } >> - >> - /// Indicates that the thread @p tid crashed. >> - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, >> - int signo, lldb::addr_t fault_addr) { >> - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); >> - message.m_crash_reason = reason; >> - return message; >> - } >> - >> - int GetExitStatus() const { >> - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); >> - return m_status; >> - } >> - >> - int GetSignal() const { >> - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || >> - GetKind() == eSignalDeliveredMessage); >> - return m_status; >> - } >> - >> - int GetStopStatus() const { >> - assert(GetKind() == eSignalMessage); >> - return m_status; >> - } >> - >> - CrashReason GetCrashReason() const { >> - assert(GetKind() == eCrashMessage); >> - return m_crash_reason; >> - } >> - >> - lldb::addr_t GetFaultAddress() const { >> - assert(GetKind() == eCrashMessage); >> - return m_addr; >> - } >> - >> - static const char * >> - GetCrashReasonString(CrashReason reason); >> - >> - const char * >> - PrintCrashReason() const; >> - >> - static const char * >> - PrintCrashReason(CrashReason reason); >> - >> - const char * >> - PrintKind() const; >> - >> - static const char * >> - PrintKind(Kind); >> - >> -private: >> - ProcessMessage(lldb::tid_t tid, Kind kind, >> - int status = 0, lldb::addr_t addr = 0) >> - : m_tid(tid), >> - m_kind(kind), >> - m_crash_reason(eInvalidCrashReason), >> - m_status(status), >> - m_addr(addr) { } >> - >> - lldb::tid_t m_tid; >> - Kind m_kind : 8; >> - CrashReason m_crash_reason : 8; >> - int m_status; >> - lldb::addr_t m_addr; >> -}; >> - >> -#endif // #ifndef liblldb_ProcessMessage_H_ >> Index: source/Plugins/Process/Linux/ProcessMonitor.h >> =================================================================== >> --- source/Plugins/Process/Linux/ProcessMonitor.h (revision 147560) >> +++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy) >> @@ -24,10 +24,12 @@ >> class Error; >> class Module; >> class Scalar; >> + >> } // End lldb_private namespace. >> >> class ProcessLinux; >> class Operation; >> +class ProcessPOSIX; >> >> /// @class ProcessMonitor >> /// @brief Manages communication with the inferior (debugee) process. >> @@ -47,7 +49,7 @@ >> >> /// Launches an inferior process ready for debugging. Forms the >> /// implementation of Process::DoLaunch. >> - ProcessMonitor(ProcessLinux *process, >> + ProcessMonitor(ProcessPOSIX *process, >> lldb_private::Module *module, >> char const *argv[], >> char const *envp[], >> @@ -56,7 +58,7 @@ >> const char *stderr_path, >> lldb_private::Error &error); >> >> - ProcessMonitor(ProcessLinux *process, >> + ProcessMonitor(ProcessPOSIX *process, >> lldb::pid_t pid, >> lldb_private::Error &error); >> >> @@ -104,7 +106,7 @@ >> /// >> /// This method is provided for use by RegisterContextLinux derivatives. >> bool >> - ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value); >> + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); >> >> /// Writes the given value to the register identified by the given >> /// (architecture dependent) offset. >> Index: source/Plugins/Process/Linux/Makefile >> =================================================================== >> --- source/Plugins/Process/Linux/Makefile (revision 147560) >> +++ source/Plugins/Process/Linux/Makefile (working copy) >> @@ -12,6 +12,6 @@ >> BUILD_ARCHIVE = 1 >> >> # Extend the include path so we may locate UnwindLLDB.h >> -CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility >> +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility >> >> include $(LLDB_LEVEL)/Makefile >> Index: source/Plugins/Process/Linux/LinuxThread.h >> =================================================================== >> --- source/Plugins/Process/Linux/LinuxThread.h (revision 147560) >> +++ source/Plugins/Process/Linux/LinuxThread.h (working copy) >> @@ -1,102 +0,0 @@ >> -//===-- LinuxThread.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_LinuxThread_H_ >> -#define liblldb_LinuxThread_H_ >> - >> -// C Includes >> -// C++ Includes >> -#include >> - >> -// Other libraries and framework includes >> -#include "lldb/Target/Thread.h" >> - >> -class ProcessMessage; >> -class ProcessMonitor; >> -class RegisterContextLinux; >> - >> -//------------------------------------------------------------------------------ >> -// @class LinuxThread >> -// @brief Abstraction of a linux process (thread). >> -class LinuxThread >> - : public lldb_private::Thread >> -{ >> -public: >> - LinuxThread(lldb_private::Process &process, lldb::tid_t tid); >> - >> - virtual ~LinuxThread(); >> - >> - void >> - RefreshStateAfterStop(); >> - >> - bool >> - WillResume(lldb::StateType resume_state); >> - >> - const char * >> - GetInfo(); >> - >> - virtual lldb::RegisterContextSP >> - GetRegisterContext(); >> - >> - virtual lldb::RegisterContextSP >> - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); >> - >> - //-------------------------------------------------------------------------- >> - // These static functions provide a mapping from the register offset >> - // back to the register index or name for use in debugging or log >> - // output. >> - >> - static unsigned >> - GetRegisterIndexFromOffset(unsigned offset); >> - >> - static const char * >> - GetRegisterName(unsigned reg); >> - >> - static const char * >> - GetRegisterNameFromOffset(unsigned offset); >> - >> - //-------------------------------------------------------------------------- >> - // These methods form a specialized interface to linux threads. >> - // >> - bool Resume(); >> - >> - void Notify(const ProcessMessage &message); >> - >> -private: >> - RegisterContextLinux * >> - GetRegisterContextLinux () >> - { >> - if (!m_reg_context_sp) >> - GetRegisterContext(); >> - return (RegisterContextLinux *)m_reg_context_sp.get(); >> - } >> - >> - std::auto_ptr m_frame_ap; >> - >> - lldb::BreakpointSiteSP m_breakpoint; >> - lldb::StopInfoSP m_stop_info; >> - >> - ProcessMonitor & >> - GetMonitor(); >> - >> - lldb::StopInfoSP >> - GetPrivateStopReason(); >> - >> - void BreakNotify(const ProcessMessage &message); >> - void TraceNotify(const ProcessMessage &message); >> - void LimboNotify(const ProcessMessage &message); >> - void SignalNotify(const ProcessMessage &message); >> - void SignalDeliveredNotify(const ProcessMessage &message); >> - void CrashNotify(const ProcessMessage &message); >> - >> - lldb_private::Unwind * >> - GetUnwinder(); >> -}; >> - >> -#endif // #ifndef liblldb_LinuxThread_H_ >> Index: source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h >> =================================================================== >> --- source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (revision 147560) >> +++ source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (working copy) >> @@ -10,67 +10,7 @@ >> #ifndef liblldb_RegisterContextLinux_x86_64_H_ >> #define liblldb_RegisterContextLinux_x86_64_H_ >> >> -#include "RegisterContextLinux.h" >> - >> -class ProcessMonitor; >> - >> -class RegisterContextLinux_x86_64 >> - : public RegisterContextLinux >> -{ >> -public: >> - RegisterContextLinux_x86_64 (lldb_private::Thread &thread, >> - uint32_t concrete_frame_idx); >> - >> - ~RegisterContextLinux_x86_64(); >> - >> - void >> - Invalidate(); >> - >> - void >> - InvalidateAllRegisters(); >> - >> - size_t >> - GetRegisterCount(); >> - >> - const lldb_private::RegisterInfo * >> - GetRegisterInfoAtIndex(uint32_t reg); >> - >> - size_t >> - GetRegisterSetCount(); >> - >> - const lldb_private::RegisterSet * >> - GetRegisterSet(uint32_t set); >> - >> - static unsigned >> - GetRegisterIndexFromOffset(unsigned offset); >> - >> - static const char * >> - GetRegisterName(unsigned reg); >> - >> - virtual bool >> - ReadRegister(const lldb_private::RegisterInfo *reg_info, >> - lldb_private::RegisterValue &value); >> - >> - bool >> - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); >> - >> - virtual bool >> - WriteRegister(const lldb_private::RegisterInfo *reg_info, >> - const lldb_private::RegisterValue &value); >> - >> - bool >> - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); >> - >> - uint32_t >> - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); >> - >> - bool >> - HardwareSingleStep(bool enable); >> - >> - bool >> - UpdateAfterBreakpoint(); >> - >> - struct GPR >> + typedef struct _GPR >> { >> uint64_t r15; >> uint64_t r14; >> @@ -99,67 +39,6 @@ >> uint64_t es; >> uint64_t fs; >> uint64_t gs; >> - }; >> + } GPR; >> >> - struct MMSReg >> - { >> - uint8_t bytes[10]; >> - uint8_t pad[6]; >> - }; >> - >> - struct XMMReg >> - { >> - uint8_t bytes[16]; >> - }; >> - >> - struct FPU >> - { >> - uint16_t fcw; >> - uint16_t fsw; >> - uint16_t ftw; >> - uint16_t fop; >> - uint64_t ip; >> - uint64_t dp; >> - uint32_t mxcsr; >> - uint32_t mxcsrmask; >> - MMSReg stmm[8]; >> - XMMReg xmm[16]; >> - uint32_t padding[24]; >> - }; >> - >> - struct UserArea >> - { >> - GPR regs; // General purpose registers. >> - int32_t fpvalid; // True if FPU is being used. >> - int32_t pad0; >> - FPU i387; // FPU registers. >> - uint64_t tsize; // Text segment size. >> - uint64_t dsize; // Data segment size. >> - uint64_t ssize; // Stack segment size. >> - uint64_t start_code; // VM address of text. >> - uint64_t start_stack; // VM address of stack bottom (top in rsp). >> - int64_t signal; // Signal causing core dump. >> - int32_t reserved; // Unused. >> - int32_t pad1; >> - uint64_t ar0; // Location of GPR's. >> - FPU* fpstate; // Location of FPR's. >> - uint64_t magic; // Identifier for core dumps. >> - char u_comm[32]; // Command causing core dump. >> - uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). >> - uint64_t error_code; // CPU error code. >> - uint64_t fault_address; // Control register CR3. >> - }; >> - >> -private: >> - UserArea user; >> - >> - ProcessMonitor &GetMonitor(); >> - >> - bool ReadGPR(); >> - bool ReadFPR(); >> - >> - bool WriteGPR(); >> - bool WriteFPR(); >> -}; >> - >> -#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_ >> +#endif >> Index: source/Plugins/Process/POSIX/POSIXThread.h >> =================================================================== >> --- source/Plugins/Process/POSIX/POSIXThread.h (revision 0) >> +++ source/Plugins/Process/POSIX/POSIXThread.h (revision 0) >> @@ -0,0 +1,106 @@ >> +//===-- POSIXThread.h -------------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#ifndef liblldb_POSIXThread_H_ >> +#define liblldb_POSIXThread_H_ >> + >> +// C Includes >> +// C++ Includes >> +#include >> + >> +// Other libraries and framework includes >> +#include "lldb/Target/Thread.h" >> +#include "RegisterContextPOSIX.h" >> + >> +class ProcessMessage; >> +class ProcessMonitor; >> +class RegisterContextPOSIX; >> + >> +//------------------------------------------------------------------------------ >> +// @class POSIXThread >> +// @brief Abstraction of a linux process (thread). >> +class POSIXThread >> + : public lldb_private::Thread >> +{ >> +public: >> + POSIXThread(lldb_private::Process &process, lldb::tid_t tid); >> + >> + virtual ~POSIXThread(); >> + >> + void >> + RefreshStateAfterStop(); >> + >> + bool >> + WillResume(lldb::StateType resume_state); >> + >> + const char * >> + GetInfo(); >> + >> + virtual lldb::RegisterContextSP >> + GetRegisterContext(); >> + >> + virtual lldb::RegisterContextSP >> + CreateRegisterContextForFrame (lldb_private::StackFrame *frame); >> + >> + //-------------------------------------------------------------------------- >> + // These static functions provide a mapping from the register offset >> + // back to the register index or name for use in debugging or log >> + // output. >> + >> + static unsigned >> + GetRegisterIndexFromOffset(unsigned offset); >> + >> + static const char * >> + GetRegisterName(unsigned reg); >> + >> + static const char * >> + GetRegisterNameFromOffset(unsigned offset); >> + >> + //-------------------------------------------------------------------------- >> + // These methods form a specialized interface to linux threads. >> + // >> + bool Resume(); >> + >> + void Notify(const ProcessMessage &message); >> + >> +private: >> + RegisterContextPOSIX * >> + GetRegisterContextPOSIX () >> + { >> + if (!m_reg_context_sp) >> + m_reg_context_sp = GetRegisterContext(); >> +#if 0 >> + return dynamic_cast(m_reg_context_sp.get()); >> +#endif >> + return (RegisterContextPOSIX *)m_reg_context_sp.get(); >> + } >> + >> + std::auto_ptr m_frame_ap; >> + >> + lldb::BreakpointSiteSP m_breakpoint; >> + lldb::StopInfoSP m_stop_info; >> + >> + ProcessMonitor & >> + GetMonitor(); >> + >> + lldb::StopInfoSP >> + GetPrivateStopReason(); >> + >> + void BreakNotify(const ProcessMessage &message); >> + void TraceNotify(const ProcessMessage &message); >> + void LimboNotify(const ProcessMessage &message); >> + void SignalNotify(const ProcessMessage &message); >> + void SignalDeliveredNotify(const ProcessMessage &message); >> + void CrashNotify(const ProcessMessage &message); >> + >> + lldb_private::Unwind * >> + GetUnwinder(); >> +}; >> + >> +#endif // #ifndef liblldb_POSIXThread_H_ >> Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 0) >> @@ -0,0 +1,594 @@ >> +//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +// C Includes >> +#include >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/PluginManager.h" >> +#include "lldb/Core/State.h" >> +#include "lldb/Host/Host.h" >> +#include "lldb/Symbol/ObjectFile.h" >> +#include "lldb/Target/DynamicLoader.h" >> +#include "lldb/Target/Target.h" >> + >> +#include "ProcessPOSIX.h" >> +#include "ProcessPOSIXLog.h" >> +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" >> +#include "ProcessMonitor.h" >> +#include "POSIXThread.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +//------------------------------------------------------------------------------ >> +// Static functions. >> +#if 0 >> +Process* >> +ProcessPOSIX::CreateInstance(Target& target, Listener &listener) >> +{ >> + return new ProcessPOSIX(target, listener); >> +} >> + >> + >> +void >> +ProcessPOSIX::Initialize() >> +{ >> + static bool g_initialized = false; >> + >> + if (!g_initialized) >> + { >> + g_initialized = true; >> + PluginManager::RegisterPlugin(GetPluginNameStatic(), >> + GetPluginDescriptionStatic(), >> + CreateInstance); >> + >> + Log::Callbacks log_callbacks = { >> + ProcessPOSIXLog::DisableLog, >> + ProcessPOSIXLog::EnableLog, >> + ProcessPOSIXLog::ListLogCategories >> + }; >> + >> + Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks); >> + } >> +} >> +#endif >> + >> +//------------------------------------------------------------------------------ >> +// Constructors and destructors. >> + >> +ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener) >> + : Process(target, listener), >> + m_monitor(NULL), >> + m_module(NULL), >> + m_in_limbo(false), >> + m_exit_now(false) >> +{ >> + // FIXME: Putting this code in the ctor and saving the byte order in a >> + // member variable is a hack to avoid const qual issues in GetByteOrder. >> + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); >> + m_byte_order = obj_file->GetByteOrder(); >> +} >> + >> +ProcessPOSIX::~ProcessPOSIX() >> +{ >> + delete m_monitor; >> +} >> + >> +//------------------------------------------------------------------------------ >> +// Process protocol. >> + >> +bool >> +ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name) >> +{ >> + // For now we are just making sure the file exists for a given module >> + ModuleSP exe_module_sp(target.GetExecutableModule()); >> + if (exe_module_sp.get()) >> + return exe_module_sp->GetFileSpec().Exists(); >> + return false; >> +} >> + >> +Error >> +ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid) >> +{ >> + Error error; >> + assert(m_monitor == NULL); >> + >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("ProcessPOSIX::%s(pid = %i)", __FUNCTION__, GetID()); >> + >> + m_monitor = new ProcessMonitor(this, pid, error); >> + >> + if (!error.Success()) >> + return error; >> + >> + SetID(pid); >> + return error; >> +} >> + >> +Error >> +ProcessPOSIX::WillLaunch(Module* module) >> +{ >> + Error error; >> + return error; >> +} >> + >> +const char * >> +ProcessPOSIX::GetFilePath( >> + const lldb_private::ProcessLaunchInfo::FileAction *file_action, >> + const char *default_path) >> +{ >> + const char *pts_name = "/dev/pts/"; >> + const char *path = NULL; >> + >> + if (file_action) >> + { >> + if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) >> + path = file_action->GetPath(); >> + // By default the stdio paths passed in will be pseudo-terminal >> + // (/dev/pts). If so, convert to using a different default path >> + // instead to redirect I/O to the debugger console. This should >> + // also handle user overrides to /dev/null or a different file. >> + if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0) >> + path = default_path; >> + } >> + >> + return path; >> +} >> + >> +Error >> +ProcessPOSIX::DoLaunch (Module *module, >> + const ProcessLaunchInfo &launch_info) >> +{ >> + Error error; >> + assert(m_monitor == NULL); >> + >> + SetPrivateState(eStateLaunching); >> + >> + const lldb_private::ProcessLaunchInfo::FileAction *file_action; >> + >> + // Default of NULL will mean to use existing open file descriptors >> + const char *stdin_path = NULL; >> + const char *stdout_path = NULL; >> + const char *stderr_path = NULL; >> + >> + file_action = launch_info.GetFileActionForFD (STDIN_FILENO); >> + stdin_path = GetFilePath(file_action, stdin_path); >> + >> + file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); >> + stdout_path = GetFilePath(file_action, stdout_path); >> + >> + file_action = launch_info.GetFileActionForFD (STDERR_FILENO); >> + stderr_path = GetFilePath(file_action, stderr_path); >> + >> + m_monitor = new ProcessMonitor (this, >> + module, >> + launch_info.GetArguments().GetConstArgumentVector(), >> + launch_info.GetEnvironmentEntries().GetConstArgumentVector(), >> + stdin_path, >> + stdout_path, >> + stderr_path, >> + error); >> + >> + m_module = module; >> + >> + if (!error.Success()) >> + return error; >> + >> + SetID(m_monitor->GetPID()); >> + return error; >> +} >> + >> +void >> +ProcessPOSIX::DidLaunch() >> +{ >> +} >> + >> +Error >> +ProcessPOSIX::DoResume() >> +{ >> + StateType state = GetPrivateState(); >> + >> + assert(state == eStateStopped || state == eStateCrashed); >> + >> + // We are about to resume a thread that will cause the process to exit so >> + // set our exit status now. Do not change our state if the inferior >> + // crashed. >> + if (state == eStateStopped) >> + { >> + if (m_in_limbo) >> + SetExitStatus(m_exit_status, NULL); >> + else >> + SetPrivateState(eStateRunning); >> + } >> + >> + bool did_resume = false; >> + uint32_t thread_count = m_thread_list.GetSize(false); >> + for (uint32_t i = 0; i < thread_count; ++i) >> + { >> + POSIXThread *thread = static_cast( >> + m_thread_list.GetThreadAtIndex(i, false).get()); >> + did_resume = thread->Resume() || did_resume; >> + } >> + assert(did_resume && "Process resume failed!"); >> + >> + return Error(); >> +} >> + >> +addr_t >> +ProcessPOSIX::GetImageInfoAddress() >> +{ >> + Target *target = &GetTarget(); >> + ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); >> + Address addr = obj_file->GetImageInfoAddress(); >> + >> + if (addr.IsValid()) >> + return addr.GetLoadAddress(target); >> + else >> + return LLDB_INVALID_ADDRESS; >> +} >> + >> +Error >> +ProcessPOSIX::DoHalt(bool &caused_stop) >> +{ >> + Error error; >> + >> + if (IsStopped()) >> + { >> + caused_stop = false; >> + } >> + else if (kill(GetID(), SIGSTOP)) >> + { >> + caused_stop = false; >> + error.SetErrorToErrno(); >> + } >> + else >> + { >> + caused_stop = true; >> + } >> + >> + return error; >> +} >> + >> +Error >> +ProcessPOSIX::DoDetach() >> +{ >> + Error error; >> + >> + error = m_monitor->Detach(); >> + if (error.Success()) >> + SetPrivateState(eStateDetached); >> + >> + return error; >> +} >> + >> +Error >> +ProcessPOSIX::DoSignal(int signal) >> +{ >> + Error error; >> + >> + if (kill(GetID(), signal)) >> + error.SetErrorToErrno(); >> + >> + return error; >> +} >> + >> +Error >> +ProcessPOSIX::DoDestroy() >> +{ >> + Error error; >> + >> + if (!HasExited()) >> + { >> + // Drive the exit event to completion (do not keep the inferior in >> + // limbo). >> + m_exit_now = true; >> + >> + if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) >> + { >> + error.SetErrorToErrno(); >> + return error; >> + } >> + >> + SetPrivateState(eStateExited); >> + } >> + >> + return error; >> +} >> + >> +void >> +ProcessPOSIX::SendMessage(const ProcessMessage &message) >> +{ >> + Mutex::Locker lock(m_message_mutex); >> + >> + switch (message.GetKind()) >> + { >> + default: >> + assert(false && "Unexpected process message!"); >> + break; >> + >> + case ProcessMessage::eInvalidMessage: >> + return; >> + >> + case ProcessMessage::eLimboMessage: >> + m_in_limbo = true; >> + m_exit_status = message.GetExitStatus(); >> + if (m_exit_now) >> + { >> + SetPrivateState(eStateExited); >> + m_monitor->Detach(); >> + } >> + else >> + SetPrivateState(eStateStopped); >> + break; >> + >> + case ProcessMessage::eExitMessage: >> + m_exit_status = message.GetExitStatus(); >> + SetExitStatus(m_exit_status, NULL); >> + break; >> + >> + case ProcessMessage::eTraceMessage: >> + case ProcessMessage::eBreakpointMessage: >> + SetPrivateState(eStateStopped); >> + break; >> + >> + case ProcessMessage::eSignalMessage: >> + case ProcessMessage::eSignalDeliveredMessage: >> + SetPrivateState(eStateStopped); >> + break; >> + >> + case ProcessMessage::eCrashMessage: >> + SetPrivateState(eStateCrashed); >> + break; >> + } >> + >> + m_message_queue.push(message); >> +} >> + >> +void >> +ProcessPOSIX::RefreshStateAfterStop() >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("ProcessPOSIX::%s()", __FUNCTION__); >> + >> + Mutex::Locker lock(m_message_mutex); >> + if (m_message_queue.empty()) >> + return; >> + >> + ProcessMessage &message = m_message_queue.front(); >> + >> + // Resolve the thread this message corresponds to and pass it along. >> + // FIXME: we're really dealing with the pid here. This should get >> + // fixed when this code is fixed to handle multiple threads. >> + lldb::tid_t tid = message.GetTID(); >> + if (log) >> + log->Printf ("ProcessPOSIX::%s() pid = %i", __FUNCTION__, tid); >> + POSIXThread *thread = static_cast( >> + GetThreadList().FindThreadByID(tid, false).get()); >> + >> + assert(thread); >> + thread->Notify(message); >> + >> + m_message_queue.pop(); >> +} >> + >> +bool >> +ProcessPOSIX::IsAlive() >> +{ >> + StateType state = GetPrivateState(); >> + return state != eStateDetached && state != eStateExited && state != eStateInvalid; >> +} >> + >> +size_t >> +ProcessPOSIX::DoReadMemory(addr_t vm_addr, >> + void *buf, size_t size, Error &error) >> +{ >> + assert(m_monitor); >> + return m_monitor->ReadMemory(vm_addr, buf, size, error); >> +} >> + >> +size_t >> +ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, >> + Error &error) >> +{ >> + assert(m_monitor); >> + return m_monitor->WriteMemory(vm_addr, buf, size, error); >> +} >> + >> +addr_t >> +ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions, >> + Error &error) >> +{ >> + addr_t allocated_addr = LLDB_INVALID_ADDRESS; >> + >> + unsigned prot = 0; >> + if (permissions & lldb::ePermissionsReadable) >> + prot |= eMmapProtRead; >> + if (permissions & lldb::ePermissionsWritable) >> + prot |= eMmapProtWrite; >> + if (permissions & lldb::ePermissionsExecutable) >> + prot |= eMmapProtExec; >> + >> + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, >> + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { >> + m_addr_to_mmap_size[allocated_addr] = size; >> + error.Clear(); >> + } else { >> + allocated_addr = LLDB_INVALID_ADDRESS; >> + error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); >> + } >> + >> + return allocated_addr; >> +} >> + >> +Error >> +ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) >> +{ >> + Error error; >> + MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); >> + if (pos != m_addr_to_mmap_size.end() && >> + InferiorCallMunmap(this, addr, pos->second)) >> + m_addr_to_mmap_size.erase (pos); >> + else >> + error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); >> + >> + return error; >> +} >> + >> +size_t >> +ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) >> +{ >> + static const uint8_t g_i386_opcode[] = { 0xCC }; >> + >> + ArchSpec arch = GetTarget().GetArchitecture(); >> + const uint8_t *opcode = NULL; >> + size_t opcode_size = 0; >> + >> + switch (arch.GetCore()) >> + { >> + default: >> + assert(false && "CPU type not supported!"); >> + break; >> + >> + case ArchSpec::eCore_x86_32_i386: >> + case ArchSpec::eCore_x86_64_x86_64: >> + opcode = g_i386_opcode; >> + opcode_size = sizeof(g_i386_opcode); >> + break; >> + } >> + >> + bp_site->SetTrapOpcode(opcode, opcode_size); >> + return opcode_size; >> +} >> + >> +Error >> +ProcessPOSIX::EnableBreakpoint(BreakpointSite *bp_site) >> +{ >> + return EnableSoftwareBreakpoint(bp_site); >> +} >> + >> +Error >> +ProcessPOSIX::DisableBreakpoint(BreakpointSite *bp_site) >> +{ >> + return DisableSoftwareBreakpoint(bp_site); >> +} >> + >> +uint32_t >> +ProcessPOSIX::UpdateThreadListIfNeeded() >> +{ >> + // Do not allow recursive updates. >> + return m_thread_list.GetSize(false); >> +} >> + >> +uint32_t >> +ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("ProcessPOSIX::%s() (pid = %i)", __FUNCTION__, GetID()); >> + >> + // Update the process thread list with this new thread. >> + // FIXME: We should be using tid, not pid. >> + assert(m_monitor); >> + ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); >> + if (!thread_sp) >> + thread_sp.reset(new POSIXThread(*this, GetID())); >> + >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("ProcessPOSIX::%s() updated pid = %i", __FUNCTION__, GetID()); >> + new_thread_list.AddThread(thread_sp); >> + >> + return new_thread_list.GetSize(false); >> +} >> + >> +ByteOrder >> +ProcessPOSIX::GetByteOrder() const >> +{ >> + // FIXME: We should be able to extract this value directly. See comment in >> + // ProcessPOSIX(). >> + return m_byte_order; >> +} >> + >> +size_t >> +ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error) >> +{ >> + ssize_t status; >> + if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) >> + { >> + error.SetErrorToErrno(); >> + return 0; >> + } >> + return status; >> +} >> + >> +size_t >> +ProcessPOSIX::GetSTDOUT(char *buf, size_t len, Error &error) >> +{ >> + ssize_t bytes_read; >> + >> + // The terminal file descriptor is always in non-block mode. >> + if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) >> + { >> + if (errno != EAGAIN) >> + error.SetErrorToErrno(); >> + return 0; >> + } >> + return bytes_read; >> +} >> + >> +size_t >> +ProcessPOSIX::GetSTDERR(char *buf, size_t len, Error &error) >> +{ >> + return GetSTDOUT(buf, len, error); >> +} >> + >> +UnixSignals & >> +ProcessPOSIX::GetUnixSignals() >> +{ >> + return m_signals; >> +} >> + >> +//------------------------------------------------------------------------------ >> +// Utility functions. >> + >> +bool >> +ProcessPOSIX::HasExited() >> +{ >> + switch (GetPrivateState()) >> + { >> + default: >> + break; >> + >> + case eStateDetached: >> + case eStateExited: >> + return true; >> + } >> + >> + return false; >> +} >> + >> +bool >> +ProcessPOSIX::IsStopped() >> +{ >> + switch (GetPrivateState()) >> + { >> + default: >> + break; >> + >> + case eStateStopped: >> + case eStateCrashed: >> + case eStateSuspended: >> + return true; >> + } >> + >> + return false; >> +} >> Index: source/Plugins/Process/POSIX/RegisterContext_i386.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/RegisterContext_i386.cpp (revision 0) >> @@ -0,0 +1,643 @@ >> +//===-- RegisterContextPOSIX_i386.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/Core/DataExtractor.h" >> +#include "lldb/Target/Thread.h" >> +#include "lldb/Host/Endian.h" >> + >> +#include "ProcessPOSIX.h" >> +#include "ProcessPOSIXLog.h" >> +#include "ProcessMonitor.h" >> +#include "RegisterContext_i386.h" >> + >> +using namespace lldb_private; >> +using namespace lldb; >> + >> +enum >> +{ >> + k_first_gpr, >> + gpr_eax = k_first_gpr, >> + gpr_ebx, >> + gpr_ecx, >> + gpr_edx, >> + gpr_edi, >> + gpr_esi, >> + gpr_ebp, >> + gpr_esp, >> + gpr_ss, >> + gpr_eflags, >> +#ifdef __FreeBSD__ >> + gpr_orig_ax, >> +#endif >> + gpr_eip, >> + gpr_cs, >> + gpr_ds, >> + gpr_es, >> + gpr_fs, >> + gpr_gs, >> + k_last_gpr = gpr_gs, >> + >> + k_first_fpr, >> + fpu_fcw = k_first_fpr, >> + fpu_fsw, >> + fpu_ftw, >> + fpu_fop, >> + fpu_ip, >> + fpu_cs, >> + fpu_foo, >> + fpu_fos, >> + fpu_mxcsr, >> + fpu_stmm0, >> + fpu_stmm1, >> + fpu_stmm2, >> + fpu_stmm3, >> + fpu_stmm4, >> + fpu_stmm5, >> + fpu_stmm6, >> + fpu_stmm7, >> + fpu_xmm0, >> + fpu_xmm1, >> + fpu_xmm2, >> + fpu_xmm3, >> + fpu_xmm4, >> + fpu_xmm5, >> + fpu_xmm6, >> + fpu_xmm7, >> + k_last_fpr = fpu_xmm7, >> + >> + k_num_registers, >> + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, >> + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 >> +}; >> + >> +// Number of register sets provided by this context. >> +enum >> +{ >> + k_num_register_sets = 2 >> +}; >> + >> +enum >> +{ >> + gcc_eax = 0, >> + gcc_ecx, >> + gcc_edx, >> + gcc_ebx, >> + gcc_ebp, >> + gcc_esp, >> + gcc_esi, >> + gcc_edi, >> + gcc_eip, >> + gcc_eflags >> +}; >> + >> +enum >> +{ >> + dwarf_eax = 0, >> + dwarf_ecx, >> + dwarf_edx, >> + dwarf_ebx, >> + dwarf_esp, >> + dwarf_ebp, >> + dwarf_esi, >> + dwarf_edi, >> + dwarf_eip, >> + dwarf_eflags, >> + dwarf_stmm0 = 11, >> + dwarf_stmm1, >> + dwarf_stmm2, >> + dwarf_stmm3, >> + dwarf_stmm4, >> + dwarf_stmm5, >> + dwarf_stmm6, >> + dwarf_stmm7, >> + dwarf_xmm0 = 21, >> + dwarf_xmm1, >> + dwarf_xmm2, >> + dwarf_xmm3, >> + dwarf_xmm4, >> + dwarf_xmm5, >> + dwarf_xmm6, >> + dwarf_xmm7 >> +}; >> + >> +enum >> +{ >> + gdb_eax = 0, >> + gdb_ecx = 1, >> + gdb_edx = 2, >> + gdb_ebx = 3, >> + gdb_esp = 4, >> + gdb_ebp = 5, >> + gdb_esi = 6, >> + gdb_edi = 7, >> + gdb_eip = 8, >> + gdb_eflags = 9, >> + gdb_cs = 10, >> + gdb_ss = 11, >> + gdb_ds = 12, >> + gdb_es = 13, >> + gdb_fs = 14, >> + gdb_gs = 15, >> + gdb_stmm0 = 16, >> + gdb_stmm1 = 17, >> + gdb_stmm2 = 18, >> + gdb_stmm3 = 19, >> + gdb_stmm4 = 20, >> + gdb_stmm5 = 21, >> + gdb_stmm6 = 22, >> + gdb_stmm7 = 23, >> + gdb_fcw = 24, >> + gdb_fsw = 25, >> + gdb_ftw = 26, >> + gdb_fpu_cs = 27, >> + gdb_ip = 28, >> + gdb_fpu_ds = 29, >> + gdb_dp = 30, >> + gdb_fop = 31, >> + gdb_xmm0 = 32, >> + gdb_xmm1 = 33, >> + gdb_xmm2 = 34, >> + gdb_xmm3 = 35, >> + gdb_xmm4 = 36, >> + gdb_xmm5 = 37, >> + gdb_xmm6 = 38, >> + gdb_xmm7 = 39, >> + gdb_mxcsr = 40, >> + gdb_mm0 = 41, >> + gdb_mm1 = 42, >> + gdb_mm2 = 43, >> + gdb_mm3 = 44, >> + gdb_mm4 = 45, >> + gdb_mm5 = 46, >> + gdb_mm6 = 47, >> + gdb_mm7 = 48 >> +}; >> + >> +static const >> +uint32_t g_gpr_regnums[k_num_gpr_registers] = >> +{ >> + gpr_eax, >> + gpr_ebx, >> + gpr_ecx, >> + gpr_edx, >> + gpr_edi, >> + gpr_esi, >> + gpr_ebp, >> + gpr_esp, >> + gpr_ss, >> + gpr_eflags, >> +#ifdef __FreeBSD__ >> + gpr_orig_ax, >> +#endif >> + gpr_eip, >> + gpr_cs, >> + gpr_ds, >> + gpr_es, >> + gpr_fs, >> + gpr_gs, >> +}; >> + >> +static const uint32_t >> +g_fpu_regnums[k_num_fpu_registers] = >> +{ >> + fpu_fcw, >> + fpu_fsw, >> + fpu_ftw, >> + fpu_fop, >> + fpu_ip, >> + fpu_cs, >> + fpu_foo, >> + fpu_fos, >> + fpu_mxcsr, >> + fpu_stmm0, >> + fpu_stmm1, >> + fpu_stmm2, >> + fpu_stmm3, >> + fpu_stmm4, >> + fpu_stmm5, >> + fpu_stmm6, >> + fpu_stmm7, >> + fpu_xmm0, >> + fpu_xmm1, >> + fpu_xmm2, >> + fpu_xmm3, >> + fpu_xmm4, >> + fpu_xmm5, >> + fpu_xmm6, >> + fpu_xmm7, >> +}; >> + >> +static const RegisterSet >> +g_reg_sets[k_num_register_sets] = >> +{ >> + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, >> + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } >> +}; >> + >> +// Computes the offset of the given GPR in the user data area. >> +#define GPR_OFFSET(regname) \ >> + (offsetof(RegisterContext_i386::UserArea, regs) + \ >> + offsetof(RegisterContext_i386::GPR, regname)) >> + >> +// Computes the offset of the given FPR in the user data area. >> +#define FPR_OFFSET(regname) \ >> + (offsetof(RegisterContext_i386::UserArea, i387) + \ >> + offsetof(RegisterContext_i386::FPU, regname)) >> + >> +// Number of bytes needed to represent a GPR. >> +#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg) >> + >> +// Number of bytes needed to represent a FPR. >> +#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg) >> + >> +// Number of bytes needed to represent the i'th FP register. >> +#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes) >> + >> +// Number of bytes needed to represent an XMM register. >> +#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg) >> + >> +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ >> + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ >> + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } >> + >> +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ >> + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ >> + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } >> + >> +#define DEFINE_FP(reg, i) \ >> + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> + eFormatVectorOfUInt8, \ >> + { dwarf_##reg##i, dwarf_##reg##i, \ >> + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } >> + >> +#define DEFINE_XMM(reg, i) \ >> + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> + eFormatVectorOfUInt8, \ >> + { dwarf_##reg##i, dwarf_##reg##i, \ >> + LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } >> + >> +static RegisterInfo >> +g_register_infos[k_num_registers] = >> +{ >> + // General purpose registers. >> + DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), >> + DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), >> + DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), >> + DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), >> + DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), >> + DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), >> + DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), >> + DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), >> + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), >> + DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), >> + DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), >> + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), >> + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), >> + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), >> + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), >> + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), >> + >> + // Floating point registers. >> + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), >> + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), >> + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), >> + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), >> + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), >> + DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), >> + DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), >> + DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), >> + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), >> + >> + DEFINE_FP(stmm, 0), >> + DEFINE_FP(stmm, 1), >> + DEFINE_FP(stmm, 2), >> + DEFINE_FP(stmm, 3), >> + DEFINE_FP(stmm, 4), >> + DEFINE_FP(stmm, 5), >> + DEFINE_FP(stmm, 6), >> + DEFINE_FP(stmm, 7), >> + >> + // XMM registers >> + DEFINE_XMM(xmm, 0), >> + DEFINE_XMM(xmm, 1), >> + DEFINE_XMM(xmm, 2), >> + DEFINE_XMM(xmm, 3), >> + DEFINE_XMM(xmm, 4), >> + DEFINE_XMM(xmm, 5), >> + DEFINE_XMM(xmm, 6), >> + DEFINE_XMM(xmm, 7), >> + >> +}; >> + >> +#ifndef NDEBUG >> +static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); >> +#endif >> + >> +static unsigned GetRegOffset(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register number."); >> + return g_register_infos[reg].byte_offset; >> +} >> + >> +static unsigned GetRegSize(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register number."); >> + return g_register_infos[reg].byte_size; >> +} >> + >> +RegisterContext_i386::RegisterContext_i386(Thread &thread, >> + uint32_t concrete_frame_idx) >> + : RegisterContextPOSIX(thread, concrete_frame_idx) >> +{ >> +} >> + >> +RegisterContext_i386::~RegisterContext_i386() >> +{ >> +} >> + >> +ProcessMonitor & >> +RegisterContext_i386::GetMonitor() >> +{ >> + ProcessPOSIX *process = static_cast(CalculateProcess()); >> + return process->GetMonitor(); >> +} >> + >> +void >> +RegisterContext_i386::Invalidate() >> +{ >> +} >> + >> +void >> +RegisterContext_i386::InvalidateAllRegisters() >> +{ >> +} >> + >> +size_t >> +RegisterContext_i386::GetRegisterCount() >> +{ >> + assert(k_num_register_infos == k_num_registers); >> + return k_num_registers; >> +} >> + >> +const RegisterInfo * >> +RegisterContext_i386::GetRegisterInfoAtIndex(uint32_t reg) >> +{ >> + assert(k_num_register_infos == k_num_registers); >> + if (reg < k_num_registers) >> + return &g_register_infos[reg]; >> + else >> + return NULL; >> +} >> + >> +size_t >> +RegisterContext_i386::GetRegisterSetCount() >> +{ >> + return k_num_register_sets; >> +} >> + >> +const RegisterSet * >> +RegisterContext_i386::GetRegisterSet(uint32_t set) >> +{ >> + if (set < k_num_register_sets) >> + return &g_reg_sets[set]; >> + else >> + return NULL; >> +} >> + >> +unsigned >> +RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset) >> +{ >> + unsigned reg; >> + for (reg = 0; reg < k_num_registers; reg++) >> + { >> + if (g_register_infos[reg].byte_offset == offset) >> + break; >> + } >> + assert(reg < k_num_registers && "Invalid register offset."); >> + return reg; >> +} >> + >> +const char * >> +RegisterContext_i386::GetRegisterName(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register offset."); >> + return g_register_infos[reg].name; >> +} >> + >> +bool >> +RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info, >> + RegisterValue &value) >> +{ >> + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); >> +} >> + >> +bool >> +RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp) >> +{ >> + return false; >> +} >> + >> +bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info, >> + const RegisterValue &value) >> +{ >> + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.WriteRegisterValue(GetRegOffset(reg), value); >> +} >> + >> +bool >> +RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data) >> +{ >> + return false; >> +} >> + >> +bool >> +RegisterContext_i386::UpdateAfterBreakpoint() >> +{ >> + // PC points one byte past the int3 responsible for the breakpoint. >> + lldb::addr_t pc; >> + >> + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) >> + return false; >> + >> + SetPC(pc - 1); >> + return true; >> +} >> + >> +uint32_t >> +RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, >> + uint32_t num) >> +{ >> + if (kind == eRegisterKindGeneric) >> + { >> + switch (num) >> + { >> + case LLDB_REGNUM_GENERIC_PC: return gpr_eip; >> + case LLDB_REGNUM_GENERIC_SP: return gpr_esp; >> + case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; >> + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; >> + case LLDB_REGNUM_GENERIC_RA: >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + >> + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) >> + { >> + switch (num) >> + { >> + case dwarf_eax: return gpr_eax; >> + case dwarf_edx: return gpr_edx; >> + case dwarf_ecx: return gpr_ecx; >> + case dwarf_ebx: return gpr_ebx; >> + case dwarf_esi: return gpr_esi; >> + case dwarf_edi: return gpr_edi; >> + case dwarf_ebp: return gpr_ebp; >> + case dwarf_esp: return gpr_esp; >> + case dwarf_eip: return gpr_eip; >> + case dwarf_xmm0: return fpu_xmm0; >> + case dwarf_xmm1: return fpu_xmm1; >> + case dwarf_xmm2: return fpu_xmm2; >> + case dwarf_xmm3: return fpu_xmm3; >> + case dwarf_xmm4: return fpu_xmm4; >> + case dwarf_xmm5: return fpu_xmm5; >> + case dwarf_xmm6: return fpu_xmm6; >> + case dwarf_xmm7: return fpu_xmm7; >> + case dwarf_stmm0: return fpu_stmm0; >> + case dwarf_stmm1: return fpu_stmm1; >> + case dwarf_stmm2: return fpu_stmm2; >> + case dwarf_stmm3: return fpu_stmm3; >> + case dwarf_stmm4: return fpu_stmm4; >> + case dwarf_stmm5: return fpu_stmm5; >> + case dwarf_stmm6: return fpu_stmm6; >> + case dwarf_stmm7: return fpu_stmm7; >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + >> + if (kind == eRegisterKindGDB) >> + { >> + switch (num) >> + { >> + case gdb_eax : return gpr_eax; >> + case gdb_ebx : return gpr_ebx; >> + case gdb_ecx : return gpr_ecx; >> + case gdb_edx : return gpr_edx; >> + case gdb_esi : return gpr_esi; >> + case gdb_edi : return gpr_edi; >> + case gdb_ebp : return gpr_ebp; >> + case gdb_esp : return gpr_esp; >> + case gdb_eip : return gpr_eip; >> + case gdb_eflags : return gpr_eflags; >> + case gdb_cs : return gpr_cs; >> + case gdb_ss : return gpr_ss; >> + case gdb_ds : return gpr_ds; >> + case gdb_es : return gpr_es; >> + case gdb_fs : return gpr_fs; >> + case gdb_gs : return gpr_gs; >> + case gdb_stmm0 : return fpu_stmm0; >> + case gdb_stmm1 : return fpu_stmm1; >> + case gdb_stmm2 : return fpu_stmm2; >> + case gdb_stmm3 : return fpu_stmm3; >> + case gdb_stmm4 : return fpu_stmm4; >> + case gdb_stmm5 : return fpu_stmm5; >> + case gdb_stmm6 : return fpu_stmm6; >> + case gdb_stmm7 : return fpu_stmm7; >> + case gdb_fcw : return fpu_fcw; >> + case gdb_fsw : return fpu_fsw; >> + case gdb_ftw : return fpu_ftw; >> + case gdb_fpu_cs : return fpu_cs; >> + case gdb_ip : return fpu_ip; >> + case gdb_fpu_ds : return fpu_fos; >> + case gdb_dp : return fpu_foo; >> + case gdb_fop : return fpu_fop; >> + case gdb_xmm0 : return fpu_xmm0; >> + case gdb_xmm1 : return fpu_xmm1; >> + case gdb_xmm2 : return fpu_xmm2; >> + case gdb_xmm3 : return fpu_xmm3; >> + case gdb_xmm4 : return fpu_xmm4; >> + case gdb_xmm5 : return fpu_xmm5; >> + case gdb_xmm6 : return fpu_xmm6; >> + case gdb_xmm7 : return fpu_xmm7; >> + case gdb_mxcsr : return fpu_mxcsr; >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + else if (kind == eRegisterKindLLDB) >> + { >> + return num; >> + } >> + >> + return LLDB_INVALID_REGNUM; >> +} >> + >> +bool >> +RegisterContext_i386::HardwareSingleStep(bool enable) >> +{ >> + enum { TRACE_BIT = 0x100 }; >> + uint64_t eflags; >> + >> + if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) >> + return false; >> + >> + if (enable) >> + { >> + if (eflags & TRACE_BIT) >> + return true; >> + >> + eflags |= TRACE_BIT; >> + } >> + else >> + { >> + if (!(eflags & TRACE_BIT)) >> + return false; >> + >> + eflags &= ~TRACE_BIT; >> + } >> + >> + return WriteRegisterFromUnsigned(gpr_eflags, eflags); >> +} >> + >> +void >> +RegisterContext_i386::LogGPR(const char *title) >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); >> + if (log) >> + { >> + if (title) >> + log->Printf ("%s", title); >> + for (uint32_t i=0; i> + { >> + uint32_t reg = gpr_eax + i; >> + log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); >> + } >> + } >> +} >> + >> +bool >> +RegisterContext_i386::ReadGPR() >> +{ >> + bool result; >> + >> + ProcessMonitor &monitor = GetMonitor(); >> + result = monitor.ReadGPR(&user.regs); >> + LogGPR("RegisterContext_i386::ReadGPR()"); >> + return result; >> +} >> + >> +bool >> +RegisterContext_i386::ReadFPR() >> +{ >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.ReadFPR(&user.i387); >> +} >> Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp (revision 0) >> @@ -0,0 +1,195 @@ >> +//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#include "ProcessPOSIXLog.h" >> + >> +#include "lldb/Interpreter/Args.h" >> +#include "lldb/Core/StreamFile.h" >> + >> +#include "ProcessPOSIX.h" >> +#include "ProcessPOSIXLog.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> + >> +// We want to avoid global constructors where code needs to be run so here we >> +// control access to our static g_log_sp by hiding it in a singleton function >> +// that will construct the static g_lob_sp the first time this function is >> +// called. >> +static LogSP & >> +GetLog () >> +{ >> + static LogSP g_log_sp; >> + return g_log_sp; >> +} >> + >> +LogSP >> +ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask) >> +{ >> + LogSP log(GetLog ()); >> + if (log && mask) >> + { >> + uint32_t log_mask = log->GetMask().Get(); >> + if ((log_mask & mask) != mask) >> + return LogSP(); >> + } >> + return log; >> +} >> + >> +void >> +ProcessPOSIXLog::DisableLog (Args &args, Stream *feedback_strm) >> +{ >> + LogSP log (GetLog ()); >> + if (log) >> + { >> + uint32_t flag_bits = 0; >> + >> + const size_t argc = args.GetArgumentCount (); >> + if (argc > 0) >> + { >> + flag_bits = log->GetMask().Get(); >> + for (size_t i = 0; i < argc; ++i) >> + { >> + const char *arg = args.GetArgumentAtIndex (i); >> + >> + >> + if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~POSIX_LOG_ALL; >> + else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~POSIX_LOG_ASYNC; >> + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~POSIX_LOG_BREAKPOINTS; >> + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~POSIX_LOG_COMM; >> + else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~POSIX_LOG_DEFAULT; >> + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~POSIX_LOG_PACKETS; >> + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY; >> + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_SHORT; >> + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~POSIX_LOG_MEMORY_DATA_LONG; >> + else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~POSIX_LOG_PROCESS; >> + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~POSIX_LOG_PTRACE; >> + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~POSIX_LOG_REGISTERS; >> + else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~POSIX_LOG_STEP; >> + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~POSIX_LOG_THREAD; >> + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~POSIX_LOG_VERBOSE; >> + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~POSIX_LOG_WATCHPOINTS; >> + else >> + { >> + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); >> + ListLogCategories (feedback_strm); >> + } >> + >> + } >> + } >> + >> + if (flag_bits == 0) >> + GetLog ().reset(); >> + else >> + log->GetMask().Reset (flag_bits); >> + } >> + >> + return; >> +} >> + >> +LogSP >> +ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) >> +{ >> + // Try see if there already is a log - that way we can reuse its settings. >> + // We could reuse the log in toto, but we don't know that the stream is the same. >> + uint32_t flag_bits = 0; >> + LogSP log(GetLog ()); >> + if (log) >> + flag_bits = log->GetMask().Get(); >> + >> + // Now make a new log with this stream if one was provided >> + if (log_stream_sp) >> + { >> + log = make_shared(log_stream_sp); >> + GetLog () = log; >> + } >> + >> + if (log) >> + { >> + bool got_unknown_category = false; >> + const size_t argc = args.GetArgumentCount(); >> + for (size_t i=0; i> + { >> + const char *arg = args.GetArgumentAtIndex(i); >> + >> + if (::strcasecmp (arg, "all") == 0 ) flag_bits |= POSIX_LOG_ALL; >> + else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= POSIX_LOG_ASYNC; >> + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= POSIX_LOG_BREAKPOINTS; >> + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= POSIX_LOG_COMM; >> + else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= POSIX_LOG_DEFAULT; >> + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= POSIX_LOG_PACKETS; >> + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= POSIX_LOG_MEMORY; >> + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_SHORT; >> + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= POSIX_LOG_MEMORY_DATA_LONG; >> + else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= POSIX_LOG_PROCESS; >> + else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits |= POSIX_LOG_PTRACE; >> + else if (::strcasecmp (arg, "registers") == 0 ) flag_bits |= POSIX_LOG_REGISTERS; >> + else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= POSIX_LOG_STEP; >> + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= POSIX_LOG_THREAD; >> + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= POSIX_LOG_VERBOSE; >> + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= POSIX_LOG_WATCHPOINTS; >> + else >> + { >> + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); >> + if (got_unknown_category == false) >> + { >> + got_unknown_category = true; >> + ListLogCategories (feedback_strm); >> + } >> + } >> + } >> + if (flag_bits == 0) >> + flag_bits = POSIX_LOG_DEFAULT; >> + log->GetMask().Reset(flag_bits); >> + log->GetOptions().Reset(log_options); >> + } >> + return log; >> +} >> + >> +void >> +ProcessPOSIXLog::ListLogCategories (Stream *strm) >> +{ >> + strm->Printf ("Logging categories for '%s':\n" >> + " all - turn on all available logging categories\n" >> + " async - log asynchronous activity\n" >> + " break - log breakpoints\n" >> + " communication - log communication activity\n" >> + " default - enable the default set of logging categories for liblldb\n" >> + " packets - log gdb remote packets\n" >> + " memory - log memory reads and writes\n" >> + " data-short - log memory bytes for memory reads and writes for short transactions only\n" >> + " data-long - log memory bytes for memory reads and writes for all transactions\n" >> + " process - log process events and activities\n" >> +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> + " ptrace - log all calls to ptrace\n" >> +#endif >> + " registers - log register read/writes\n" >> + " thread - log thread events and activities\n" >> + " step - log step related activities\n" >> + " verbose - enable verbose logging\n" >> + " watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname); >> +} >> + >> + >> +void >> +ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...) >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask)); >> + if (log) >> + { >> + va_list args; >> + va_start (args, format); >> + log->VAPrintf (format, args); >> + va_end (args); >> + } >> +} >> + >> +int ProcessPOSIXLog::m_nestinglevel; >> +const char *ProcessPOSIXLog::m_pluginname = ""; >> Index: source/Plugins/Process/POSIX/ProcessPOSIX.h >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 0) >> @@ -0,0 +1,180 @@ >> +//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#ifndef liblldb_ProcessPOSIX_H_ >> +#define liblldb_ProcessPOSIX_H_ >> + >> +// C Includes >> + >> +// C++ Includes >> +#include >> + >> +// Other libraries and framework includes >> +#include "lldb/Target/Process.h" >> +#include "lldb/Target/UnixSignals.h" >> +#include "ProcessMessage.h" >> + >> +class ProcessMonitor; >> + >> +class ProcessPOSIX : >> + public lldb_private::Process >> +{ >> +public: >> + >> + //------------------------------------------------------------------ >> + // Constructors and destructors >> + //------------------------------------------------------------------ >> + ProcessPOSIX(lldb_private::Target& target, >> + lldb_private::Listener &listener); >> + >> + virtual >> + ~ProcessPOSIX(); >> + >> + //------------------------------------------------------------------ >> + // Process protocol. >> + //------------------------------------------------------------------ >> + virtual bool >> + CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); >> + >> + virtual lldb_private::Error >> + WillLaunch(lldb_private::Module *module); >> + >> + virtual lldb_private::Error >> + DoAttachToProcessWithID(lldb::pid_t pid); >> + >> + virtual lldb_private::Error >> + DoLaunch (lldb_private::Module *exe_module, >> + const lldb_private::ProcessLaunchInfo &launch_info); >> + >> + virtual void >> + DidLaunch(); >> + >> + virtual lldb_private::Error >> + DoResume(); >> + >> + virtual lldb_private::Error >> + DoHalt(bool &caused_stop); >> + >> + virtual lldb_private::Error >> + DoDetach(); >> + >> + virtual lldb_private::Error >> + DoSignal(int signal); >> + >> + virtual lldb_private::Error >> + DoDestroy(); >> + >> + virtual void >> + RefreshStateAfterStop(); >> + >> + virtual bool >> + IsAlive(); >> + >> + virtual size_t >> + DoReadMemory(lldb::addr_t vm_addr, >> + void *buf, >> + size_t size, >> + lldb_private::Error &error); >> + >> + virtual size_t >> + DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, >> + lldb_private::Error &error); >> + >> + virtual lldb::addr_t >> + DoAllocateMemory(size_t size, uint32_t permissions, >> + lldb_private::Error &error); >> + >> + virtual lldb_private::Error >> + DoDeallocateMemory(lldb::addr_t ptr); >> + >> + virtual size_t >> + GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); >> + >> + virtual lldb_private::Error >> + EnableBreakpoint(lldb_private::BreakpointSite *bp_site); >> + >> + virtual lldb_private::Error >> + DisableBreakpoint(lldb_private::BreakpointSite *bp_site); >> + >> + virtual uint32_t >> + UpdateThreadListIfNeeded(); >> + >> + virtual uint32_t >> + UpdateThreadList(lldb_private::ThreadList &old_thread_list, >> + lldb_private::ThreadList &new_thread_list) = 0; >> + >> + virtual lldb::ByteOrder >> + GetByteOrder() const; >> + >> + virtual lldb::addr_t >> + GetImageInfoAddress(); >> + >> + virtual size_t >> + PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); >> + >> + virtual size_t >> + GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); >> + >> + virtual size_t >> + GetSTDERR(char *buf, size_t len, lldb_private::Error &error); >> + >> + //-------------------------------------------------------------------------- >> + // ProcessPOSIX internal API. >> + >> + /// Registers the given message with this process. >> + void SendMessage(const ProcessMessage &message); >> + >> + ProcessMonitor & >> + GetMonitor() { assert(m_monitor); return *m_monitor; } >> + >> + lldb_private::UnixSignals & >> + GetUnixSignals(); >> + >> + const char * >> + GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action, >> + const char *default_path); >> + >> +protected: >> + /// Target byte order. >> + lldb::ByteOrder m_byte_order; >> + >> + /// Process monitor; >> + ProcessMonitor *m_monitor; >> + >> + /// The module we are executing. >> + lldb_private::Module *m_module; >> + >> + /// Message queue notifying this instance of inferior process state changes. >> + lldb_private::Mutex m_message_mutex; >> + std::queue m_message_queue; >> + >> + /// True when the process has entered a state of "limbo". >> + /// >> + /// This flag qualifies eStateStopped. It lets us know that when we >> + /// continue from this state the process will exit. Also, when true, >> + /// Process::m_exit_status is set. >> + bool m_in_limbo; >> + >> + /// Drive any exit events to completion. >> + bool m_exit_now; >> + >> + /// OS-specific signal set. >> + lldb_private::UnixSignals m_signals; >> + >> + /// Returns true if the process has exited. >> + bool HasExited(); >> + >> + /// Returns true if the process is stopped. >> + bool IsStopped(); >> + >> + typedef std::map MMapMap; >> + MMapMap m_addr_to_mmap_size; >> +}; >> + >> +#endif // liblldb_MacOSXProcess_H_ >> Index: source/Plugins/Process/POSIX/RegisterContext_i386.h >> =================================================================== >> --- source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) >> +++ source/Plugins/Process/POSIX/RegisterContext_i386.h (revision 0) >> @@ -0,0 +1,169 @@ >> +//===-- RegisterContext_i386.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_RegisterContext_i386_h_ >> +#define liblldb_RegisterContext_i386_h_ >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +// Project includes >> +#include "lldb/Core/Log.h" >> +#include "RegisterContextPOSIX.h" >> + >> +class RegisterContext_i386 : public RegisterContextPOSIX >> +{ >> +public: >> + RegisterContext_i386(lldb_private::Thread &thread, >> + uint32_t concreate_frame_idx); >> + >> + ~RegisterContext_i386(); >> + >> + void >> + Invalidate(); >> + >> + void >> + InvalidateAllRegisters(); >> + >> + size_t >> + GetRegisterCount(); >> + >> + const lldb_private::RegisterInfo * >> + GetRegisterInfoAtIndex(uint32_t reg); >> + >> + size_t >> + GetRegisterSetCount(); >> + >> + const lldb_private::RegisterSet * >> + GetRegisterSet(uint32_t set); >> + >> + static unsigned >> + GetRegisterIndexFromOffset(unsigned offset); >> + >> + static const char * >> + GetRegisterName(unsigned reg); >> + >> + bool >> + ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); >> + >> + bool >> + ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); >> + >> + virtual bool >> + ReadRegister(const lldb_private::RegisterInfo *reg_info, >> + lldb_private::RegisterValue &value); >> + >> + bool >> + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); >> + >> + bool >> + WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); >> + >> + bool >> + WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, >> + uint32_t data_offset = 0); >> + >> + virtual bool >> + WriteRegister(const lldb_private::RegisterInfo *reg_info, >> + const lldb_private::RegisterValue &value); >> + >> + bool >> + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); >> + >> + uint32_t >> + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); >> + >> + bool >> + HardwareSingleStep(bool enable); >> + >> + bool >> + UpdateAfterBreakpoint(); >> + >> + struct GPR >> + { >> + uint32_t ebx; >> + uint32_t ecx; >> + uint32_t edx; >> + uint32_t esi; >> + uint32_t edi; >> + uint32_t ebp; >> + uint32_t eax; >> + uint32_t ds; >> + uint32_t es; >> + uint32_t fs; >> + uint32_t gs; >> + uint32_t orig_ax; >> + uint32_t eip; >> + uint32_t cs; >> + uint32_t eflags; >> + uint32_t esp; >> + uint32_t ss; >> + }; >> + >> + struct MMSReg >> + { >> + uint8_t bytes[8]; >> + }; >> + >> + struct XMMReg >> + { >> + uint8_t bytes[16]; >> + }; >> + >> + struct FPU >> + { >> + uint16_t fcw; >> + uint16_t fsw; >> + uint16_t ftw; >> + uint16_t fop; >> + uint32_t ip; >> + uint32_t cs; >> + uint32_t foo; >> + uint32_t fos; >> + uint32_t mxcsr; >> + uint32_t reserved; >> + MMSReg stmm[8]; >> + XMMReg xmm[8]; >> + uint32_t pad[56]; >> + }; >> + >> + // A user area like this no longer exists on FreeBSD >> + // making this a Linux artifact. Nonetheless, it is safe >> + // leaving it here while the code is being cleaned up and generalized. >> + >> + struct UserArea >> + { >> + GPR regs; // General purpose registers. >> + int32_t fpvalid; // True if FPU is being used. >> + FPU i387; // FPU registers. >> + uint32_t tsize; // Text segment size. >> + uint32_t dsize; // Data segment size. >> + uint32_t ssize; // Stack segment size. >> + uint32_t start_code; // VM address of text. >> + uint32_t start_stack; // VM address of stack bottom (top in rsp). >> + int32_t signal; // Signal causing core dump. >> + int32_t reserved; // Unused. >> + uint32_t ar0; // Location of GPR's. >> + FPU* fpstate; // Location of FPR's. >> + uint32_t magic; // Identifier for core dumps. >> + char u_comm[32]; // Command causing core dump. >> + uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). >> + }; >> +private: >> + UserArea user; >> + >> + ProcessMonitor &GetMonitor(); >> + >> + void LogGPR(const char *title); >> + >> + bool ReadGPR(); >> + bool ReadFPR(); >> +}; >> + >> +#endif // #ifndef liblldb_RegisterContext_i386_h_ >> Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 0) >> @@ -0,0 +1,757 @@ >> +//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#include >> +#include >> +#include >> + >> +#include "lldb/Core/DataBufferHeap.h" >> +#include "lldb/Core/DataExtractor.h" >> +#include "lldb/Core/Scalar.h" >> +#include "lldb/Target/Thread.h" >> +#include "lldb/Host/Endian.h" >> + >> +#include "ProcessPOSIX.h" >> +#include "ProcessMonitor.h" >> +#include "RegisterContext_x86_64.h" >> + >> +using namespace lldb_private; >> +using namespace lldb; >> + >> +// Internal codes for all x86_64 registers. >> +enum >> +{ >> + k_first_gpr, >> + gpr_rax = k_first_gpr, >> + gpr_rbx, >> + gpr_rcx, >> + gpr_rdx, >> + gpr_rdi, >> + gpr_rsi, >> + gpr_rbp, >> + gpr_rsp, >> + gpr_r8, >> + gpr_r9, >> + gpr_r10, >> + gpr_r11, >> + gpr_r12, >> + gpr_r13, >> + gpr_r14, >> + gpr_r15, >> + gpr_rip, >> + gpr_rflags, >> + gpr_cs, >> + gpr_fs, >> + gpr_gs, >> + gpr_ss, >> + gpr_ds, >> + gpr_es, >> + k_last_gpr = gpr_es, >> + >> + k_first_fpr, >> + fpu_fcw = k_first_fpr, >> + fpu_fsw, >> + fpu_ftw, >> + fpu_fop, >> + fpu_ip, >> + fpu_cs, >> + fpu_dp, >> + fpu_ds, >> + fpu_mxcsr, >> + fpu_mxcsrmask, >> + fpu_stmm0, >> + fpu_stmm1, >> + fpu_stmm2, >> + fpu_stmm3, >> + fpu_stmm4, >> + fpu_stmm5, >> + fpu_stmm6, >> + fpu_stmm7, >> + fpu_xmm0, >> + fpu_xmm1, >> + fpu_xmm2, >> + fpu_xmm3, >> + fpu_xmm4, >> + fpu_xmm5, >> + fpu_xmm6, >> + fpu_xmm7, >> + fpu_xmm8, >> + fpu_xmm9, >> + fpu_xmm10, >> + fpu_xmm11, >> + fpu_xmm12, >> + fpu_xmm13, >> + fpu_xmm14, >> + fpu_xmm15, >> + k_last_fpr = fpu_xmm15, >> + >> + k_num_registers, >> + k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, >> + k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 >> +}; >> + >> +// Number of register sets provided by this context. >> +enum >> +{ >> + k_num_register_sets = 2 >> +}; >> + >> +enum gcc_dwarf_regnums >> +{ >> + gcc_dwarf_gpr_rax = 0, >> + gcc_dwarf_gpr_rdx, >> + gcc_dwarf_gpr_rcx, >> + gcc_dwarf_gpr_rbx, >> + gcc_dwarf_gpr_rsi, >> + gcc_dwarf_gpr_rdi, >> + gcc_dwarf_gpr_rbp, >> + gcc_dwarf_gpr_rsp, >> + gcc_dwarf_gpr_r8, >> + gcc_dwarf_gpr_r9, >> + gcc_dwarf_gpr_r10, >> + gcc_dwarf_gpr_r11, >> + gcc_dwarf_gpr_r12, >> + gcc_dwarf_gpr_r13, >> + gcc_dwarf_gpr_r14, >> + gcc_dwarf_gpr_r15, >> + gcc_dwarf_gpr_rip, >> + gcc_dwarf_fpu_xmm0, >> + gcc_dwarf_fpu_xmm1, >> + gcc_dwarf_fpu_xmm2, >> + gcc_dwarf_fpu_xmm3, >> + gcc_dwarf_fpu_xmm4, >> + gcc_dwarf_fpu_xmm5, >> + gcc_dwarf_fpu_xmm6, >> + gcc_dwarf_fpu_xmm7, >> + gcc_dwarf_fpu_xmm8, >> + gcc_dwarf_fpu_xmm9, >> + gcc_dwarf_fpu_xmm10, >> + gcc_dwarf_fpu_xmm11, >> + gcc_dwarf_fpu_xmm12, >> + gcc_dwarf_fpu_xmm13, >> + gcc_dwarf_fpu_xmm14, >> + gcc_dwarf_fpu_xmm15, >> + gcc_dwarf_fpu_stmm0, >> + gcc_dwarf_fpu_stmm1, >> + gcc_dwarf_fpu_stmm2, >> + gcc_dwarf_fpu_stmm3, >> + gcc_dwarf_fpu_stmm4, >> + gcc_dwarf_fpu_stmm5, >> + gcc_dwarf_fpu_stmm6, >> + gcc_dwarf_fpu_stmm7 >> +}; >> + >> +enum gdb_regnums >> +{ >> + gdb_gpr_rax = 0, >> + gdb_gpr_rbx = 1, >> + gdb_gpr_rcx = 2, >> + gdb_gpr_rdx = 3, >> + gdb_gpr_rsi = 4, >> + gdb_gpr_rdi = 5, >> + gdb_gpr_rbp = 6, >> + gdb_gpr_rsp = 7, >> + gdb_gpr_r8 = 8, >> + gdb_gpr_r9 = 9, >> + gdb_gpr_r10 = 10, >> + gdb_gpr_r11 = 11, >> + gdb_gpr_r12 = 12, >> + gdb_gpr_r13 = 13, >> + gdb_gpr_r14 = 14, >> + gdb_gpr_r15 = 15, >> + gdb_gpr_rip = 16, >> + gdb_gpr_rflags = 17, >> + gdb_gpr_cs = 18, >> + gdb_gpr_ss = 19, >> + gdb_gpr_ds = 20, >> + gdb_gpr_es = 21, >> + gdb_gpr_fs = 22, >> + gdb_gpr_gs = 23, >> + gdb_fpu_stmm0 = 24, >> + gdb_fpu_stmm1 = 25, >> + gdb_fpu_stmm2 = 26, >> + gdb_fpu_stmm3 = 27, >> + gdb_fpu_stmm4 = 28, >> + gdb_fpu_stmm5 = 29, >> + gdb_fpu_stmm6 = 30, >> + gdb_fpu_stmm7 = 31, >> + gdb_fpu_fcw = 32, >> + gdb_fpu_fsw = 33, >> + gdb_fpu_ftw = 34, >> + gdb_fpu_cs = 35, >> + gdb_fpu_ip = 36, >> + gdb_fpu_ds = 37, >> + gdb_fpu_dp = 38, >> + gdb_fpu_fop = 39, >> + gdb_fpu_xmm0 = 40, >> + gdb_fpu_xmm1 = 41, >> + gdb_fpu_xmm2 = 42, >> + gdb_fpu_xmm3 = 43, >> + gdb_fpu_xmm4 = 44, >> + gdb_fpu_xmm5 = 45, >> + gdb_fpu_xmm6 = 46, >> + gdb_fpu_xmm7 = 47, >> + gdb_fpu_xmm8 = 48, >> + gdb_fpu_xmm9 = 49, >> + gdb_fpu_xmm10 = 50, >> + gdb_fpu_xmm11 = 51, >> + gdb_fpu_xmm12 = 52, >> + gdb_fpu_xmm13 = 53, >> + gdb_fpu_xmm14 = 54, >> + gdb_fpu_xmm15 = 55, >> + gdb_fpu_mxcsr = 56 >> +}; >> + >> +static const >> +uint32_t g_gpr_regnums[k_num_gpr_registers] = >> +{ >> + gpr_rax, >> + gpr_rbx, >> + gpr_rcx, >> + gpr_rdx, >> + gpr_rdi, >> + gpr_rsi, >> + gpr_rbp, >> + gpr_rsp, >> + gpr_r8, >> + gpr_r9, >> + gpr_r10, >> + gpr_r11, >> + gpr_r12, >> + gpr_r13, >> + gpr_r14, >> + gpr_r15, >> + gpr_rip, >> + gpr_rflags, >> + gpr_cs, >> + gpr_fs, >> + gpr_gs, >> + gpr_ss, >> + gpr_ds, >> + gpr_es >> +}; >> + >> +static const uint32_t >> +g_fpu_regnums[k_num_fpu_registers] = >> +{ >> + fpu_fcw, >> + fpu_fsw, >> + fpu_ftw, >> + fpu_fop, >> + fpu_ip, >> + fpu_cs, >> + fpu_dp, >> + fpu_ds, >> + fpu_mxcsr, >> + fpu_mxcsrmask, >> + fpu_stmm0, >> + fpu_stmm1, >> + fpu_stmm2, >> + fpu_stmm3, >> + fpu_stmm4, >> + fpu_stmm5, >> + fpu_stmm6, >> + fpu_stmm7, >> + fpu_xmm0, >> + fpu_xmm1, >> + fpu_xmm2, >> + fpu_xmm3, >> + fpu_xmm4, >> + fpu_xmm5, >> + fpu_xmm6, >> + fpu_xmm7, >> + fpu_xmm8, >> + fpu_xmm9, >> + fpu_xmm10, >> + fpu_xmm11, >> + fpu_xmm12, >> + fpu_xmm13, >> + fpu_xmm14, >> + fpu_xmm15 >> +}; >> + >> +static const RegisterSet >> +g_reg_sets[k_num_register_sets] = >> +{ >> + { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, >> + { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } >> +}; >> + >> +// Computes the offset of the given GPR in the user data area. >> +#define GPR_OFFSET(regname) \ >> + (offsetof(RegisterContext_x86_64::UserArea, regs) + \ >> + offsetof(GPR, regname)) >> + >> +// Computes the offset of the given FPR in the user data area. >> +#define FPR_OFFSET(regname) \ >> + (offsetof(RegisterContext_x86_64::UserArea, i387) + \ >> + offsetof(RegisterContext_x86_64::FPU, regname)) >> + >> +// Number of bytes needed to represent a GPR. >> +#define GPR_SIZE(reg) sizeof(((GPR*)NULL)->reg) >> + >> +// Number of bytes needed to represent a FPR. >> +#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FPU*)NULL)->reg) >> + >> +// Number of bytes needed to represent the i'th FP register. >> +#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes) >> + >> +// Number of bytes needed to represent an XMM register. >> +#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg) >> + >> +#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ >> + { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ >> + eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } >> + >> +#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ >> + { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ >> + eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } >> + >> +#define DEFINE_FP(reg, i) \ >> + { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> + eFormatVectorOfUInt8, \ >> + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ >> + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } >> + >> +#define DEFINE_XMM(reg, i) \ >> + { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ >> + eFormatVectorOfUInt8, \ >> + { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ >> + LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } >> + >> +#define REG_CONTEXT_SIZE (sizeof(GPR) + sizeof(RegisterContext_x86_64::FPU)) >> + >> +static RegisterInfo >> +g_register_infos[k_num_registers] = >> +{ >> + // General purpose registers. >> + DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), >> + DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), >> + DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), >> + DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), >> + DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), >> + DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), >> + DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), >> + DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), >> + DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), >> + DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), >> + DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), >> + DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), >> + DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), >> + DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), >> + DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), >> + DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), >> + DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), >> + DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), >> + DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), >> + DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), >> + DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), >> + DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), >> + DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), >> + DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), >> + >> + // i387 Floating point registers. >> + DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), >> + DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), >> + DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), >> + DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), >> + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), >> + // FIXME: Extract segment from ip. >> + DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), >> + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), >> + // FIXME: Extract segment from dp. >> + DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), >> + DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), >> + DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), >> + >> + // FP registers. >> + DEFINE_FP(stmm, 0), >> + DEFINE_FP(stmm, 1), >> + DEFINE_FP(stmm, 2), >> + DEFINE_FP(stmm, 3), >> + DEFINE_FP(stmm, 4), >> + DEFINE_FP(stmm, 5), >> + DEFINE_FP(stmm, 6), >> + DEFINE_FP(stmm, 7), >> + >> + // XMM registers >> + DEFINE_XMM(xmm, 0), >> + DEFINE_XMM(xmm, 1), >> + DEFINE_XMM(xmm, 2), >> + DEFINE_XMM(xmm, 3), >> + DEFINE_XMM(xmm, 4), >> + DEFINE_XMM(xmm, 5), >> + DEFINE_XMM(xmm, 6), >> + DEFINE_XMM(xmm, 7), >> + DEFINE_XMM(xmm, 8), >> + DEFINE_XMM(xmm, 9), >> + DEFINE_XMM(xmm, 10), >> + DEFINE_XMM(xmm, 11), >> + DEFINE_XMM(xmm, 12), >> + DEFINE_XMM(xmm, 13), >> + DEFINE_XMM(xmm, 14), >> + DEFINE_XMM(xmm, 15) >> +}; >> + >> +static unsigned GetRegOffset(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register number."); >> + return g_register_infos[reg].byte_offset; >> +} >> + >> +static unsigned GetRegSize(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register number."); >> + return g_register_infos[reg].byte_size; >> +} >> + >> +static bool IsGPR(unsigned reg) >> +{ >> + return reg <= k_last_gpr; // GPR's come first. >> +} >> + >> +static bool IsFPR(unsigned reg) >> +{ >> + return (k_first_fpr <= reg && reg <= k_last_fpr); >> +} >> + >> +RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread, >> + uint32_t concrete_frame_idx) >> + : RegisterContextPOSIX(thread, concrete_frame_idx) >> +{ >> +} >> + >> +RegisterContext_x86_64::~RegisterContext_x86_64() >> +{ >> +} >> + >> +ProcessMonitor & >> +RegisterContext_x86_64::GetMonitor() >> +{ >> + ProcessPOSIX *process = static_cast(CalculateProcess()); >> + return process->GetMonitor(); >> +} >> + >> +void >> +RegisterContext_x86_64::Invalidate() >> +{ >> +} >> + >> +void >> +RegisterContext_x86_64::InvalidateAllRegisters() >> +{ >> +} >> + >> +size_t >> +RegisterContext_x86_64::GetRegisterCount() >> +{ >> + return k_num_registers; >> +} >> + >> +const RegisterInfo * >> +RegisterContext_x86_64::GetRegisterInfoAtIndex(uint32_t reg) >> +{ >> + if (reg < k_num_registers) >> + return &g_register_infos[reg]; >> + else >> + return NULL; >> +} >> + >> +size_t >> +RegisterContext_x86_64::GetRegisterSetCount() >> +{ >> + return k_num_register_sets; >> +} >> + >> +const RegisterSet * >> +RegisterContext_x86_64::GetRegisterSet(uint32_t set) >> +{ >> + if (set < k_num_register_sets) >> + return &g_reg_sets[set]; >> + else >> + return NULL; >> +} >> + >> +unsigned >> +RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset) >> +{ >> + unsigned reg; >> + for (reg = 0; reg < k_num_registers; reg++) >> + { >> + if (g_register_infos[reg].byte_offset == offset) >> + break; >> + } >> + assert(reg < k_num_registers && "Invalid register offset."); >> + return reg; >> +} >> + >> +const char * >> +RegisterContext_x86_64::GetRegisterName(unsigned reg) >> +{ >> + assert(reg < k_num_registers && "Invalid register offset."); >> + return g_register_infos[reg].name; >> +} >> + >> +bool >> +RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, >> + RegisterValue &value) >> +{ >> + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.ReadRegisterValue(GetRegOffset(reg), GetRegSize(reg), value); >> +} >> + >> +bool >> +RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) >> +{ >> + data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); >> + if (data_sp && ReadGPR () && ReadFPR ()) >> + { >> + uint8_t *dst = data_sp->GetBytes(); >> + ::memcpy (dst, &user.regs, sizeof(user.regs)); >> + dst += sizeof(user.regs); >> + >> + ::memcpy (dst, &user.i387, sizeof(user.i387)); >> + return true; >> + } >> + return false; >> +} >> + >> +bool >> +RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, >> + const lldb_private::RegisterValue &value) >> +{ >> + const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.WriteRegisterValue(GetRegOffset(reg), value); >> +} >> + >> +bool >> +RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) >> +{ >> + if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) >> + { >> + const uint8_t *src = data_sp->GetBytes(); >> + ::memcpy (&user.regs, src, sizeof(user.regs)); >> + src += sizeof(user.regs); >> + >> + ::memcpy (&user.i387, src, sizeof(user.i387)); >> + return WriteGPR() & WriteFPR(); >> + } >> + return false; >> +} >> + >> +bool >> +RegisterContext_x86_64::UpdateAfterBreakpoint() >> +{ >> + // PC points one byte past the int3 responsible for the breakpoint. >> + lldb::addr_t pc; >> + >> + if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) >> + return false; >> + >> + SetPC(pc - 1); >> + return true; >> +} >> + >> +uint32_t >> +RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, >> + uint32_t num) >> +{ >> + if (kind == eRegisterKindGeneric) >> + { >> + switch (num) >> + { >> + case LLDB_REGNUM_GENERIC_PC: return gpr_rip; >> + case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; >> + case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; >> + case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; >> + case LLDB_REGNUM_GENERIC_RA: >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + >> + if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) >> + { >> + switch (num) >> + { >> + case gcc_dwarf_gpr_rax: return gpr_rax; >> + case gcc_dwarf_gpr_rdx: return gpr_rdx; >> + case gcc_dwarf_gpr_rcx: return gpr_rcx; >> + case gcc_dwarf_gpr_rbx: return gpr_rbx; >> + case gcc_dwarf_gpr_rsi: return gpr_rsi; >> + case gcc_dwarf_gpr_rdi: return gpr_rdi; >> + case gcc_dwarf_gpr_rbp: return gpr_rbp; >> + case gcc_dwarf_gpr_rsp: return gpr_rsp; >> + case gcc_dwarf_gpr_r8: return gpr_r8; >> + case gcc_dwarf_gpr_r9: return gpr_r9; >> + case gcc_dwarf_gpr_r10: return gpr_r10; >> + case gcc_dwarf_gpr_r11: return gpr_r11; >> + case gcc_dwarf_gpr_r12: return gpr_r12; >> + case gcc_dwarf_gpr_r13: return gpr_r13; >> + case gcc_dwarf_gpr_r14: return gpr_r14; >> + case gcc_dwarf_gpr_r15: return gpr_r15; >> + case gcc_dwarf_gpr_rip: return gpr_rip; >> + case gcc_dwarf_fpu_xmm0: return fpu_xmm0; >> + case gcc_dwarf_fpu_xmm1: return fpu_xmm1; >> + case gcc_dwarf_fpu_xmm2: return fpu_xmm2; >> + case gcc_dwarf_fpu_xmm3: return fpu_xmm3; >> + case gcc_dwarf_fpu_xmm4: return fpu_xmm4; >> + case gcc_dwarf_fpu_xmm5: return fpu_xmm5; >> + case gcc_dwarf_fpu_xmm6: return fpu_xmm6; >> + case gcc_dwarf_fpu_xmm7: return fpu_xmm7; >> + case gcc_dwarf_fpu_xmm8: return fpu_xmm8; >> + case gcc_dwarf_fpu_xmm9: return fpu_xmm9; >> + case gcc_dwarf_fpu_xmm10: return fpu_xmm10; >> + case gcc_dwarf_fpu_xmm11: return fpu_xmm11; >> + case gcc_dwarf_fpu_xmm12: return fpu_xmm12; >> + case gcc_dwarf_fpu_xmm13: return fpu_xmm13; >> + case gcc_dwarf_fpu_xmm14: return fpu_xmm14; >> + case gcc_dwarf_fpu_xmm15: return fpu_xmm15; >> + case gcc_dwarf_fpu_stmm0: return fpu_stmm0; >> + case gcc_dwarf_fpu_stmm1: return fpu_stmm1; >> + case gcc_dwarf_fpu_stmm2: return fpu_stmm2; >> + case gcc_dwarf_fpu_stmm3: return fpu_stmm3; >> + case gcc_dwarf_fpu_stmm4: return fpu_stmm4; >> + case gcc_dwarf_fpu_stmm5: return fpu_stmm5; >> + case gcc_dwarf_fpu_stmm6: return fpu_stmm6; >> + case gcc_dwarf_fpu_stmm7: return fpu_stmm7; >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + >> + if (kind == eRegisterKindGDB) >> + { >> + switch (num) >> + { >> + case gdb_gpr_rax : return gpr_rax; >> + case gdb_gpr_rbx : return gpr_rbx; >> + case gdb_gpr_rcx : return gpr_rcx; >> + case gdb_gpr_rdx : return gpr_rdx; >> + case gdb_gpr_rsi : return gpr_rsi; >> + case gdb_gpr_rdi : return gpr_rdi; >> + case gdb_gpr_rbp : return gpr_rbp; >> + case gdb_gpr_rsp : return gpr_rsp; >> + case gdb_gpr_r8 : return gpr_r8; >> + case gdb_gpr_r9 : return gpr_r9; >> + case gdb_gpr_r10 : return gpr_r10; >> + case gdb_gpr_r11 : return gpr_r11; >> + case gdb_gpr_r12 : return gpr_r12; >> + case gdb_gpr_r13 : return gpr_r13; >> + case gdb_gpr_r14 : return gpr_r14; >> + case gdb_gpr_r15 : return gpr_r15; >> + case gdb_gpr_rip : return gpr_rip; >> + case gdb_gpr_rflags : return gpr_rflags; >> + case gdb_gpr_cs : return gpr_cs; >> + case gdb_gpr_ss : return gpr_ss; >> + case gdb_gpr_ds : return gpr_ds; >> + case gdb_gpr_es : return gpr_es; >> + case gdb_gpr_fs : return gpr_fs; >> + case gdb_gpr_gs : return gpr_gs; >> + case gdb_fpu_stmm0 : return fpu_stmm0; >> + case gdb_fpu_stmm1 : return fpu_stmm1; >> + case gdb_fpu_stmm2 : return fpu_stmm2; >> + case gdb_fpu_stmm3 : return fpu_stmm3; >> + case gdb_fpu_stmm4 : return fpu_stmm4; >> + case gdb_fpu_stmm5 : return fpu_stmm5; >> + case gdb_fpu_stmm6 : return fpu_stmm6; >> + case gdb_fpu_stmm7 : return fpu_stmm7; >> + case gdb_fpu_fcw : return fpu_fcw; >> + case gdb_fpu_fsw : return fpu_fsw; >> + case gdb_fpu_ftw : return fpu_ftw; >> + case gdb_fpu_cs : return fpu_cs; >> + case gdb_fpu_ip : return fpu_ip; >> + case gdb_fpu_ds : return fpu_ds; >> + case gdb_fpu_dp : return fpu_dp; >> + case gdb_fpu_fop : return fpu_fop; >> + case gdb_fpu_xmm0 : return fpu_xmm0; >> + case gdb_fpu_xmm1 : return fpu_xmm1; >> + case gdb_fpu_xmm2 : return fpu_xmm2; >> + case gdb_fpu_xmm3 : return fpu_xmm3; >> + case gdb_fpu_xmm4 : return fpu_xmm4; >> + case gdb_fpu_xmm5 : return fpu_xmm5; >> + case gdb_fpu_xmm6 : return fpu_xmm6; >> + case gdb_fpu_xmm7 : return fpu_xmm7; >> + case gdb_fpu_xmm8 : return fpu_xmm8; >> + case gdb_fpu_xmm9 : return fpu_xmm9; >> + case gdb_fpu_xmm10 : return fpu_xmm10; >> + case gdb_fpu_xmm11 : return fpu_xmm11; >> + case gdb_fpu_xmm12 : return fpu_xmm12; >> + case gdb_fpu_xmm13 : return fpu_xmm13; >> + case gdb_fpu_xmm14 : return fpu_xmm14; >> + case gdb_fpu_xmm15 : return fpu_xmm15; >> + case gdb_fpu_mxcsr : return fpu_mxcsr; >> + default: >> + return LLDB_INVALID_REGNUM; >> + } >> + } >> + else if (kind == eRegisterKindLLDB) >> + { >> + return num; >> + } >> + >> + return LLDB_INVALID_REGNUM; >> +} >> + >> +bool >> +RegisterContext_x86_64::HardwareSingleStep(bool enable) >> +{ >> + enum { TRACE_BIT = 0x100 }; >> + uint64_t rflags; >> + >> + if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) >> + return false; >> + >> + if (enable) >> + { >> + if (rflags & TRACE_BIT) >> + return true; >> + >> + rflags |= TRACE_BIT; >> + } >> + else >> + { >> + if (!(rflags & TRACE_BIT)) >> + return false; >> + >> + rflags &= ~TRACE_BIT; >> + } >> + >> + return WriteRegisterFromUnsigned(gpr_rflags, rflags); >> +} >> + >> +bool >> +RegisterContext_x86_64::ReadGPR() >> +{ >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.ReadGPR(&user.regs); >> +} >> + >> +bool >> +RegisterContext_x86_64::ReadFPR() >> +{ >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.ReadFPR(&user.i387); >> +} >> + >> +bool >> +RegisterContext_x86_64::WriteGPR() >> +{ >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.WriteGPR(&user.regs); >> +} >> + >> +bool >> +RegisterContext_x86_64::WriteFPR() >> +{ >> + ProcessMonitor &monitor = GetMonitor(); >> + return monitor.WriteFPR(&user.i387); >> +} >> Index: source/Plugins/Process/POSIX/ProcessPOSIXLog.h >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessPOSIXLog.h (revision 0) >> @@ -0,0 +1,106 @@ >> +//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ >> +#define liblldb_ProcessLinuxLog_h_ >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> + >> +// Project includes >> +#include "lldb/Core/Log.h" >> + >> +#define POSIX_LOG_VERBOSE (1u << 0) >> +#define POSIX_LOG_PROCESS (1u << 1) >> +#define POSIX_LOG_THREAD (1u << 2) >> +#define POSIX_LOG_PACKETS (1u << 3) >> +#define POSIX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls >> +#define POSIX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes >> +#define POSIX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes >> +#define POSIX_LOG_BREAKPOINTS (1u << 7) >> +#define POSIX_LOG_WATCHPOINTS (1u << 8) >> +#define POSIX_LOG_STEP (1u << 9) >> +#define POSIX_LOG_COMM (1u << 10) >> +#define POSIX_LOG_ASYNC (1u << 11) >> +#define POSIX_LOG_PTRACE (1u << 12) >> +#define POSIX_LOG_REGISTERS (1u << 13) >> +#define POSIX_LOG_ALL (UINT32_MAX) >> +#define POSIX_LOG_DEFAULT POSIX_LOG_PACKETS >> + >> +// The size which determines "short memory reads/writes". >> +#define POSIX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) >> + >> +class ProcessPOSIXLog >> +{ >> + static int m_nestinglevel; >> + static const char *m_pluginname; >> + >> +public: >> + static void >> + RegisterPluginName(const char *pluginName) >> + { >> + m_pluginname = pluginName; >> + } >> + >> + >> + static lldb::LogSP >> + GetLogIfAllCategoriesSet(uint32_t mask = 0); >> + >> + static void >> + DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); >> + >> + static lldb::LogSP >> + EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, >> + lldb_private::Args &args, lldb_private::Stream *feedback_strm); >> + >> + static void >> + ListLogCategories (lldb_private::Stream *strm); >> + >> + static void >> + LogIf (uint32_t mask, const char *format, ...); >> + >> + // The following functions can be used to enable the client to limit >> + // logging to only the top level function calls. This is useful for >> + // recursive functions. FIXME: not thread safe! >> + // Example: >> + // void NestingFunc() { >> + // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL)); >> + // if (log) >> + // { >> + // ProcessLinuxLog::IncNestLevel(); >> + // if (ProcessLinuxLog::AtTopNestLevel()) >> + // log->Print(msg); >> + // } >> + // NestingFunc(); >> + // if (log) >> + // ProcessLinuxLog::DecNestLevel(); >> + // } >> + >> + static bool >> + AtTopNestLevel() >> + { >> + return m_nestinglevel == 1; >> + } >> + >> + static void >> + IncNestLevel() >> + { >> + ++m_nestinglevel; >> + } >> + >> + static void >> + DecNestLevel() >> + { >> + --m_nestinglevel; >> + assert(m_nestinglevel >= 0); >> + } >> +}; >> + >> +#endif // liblldb_ProcessLinuxLog_h_ >> Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h >> =================================================================== >> --- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) >> +++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 0) >> @@ -0,0 +1,143 @@ >> +//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#ifndef liblldb_RegisterContext_x86_64_H_ >> +#define liblldb_RegisterContext_x86_64_H_ >> + >> +#include "lldb/Core/Log.h" >> +#include "RegisterContextPOSIX.h" >> + >> +#ifdef __FreeBSD__ >> +#include "RegisterContextFreeBSD_x86_64.h" >> +#endif >> + >> +#ifdef __linux__ >> +#include "RegisterContextLinux_x86_64.h" >> +#endif >> + >> +class ProcessMonitor; >> + >> +class RegisterContext_x86_64 >> + : public RegisterContextPOSIX >> +{ >> +public: >> + RegisterContext_x86_64 (lldb_private::Thread &thread, >> + uint32_t concrete_frame_idx); >> + >> + ~RegisterContext_x86_64(); >> + >> + void >> + Invalidate(); >> + >> + void >> + InvalidateAllRegisters(); >> + >> + size_t >> + GetRegisterCount(); >> + >> + const lldb_private::RegisterInfo * >> + GetRegisterInfoAtIndex(uint32_t reg); >> + >> + size_t >> + GetRegisterSetCount(); >> + >> + const lldb_private::RegisterSet * >> + GetRegisterSet(uint32_t set); >> + >> + static unsigned >> + GetRegisterIndexFromOffset(unsigned offset); >> + >> + static const char * >> + GetRegisterName(unsigned reg); >> + >> + virtual bool >> + ReadRegister(const lldb_private::RegisterInfo *reg_info, >> + lldb_private::RegisterValue &value); >> + >> + bool >> + ReadAllRegisterValues(lldb::DataBufferSP &data_sp); >> + >> + virtual bool >> + WriteRegister(const lldb_private::RegisterInfo *reg_info, >> + const lldb_private::RegisterValue &value); >> + >> + bool >> + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); >> + >> + uint32_t >> + ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); >> + >> + bool >> + HardwareSingleStep(bool enable); >> + >> + bool >> + UpdateAfterBreakpoint(); >> + >> + struct MMSReg >> + { >> + uint8_t bytes[10]; >> + uint8_t pad[6]; >> + }; >> + >> + struct XMMReg >> + { >> + uint8_t bytes[16]; >> + }; >> + >> + struct FPU >> + { >> + uint16_t fcw; >> + uint16_t fsw; >> + uint16_t ftw; >> + uint16_t fop; >> + uint64_t ip; >> + uint64_t dp; >> + uint32_t mxcsr; >> + uint32_t mxcsrmask; >> + MMSReg stmm[8]; >> + XMMReg xmm[16]; >> + uint32_t padding[24]; >> + }; >> + >> + struct UserArea >> + { >> + GPR regs; // General purpose registers. >> + int32_t fpvalid; // True if FPU is being used. >> + int32_t pad0; >> + FPU i387; // FPU registers. >> + uint64_t tsize; // Text segment size. >> + uint64_t dsize; // Data segment size. >> + uint64_t ssize; // Stack segment size. >> + uint64_t start_code; // VM address of text. >> + uint64_t start_stack; // VM address of stack bottom (top in rsp). >> + int64_t signal; // Signal causing core dump. >> + int32_t reserved; // Unused. >> + int32_t pad1; >> + uint64_t ar0; // Location of GPR's. >> + FPU* fpstate; // Location of FPR's. >> + uint64_t magic; // Identifier for core dumps. >> + char u_comm[32]; // Command causing core dump. >> + uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). >> + uint64_t error_code; // CPU error code. >> + uint64_t fault_address; // Control register CR3. >> + }; >> + >> +private: >> + UserArea user; >> + >> + ProcessMonitor &GetMonitor(); >> + >> + bool ReadGPR(); >> + bool ReadFPR(); >> + >> + bool WriteGPR(); >> + bool WriteFPR(); >> +}; >> + >> +#endif // #ifndef liblldb_RegisterContext_x86_64_H_ >> Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h >> =================================================================== >> --- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) >> +++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 0) >> @@ -0,0 +1,40 @@ >> +//===-- RegisterContextPOSIX.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_RegisterContextPOSIX_H_ >> +#define liblldb_RegisterContextPOSIX_H_ >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Target/RegisterContext.h" >> + >> +//------------------------------------------------------------------------------ >> +/// @class RegisterContextPOSIX >> +/// >> +/// @brief Extends RegisterClass with a few virtual operations useful on POSIX. >> +class RegisterContextPOSIX >> + : public lldb_private::RegisterContext >> +{ >> +public: >> + RegisterContextPOSIX(lldb_private::Thread &thread, >> + uint32_t concrete_frame_idx) >> + : RegisterContext(thread, concrete_frame_idx) { } >> + >> + /// Updates the register state of the associated thread after hitting a >> + /// breakpoint (if that make sense for the architecture). Default >> + /// implementation simply returns true for architectures which do not >> + /// require any update. >> + /// >> + /// @return >> + /// True if the operation succeeded and false otherwise. >> + virtual bool UpdateAfterBreakpoint() { return true; } >> +}; >> + >> +#endif // #ifndef liblldb_RegisterContextPOSIX_H_ >> Index: source/Plugins/Process/POSIX/ProcessMessage.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessMessage.cpp (revision 0) >> @@ -0,0 +1,245 @@ >> +//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#include "ProcessMessage.h" >> + >> +using namespace lldb_private; >> + >> +const char * >> +ProcessMessage::GetCrashReasonString(CrashReason reason) >> +{ >> + const char *str = NULL; >> + >> + switch (reason) >> + { >> + default: >> + assert(false && "invalid CrashReason"); >> + break; >> + >> + case eInvalidAddress: >> + str = "invalid address"; >> + break; >> + case ePrivilegedAddress: >> + str = "address access protected"; >> + break; >> + case eIllegalOpcode: >> + str = "illegal instruction"; >> + break; >> + case eIllegalOperand: >> + str = "illegal instruction operand"; >> + break; >> + case eIllegalAddressingMode: >> + str = "illegal addressing mode"; >> + break; >> + case eIllegalTrap: >> + str = "illegal trap"; >> + break; >> + case ePrivilegedOpcode: >> + str = "privileged instruction"; >> + break; >> + case ePrivilegedRegister: >> + str = "privileged register"; >> + break; >> + case eCoprocessorError: >> + str = "coprocessor error"; >> + break; >> + case eInternalStackError: >> + str = "internal stack error"; >> + break; >> + case eIllegalAlignment: >> + str = "illegal alignment"; >> + break; >> + case eIllegalAddress: >> + str = "illegal address"; >> + break; >> + case eHardwareError: >> + str = "hardware error"; >> + break; >> + case eIntegerDivideByZero: >> + str = "integer divide by zero"; >> + break; >> + case eIntegerOverflow: >> + str = "integer overflow"; >> + break; >> + case eFloatDivideByZero: >> + str = "floating point divide by zero"; >> + break; >> + case eFloatOverflow: >> + str = "floating point overflow"; >> + break; >> + case eFloatUnderflow: >> + str = "floating point underflow"; >> + break; >> + case eFloatInexactResult: >> + str = "inexact floating point result"; >> + break; >> + case eFloatInvalidOperation: >> + str = "invalid floating point operation"; >> + break; >> + case eFloatSubscriptRange: >> + str = "invalid floating point subscript range"; >> + break; >> + } >> + >> + return str; >> +} >> + >> +const char * >> +ProcessMessage::PrintCrashReason(CrashReason reason) >> +{ >> +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> + // Just return the code in asci for integration builds. >> + chcar str[8]; >> + sprintf(str, "%d", reason); >> +#else >> + const char *str = NULL; >> + >> + switch (reason) >> + { >> + default: >> + assert(false && "invalid CrashReason"); >> + break; >> + >> + case eInvalidCrashReason: >> + str = "eInvalidCrashReason"; >> + break; >> + >> + // SIGSEGV crash reasons. >> + case eInvalidAddress: >> + str = "eInvalidAddress"; >> + break; >> + case ePrivilegedAddress: >> + str = "ePrivilegedAddress"; >> + break; >> + >> + // SIGILL crash reasons. >> + case eIllegalOpcode: >> + str = "eIllegalOpcode"; >> + break; >> + case eIllegalOperand: >> + str = "eIllegalOperand"; >> + break; >> + case eIllegalAddressingMode: >> + str = "eIllegalAddressingMode"; >> + break; >> + case eIllegalTrap: >> + str = "eIllegalTrap"; >> + break; >> + case ePrivilegedOpcode: >> + str = "ePrivilegedOpcode"; >> + break; >> + case ePrivilegedRegister: >> + str = "ePrivilegedRegister"; >> + break; >> + case eCoprocessorError: >> + str = "eCoprocessorError"; >> + break; >> + case eInternalStackError: >> + str = "eInternalStackError"; >> + break; >> + >> + // SIGBUS crash reasons: >> + case eIllegalAlignment: >> + str = "eIllegalAlignment"; >> + break; >> + case eIllegalAddress: >> + str = "eIllegalAddress"; >> + break; >> + case eHardwareError: >> + str = "eHardwareError"; >> + break; >> + >> + // SIGFPE crash reasons: >> + case eIntegerDivideByZero: >> + str = "eIntegerDivideByZero"; >> + break; >> + case eIntegerOverflow: >> + str = "eIntegerOverflow"; >> + break; >> + case eFloatDivideByZero: >> + str = "eFloatDivideByZero"; >> + break; >> + case eFloatOverflow: >> + str = "eFloatOverflow"; >> + break; >> + case eFloatUnderflow: >> + str = "eFloatUnderflow"; >> + break; >> + case eFloatInexactResult: >> + str = "eFloatInexactResult"; >> + break; >> + case eFloatInvalidOperation: >> + str = "eFloatInvalidOperation"; >> + break; >> + case eFloatSubscriptRange: >> + str = "eFloatSubscriptRange"; >> + break; >> + } >> +#endif >> + >> + return str; >> +} >> + >> +const char * >> +ProcessMessage::PrintCrashReason() const >> +{ >> + return PrintCrashReason(m_crash_reason); >> +} >> + >> +const char * >> +ProcessMessage::PrintKind(Kind kind) >> +{ >> +#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> + // Just return the code in asci for integration builds. >> + chcar str[8]; >> + sprintf(str, "%d", reason); >> +#else >> + const char *str = NULL; >> + >> + switch (kind) >> + { >> + default: >> + assert(false && "invalid Kind"); >> + break; >> + >> + case eInvalidMessage: >> + str = "eInvalidMessage"; >> + break; >> + case eExitMessage: >> + str = "eExitMessage"; >> + break; >> + case eLimboMessage: >> + str = "eLimboMessage"; >> + break; >> + case eSignalMessage: >> + str = "eSignalMessage"; >> + break; >> + case eSignalDeliveredMessage: >> + str = "eSignalDeliveredMessage"; >> + break; >> + case eTraceMessage: >> + str = "eTraceMessage"; >> + break; >> + case eBreakpointMessage: >> + str = "eBreakpointMessage"; >> + break; >> + case eCrashMessage: >> + str = "eCrashMessage"; >> + break; >> + } >> +#endif >> + >> + return str; >> +} >> + >> +const char * >> +ProcessMessage::PrintKind() const >> +{ >> + return PrintKind(m_kind); >> +} >> Index: source/Plugins/Process/POSIX/POSIXStopInfo.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/POSIXStopInfo.cpp (revision 0) >> @@ -0,0 +1,60 @@ >> +//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#include "POSIXStopInfo.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> + >> +//===----------------------------------------------------------------------===// >> +// POSIXLimboStopInfo >> + >> +POSIXLimboStopInfo::~POSIXLimboStopInfo() { } >> + >> +lldb::StopReason >> +POSIXLimboStopInfo::GetStopReason() const >> +{ >> + return lldb::eStopReasonTrace; >> +} >> + >> +const char * >> +POSIXLimboStopInfo::GetDescription() >> +{ >> + return "thread exiting"; >> +} >> + >> +bool >> +POSIXLimboStopInfo::ShouldStop(Event *event_ptr) >> +{ >> + return true; >> +} >> + >> +bool >> +POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) >> +{ >> + return true; >> +} >> + >> +//===----------------------------------------------------------------------===// >> +// POSIXCrashStopInfo >> + >> +POSIXCrashStopInfo::~POSIXCrashStopInfo() { } >> + >> +lldb::StopReason >> +POSIXCrashStopInfo::GetStopReason() const >> +{ >> + return lldb::eStopReasonException; >> +} >> + >> +const char * >> +POSIXCrashStopInfo::GetDescription() >> +{ >> + return ProcessMessage::GetCrashReasonString(m_crash_reason); >> +} >> Index: source/Plugins/Process/POSIX/ProcessMessage.h >> =================================================================== >> --- source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) >> +++ source/Plugins/Process/POSIX/ProcessMessage.h (revision 0) >> @@ -0,0 +1,171 @@ >> +//===-- ProcessMessage.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_ProcessMessage_H_ >> +#define liblldb_ProcessMessage_H_ >> + >> +#include >> + >> +#include "lldb/lldb-defines.h" >> +#include "lldb/lldb-types.h" >> + >> +class ProcessMessage >> +{ >> +public: >> + >> + /// The type of signal this message can correspond to. >> + enum Kind >> + { >> + eInvalidMessage, >> + eExitMessage, >> + eLimboMessage, >> + eSignalMessage, >> + eSignalDeliveredMessage, >> + eTraceMessage, >> + eBreakpointMessage, >> + eCrashMessage >> + }; >> + >> + enum CrashReason >> + { >> + eInvalidCrashReason, >> + >> + // SIGSEGV crash reasons. >> + eInvalidAddress, >> + ePrivilegedAddress, >> + >> + // SIGILL crash reasons. >> + eIllegalOpcode, >> + eIllegalOperand, >> + eIllegalAddressingMode, >> + eIllegalTrap, >> + ePrivilegedOpcode, >> + ePrivilegedRegister, >> + eCoprocessorError, >> + eInternalStackError, >> + >> + // SIGBUS crash reasons, >> + eIllegalAlignment, >> + eIllegalAddress, >> + eHardwareError, >> + >> + // SIGFPE crash reasons, >> + eIntegerDivideByZero, >> + eIntegerOverflow, >> + eFloatDivideByZero, >> + eFloatOverflow, >> + eFloatUnderflow, >> + eFloatInexactResult, >> + eFloatInvalidOperation, >> + eFloatSubscriptRange >> + }; >> + >> + ProcessMessage() >> + : m_tid(LLDB_INVALID_PROCESS_ID), >> + m_kind(eInvalidMessage), >> + m_crash_reason(eInvalidCrashReason), >> + m_status(0), >> + m_addr(0) { } >> + >> + Kind GetKind() const { return m_kind; } >> + >> + lldb::tid_t GetTID() const { return m_tid; } >> + >> + /// Indicates that the thread @p tid is about to exit with status @p status. >> + static ProcessMessage Limbo(lldb::tid_t tid, int status) { >> + return ProcessMessage(tid, eLimboMessage, status); >> + } >> + >> + /// Indicates that the thread @p tid had the signal @p signum delivered. >> + static ProcessMessage Signal(lldb::tid_t tid, int signum) { >> + return ProcessMessage(tid, eSignalMessage, signum); >> + } >> + >> + /// Indicates that a signal @p signum generated by the debugging process was >> + /// delivered to the thread @p tid. >> + static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { >> + return ProcessMessage(tid, eSignalDeliveredMessage, signum); >> + } >> + >> + /// Indicates that the thread @p tid encountered a trace point. >> + static ProcessMessage Trace(lldb::tid_t tid) { >> + return ProcessMessage(tid, eTraceMessage); >> + } >> + >> + /// Indicates that the thread @p tid encountered a break point. >> + static ProcessMessage Break(lldb::tid_t tid) { >> + return ProcessMessage(tid, eBreakpointMessage); >> + } >> + >> + /// Indicates that the thread @p tid crashed. >> + static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, >> + int signo, lldb::addr_t fault_addr) { >> + ProcessMessage message(pid, eCrashMessage, signo, fault_addr); >> + message.m_crash_reason = reason; >> + return message; >> + } >> + >> + int GetExitStatus() const { >> + assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); >> + return m_status; >> + } >> + >> + int GetSignal() const { >> + assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || >> + GetKind() == eSignalDeliveredMessage); >> + return m_status; >> + } >> + >> + int GetStopStatus() const { >> + assert(GetKind() == eSignalMessage); >> + return m_status; >> + } >> + >> + CrashReason GetCrashReason() const { >> + assert(GetKind() == eCrashMessage); >> + return m_crash_reason; >> + } >> + >> + lldb::addr_t GetFaultAddress() const { >> + assert(GetKind() == eCrashMessage); >> + return m_addr; >> + } >> + >> + static const char * >> + GetCrashReasonString(CrashReason reason); >> + >> + const char * >> + PrintCrashReason() const; >> + >> + static const char * >> + PrintCrashReason(CrashReason reason); >> + >> + const char * >> + PrintKind() const; >> + >> + static const char * >> + PrintKind(Kind); >> + >> +private: >> + ProcessMessage(lldb::tid_t tid, Kind kind, >> + int status = 0, lldb::addr_t addr = 0) >> + : m_tid(tid), >> + m_kind(kind), >> + m_crash_reason(eInvalidCrashReason), >> + m_status(status), >> + m_addr(addr) { } >> + >> + lldb::tid_t m_tid; >> + Kind m_kind : 8; >> + CrashReason m_crash_reason : 8; >> + int m_status; >> + lldb::addr_t m_addr; >> +}; >> + >> +#endif // #ifndef liblldb_ProcessMessage_H_ >> Index: source/Plugins/Process/POSIX/POSIXStopInfo.h >> =================================================================== >> --- source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) >> +++ source/Plugins/Process/POSIX/POSIXStopInfo.h (revision 0) >> @@ -0,0 +1,92 @@ >> +//===-- POSIXStopInfo.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_POSIXStopInfo_H_ >> +#define liblldb_POSIXStopInfo_H_ >> + >> +// C Includes >> +// C++ Includes >> +// Other libraries and framework includes >> +// Project includes >> +#include "lldb/Target/StopInfo.h" >> + >> +#include "POSIXThread.h" >> +#include "ProcessMessage.h" >> + >> +//===----------------------------------------------------------------------===// >> +/// @class POSIXStopInfo >> +/// @brief Simple base class for all POSIX-specific StopInfo objects. >> +/// >> +class POSIXStopInfo >> + : public lldb_private::StopInfo >> +{ >> +public: >> + POSIXStopInfo(lldb_private::Thread &thread, uint32_t status) >> + : StopInfo(thread, status) >> + { } >> +}; >> + >> +//===----------------------------------------------------------------------===// >> +/// @class POSIXLimboStopInfo >> +/// @brief Represents the stop state of a process ready to exit. >> +/// >> +class POSIXLimboStopInfo >> + : public POSIXStopInfo >> +{ >> +public: >> + POSIXLimboStopInfo(POSIXThread &thread) >> + : POSIXStopInfo(thread, 0) >> + { } >> + >> + ~POSIXLimboStopInfo(); >> + >> + lldb::StopReason >> + GetStopReason() const; >> + >> + const char * >> + GetDescription(); >> + >> + bool >> + ShouldStop(lldb_private::Event *event_ptr); >> + >> + bool >> + ShouldNotify(lldb_private::Event *event_ptr); >> +}; >> + >> + >> +//===----------------------------------------------------------------------===// >> +/// @class POSIXCrashStopInfo >> +/// @brief Represents the stop state of process that is ready to crash. >> +/// >> +class POSIXCrashStopInfo >> + : public POSIXStopInfo >> +{ >> +public: >> + POSIXCrashStopInfo(POSIXThread &thread, uint32_t status, >> + ProcessMessage::CrashReason reason) >> + : POSIXStopInfo(thread, status), >> + m_crash_reason(reason) >> + { } >> + >> + ~POSIXCrashStopInfo(); >> + >> + lldb::StopReason >> + GetStopReason() const; >> + >> + const char * >> + GetDescription(); >> + >> + ProcessMessage::CrashReason >> + GetCrashReason() const; >> + >> +private: >> + ProcessMessage::CrashReason m_crash_reason; >> +}; >> + >> +#endif >> Index: source/Plugins/Process/POSIX/POSIXThread.cpp >> =================================================================== >> --- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) >> +++ source/Plugins/Process/POSIX/POSIXThread.cpp (revision 0) >> @@ -0,0 +1,352 @@ >> +//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +// C Includes >> +#include >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +// Project includes >> +#include "lldb/Core/Debugger.h" >> +#include "lldb/Host/Host.h" >> +#include "lldb/Target/Process.h" >> +#include "lldb/Target/StopInfo.h" >> +#include "lldb/Target/Target.h" >> +#include "POSIXStopInfo.h" >> +#include "POSIXThread.h" >> +#include "ProcessPOSIX.h" >> +#include "ProcessPOSIXLog.h" >> +#include "ProcessMonitor.h" >> +#include "RegisterContext_i386.h" >> +#include "RegisterContext_x86_64.h" >> +#include "RegisterContextPOSIX.h" >> + >> +#include "UnwindLLDB.h" >> + >> +using namespace lldb_private; >> + >> + >> +POSIXThread::POSIXThread(Process &process, lldb::tid_t tid) >> + : Thread(process, tid), >> + m_frame_ap(0) >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("POSIXThread::%s (tid = %i)", __FUNCTION__, tid); >> +} >> + >> +POSIXThread::~POSIXThread() >> +{ >> + DestroyThread(); >> +} >> + >> +ProcessMonitor & >> +POSIXThread::GetMonitor() >> +{ >> + ProcessPOSIX &process = static_cast(GetProcess()); >> + return process.GetMonitor(); >> +} >> + >> +void >> +POSIXThread::RefreshStateAfterStop() >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("POSIXThread::%s ()", __FUNCTION__); >> + >> + // Let all threads recover from stopping and do any clean up based >> + // on the previous thread state (if any). >> + ProcessPOSIX &process = static_cast(GetProcess()); >> + process.GetThreadList().RefreshStateAfterStop(); >> +} >> + >> +const char * >> +POSIXThread::GetInfo() >> +{ >> + return NULL; >> +} >> + >> +lldb::RegisterContextSP >> +POSIXThread::GetRegisterContext() >> +{ >> + if (!m_reg_context_sp) >> + { >> + ArchSpec arch = Host::GetArchitecture(); >> + >> + switch (arch.GetCore()) >> + { >> + default: >> + assert(false && "CPU type not supported!"); >> + break; >> + >> + case ArchSpec::eCore_x86_32_i386: >> + case ArchSpec::eCore_x86_32_i486: >> + case ArchSpec::eCore_x86_32_i486sx: >> + m_reg_context_sp.reset(new RegisterContext_i386(*this, 0)); >> + break; >> + >> + case ArchSpec::eCore_x86_64_x86_64: >> + m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0)); >> + break; >> + } >> + } >> + return m_reg_context_sp; >> +} >> + >> +lldb::RegisterContextSP >> +POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) >> +{ >> + lldb::RegisterContextSP reg_ctx_sp; >> + uint32_t concrete_frame_idx = 0; >> + >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("POSIXThread::%s ()", __FUNCTION__); >> + >> + if (frame) >> + concrete_frame_idx = frame->GetConcreteFrameIndex(); >> + >> + if (concrete_frame_idx == 0) >> + reg_ctx_sp = GetRegisterContext(); >> + else >> + { >> + assert(GetUnwinder()); >> + reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); >> + } >> + >> + return reg_ctx_sp; >> +} >> + >> +lldb::StopInfoSP >> +POSIXThread::GetPrivateStopReason() >> +{ >> + return m_stop_info; >> +} >> + >> +Unwind * >> +POSIXThread::GetUnwinder() >> +{ >> + if (m_unwinder_ap.get() == NULL) >> + m_unwinder_ap.reset(new UnwindLLDB(*this)); >> + >> + return m_unwinder_ap.get(); >> +} >> + >> +bool >> +POSIXThread::WillResume(lldb::StateType resume_state) >> +{ >> + SetResumeState(resume_state); >> + >> + ClearStackFrames(); >> + if (m_unwinder_ap.get()) >> + m_unwinder_ap->Clear(); >> + >> + return Thread::WillResume(resume_state); >> +} >> + >> +bool >> +POSIXThread::Resume() >> +{ >> + lldb::StateType resume_state = GetResumeState(); >> + ProcessMonitor &monitor = GetMonitor(); >> + bool status; >> + >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) >> + log->Printf ("POSIXThread::%s ()", __FUNCTION__); >> + >> + switch (resume_state) >> + { >> + default: >> + assert(false && "Unexpected state for resume!"); >> + status = false; >> + break; >> + >> + case lldb::eStateRunning: >> + SetState(resume_state); >> + status = monitor.Resume(GetID(), GetResumeSignal()); >> + break; >> + >> + case lldb::eStateStepping: >> + SetState(resume_state); >> + status = monitor.SingleStep(GetID(), GetResumeSignal()); >> + break; >> + } >> + >> + return status; >> +} >> + >> +void >> +POSIXThread::Notify(const ProcessMessage &message) >> +{ >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log) >> + log->Printf ("POSIXThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); >> + >> + switch (message.GetKind()) >> + { >> + default: >> + assert(false && "Unexpected message kind!"); >> + break; >> + >> + case ProcessMessage::eLimboMessage: >> + LimboNotify(message); >> + break; >> + >> + case ProcessMessage::eSignalMessage: >> + SignalNotify(message); >> + break; >> + >> + case ProcessMessage::eSignalDeliveredMessage: >> + SignalDeliveredNotify(message); >> + break; >> + >> + case ProcessMessage::eTraceMessage: >> + TraceNotify(message); >> + break; >> + >> + case ProcessMessage::eBreakpointMessage: >> + BreakNotify(message); >> + break; >> + >> + case ProcessMessage::eCrashMessage: >> + CrashNotify(message); >> + break; >> + } >> +} >> + >> +void >> +POSIXThread::BreakNotify(const ProcessMessage &message) >> +{ >> + bool status; >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + >> + assert(GetRegisterContext()); >> + status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint(); >> + assert(status && "Breakpoint update failed!"); >> + >> + // With our register state restored, resolve the breakpoint object >> + // corresponding to our current PC. >> + assert(GetRegisterContext()); >> + lldb::addr_t pc = GetRegisterContext()->GetPC(); >> + if (log) >> + log->Printf ("POSIXThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); >> + lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); >> + assert(bp_site); >> + lldb::break_id_t bp_id = bp_site->GetID(); >> + assert(bp_site && bp_site->ValidForThisThread(this)); >> + >> + >> + m_breakpoint = bp_site; >> + m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); >> +} >> + >> +void >> +POSIXThread::TraceNotify(const ProcessMessage &message) >> +{ >> + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); >> +} >> + >> +void >> +POSIXThread::LimboNotify(const ProcessMessage &message) >> +{ >> + m_stop_info = lldb::StopInfoSP(new POSIXLimboStopInfo(*this)); >> +} >> + >> +void >> +POSIXThread::SignalNotify(const ProcessMessage &message) >> +{ >> + int signo = message.GetSignal(); >> + >> + m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); >> + SetResumeSignal(signo); >> +} >> + >> +void >> +POSIXThread::SignalDeliveredNotify(const ProcessMessage &message) >> +{ >> + int signo = message.GetSignal(); >> + >> + // Just treat debugger generated signal events like breakpoints for now. >> + m_stop_info = StopInfo::CreateStopReasonToTrace(*this); >> + SetResumeSignal(signo); >> +} >> + >> +void >> +POSIXThread::CrashNotify(const ProcessMessage &message) >> +{ >> + int signo = message.GetSignal(); >> + >> + assert(message.GetKind() == ProcessMessage::eCrashMessage); >> + >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); >> + if (log) >> + log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); >> + >> + m_stop_info = lldb::StopInfoSP(new POSIXCrashStopInfo( >> + *this, signo, message.GetCrashReason())); >> + SetResumeSignal(signo); >> +} >> + >> +unsigned >> +POSIXThread::GetRegisterIndexFromOffset(unsigned offset) >> +{ >> + unsigned reg; >> + ArchSpec arch = Host::GetArchitecture(); >> + >> + switch (arch.GetCore()) >> + { >> + default: >> + assert(false && "CPU type not supported!"); >> + break; >> + >> + case ArchSpec::eCore_x86_32_i386: >> + case ArchSpec::eCore_x86_32_i486: >> + case ArchSpec::eCore_x86_32_i486sx: >> + reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset); >> + break; >> + >> + case ArchSpec::eCore_x86_64_x86_64: >> + reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset); >> + break; >> + } >> + return reg; >> +} >> + >> +const char * >> +POSIXThread::GetRegisterName(unsigned reg) >> +{ >> + const char * name; >> + ArchSpec arch = Host::GetArchitecture(); >> + >> + switch (arch.GetCore()) >> + { >> + default: >> + assert(false && "CPU type not supported!"); >> + break; >> + >> + case ArchSpec::eCore_x86_32_i386: >> + case ArchSpec::eCore_x86_32_i486: >> + case ArchSpec::eCore_x86_32_i486sx: >> + name = RegisterContext_i386::GetRegisterName(reg); >> + break; >> + >> + case ArchSpec::eCore_x86_64_x86_64: >> + name = RegisterContext_x86_64::GetRegisterName(reg); >> + break; >> + } >> + return name; >> +} >> + >> +const char * >> +POSIXThread::GetRegisterNameFromOffset(unsigned offset) >> +{ >> + return GetRegisterName(GetRegisterIndexFromOffset(offset)); >> +} >> + >> Index: source/Plugins/Process/POSIX/Makefile >> =================================================================== >> --- source/Plugins/Process/POSIX/Makefile (revision 0) >> +++ source/Plugins/Process/POSIX/Makefile (revision 0) >> @@ -0,0 +1,28 @@ >> +##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===## >> +# >> +# The LLVM Compiler Infrastructure >> +# >> +# This file is distributed under the University of Illinois Open Source >> +# License. See LICENSE.TXT for details. >> +# >> +##===----------------------------------------------------------------------===## >> + >> +LLDB_LEVEL := ../../../.. >> +LIBRARYNAME := lldbPluginProcessPOSIX >> +BUILD_ARCHIVE = 1 >> + >> +include $(LLDB_LEVEL)/../../Makefile.config >> + >> +# Extend the include path so we may locate UnwindLLDB.h >> +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility >> + >> +ifeq ($(HOST_OS),Linux) >> +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux >> +endif >> + >> +ifeq ($(HOST_OS),FreeBSD) >> +# Extend the include path so we may locate ProcessMonitor >> +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD >> +endif >> + >> +include $(LLDB_LEVEL)/Makefile >> Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.h >> =================================================================== >> --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) >> +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.h (revision 0) >> @@ -0,0 +1,84 @@ >> +//===-- ProcessFreeBSD.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_ProcessFreeBSD_H_ >> +#define liblldb_ProcessFreeBSD_H_ >> + >> +// C Includes >> + >> +// C++ Includes >> +#include >> + >> +// Other libraries and framework includes >> +#include "lldb/Target/Process.h" >> +#include "lldb/Target/ThreadList.h" >> +#include "ProcessMessage.h" >> +#include "ProcessPOSIX.h" >> + >> +class ProcessMonitor; >> + >> +class ProcessFreeBSD : >> + public ProcessPOSIX >> +{ >> + >> +public: >> + //------------------------------------------------------------------ >> + // Static functions. >> + //------------------------------------------------------------------ >> + static Process* >> + CreateInstance(lldb_private::Target& target, >> + lldb_private::Listener &listener); >> + >> + static void >> + Initialize(); >> + >> + static void >> + Terminate(); >> + >> + static const char * >> + GetPluginNameStatic(); >> + >> + static const char * >> + GetPluginDescriptionStatic(); >> + >> + //------------------------------------------------------------------ >> + // Constructors and destructors >> + //------------------------------------------------------------------ >> + ProcessFreeBSD(lldb_private::Target& target, >> + lldb_private::Listener &listener); >> + >> + virtual uint32_t >> + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); >> + >> + //------------------------------------------------------------------ >> + // PluginInterface protocol >> + //------------------------------------------------------------------ >> + virtual const char * >> + GetPluginName(); >> + >> + virtual const char * >> + GetShortPluginName(); >> + >> + virtual uint32_t >> + GetPluginVersion(); >> + >> + virtual void >> + GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); >> + >> + virtual lldb_private::Error >> + ExecutePluginCommand(lldb_private::Args &command, >> + lldb_private::Stream *strm); >> + >> + virtual lldb_private::Log * >> + EnablePluginLogging(lldb_private::Stream *strm, >> + lldb_private::Args &command); >> + >> +}; >> + >> +#endif // liblldb_MacOSXProcess_H_ >> Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp >> =================================================================== >> --- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) >> +++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 0) >> @@ -0,0 +1,1558 @@ >> +//===-- ProcessMonitor.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 >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/Error.h" >> +#include "lldb/Core/RegisterValue.h" >> +#include "lldb/Core/Scalar.h" >> +#include "lldb/Host/Host.h" >> +#include "lldb/Target/Thread.h" >> +#include "lldb/Target/RegisterContext.h" >> +#include "lldb/Utility/PseudoTerminal.h" >> + >> + >> +#include "POSIXThread.h" >> +#include "ProcessFreeBSD.h" >> +#include "ProcessPOSIXLog.h" >> +#include "ProcessMonitor.h" >> + >> +extern "C" { >> + extern char ** environ; >> + } >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +// We disable the tracing of ptrace calls for integration builds to >> +// avoid the additional indirection and checks. >> +#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION >> +// Wrapper for ptrace to catch errors and log calls. >> + >> +const char * >> +Get_PT_IO_OP(int op) >> +{ >> + switch (op) { >> + case PIOD_READ_D: return "READ_D"; >> + case PIOD_WRITE_D: return "WRITE_D"; >> + case PIOD_READ_I: return "READ_I"; >> + case PIOD_WRITE_I: return "WRITE_I"; >> + default: return "Unknown op"; >> + } >> +} >> + >> +extern long >> +PtraceWrapper(int req, ::pid_t pid, void *addr, int data, >> + const char* reqName, const char* file, int line) >> +{ >> + long int result; >> + >> + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE)); >> + >> + if (log) { >> + log->Printf("ptrace(%s, %u, %p, %x) called from file %s line %d", >> + reqName, pid, addr, data, file, line); >> + if (req == PT_IO) { >> + struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr; >> + >> + log->Printf("PT_IO: op=%s offs=%zx size=%ld", >> + Get_PT_IO_OP(pi->piod_op), pi->piod_offs, pi->piod_len); >> + } >> + } >> + >> + //PtraceDisplayBytes(req, data); >> + >> + errno = 0; >> + result = ptrace(req, pid, (caddr_t) addr, data); >> + >> + //PtraceDisplayBytes(req, data); >> + >> + if (log && (result == -1 || errno != 0)) >> + { >> + const char* str; >> + switch (errno) >> + { >> + case ESRCH: str = "ESRCH"; break; >> + case EINVAL: str = "EINVAL"; break; >> + case EBUSY: str = "EBUSY"; break; >> + case EPERM: str = "EPERM"; break; >> + default: str = ""; >> + } >> + log->Printf("ptrace() failed; errno=%d (%s)", errno, str); >> + } >> + >> + if (log) { >> + if (req == PT_GETREGS) { >> + struct reg *r = (struct reg *) addr; >> + >> + log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip); >> + log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp); >> + log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp); >> + log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax); >> + } >> + } >> + >> + return result; >> +} >> + >> +#define PTRACE(req, pid, addr, data) \ >> + PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__) >> +#else >> +#define PTRACE ptrace >> +#endif >> + >> +//------------------------------------------------------------------------------ >> +// Static implementations of ProcessMonitor::ReadMemory and >> +// ProcessMonitor::WriteMemory. This enables mutual recursion between these >> +// functions without needed to go thru the thread funnel. >> + >> +static size_t >> +DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, >> + Error &error) >> +{ >> + struct ptrace_io_desc pi_desc; >> + >> + pi_desc.piod_op = PIOD_READ_D; >> + pi_desc.piod_offs = (void *)vm_addr; >> + pi_desc.piod_addr = buf; >> + pi_desc.piod_len = size; >> + >> + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) >> + error.SetErrorToErrno(); >> + return pi_desc.piod_len; >> +} >> + >> +static size_t >> +DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, >> + size_t size, Error &error) >> +{ >> + struct ptrace_io_desc pi_desc; >> + >> + pi_desc.piod_op = PIOD_WRITE_D; >> + pi_desc.piod_offs = (void *)vm_addr; >> + pi_desc.piod_addr = (void *)buf; >> + pi_desc.piod_len = size; >> + >> + if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) >> + error.SetErrorToErrno(); >> + return pi_desc.piod_len; >> +} >> + >> +// Simple helper function to ensure flags are enabled on the given file >> +// descriptor. >> +static bool >> +EnsureFDFlags(int fd, int flags, Error &error) >> +{ >> + int status; >> + >> + if ((status = fcntl(fd, F_GETFL)) == -1) >> + { >> + error.SetErrorToErrno(); >> + return false; >> + } >> + >> + if (fcntl(fd, F_SETFL, status | flags) == -1) >> + { >> + error.SetErrorToErrno(); >> + return false; >> + } >> + >> + return true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class Operation >> +/// @brief Represents a ProcessMonitor operation. >> +/// >> +/// Under FreeBSD, it is not possible to ptrace() from any other thread but the >> +/// one that spawned or attached to the process from the start. Therefore, when >> +/// a ProcessMonitor is asked to deliver or change the state of an inferior >> +/// process the operation must be "funneled" to a specific thread to perform the >> +/// task. The Operation class provides an abstract base for all services the >> +/// ProcessMonitor must perform via the single virtual function Execute, thus >> +/// encapsulating the code that needs to run in the privileged context. >> +class Operation >> +{ >> +public: >> + virtual void Execute(ProcessMonitor *monitor) = 0; >> +}; >> + >> +//------------------------------------------------------------------------------ >> +/// @class ReadOperation >> +/// @brief Implements ProcessMonitor::ReadMemory. >> +class ReadOperation : public Operation >> +{ >> +public: >> + ReadOperation(lldb::addr_t addr, void *buff, size_t size, >> + Error &error, size_t &result) >> + : m_addr(addr), m_buff(buff), m_size(size), >> + m_error(error), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::addr_t m_addr; >> + void *m_buff; >> + size_t m_size; >> + Error &m_error; >> + size_t &m_result; >> +}; >> + >> +void >> +ReadOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + >> + m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error); >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ReadOperation >> +/// @brief Implements ProcessMonitor::WriteMemory. >> +class WriteOperation : public Operation >> +{ >> +public: >> + WriteOperation(lldb::addr_t addr, const void *buff, size_t size, >> + Error &error, size_t &result) >> + : m_addr(addr), m_buff(buff), m_size(size), >> + m_error(error), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::addr_t m_addr; >> + const void *m_buff; >> + size_t m_size; >> + Error &m_error; >> + size_t &m_result; >> +}; >> + >> +void >> +WriteOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + >> + m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error); >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ReadRegOperation >> +/// @brief Implements ProcessMonitor::ReadRegisterValue. >> +class ReadRegOperation : public Operation >> +{ >> +public: >> + ReadRegOperation(unsigned offset, unsigned size, RegisterValue &value, bool &result) >> + : m_offset(offset), m_size(size), m_value(value), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + unsigned m_offset; >> + unsigned m_size; >> + RegisterValue &m_value; >> + bool &m_result; >> +}; >> + >> +void >> +ReadRegOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + struct reg regs; >> + int rc; >> + >> + if ((rc = PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0)) < 0) { >> + m_result = false; >> + } else { >> + if (m_size == sizeof(uintptr_t)) >> + m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset); >> + else >> + memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size); >> + m_result = true; >> + } >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class WriteRegOperation >> +/// @brief Implements ProcessMonitor::WriteRegisterValue. >> +class WriteRegOperation : public Operation >> +{ >> +public: >> + WriteRegOperation(unsigned offset, const RegisterValue &value, bool &result) >> + : m_offset(offset), m_value(value), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + unsigned m_offset; >> + const RegisterValue &m_value; >> + bool &m_result; >> +}; >> + >> +void >> +WriteRegOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + struct reg regs; >> + >> + if (PTRACE(PT_GETREGS, pid, (caddr_t)®s, 0) < 0) { >> + m_result = false; >> + return; >> + } >> + *(uintptr_t *)(((caddr_t)®s) + m_offset) = (uintptr_t)m_value.GetAsUInt64(); >> + if (PTRACE(PT_SETREGS, pid, (caddr_t)®s, 0) < 0) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ReadGPROperation >> +/// @brief Implements ProcessMonitor::ReadGPR. >> +class ReadGPROperation : public Operation >> +{ >> +public: >> + ReadGPROperation(void *buf, bool &result) >> + : m_buf(buf), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + void *m_buf; >> + bool &m_result; >> +}; >> + >> +void >> +ReadGPROperation::Execute(ProcessMonitor *monitor) >> +{ >> + int rc; >> + >> + errno = 0; >> + rc = PTRACE(PT_GETREGS, monitor->GetPID(), (caddr_t)m_buf, 0); >> + if (errno != 0) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ReadFPROperation >> +/// @brief Implements ProcessMonitor::ReadFPR. >> +class ReadFPROperation : public Operation >> +{ >> +public: >> + ReadFPROperation(void *buf, bool &result) >> + : m_buf(buf), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + void *m_buf; >> + bool &m_result; >> +}; >> + >> +void >> +ReadFPROperation::Execute(ProcessMonitor *monitor) >> +{ >> + if (PTRACE(PT_GETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class WriteGPROperation >> +/// @brief Implements ProcessMonitor::WriteGPR. >> +class WriteGPROperation : public Operation >> +{ >> +public: >> + WriteGPROperation(void *buf, bool &result) >> + : m_buf(buf), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + void *m_buf; >> + bool &m_result; >> +}; >> + >> +void >> +WriteGPROperation::Execute(ProcessMonitor *monitor) >> +{ >> + if (PTRACE(PT_SETREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class WriteFPROperation >> +/// @brief Implements ProcessMonitor::WriteFPR. >> +class WriteFPROperation : public Operation >> +{ >> +public: >> + WriteFPROperation(void *buf, bool &result) >> + : m_buf(buf), m_result(result) >> + { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + void *m_buf; >> + bool &m_result; >> +}; >> + >> +void >> +WriteFPROperation::Execute(ProcessMonitor *monitor) >> +{ >> + if (PTRACE(PT_SETFPREGS, monitor->GetPID(), (caddr_t)m_buf, 0) < 0) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ResumeOperation >> +/// @brief Implements ProcessMonitor::Resume. >> +class ResumeOperation : public Operation >> +{ >> +public: >> + ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) : >> + m_tid(tid), m_signo(signo), m_result(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::tid_t m_tid; >> + uint32_t m_signo; >> + bool &m_result; >> +}; >> + >> +void >> +ResumeOperation::Execute(ProcessMonitor *monitor) >> +{ >> + int data = 0; >> + >> + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) >> + data = m_signo; >> + >> + if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data)) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class ResumeOperation >> +/// @brief Implements ProcessMonitor::SingleStep. >> +class SingleStepOperation : public Operation >> +{ >> +public: >> + SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result) >> + : m_tid(tid), m_signo(signo), m_result(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::tid_t m_tid; >> + uint32_t m_signo; >> + bool &m_result; >> +}; >> + >> +void >> +SingleStepOperation::Execute(ProcessMonitor *monitor) >> +{ >> + int data = 0; >> + >> + if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) >> + data = m_signo; >> + >> + if (PTRACE(PT_STEP, m_tid, NULL, data)) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class SiginfoOperation >> +/// @brief Implements ProcessMonitor::GetSignalInfo. >> +class SiginfoOperation : public Operation >> +{ >> +public: >> + SiginfoOperation(lldb::tid_t tid, void *info, bool &result) >> + : m_tid(tid), m_info(info), m_result(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::tid_t m_tid; >> + void *m_info; >> + bool &m_result; >> +}; >> + >> +void >> +SiginfoOperation::Execute(ProcessMonitor *monitor) >> +{ >> + struct ptrace_lwpinfo plwp; >> + >> + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) >> + m_result = false; >> + else { >> + memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t)); >> + m_result = true; >> + } >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class EventMessageOperation >> +/// @brief Implements ProcessMonitor::GetEventMessage. >> +class EventMessageOperation : public Operation >> +{ >> +public: >> + EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result) >> + : m_tid(tid), m_message(message), m_result(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + lldb::tid_t m_tid; >> + unsigned long *m_message; >> + bool &m_result; >> +}; >> + >> +void >> +EventMessageOperation::Execute(ProcessMonitor *monitor) >> +{ >> + struct ptrace_lwpinfo plwp; >> + >> + if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) >> + m_result = false; >> + else { >> + if (plwp.pl_flags & PL_FLAG_FORKED) { >> + m_message = (unsigned long *)plwp.pl_child_pid; >> + m_result = true; >> + } else >> + m_result = false; >> + } >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class KillOperation >> +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. >> +class KillOperation : public Operation >> +{ >> +public: >> + KillOperation(bool &result) : m_result(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + bool &m_result; >> +}; >> + >> +void >> +KillOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + >> + if (PTRACE(PT_KILL, pid, NULL, 0)) >> + m_result = false; >> + else >> + m_result = true; >> +} >> + >> +//------------------------------------------------------------------------------ >> +/// @class KillOperation >> +/// @brief Implements ProcessMonitor::BringProcessIntoLimbo. >> +class DetachOperation : public Operation >> +{ >> +public: >> + DetachOperation(Error &result) : m_error(result) { } >> + >> + void Execute(ProcessMonitor *monitor); >> + >> +private: >> + Error &m_error; >> +}; >> + >> +void >> +DetachOperation::Execute(ProcessMonitor *monitor) >> +{ >> + lldb::pid_t pid = monitor->GetPID(); >> + >> + if (PTRACE(PT_DETACH, pid, NULL, 0) < 0) >> + m_error.SetErrorToErrno(); >> + >> +} >> + >> +ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor) >> + : m_monitor(monitor) >> +{ >> + sem_init(&m_semaphore, 0, 0); >> +} >> + >> +ProcessMonitor::OperationArgs::~OperationArgs() >> +{ >> + sem_destroy(&m_semaphore); >> +} >> + >> +ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor, >> + lldb_private::Module *module, >> + char const **argv, >> + char const **envp, >> + const char *stdin_path, >> + const char *stdout_path, >> + const char *stderr_path) >> + : OperationArgs(monitor), >> + m_module(module), >> + m_argv(argv), >> + m_envp(envp), >> + m_stdin_path(stdin_path), >> + m_stdout_path(stdout_path), >> + m_stderr_path(stderr_path) { } >> + >> +ProcessMonitor::LaunchArgs::~LaunchArgs() >> +{ } >> + >> +ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor, >> + lldb::pid_t pid) >> + : OperationArgs(monitor), m_pid(pid) { } >> + >> +ProcessMonitor::AttachArgs::~AttachArgs() >> +{ } >> + >> +//------------------------------------------------------------------------------ >> +/// The basic design of the ProcessMonitor is built around two threads. >> +/// >> +/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking >> +/// for changes in the debugee state. When a change is detected a >> +/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This thread >> +/// "drives" state changes in the debugger. >> +/// >> +/// The second thread (@see OperationThread) is responsible for two things 1) >> +/// launching or attaching to the inferior process, and then 2) servicing >> +/// operations such as register reads/writes, stepping, etc. See the comments >> +/// on the Operation class for more info as to why this is needed. >> +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, >> + Module *module, >> + const char *argv[], >> + const char *envp[], >> + const char *stdin_path, >> + const char *stdout_path, >> + const char *stderr_path, >> + lldb_private::Error &error) >> + : m_process(static_cast(process)), >> + m_operation_thread(LLDB_INVALID_HOST_THREAD), >> + m_monitor_thread(LLDB_INVALID_HOST_THREAD), >> + m_pid(LLDB_INVALID_PROCESS_ID), >> + m_server_mutex(Mutex::eMutexTypeRecursive), >> + m_terminal_fd(-1), >> + m_client_fd(-1), >> + m_server_fd(-1) >> +{ >> + std::auto_ptr args; >> + >> + args.reset(new LaunchArgs(this, module, argv, envp, >> + stdin_path, stdout_path, stderr_path)); >> + >> + >> + // Server/client descriptors. >> + if (!EnableIPC()) >> + { >> + error.SetErrorToGenericError(); >> + error.SetErrorString("Monitor failed to initialize."); >> + } >> + >> + StartLaunchOpThread(args.get(), error); >> + if (!error.Success()) >> + return; >> + >> +WAIT_AGAIN: >> + // Wait for the operation thread to initialize. >> + if (sem_wait(&args->m_semaphore)) >> + { >> + if (errno == EINTR) >> + goto WAIT_AGAIN; >> + else >> + { >> + error.SetErrorToErrno(); >> + return; >> + } >> + } >> + >> + // Check that the launch was a success. >> + if (!args->m_error.Success()) >> + { >> + StopLaunchOpThread(); >> + error = args->m_error; >> + return; >> + } >> + >> + // Finally, start monitoring the child process for change in state. >> + m_monitor_thread = Host::StartMonitoringChildProcess( >> + ProcessMonitor::MonitorCallback, this, GetPID(), true); >> + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) >> + { >> + error.SetErrorToGenericError(); >> + error.SetErrorString("Process launch failed."); >> + return; >> + } >> +} >> + >> +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, >> + lldb::pid_t pid, >> + lldb_private::Error &error) >> + : m_process(static_cast(process)), >> + m_operation_thread(LLDB_INVALID_HOST_THREAD), >> + m_monitor_thread(LLDB_INVALID_HOST_THREAD), >> + m_pid(pid), >> + m_server_mutex(Mutex::eMutexTypeRecursive), >> + m_terminal_fd(-1), >> + m_client_fd(-1), >> + m_server_fd(-1) >> +{ >> + std::auto_ptr args; >> + >> + args.reset(new AttachArgs(this, pid)); >> + >> + // Server/client descriptors. >> + if (!EnableIPC()) >> + { >> + error.SetErrorToGenericError(); >> + error.SetErrorString("Monitor failed to initialize."); >> + } >> + >> + StartAttachOpThread(args.get(), error); >> + if (!error.Success()) >> + return; >> + >> +WAIT_AGAIN: >> + // Wait for the operation thread to initialize. >> + if (sem_wait(&args->m_semaphore)) >> + { >> + if (errno == EINTR) >> + goto WAIT_AGAIN; >> + else >> + { >> + error.SetErrorToErrno(); >> + return; >> + } >> + } >> + >> + // Check that the launch was a success. >> + if (!args->m_error.Success()) >> + { >> + StopAttachOpThread(); >> + error = args->m_error; >> + return; >> + } >> + >> + // Finally, start monitoring the child process for change in state. >> + m_monitor_thread = Host::StartMonitoringChildProcess( >> + ProcessMonitor::MonitorCallback, this, GetPID(), true); >> + if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) >> + { >> + error.SetErrorToGenericError(); >> + error.SetErrorString("Process attach failed."); >> + return; >> + } >> +} >> + >> +ProcessMonitor::~ProcessMonitor() >> +{ >> + StopMonitor(); >> +} >> + >> +//------------------------------------------------------------------------------ >> +// Thread setup and tear down. >> +void >> +ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error) >> +{ >> + static const char *g_thread_name = "lldb.process.freebsd.operation"; >> + >> + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) >> + return; >> + >> + m_operation_thread = >> + Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error); >> +} >> + >> +void >> +ProcessMonitor::StopLaunchOpThread() >> +{ >> + lldb::thread_result_t result; >> + >> + if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) >> + return; >> + >> + Host::ThreadCancel(m_operation_thread, NULL); >> + Host::ThreadJoin(m_operation_thread, &result, NULL); >> +} >> + >> +void * >> +ProcessMonitor::LaunchOpThread(void *arg) >> +{ >> + LaunchArgs *args = static_cast(arg); >> + >> + if (!Launch(args)) { >> + sem_post(&args->m_semaphore); >> + return NULL; >> + } >> + >> + ServeOperation(args); >> + return NULL; >> +} >> + >> +bool >> +ProcessMonitor::Launch(LaunchArgs *args) >> +{ >> + ProcessMonitor *monitor = args->m_monitor; >> + ProcessFreeBSD &process = monitor->GetProcess(); >> + const char **argv = args->m_argv; >> + const char **envp = args->m_envp; >> + const char *stdin_path = args->m_stdin_path; >> + const char *stdout_path = args->m_stdout_path; >> + const char *stderr_path = args->m_stderr_path; >> + lldb::pid_t pid; >> + >> + lldb::ThreadSP inferior; >> + >> + // Propagate the environment if one is not supplied. >> + if (envp == NULL || envp[0] == NULL) >> + envp = const_cast(environ); >> + >> + // Recognized child exit status codes. >> + enum { >> + ePtraceFailed = 1, >> + eDupStdinFailed, >> + eDupStdoutFailed, >> + eDupStderrFailed, >> + eExecFailed >> + }; >> + >> + pid = fork(); >> + >> + // Child process. >> + if (pid == 0) >> + { >> + // Trace this process. >> + if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0) >> + exit(ePtraceFailed); >> + >> + // Do not inherit setgid powers. >> + setgid(getgid()); >> + >> + // Let us have our own process group. >> + setpgid(0, 0); >> + >> + // Dup file descriptors if needed. >> + // >> + // FIXME: If two or more of the paths are the same we needlessly open >> + // the same file multiple times. >> + if (stdin_path != NULL && stdin_path[0]) >> + if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY)) >> + exit(eDupStdinFailed); >> + >> + if (stdout_path != NULL && stdout_path[0]) >> + if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT)) >> + exit(eDupStdoutFailed); >> + >> + if (stderr_path != NULL && stderr_path[0]) >> + if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT)) >> + exit(eDupStderrFailed); >> + >> + // Execute. We should never return. >> + execve(argv[0], >> + const_cast(argv), >> + const_cast(envp)); >> + exit(eExecFailed); >> + } >> + >> + // Wait for the child process to to trap on its call to execve. >> + ::pid_t wpid; >> + int status; >> + if ((wpid = waitpid(pid, &status, 0)) < 0) >> + { >> + args->m_error.SetErrorToErrno(); >> + goto FINISH; >> + } >> + else if (WIFEXITED(status)) >> + { >> + // open, dup or execve likely failed for some reason. >> + args->m_error.SetErrorToGenericError(); >> + switch (WEXITSTATUS(status)) >> + { >> + case ePtraceFailed: >> + args->m_error.SetErrorString("Child ptrace failed."); >> + break; >> + case eDupStdinFailed: >> + args->m_error.SetErrorString("Child open stdin failed."); >> + break; >> + case eDupStdoutFailed: >> + args->m_error.SetErrorString("Child open stdout failed."); >> + break; >> + case eDupStderrFailed: >> + args->m_error.SetErrorString("Child open stderr failed."); >> + break; >> + case eExecFailed: >> + args->m_error.SetErrorString("Child exec failed."); >> + break; >> + default: >> + args->m_error.SetErrorString("Child returned unknown exit status."); >> + break; >> + } >> + goto FINISH; >> + } >> + assert(WIFSTOPPED(status) && wpid == pid && >> + "Could not sync with inferior process."); >> + >> +#ifdef notyet >> + // Have the child raise an event on exit. This is used to keep the child in >> + // limbo until it is destroyed. >> + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0) >> + { >> + args->m_error.SetErrorToErrno(); >> + goto FINISH; >> + } >> +#endif >> + // XXX - Release the master terminal descriptor and pass it off to the >> + // XXX - ProcessMonitor instance. Similarly stash the inferior pid. >> + // For now just use stdin fd >> + monitor->m_terminal_fd = STDIN_FILENO; >> + monitor->m_pid = pid; >> + >> + // Set the terminal fd to be in non blocking mode (it simplifies the >> + // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking >> + // descriptor to read from). >> + if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) >> + goto FINISH; >> + >> + // Update the process thread list with this new thread. >> + inferior.reset(new POSIXThread(process, pid)); >> + process.GetThreadList().AddThread(inferior); >> + >> + // Let our process instance know the thread has stopped. >> + process.SendMessage(ProcessMessage::Trace(pid)); >> + >> +FINISH: >> + return args->m_error.Success(); >> +} >> + >> +bool >> +ProcessMonitor::EnableIPC() >> +{ >> + int fd[2]; >> + >> + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) >> + return false; >> + >> + m_client_fd = fd[0]; >> + m_server_fd = fd[1]; >> + return true; >> +} >> + >> +void >> +ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error) >> +{ >> + static const char *g_thread_name = "lldb.process.freebsd.operation"; >> + >> + if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread)) >> + return; >> + >> + m_operation_thread = >> + Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error); >> +} >> + >> +void >> +ProcessMonitor::StopAttachOpThread() >> +{ >> + assert(!"Not implemented yet!!!"); >> +} >> + >> +void * >> +ProcessMonitor::AttachOpThread(void *arg) >> +{ >> + AttachArgs *args = static_cast(arg); >> + >> + if (!Attach(args)) >> + return NULL; >> + >> + ServeOperation(args); >> + return NULL; >> +} >> + >> +bool >> +ProcessMonitor::Attach(AttachArgs *args) >> +{ >> + lldb::pid_t pid = args->m_pid; >> + >> + ProcessMonitor *monitor = args->m_monitor; >> + ProcessFreeBSD &process = monitor->GetProcess(); >> + ThreadList &tl = process.GetThreadList(); >> + lldb::ThreadSP inferior; >> + >> + if (pid <= 1) >> + { >> + args->m_error.SetErrorToGenericError(); >> + args->m_error.SetErrorString("Attaching to process 1 is not allowed."); >> + goto FINISH; >> + } >> + >> + // Attach to the requested process. >> + if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0) >> + { >> + args->m_error.SetErrorToErrno(); >> + goto FINISH; >> + } >> + >> + int status; >> + if ((status = waitpid(pid, NULL, 0)) < 0) >> + { >> + args->m_error.SetErrorToErrno(); >> + goto FINISH; >> + } >> + >> + // Update the process thread list with the attached thread. >> + inferior.reset(new POSIXThread(process, pid)); >> + tl.AddThread(inferior); >> + >> + // Let our process instance know the thread has stopped. >> + process.SendMessage(ProcessMessage::Trace(pid)); >> + >> + FINISH: >> + return args->m_error.Success(); >> +} >> + >> +bool >> +ProcessMonitor::MonitorCallback(void *callback_baton, >> + lldb::pid_t pid, >> + bool exited, >> + int signal, >> + int status) >> +{ >> + ProcessMessage message; >> + ProcessMonitor *monitor = static_cast(callback_baton); >> + ProcessFreeBSD *process = monitor->m_process; >> + bool stop_monitoring; >> + siginfo_t info; >> + >> + if (!monitor->GetSignalInfo(pid, &info)) >> + stop_monitoring = true; // pid is gone. Bail. >> + else { >> + switch (info.si_signo) >> + { >> + case SIGTRAP: >> + message = MonitorSIGTRAP(monitor, &info, pid); >> + break; >> + >> + default: >> + message = MonitorSignal(monitor, &info, pid); >> + break; >> + } >> + >> + process->SendMessage(message); >> + stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage; >> + } >> + >> + return stop_monitoring; >> +} >> + >> +ProcessMessage >> +ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, >> + const siginfo_t *info, lldb::pid_t pid) >> +{ >> + ProcessMessage message; >> + >> + assert(info->si_signo == SIGTRAP && "Unexpected child signal!"); >> + >> + switch (info->si_code) >> + { >> + default: >> + assert(false && "Unexpected SIGTRAP code!"); >> + break; >> + >> + case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): >> + { >> + // The inferior process is about to exit. Maintain the process in a >> + // state of "limbo" until we are explicitly commanded to detach, >> + // destroy, resume, etc. >> + unsigned long data = 0; >> + if (!monitor->GetEventMessage(pid, &data)) >> + data = -1; >> + message = ProcessMessage::Limbo(pid, (data >> 8)); >> + break; >> + } >> + >> + case 0: >> + case TRAP_TRACE: >> + message = ProcessMessage::Trace(pid); >> + break; >> + >> + case SI_KERNEL: >> + case TRAP_BRKPT: >> + message = ProcessMessage::Break(pid); >> + break; >> + } >> + >> + return message; >> +} >> + >> +ProcessMessage >> +ProcessMonitor::MonitorSignal(ProcessMonitor *monitor, >> + const siginfo_t *info, lldb::pid_t pid) >> +{ >> + ProcessMessage message; >> + int signo = info->si_signo; >> + >> + // POSIX says that process behaviour is undefined after it ignores a SIGFPE, >> + // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a >> + // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD. >> + // >> + // IOW, user generated signals never generate what we consider to be a >> + // "crash". >> + // >> + // Similarly, ACK signals generated by this monitor. >> + if (info->si_code == SI_USER) >> + { >> + if (info->si_pid == getpid()) >> + return ProcessMessage::SignalDelivered(pid, signo); >> + else >> + return ProcessMessage::Signal(pid, signo); >> + } >> + >> + if (signo == SIGSEGV) { >> + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); >> + ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info); >> + return ProcessMessage::Crash(pid, reason, signo, fault_addr); >> + } >> + >> + if (signo == SIGILL) { >> + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); >> + ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info); >> + return ProcessMessage::Crash(pid, reason, signo, fault_addr); >> + } >> + >> + if (signo == SIGFPE) { >> + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); >> + ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info); >> + return ProcessMessage::Crash(pid, reason, signo, fault_addr); >> + } >> + >> + if (signo == SIGBUS) { >> + lldb::addr_t fault_addr = reinterpret_cast(info->si_addr); >> + ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info); >> + return ProcessMessage::Crash(pid, reason, signo, fault_addr); >> + } >> + >> + // Everything else is "normal" and does not require any special action on >> + // our part. >> + return ProcessMessage::Signal(pid, signo); >> +} >> + >> +ProcessMessage::CrashReason >> +ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info) >> +{ >> + ProcessMessage::CrashReason reason; >> + assert(info->si_signo == SIGSEGV); >> + >> + reason = ProcessMessage::eInvalidCrashReason; >> + >> + switch (info->si_code) >> + { >> + default: >> + assert(false && "unexpected si_code for SIGSEGV"); >> + break; >> + case SEGV_MAPERR: >> + reason = ProcessMessage::eInvalidAddress; >> + break; >> + case SEGV_ACCERR: >> + reason = ProcessMessage::ePrivilegedAddress; >> + break; >> + } >> + >> + return reason; >> +} >> + >> +ProcessMessage::CrashReason >> +ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info) >> +{ >> + ProcessMessage::CrashReason reason; >> + assert(info->si_signo == SIGILL); >> + >> + reason = ProcessMessage::eInvalidCrashReason; >> + >> + switch (info->si_code) >> + { >> + default: >> + assert(false && "unexpected si_code for SIGILL"); >> + break; >> + case ILL_ILLOPC: >> + reason = ProcessMessage::eIllegalOpcode; >> + break; >> + case ILL_ILLOPN: >> + reason = ProcessMessage::eIllegalOperand; >> + break; >> + case ILL_ILLADR: >> + reason = ProcessMessage::eIllegalAddressingMode; >> + break; >> + case ILL_ILLTRP: >> + reason = ProcessMessage::eIllegalTrap; >> + break; >> + case ILL_PRVOPC: >> + reason = ProcessMessage::ePrivilegedOpcode; >> + break; >> + case ILL_PRVREG: >> + reason = ProcessMessage::ePrivilegedRegister; >> + break; >> + case ILL_COPROC: >> + reason = ProcessMessage::eCoprocessorError; >> + break; >> + case ILL_BADSTK: >> + reason = ProcessMessage::eInternalStackError; >> + break; >> + } >> + >> + return reason; >> +} >> + >> +ProcessMessage::CrashReason >> +ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info) >> +{ >> + ProcessMessage::CrashReason reason; >> + assert(info->si_signo == SIGFPE); >> + >> + reason = ProcessMessage::eInvalidCrashReason; >> + >> + switch (info->si_code) >> + { >> + default: >> + assert(false && "unexpected si_code for SIGFPE"); >> + break; >> + case FPE_INTDIV: >> + reason = ProcessMessage::eIntegerDivideByZero; >> + break; >> + case FPE_INTOVF: >> + reason = ProcessMessage::eIntegerOverflow; >> + break; >> + case FPE_FLTDIV: >> + reason = ProcessMessage::eFloatDivideByZero; >> + break; >> + case FPE_FLTOVF: >> + reason = ProcessMessage::eFloatOverflow; >> + break; >> + case FPE_FLTUND: >> + reason = ProcessMessage::eFloatUnderflow; >> + break; >> + case FPE_FLTRES: >> + reason = ProcessMessage::eFloatInexactResult; >> + break; >> + case FPE_FLTINV: >> + reason = ProcessMessage::eFloatInvalidOperation; >> + break; >> + case FPE_FLTSUB: >> + reason = ProcessMessage::eFloatSubscriptRange; >> + break; >> + } >> + >> + return reason; >> +} >> + >> +ProcessMessage::CrashReason >> +ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info) >> +{ >> + ProcessMessage::CrashReason reason; >> + assert(info->si_signo == SIGBUS); >> + >> + reason = ProcessMessage::eInvalidCrashReason; >> + >> + switch (info->si_code) >> + { >> + default: >> + assert(false && "unexpected si_code for SIGBUS"); >> + break; >> + case BUS_ADRALN: >> + reason = ProcessMessage::eIllegalAlignment; >> + break; >> + case BUS_ADRERR: >> + reason = ProcessMessage::eIllegalAddress; >> + break; >> + case BUS_OBJERR: >> + reason = ProcessMessage::eHardwareError; >> + break; >> + } >> + >> + return reason; >> +} >> + >> +void >> +ProcessMonitor::ServeOperation(OperationArgs *args) >> +{ >> + int status; >> + pollfd fdset; >> + >> + ProcessMonitor *monitor = args->m_monitor; >> + >> + fdset.fd = monitor->m_server_fd; >> + fdset.events = POLLIN | POLLPRI; >> + fdset.revents = 0; >> + >> + // We are finised with the arguments and are ready to go. Sync with the >> + // parent thread and start serving operations on the inferior. >> + sem_post(&args->m_semaphore); >> + >> + for (;;) >> + { >> + if ((status = poll(&fdset, 1, -1)) < 0) >> + { >> + switch (errno) >> + { >> + default: >> + assert(false && "Unexpected poll() failure!"); >> + continue; >> + >> + case EINTR: continue; // Just poll again. >> + case EBADF: return; // Connection terminated. >> + } >> + } >> + >> + assert(status == 1 && "Too many descriptors!"); >> + >> + if (fdset.revents & POLLIN) >> + { >> + Operation *op = NULL; >> + >> + READ_AGAIN: >> + if ((status = read(fdset.fd, &op, sizeof(op))) < 0) >> + { >> + // There is only one acceptable failure. >> + assert(errno == EINTR); >> + goto READ_AGAIN; >> + } >> + >> + assert(status == sizeof(op)); >> + op->Execute(monitor); >> + write(fdset.fd, &op, sizeof(op)); >> + } >> + } >> +} >> + >> +void >> +ProcessMonitor::DoOperation(Operation *op) >> +{ >> + int status; >> + Operation *ack = NULL; >> + Mutex::Locker lock(m_server_mutex); >> + >> + // FIXME: Do proper error checking here. >> + write(m_client_fd, &op, sizeof(op)); >> + >> +READ_AGAIN: >> + if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0) >> + { >> + // If interrupted by a signal handler try again. Otherwise the monitor >> + // thread probably died and we have a stale file descriptor -- abort the >> + // operation. >> + if (errno == EINTR) >> + goto READ_AGAIN; >> + return; >> + } >> + >> + assert(status == sizeof(ack)); >> + assert(ack == op && "Invalid monitor thread response!"); >> +} >> + >> +size_t >> +ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, >> + Error &error) >> +{ >> + size_t result; >> + ReadOperation op(vm_addr, buf, size, error, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +size_t >> +ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, >> + lldb_private::Error &error) >> +{ >> + size_t result; >> + WriteOperation op(vm_addr, buf, size, error, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) >> +{ >> + bool result; >> + ReadRegOperation op(offset, size, value, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::WriteRegisterValue(unsigned offset, const RegisterValue &value) >> +{ >> + bool result; >> + WriteRegOperation op(offset, value, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::ReadGPR(void *buf) >> +{ >> + bool result; >> + ReadGPROperation op(buf, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::ReadFPR(void *buf) >> +{ >> + bool result; >> + ReadFPROperation op(buf, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::WriteGPR(void *buf) >> +{ >> + bool result; >> + WriteGPROperation op(buf, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::WriteFPR(void *buf) >> +{ >> + bool result; >> + WriteFPROperation op(buf, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo) >> +{ >> + bool result; >> + ResumeOperation op(tid, signo, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo) >> +{ >> + bool result; >> + SingleStepOperation op(tid, signo, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::BringProcessIntoLimbo() >> +{ >> + bool result; >> + KillOperation op(result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo) >> +{ >> + bool result; >> + SiginfoOperation op(tid, siginfo, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message) >> +{ >> + bool result; >> + EventMessageOperation op(tid, message, result); >> + DoOperation(&op); >> + return result; >> +} >> + >> +Error >> +ProcessMonitor::Detach() >> +{ >> + Error result; >> + DetachOperation op(result); >> + DoOperation(&op); >> + StopMonitor(); >> + return result; >> +} >> + >> +bool >> +ProcessMonitor::DupDescriptor(const char *path, int fd, int flags) >> +{ >> + int target_fd = open(path, flags, 0666); >> + >> + if (target_fd == -1) >> + return false; >> + >> + return (dup2(target_fd, fd) == -1) ? false : true; >> +} >> + >> +void >> +ProcessMonitor::StopMonitoringChildProcess() >> +{ >> + lldb::thread_result_t thread_result; >> + >> + if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread)) >> + { >> + Host::ThreadCancel(m_monitor_thread, NULL); >> + Host::ThreadJoin(m_monitor_thread, &thread_result, NULL); >> + m_monitor_thread = LLDB_INVALID_HOST_THREAD; >> + } >> +} >> + >> +void >> +ProcessMonitor::StopMonitor() >> +{ >> + StopMonitoringChildProcess(); >> + StopLaunchOpThread(); >> + CloseFD(m_terminal_fd); >> + CloseFD(m_client_fd); >> + CloseFD(m_server_fd); >> +} >> + >> +void >> +ProcessMonitor::CloseFD(int &fd) >> +{ >> + if (fd != -1) >> + { >> + close(fd); >> + fd = -1; >> + } >> +} >> Index: source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h >> =================================================================== >> --- source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) >> +++ source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h (revision 0) >> @@ -0,0 +1,43 @@ >> +//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===// >> +// >> +// The LLVM Compiler Infrastructure >> +// >> +// This file is distributed under the University of Illinois Open Source >> +// License. See LICENSE.TXT for details. >> +// >> +//===----------------------------------------------------------------------===// >> + >> +#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_ >> +#define liblldb_RegisterContextFreeBSD_x86_64_H_ >> + >> + typedef struct _GPR >> + { >> + uint64_t r15; >> + uint64_t r14; >> + uint64_t r13; >> + uint64_t r12; >> + uint64_t r11; >> + uint64_t r10; >> + uint64_t r9; >> + uint64_t r8; >> + uint64_t rdi; >> + uint64_t rsi; >> + uint64_t rbp; >> + uint64_t rbx; >> + uint64_t rdx; >> + uint64_t rcx; >> + uint64_t rax; >> + uint32_t trapno; >> + uint16_t fs; >> + uint16_t gs; >> + uint32_t err; >> + uint16_t es; >> + uint16_t ds; >> + uint64_t rip; >> + uint64_t cs; >> + uint64_t rflags; >> + uint64_t rsp; >> + uint64_t ss; >> + } GPR; >> + >> +#endif >> Index: source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp >> =================================================================== >> --- source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) >> +++ source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp (revision 0) >> @@ -0,0 +1,136 @@ >> +//===-- ProcessFreeBSD.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 >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/Core/PluginManager.h" >> +#include "lldb/Core/State.h" >> +#include "lldb/Host/Host.h" >> +#include "lldb/Symbol/ObjectFile.h" >> +#include "lldb/Target/DynamicLoader.h" >> +#include "lldb/Target/Target.h" >> + >> +#include "ProcessFreeBSD.h" >> +#include "ProcessPOSIXLog.h" >> +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" >> +#include "ProcessMonitor.h" >> +#include "POSIXThread.h" >> + >> +using namespace lldb; >> +using namespace lldb_private; >> + >> +//------------------------------------------------------------------------------ >> +// Static functions. >> + >> +Process* >> +ProcessFreeBSD::CreateInstance(Target& target, Listener &listener) >> +{ >> + return new ProcessFreeBSD(target, listener); >> +} >> + >> +void >> +ProcessFreeBSD::Initialize() >> +{ >> + static bool g_initialized = false; >> + >> + if (!g_initialized) >> + { >> + PluginManager::RegisterPlugin(GetPluginNameStatic(), >> + GetPluginDescriptionStatic(), >> + CreateInstance); >> + Log::Callbacks log_callbacks = { >> + ProcessPOSIXLog::DisableLog, >> + ProcessPOSIXLog::EnableLog, >> + ProcessPOSIXLog::ListLogCategories >> + }; >> + >> + Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks); >> + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); >> + g_initialized = true; >> + } >> +} >> + >> +const char * >> +ProcessFreeBSD::GetPluginNameStatic() >> +{ >> + return "freebsd"; >> +} >> + >> +const char * >> +ProcessFreeBSD::GetPluginDescriptionStatic() >> +{ >> + return "Process plugin for FreeBSD"; >> +} >> + >> +//------------------------------------------------------------------------------ >> +// ProcessInterface protocol. >> + >> +const char * >> +ProcessFreeBSD::GetPluginName() >> +{ >> + return "process.freebsd"; >> +} >> + >> +const char * >> +ProcessFreeBSD::GetShortPluginName() >> +{ >> + return "process.freebsd"; >> +} >> + >> +uint32_t >> +ProcessFreeBSD::GetPluginVersion() >> +{ >> + return 1; >> +} >> + >> +void >> +ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm) >> +{ >> +} >> + >> +Error >> +ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm) >> +{ >> + return Error(1, eErrorTypeGeneric); >> +} >> + >> +Log * >> +ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command) >> +{ >> + return NULL; >> +} >> + >> +//------------------------------------------------------------------------------ >> +// Constructors and destructors. >> + >> +ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener) >> + : ProcessPOSIX(target, listener) >> +{ >> + // FIXME: Putting this code in the ctor and saving the byte order in a >> + // member variable is a hack to avoid const qual issues in GetByteOrder. >> + ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile(); >> + m_byte_order = obj_file->GetByteOrder(); >> +} >> + >> +void >> +ProcessFreeBSD::Terminate() >> +{ >> +} >> + >> +uint32_t >> +ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) >> +{ >> + // XXX haxx >> + new_thread_list = old_thread_list; >> + >> + return 0; >> +} >> Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h >> =================================================================== >> --- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) >> +++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 0) >> @@ -0,0 +1,292 @@ >> +//===-- ProcessMonitor.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_ProcessMonitor_H_ >> +#define liblldb_ProcessMonitor_H_ >> + >> +// C Includes >> +#include >> +#include >> + >> +// C++ Includes >> +// Other libraries and framework includes >> +#include "lldb/lldb-types.h" >> +#include "lldb/Host/Mutex.h" >> + >> +namespace lldb_private >> +{ >> +class Error; >> +class Module; >> +class Scalar; >> +} // End lldb_private namespace. >> + >> +class ProcessFreeBSD; >> +class Operation; >> + >> +/// @class ProcessMonitor >> +/// @brief Manages communication with the inferior (debugee) process. >> +/// >> +/// Upon construction, this class prepares and launches an inferior process for >> +/// debugging. >> +/// >> +/// Changes in the inferior process state are propagated to the associated >> +/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the >> +/// appropriate ProcessMessage events. >> +/// >> +/// A purposely minimal set of operations are provided to interrogate and change >> +/// the inferior process state. >> +class ProcessMonitor >> +{ >> +public: >> + >> + /// Launches an inferior process ready for debugging. Forms the >> + /// implementation of Process::DoLaunch. >> + ProcessMonitor(ProcessPOSIX *process, >> + lldb_private::Module *module, >> + char const *argv[], >> + char const *envp[], >> + const char *stdin_path, >> + const char *stdout_path, >> + const char *stderr_path, >> + lldb_private::Error &error); >> + >> + ProcessMonitor(ProcessPOSIX *process, >> + lldb::pid_t pid, >> + lldb_private::Error &error); >> + >> + ~ProcessMonitor(); >> + >> + /// Provides the process number of debugee. >> + lldb::pid_t >> + GetPID() const { return m_pid; } >> + >> + /// Returns the process associated with this ProcessMonitor. >> + ProcessFreeBSD & >> + GetProcess() { return *m_process; } >> + >> + /// Returns a file descriptor to the controlling terminal of the inferior >> + /// process. >> + /// >> + /// Reads from this file descriptor yield both the standard output and >> + /// standard error of this debugee. Even if stderr and stdout were >> + /// redirected on launch it may still happen that data is available on this >> + /// descriptor (if the inferior process opens /dev/tty, for example). >> + /// >> + /// If this monitor was attached to an existing process this method returns >> + /// -1. >> + int >> + GetTerminalFD() const { return m_terminal_fd; } >> + >> + /// Reads @p size bytes from address @vm_adder in the inferior process >> + /// address space. >> + /// >> + /// This method is provided to implement Process::DoReadMemory. >> + size_t >> + ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, >> + lldb_private::Error &error); >> + >> + /// Writes @p size bytes from address @p vm_adder in the inferior process >> + /// address space. >> + /// >> + /// This method is provided to implement Process::DoWriteMemory. >> + size_t >> + WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, >> + lldb_private::Error &error); >> + >> + /// Reads the contents from the register identified by the given (architecture >> + /// dependent) offset. >> + /// >> + /// This method is provided for use by RegisterContextFreeBSD derivatives. >> + bool >> + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); >> + >> + /// Writes the given value to the register identified by the given >> + /// (architecture dependent) offset. >> + /// >> + /// This method is provided for use by RegisterContextFreeBSD derivatives. >> + bool >> + WriteRegisterValue(unsigned offset, const lldb_private::RegisterValue &value); >> + >> + /// Reads all general purpose registers into the specified buffer. >> + bool >> + ReadGPR(void *buf); >> + >> + /// Reads all floating point registers into the specified buffer. >> + bool >> + ReadFPR(void *buf); >> + >> + /// Writes all general purpose registers into the specified buffer. >> + bool >> + WriteGPR(void *buf); >> + >> + /// Writes all floating point registers into the specified buffer. >> + bool >> + WriteFPR(void *buf); >> + >> + /// Writes a siginfo_t structure corresponding to the given thread ID to the >> + /// memory region pointed to by @p siginfo. >> + bool >> + GetSignalInfo(lldb::tid_t tid, void *siginfo); >> + >> + /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG) >> + /// corresponding to the given thread IDto the memory pointed to by @p >> + /// message. >> + bool >> + GetEventMessage(lldb::tid_t tid, unsigned long *message); >> + >> + /// Resumes the given thread. If @p signo is anything but >> + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. >> + bool >> + Resume(lldb::tid_t tid, uint32_t signo); >> + >> + /// Single steps the given thread. If @p signo is anything but >> + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. >> + bool >> + SingleStep(lldb::tid_t tid, uint32_t signo); >> + >> + /// Sends the inferior process a PTRACE_KILL signal. The inferior will >> + /// still exists and can be interrogated. Once resumed it will exit as >> + /// though it received a SIGKILL. >> + bool >> + BringProcessIntoLimbo(); >> + >> + lldb_private::Error >> + Detach(); >> + >> + >> +private: >> + ProcessFreeBSD *m_process; >> + >> + lldb::thread_t m_operation_thread; >> + lldb::thread_t m_monitor_thread; >> + lldb::pid_t m_pid; >> + >> + >> + lldb_private::Mutex m_server_mutex; >> + int m_terminal_fd; >> + int m_client_fd; >> + int m_server_fd; >> + >> + struct OperationArgs >> + { >> + OperationArgs(ProcessMonitor *monitor); >> + >> + ~OperationArgs(); >> + >> + ProcessMonitor *m_monitor; // The monitor performing the attach. >> + sem_t m_semaphore; // Posted to once operation complete. >> + lldb_private::Error m_error; // Set if process operation failed. >> + }; >> + >> + /// @class LauchArgs >> + /// >> + /// @brief Simple structure to pass data to the thread responsible for >> + /// launching a child process. >> + struct LaunchArgs : OperationArgs >> + { >> + LaunchArgs(ProcessMonitor *monitor, >> + lldb_private::Module *module, >> + char const **argv, >> + char const **envp, >> + const char *stdin_path, >> + const char *stdout_path, >> + const char *stderr_path); >> + >> + ~LaunchArgs(); >> + >> + lldb_private::Module *m_module; // The executable image to launch. >> + char const **m_argv; // Process arguments. >> + char const **m_envp; // Process environment. >> + const char *m_stdin_path; // Redirect stdin or NULL. >> + const char *m_stdout_path; // Redirect stdout or NULL. >> + const char *m_stderr_path; // Redirect stderr or NULL. >> + }; >> + >> + void >> + StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error); >> + >> + void >> + StopLaunchOpThread(); >> + >> + static void * >> + LaunchOpThread(void *arg); >> + >> + static bool >> + Launch(LaunchArgs *args); >> + >> + bool >> + EnableIPC(); >> + >> + struct AttachArgs : OperationArgs >> + { >> + AttachArgs(ProcessMonitor *monitor, >> + lldb::pid_t pid); >> + >> + ~AttachArgs(); >> + >> + lldb::pid_t m_pid; // pid of the process to be attached. >> + }; >> + >> + void >> + StartAttachOpThread(AttachArgs *args, lldb_private::Error &error); >> + >> + void >> + StopAttachOpThread(); >> + >> + static void * >> + AttachOpThread(void *args); >> + >> + static bool >> + Attach(AttachArgs *args); >> + >> + static void >> + ServeOperation(OperationArgs *args); >> + >> + static bool >> + DupDescriptor(const char *path, int fd, int flags); >> + >> + static bool >> + MonitorCallback(void *callback_baton, >> + lldb::pid_t pid, bool exited, int signal, int status); >> + >> + static ProcessMessage >> + MonitorSIGTRAP(ProcessMonitor *monitor, >> + const siginfo_t *info, lldb::pid_t pid); >> + >> + static ProcessMessage >> + MonitorSignal(ProcessMonitor *monitor, >> + const siginfo_t *info, lldb::pid_t pid); >> + >> + static ProcessMessage::CrashReason >> + GetCrashReasonForSIGSEGV(const siginfo_t *info); >> + >> + static ProcessMessage::CrashReason >> + GetCrashReasonForSIGILL(const siginfo_t *info); >> + >> + static ProcessMessage::CrashReason >> + GetCrashReasonForSIGFPE(const siginfo_t *info); >> + >> + static ProcessMessage::CrashReason >> + GetCrashReasonForSIGBUS(const siginfo_t *info); >> + >> + void >> + DoOperation(Operation *op); >> + >> + /// Stops the child monitor thread. >> + void >> + StopMonitoringChildProcess(); >> + >> + void >> + StopMonitor(); >> + >> + void >> + CloseFD(int &fd); >> +}; >> + >> +#endif // #ifndef liblldb_ProcessMonitor_H_ >> Index: source/Plugins/Process/FreeBSD/Makefile >> =================================================================== >> --- source/Plugins/Process/FreeBSD/Makefile (revision 0) >> +++ source/Plugins/Process/FreeBSD/Makefile (revision 0) >> @@ -0,0 +1,17 @@ >> +##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===## >> +# >> +# The LLVM Compiler Infrastructure >> +# >> +# This file is distributed under the University of Illinois Open Source >> +# License. See LICENSE.TXT for details. >> +# >> +##===----------------------------------------------------------------------===## >> + >> +LLDB_LEVEL := ../../../.. >> +LIBRARYNAME := lldbPluginProcessFreeBSD >> +BUILD_ARCHIVE = 1 >> + >> +# Extend the include path so we may locate UnwindLLDB.h >> +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility >> + >> +include $(LLDB_LEVEL)/Makefile >> Index: source/Host/linux/Host.cpp >> =================================================================== >> --- source/Host/linux/Host.cpp (revision 147560) >> +++ source/Host/linux/Host.cpp (working copy) >> @@ -10,12 +10,20 @@ >> // C Includes >> #include >> #include >> +#include >> +#include >> +#include >> >> + >> // C++ Includes >> // Other libraries and framework includes >> // Project includes >> #include "lldb/Core/Error.h" >> +#include "lldb/Target/Process.h" >> + >> #include "lldb/Host/Host.h" >> +#include "lldb/Core/DataBufferHeap.h" >> +#include "lldb/Core/DataExtractor.h" >> >> using namespace lldb; >> using namespace lldb_private; >> @@ -43,3 +51,48 @@ >> return error; >> } >> >> +lldb::DataBufferSP >> +Host::GetAuxvData(lldb_private::Process *process) >> +{ >> + static const size_t path_size = 128; >> + static char path[path_size]; >> + lldb::DataBufferSP buf_sp; >> + >> + int fd; >> + >> + // Ideally, we would simply create a FileSpec and call ReadFileContents. >> + // However, files in procfs have zero size (since they are, in general, >> + // dynamically generated by the kernel) which is incompatible with the >> + // current ReadFileContents implementation. Therefore we simply stream the >> + // data into a DataBuffer ourselves. >> + if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0) >> + return buf_sp; >> + >> + if ((fd = open(path, O_RDONLY, 0)) < 0) >> + return buf_sp; >> + >> + size_t bytes_read = 0; >> + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); >> + for (;;) >> + { >> + size_t avail = buf_ap->GetByteSize() - bytes_read; >> + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); >> + >> + if (status < 0) >> + break; >> + >> + bytes_read += status; >> + >> + if (status == 0) >> + { >> + buf_ap->SetByteSize(bytes_read); >> + buf_sp.reset(buf_ap.release()); >> + break; >> + } >> + >> + if (avail - status == 0) >> + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); >> + } >> + >> + return buf_sp; >> +} >> Index: source/Host/freebsd/Host.cpp >> =================================================================== >> --- source/Host/freebsd/Host.cpp (revision 147560) >> +++ source/Host/freebsd/Host.cpp (working copy) >> @@ -9,12 +9,18 @@ >> >> // C Includes >> #include >> +#include >> #include >> #include >> #include >> #include >> #include >> >> +#include >> +#include >> +#include >> + >> + >> // C++ Includes >> // Other libraries and framework includes >> // Project includes >> @@ -26,15 +32,19 @@ >> #include "lldb/Core/StreamString.h" >> #include "lldb/Target/Process.h" >> >> +#include "lldb/Core/DataBufferHeap.h" >> +#include "lldb/Core/DataExtractor.h" >> #include "llvm/Support/Host.h" >> >> + >> extern "C" { >> - char **environ; >> + extern char **environ; >> } >> >> using namespace lldb; >> using namespace lldb_private; >> >> + >> class FreeBSDThread >> { >> public: >> @@ -77,7 +87,7 @@ >> std::vector frame_buffer (max_frames, NULL); >> int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); >> ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); >> - >> + >> const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); >> >> if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) >> @@ -101,7 +111,7 @@ >> { >> char *v; >> char **var = environ; >> - for (var = environ; var != NULL; ++var) { >> + for (; var != NULL && *var != NULL; ++var) { >> v = strchr(*var, (int)'-'); >> if (v == NULL) >> continue; >> @@ -168,49 +178,47 @@ >> ProcessInstanceInfo &process_info) >> { >> if (process_info.ProcessIDIsValid()) { >> - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; >> + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; >> >> char arg_data[8192]; >> size_t arg_data_size = sizeof(arg_data); >> - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) >> + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) >> { >> DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); >> uint32_t offset = 0; >> - uint32_t start_offset; >> - uint32_t argc = data.GetU32 (&offset); >> const char *cstr; >> - >> + >> cstr = data.GetCStr (&offset); >> if (cstr) >> { >> process_info.GetExecutableFile().SetFile(cstr, false); >> >> - if (match_info_ptr == NULL || >> + if (!(match_info_ptr == NULL || >> NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), >> match_info_ptr->GetNameMatchType(), >> - match_info_ptr->GetProcessInfo().GetName())) >> + match_info_ptr->GetProcessInfo().GetName()))) >> + return false; >> + >> + Args &proc_args = process_info.GetArguments(); >> + while (1) >> { >> - // Skip NULLs >> - while (1) >> + const uint8_t *p = data.PeekData(offset, 1); >> + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) >> { >> - const uint8_t *p = data.PeekData(offset, 1); >> - if ((p == NULL) || (*p != '\0')) >> - break; >> ++offset; >> + p = data.PeekData(offset, 1); >> } >> - // Now extract all arguments >> - Args &proc_args = process_info.GetArguments(); >> - for (int i=0; i> - { >> - start_offset = offset; >> - cstr = data.GetCStr(&offset); >> - if (cstr) >> - proc_args.AppendArgument(cstr); >> - } >> - return true; >> + if (p == NULL || offset >= arg_data_size) >> + return true; >> + >> + cstr = data.GetCStr(&offset); >> + if (cstr) >> + proc_args.AppendArgument(cstr); >> + else >> + return true; >> } >> } >> - } >> + } >> } >> return false; >> } >> @@ -219,8 +227,8 @@ >> GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) >> { >> if (process_info.ProcessIDIsValid()) { >> - // TODO: This >> - // return true; >> + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); >> + return true; >> } >> process_info.GetArchitecture().Clear(); >> return false; >> @@ -249,7 +257,7 @@ >> if (proc_kinfo.ki_ngroups > 0) >> process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); >> else >> - process_info.SetEffectiveGroupID (UINT32_MAX); >> + process_info.SetEffectiveGroupID (UINT32_MAX); >> return true; >> } >> } >> @@ -258,7 +266,7 @@ >> process_info.SetUserID (UINT32_MAX); >> process_info.SetGroupID (UINT32_MAX); >> process_info.SetEffectiveUserID (UINT32_MAX); >> - process_info.SetEffectiveGroupID (UINT32_MAX); >> + process_info.SetEffectiveGroupID (UINT32_MAX); >> return false; >> } >> >> @@ -275,3 +283,46 @@ >> process_info.Clear(); >> return false; >> } >> + >> +lldb::DataBufferSP >> +Host::GetAuxvData(lldb_private::Process *process) >> +{ >> + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; >> + void *ps_strings_addr, *auxv_addr; >> + size_t ps_strings_size = sizeof(void *); >> + Elf_Auxinfo aux_info[AT_COUNT]; >> + struct ps_strings ps_strings; >> + struct ptrace_io_desc pid; >> + DataBufferSP buf_sp; >> + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); >> + >> + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { >> + pid.piod_op = PIOD_READ_D; >> + pid.piod_addr = &ps_strings; >> + pid.piod_offs = ps_strings_addr; >> + pid.piod_len = sizeof(ps_strings); >> + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { >> + perror("failed to fetch ps_strings"); >> + buf_ap.release(); >> + goto done; >> + } >> + >> + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; >> + >> + pid.piod_addr = aux_info; >> + pid.piod_offs = auxv_addr; >> + pid.piod_len = sizeof(aux_info); >> + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { >> + perror("failed to fetch aux_info"); >> + buf_ap.release(); >> + goto done; >> + } >> + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); >> + buf_sp.reset(buf_ap.release()); >> + } else { >> + perror("sysctl failed on ps_strings"); >> + } >> + >> + done: >> + return buf_sp; >> +} >> Index: source/lldb.cpp >> =================================================================== >> --- source/lldb.cpp (revision 147560) >> +++ source/lldb.cpp (working copy) >> @@ -52,13 +52,16 @@ >> #endif >> >> #if defined (__linux__) >> -#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h" >> +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" >> #include "Plugins/Platform/Linux/PlatformLinux.h" >> #include "Plugins/Process/Linux/ProcessLinux.h" >> #endif >> >> #if defined (__FreeBSD__) >> +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" >> #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" >> +#include "Plugins/Process/POSIX/ProcessPOSIX.h" >> +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" >> #endif >> >> #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" >> @@ -120,10 +123,12 @@ >> //---------------------------------------------------------------------- >> PlatformLinux::Initialize(); >> ProcessLinux::Initialize(); >> - DynamicLoaderLinuxDYLD::Initialize(); >> + DynamicLoaderPOSIXDYLD::Initialize(); >> #endif >> #if defined (__FreeBSD__) >> - PlatformFreeBSD::Initialize(); >> + PlatformFreeBSD::Initialize(); >> + ProcessFreeBSD::Initialize(); >> + DynamicLoaderPOSIXDYLD::Initialize(); >> #endif >> //---------------------------------------------------------------------- >> // Platform agnostic plugins >> @@ -190,11 +195,13 @@ >> #if defined (__linux__) >> PlatformLinux::Terminate(); >> ProcessLinux::Terminate(); >> - DynamicLoaderLinuxDYLD::Terminate(); >> + DynamicLoaderPOSIXDYLD::Terminate(); >> #endif >> >> #if defined (__FreeBSD__) >> - PlatformFreeBSD::Terminate(); >> + PlatformFreeBSD::Terminate(); >> + ProcessFreeBSD::Terminate(); >> + DynamicLoaderPOSIXDYLD::Terminate(); >> #endif >> >> DynamicLoaderStatic::Terminate(); >> Index: tools/driver/Makefile >> =================================================================== >> --- tools/driver/Makefile (revision 147560) >> +++ tools/driver/Makefile (working copy) >> @@ -25,7 +25,6 @@ >> >> ifeq ($(HOST_OS),FreeBSD) >> CPP.Flags += -I/usr/include/edit #-v >> - LD.Flags += -lEnhancedDisassembly >> LD.Flags += -Wl,-rpath,$(LibDir) >> endif >> >> Index: lib/Makefile >> =================================================================== >> --- lib/Makefile (revision 147560) >> +++ lib/Makefile (working copy) >> @@ -81,15 +81,19 @@ >> endif >> >> ifeq ($(HOST_OS),Linux) >> - USEDLIBS += lldbPluginProcessLinux.a \ >> - lldbPluginDynamicLoaderLinux.a \ >> + USEDLIBS += lldbPluginProcessPOSIX.a \ >> + lldbPluginProcessLinux.a \ >> + lldbPluginDynamicLoaderPOSIX.a \ >> lldbPluginPlatformLinux.a \ >> lldbHostLinux.a >> endif >> >> ifeq ($(HOST_OS),FreeBSD) >> USEDLIBS += lldbHostFreeBSD.a \ >> - lldbPluginPlatformFreeBSD.a >> + lldbPluginDynamicLoaderPOSIX.a \ >> + lldbPluginProcessPOSIX.a \ >> + lldbPluginProcessFreeBSD.a \ >> + lldbPluginPlatformFreeBSD.a >> endif >> >> include $(LEVEL)/Makefile.common >> @@ -130,8 +134,8 @@ >> # Include everything from the .a's into the shared library. >> ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \ >> -Wl,--no-whole-archive >> - # Don't allow unresolved symbols. >> - LLVMLibsOptions += -Wl,--no-undefined >> + # Allow unresolved symbols. >> + LLVMLibsOptions += -Wl,--allow-shlib-undefined >> # Link in python >> LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo >> endif >> Index: Makefile >> =================================================================== >> --- Makefile (revision 147560) >> +++ Makefile (working copy) >> @@ -39,6 +39,7 @@ >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility >> +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX >> ifeq ($(HOST_OS),Darwin) >> CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks >> endif > >> _______________________________________________ >> lldb-commits mailing list >> lldb-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > From johnny.chen at apple.com Thu Jan 5 13:17:39 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 05 Jan 2012 19:17:39 -0000 Subject: [Lldb-commits] [lldb] r147609 - in /lldb/trunk: ./ include/lldb/Host/ lib/ source/ source/Host/freebsd/ source/Host/linux/ source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/ source/Plugins/Platform/FreeBSD/ source/Plugins/Platform/Linux/ source/Plugins/Process/Linux/ tools/driver/ Message-ID: <20120105191739.DCD8D1BE003@llvm.org> Author: johnny Date: Thu Jan 5 13:17:38 2012 New Revision: 147609 URL: http://llvm.org/viewvc/llvm-project?rev=147609&view=rev Log: This patch combines common code from Linux and FreeBSD into a new POSIX platform. It also contains fixes for 64bit FreeBSD. The patch is based on changes by Mark Peek and "K. Macy" in their github repo located at https://github.com/fbsd/lldb. Modified: lldb/trunk/Makefile lldb/trunk/include/lldb/Host/Host.h lldb/trunk/lib/Makefile lldb/trunk/source/Host/freebsd/Host.cpp lldb/trunk/source/Host/linux/Host.cpp lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile lldb/trunk/source/Plugins/Makefile lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h lldb/trunk/source/Plugins/Process/Linux/Makefile lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h lldb/trunk/source/lldb.cpp lldb/trunk/tools/driver/Makefile Modified: lldb/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/Makefile (original) +++ lldb/trunk/Makefile Thu Jan 5 13:17:38 2012 @@ -39,6 +39,7 @@ CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX ifeq ($(HOST_OS),Darwin) CPP.Flags += -F/System/Library/Frameworks -F/System/Library/PrivateFrameworks endif Modified: lldb/trunk/include/lldb/Host/Host.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Host.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/include/lldb/Host/Host.h (original) +++ lldb/trunk/include/lldb/Host/Host.h Thu Jan 5 13:17:38 2012 @@ -367,7 +367,10 @@ static Error LaunchProcess (ProcessLaunchInfo &launch_info); - + + static lldb::DataBufferSP + GetAuxvData (lldb_private::Process *process); + static lldb::TargetSP GetDummyTarget (Debugger &debugger); Modified: lldb/trunk/lib/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/lib/Makefile (original) +++ lldb/trunk/lib/Makefile Thu Jan 5 13:17:38 2012 @@ -81,15 +81,19 @@ endif ifeq ($(HOST_OS),Linux) - USEDLIBS += lldbPluginProcessLinux.a \ - lldbPluginDynamicLoaderLinux.a \ + USEDLIBS += lldbPluginProcessPOSIX.a \ + lldbPluginProcessLinux.a \ + lldbPluginDynamicLoaderPOSIX.a \ lldbPluginPlatformLinux.a \ lldbHostLinux.a endif ifeq ($(HOST_OS),FreeBSD) USEDLIBS += lldbHostFreeBSD.a \ - lldbPluginPlatformFreeBSD.a + lldbPluginDynamicLoaderPOSIX.a \ + lldbPluginProcessPOSIX.a \ + lldbPluginProcessFreeBSD.a \ + lldbPluginPlatformFreeBSD.a endif include $(LEVEL)/Makefile.common @@ -130,8 +134,8 @@ # Include everything from the .a's into the shared library. ProjLibsOptions := -Wl,--whole-archive $(ProjLibsOptions) \ -Wl,--no-whole-archive - # Don't allow unresolved symbols. - LLVMLibsOptions += -Wl,--no-undefined + # Allow unresolved symbols. + LLVMLibsOptions += -Wl,--allow-shlib-undefined # Link in python LD.Flags += $(PYTHON_BUILD_FLAGS) -lrt -L/usr/local/lib -lexecinfo endif Modified: lldb/trunk/source/Host/freebsd/Host.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/freebsd/Host.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Host/freebsd/Host.cpp (original) +++ lldb/trunk/source/Host/freebsd/Host.cpp Thu Jan 5 13:17:38 2012 @@ -9,12 +9,18 @@ // C Includes #include +#include #include #include #include #include #include +#include +#include +#include + + // C++ Includes // Other libraries and framework includes // Project includes @@ -26,15 +32,19 @@ #include "lldb/Core/StreamString.h" #include "lldb/Target/Process.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "llvm/Support/Host.h" + extern "C" { - char **environ; + extern char **environ; } using namespace lldb; using namespace lldb_private; + class FreeBSDThread { public: @@ -77,7 +87,7 @@ std::vector frame_buffer (max_frames, NULL); int count = ::backtrace (&frame_buffer[0], frame_buffer.size()); ::backtrace_symbols_fd (&frame_buffer[0], count, backtrace_fd); - + const off_t buffer_size = ::lseek(backtrace_fd, 0, SEEK_CUR); if (::lseek(backtrace_fd, 0, SEEK_SET) == 0) @@ -101,7 +111,7 @@ { char *v; char **var = environ; - for (var = environ; var != NULL; ++var) { + for (; var != NULL && *var != NULL; ++var) { v = strchr(*var, (int)'-'); if (v == NULL) continue; @@ -168,49 +178,47 @@ ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - int mib[3] = { CTL_KERN, KERN_PROC_ARGS, process_info.GetProcessID() }; + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ARGS, process_info.GetProcessID() }; char arg_data[8192]; size_t arg_data_size = sizeof(arg_data); - if (::sysctl (mib, 3, arg_data, &arg_data_size , NULL, 0) == 0) + if (::sysctl (mib, 4, arg_data, &arg_data_size , NULL, 0) == 0) { DataExtractor data (arg_data, arg_data_size, lldb::endian::InlHostByteOrder(), sizeof(void *)); uint32_t offset = 0; - uint32_t start_offset; - uint32_t argc = data.GetU32 (&offset); const char *cstr; - + cstr = data.GetCStr (&offset); if (cstr) { process_info.GetExecutableFile().SetFile(cstr, false); - if (match_info_ptr == NULL || + if (!(match_info_ptr == NULL || NameMatches (process_info.GetExecutableFile().GetFilename().GetCString(), match_info_ptr->GetNameMatchType(), - match_info_ptr->GetProcessInfo().GetName())) + match_info_ptr->GetProcessInfo().GetName()))) + return false; + + Args &proc_args = process_info.GetArguments(); + while (1) { - // Skip NULLs - while (1) + const uint8_t *p = data.PeekData(offset, 1); + while ((p != NULL) && (*p == '\0') && offset < arg_data_size) { - const uint8_t *p = data.PeekData(offset, 1); - if ((p == NULL) || (*p != '\0')) - break; ++offset; + p = data.PeekData(offset, 1); } - // Now extract all arguments - Args &proc_args = process_info.GetArguments(); - for (int i=0; i= arg_data_size) + return true; + + cstr = data.GetCStr(&offset); + if (cstr) + proc_args.AppendArgument(cstr); + else + return true; } } - } + } } return false; } @@ -219,8 +227,8 @@ GetFreeBSDProcessCPUType (ProcessInstanceInfo &process_info) { if (process_info.ProcessIDIsValid()) { - // TODO: This - // return true; + process_info.GetArchitecture() = Host::GetArchitecture (Host::eSystemDefaultArchitecture); + return true; } process_info.GetArchitecture().Clear(); return false; @@ -249,7 +257,7 @@ if (proc_kinfo.ki_ngroups > 0) process_info.SetEffectiveGroupID (proc_kinfo.ki_groups[0]); else - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return true; } } @@ -258,7 +266,7 @@ process_info.SetUserID (UINT32_MAX); process_info.SetGroupID (UINT32_MAX); process_info.SetEffectiveUserID (UINT32_MAX); - process_info.SetEffectiveGroupID (UINT32_MAX); + process_info.SetEffectiveGroupID (UINT32_MAX); return false; } @@ -275,3 +283,46 @@ process_info.Clear(); return false; } + +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + int mib[2] = { CTL_KERN, KERN_PS_STRINGS }; + void *ps_strings_addr, *auxv_addr; + size_t ps_strings_size = sizeof(void *); + Elf_Auxinfo aux_info[AT_COUNT]; + struct ps_strings ps_strings; + struct ptrace_io_desc pid; + DataBufferSP buf_sp; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + + if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) { + pid.piod_op = PIOD_READ_D; + pid.piod_addr = &ps_strings; + pid.piod_offs = ps_strings_addr; + pid.piod_len = sizeof(ps_strings); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch ps_strings"); + buf_ap.release(); + goto done; + } + + auxv_addr = ps_strings.ps_envstr + ps_strings.ps_nenvstr + 1; + + pid.piod_addr = aux_info; + pid.piod_offs = auxv_addr; + pid.piod_len = sizeof(aux_info); + if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, NULL)) { + perror("failed to fetch aux_info"); + buf_ap.release(); + goto done; + } + memcpy(buf_ap->GetBytes(), aux_info, pid.piod_len); + buf_sp.reset(buf_ap.release()); + } else { + perror("sysctl failed on ps_strings"); + } + + done: + return buf_sp; +} Modified: lldb/trunk/source/Host/linux/Host.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/linux/Host.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Host/linux/Host.cpp (original) +++ lldb/trunk/source/Host/linux/Host.cpp Thu Jan 5 13:17:38 2012 @@ -10,12 +10,20 @@ // C Includes #include #include +#include +#include +#include + // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Core/Error.h" +#include "lldb/Target/Process.h" + #include "lldb/Host/Host.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" using namespace lldb; using namespace lldb_private; @@ -43,3 +51,48 @@ return error; } +lldb::DataBufferSP +Host::GetAuxvData(lldb_private::Process *process) +{ + static const size_t path_size = 128; + static char path[path_size]; + lldb::DataBufferSP buf_sp; + + int fd; + + // Ideally, we would simply create a FileSpec and call ReadFileContents. + // However, files in procfs have zero size (since they are, in general, + // dynamically generated by the kernel) which is incompatible with the + // current ReadFileContents implementation. Therefore we simply stream the + // data into a DataBuffer ourselves. + if (snprintf(path, path_size, "/proc/%d/auxv", process->GetID()) < 0) + return buf_sp; + + if ((fd = open(path, O_RDONLY, 0)) < 0) + return buf_sp; + + size_t bytes_read = 0; + std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); + for (;;) + { + size_t avail = buf_ap->GetByteSize() - bytes_read; + ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); + + if (status < 0) + break; + + bytes_read += status; + + if (status == 0) + { + buf_ap->SetByteSize(bytes_read); + buf_sp.reset(buf_ap.release()); + break; + } + + if (avail - status == 0) + buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); + } + + return buf_sp; +} Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp Thu Jan 5 13:17:38 2012 @@ -1,191 +0,0 @@ -//===-- AuxVector.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 -#include -#include - -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" - -#include "AuxVector.h" - -using namespace lldb; -using namespace lldb_private; - -static bool -GetMaxU64(DataExtractor &data, - uint32_t *offset, uint64_t *value, unsigned int byte_size) -{ - uint32_t saved_offset = *offset; - *value = data.GetMaxU64(offset, byte_size); - return *offset != saved_offset; -} - -static bool -ParseAuxvEntry(DataExtractor &data, AuxVector::Entry &entry, - uint32_t *offset, unsigned int byte_size) -{ - if (!GetMaxU64(data, offset, &entry.type, byte_size)) - return false; - - if (!GetMaxU64(data, offset, &entry.value, byte_size)) - return false; - - return true; -} - -DataBufferSP -AuxVector::GetAuxvData() -{ - static const size_t path_size = 128; - static char path[path_size]; - DataBufferSP buf_sp; - int fd; - - // Ideally, we would simply create a FileSpec and call ReadFileContents. - // However, files in procfs have zero size (since they are, in general, - // dynamically generated by the kernel) which is incompatible with the - // current ReadFileContents implementation. Therefore we simply stream the - // data into a DataBuffer ourselves. - if (snprintf(path, path_size, "/proc/%d/auxv", m_process->GetID()) < 0) - return buf_sp; - - if ((fd = open(path, O_RDONLY, 0)) < 0) - return buf_sp; - - size_t bytes_read = 0; - std::auto_ptr buf_ap(new DataBufferHeap(1024, 0)); - for (;;) - { - size_t avail = buf_ap->GetByteSize() - bytes_read; - ssize_t status = read(fd, buf_ap->GetBytes() + bytes_read, avail); - - if (status < 0) - break; - - bytes_read += status; - - if (status == 0) - { - buf_ap->SetByteSize(bytes_read); - buf_sp.reset(buf_ap.release()); - break; - } - - if (avail - status == 0) - buf_ap->SetByteSize(2 * buf_ap->GetByteSize()); - } - - return buf_sp; -} - -void -AuxVector::ParseAuxv(DataExtractor &data) -{ - const unsigned int byte_size = m_process->GetAddressByteSize(); - uint32_t offset = 0; - - for (;;) - { - Entry entry; - - if (!ParseAuxvEntry(data, entry, &offset, byte_size)) - break; - - if (entry.type == AT_NULL) - break; - - if (entry.type == AT_IGNORE) - continue; - - m_auxv.push_back(entry); - } -} - -AuxVector::AuxVector(Process *process) - : m_process(process) -{ - DataExtractor data; - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - - data.SetData(GetAuxvData()); - data.SetByteOrder(m_process->GetByteOrder()); - data.SetAddressByteSize(m_process->GetAddressByteSize()); - - ParseAuxv(data); - - if (log) - DumpToLog(log); -} - -AuxVector::iterator -AuxVector::FindEntry(EntryType type) const -{ - for (iterator I = begin(); I != end(); ++I) - { - if (I->type == static_cast(type)) - return I; - } - - return end(); -} - -void -AuxVector::DumpToLog(LogSP log) const -{ - if (!log) - return; - - log->PutCString("AuxVector: "); - for (iterator I = begin(); I != end(); ++I) - { - log->Printf(" %s [%d]: %lx", GetEntryName(*I), I->type, I->value); - } -} - -const char * -AuxVector::GetEntryName(EntryType type) -{ - const char *name; - -#define ENTRY_NAME(_type) _type: name = #_type - switch (type) - { - default: - name = "unkown"; - break; - - case ENTRY_NAME(AT_NULL); break; - case ENTRY_NAME(AT_IGNORE); break; - case ENTRY_NAME(AT_EXECFD); break; - case ENTRY_NAME(AT_PHDR); break; - case ENTRY_NAME(AT_PHENT); break; - case ENTRY_NAME(AT_PHNUM); break; - case ENTRY_NAME(AT_PAGESZ); break; - case ENTRY_NAME(AT_BASE); break; - case ENTRY_NAME(AT_FLAGS); break; - case ENTRY_NAME(AT_ENTRY); break; - case ENTRY_NAME(AT_NOTELF); break; - case ENTRY_NAME(AT_UID); break; - case ENTRY_NAME(AT_EUID); break; - case ENTRY_NAME(AT_GID); break; - case ENTRY_NAME(AT_EGID); break; - case ENTRY_NAME(AT_CLKTCK); break; - } -#undef ENTRY_NAME - - return name; -} - Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h Thu Jan 5 13:17:38 2012 @@ -1,97 +0,0 @@ -//===-- AuxVector.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_AuxVector_H_ -#define liblldb_AuxVector_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/lldb-forward-rtti.h" - -namespace lldb_private { -class DataExtractor; -} - -/// @class AuxVector -/// @brief Represents a processes auxiliary vector. -/// -/// When a process is loaded on Linux a vector of values is placed onto the -/// stack communicating operating system specific information. On construction -/// this class locates and parses this information and provides a simple -/// read-only interface to the entries found. -class AuxVector { - -public: - AuxVector(lldb_private::Process *process); - - struct Entry { - uint64_t type; - uint64_t value; - - Entry() : type(0), value(0) { } - }; - - /// Constants describing the type of entry. - enum EntryType { - AT_NULL = 0, ///< End of auxv. - AT_IGNORE = 1, ///< Ignore entry. - AT_EXECFD = 2, ///< File descriptor of program. - AT_PHDR = 3, ///< Program headers. - AT_PHENT = 4, ///< Size of program header. - AT_PHNUM = 5, ///< Number of program headers. - AT_PAGESZ = 6, ///< Page size. - AT_BASE = 7, ///< Interpreter base address. - AT_FLAGS = 8, ///< Flags. - AT_ENTRY = 9, ///< Program entry point. - AT_NOTELF = 10, ///< Set if program is not an ELF. - AT_UID = 11, ///< UID. - AT_EUID = 12, ///< Effective UID. - AT_GID = 13, ///< GID. - AT_EGID = 14, ///< Effective GID. - AT_CLKTCK = 17 ///< Clock frequency (e.g. times(2)). - }; - -private: - typedef std::vector EntryVector; - -public: - typedef EntryVector::const_iterator iterator; - - iterator begin() const { return m_auxv.begin(); } - iterator end() const { return m_auxv.end(); } - - iterator - FindEntry(EntryType type) const; - - static const char * - GetEntryName(const Entry &entry) { - return GetEntryName(static_cast(entry.type)); - } - - static const char * - GetEntryName(EntryType type); - - void - DumpToLog(lldb::LogSP log) const; - -private: - lldb_private::Process *m_process; - EntryVector m_auxv; - - lldb::DataBufferSP - GetAuxvData(); - - void - ParseAuxv(lldb_private::DataExtractor &data); -}; - -#endif Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp Thu Jan 5 13:17:38 2012 @@ -1,322 +0,0 @@ -//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/Error.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "DYLDRendezvous.h" - -using namespace lldb; -using namespace lldb_private; - -/// Locates the address of the rendezvous structure. Returns the address on -/// success and LLDB_INVALID_ADDRESS on failure. -static addr_t -ResolveRendezvousAddress(Process *process) -{ - addr_t info_location; - addr_t info_addr; - Error error; - size_t size; - - info_location = process->GetImageInfoAddress(); - - if (info_location == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - info_addr = 0; - size = process->DoReadMemory(info_location, &info_addr, - process->GetAddressByteSize(), error); - if (size != process->GetAddressByteSize() || error.Fail()) - return LLDB_INVALID_ADDRESS; - - if (info_addr == 0) - return LLDB_INVALID_ADDRESS; - - return info_addr; -} - -DYLDRendezvous::DYLDRendezvous(Process *process) - : m_process(process), - m_rendezvous_addr(LLDB_INVALID_ADDRESS), - m_current(), - m_previous(), - m_soentries(), - m_added_soentries(), - m_removed_soentries() -{ -} - -bool -DYLDRendezvous::Resolve() -{ - const size_t word_size = 4; - Rendezvous info; - size_t address_size; - size_t padding; - addr_t info_addr; - addr_t cursor; - - address_size = m_process->GetAddressByteSize(); - padding = address_size - word_size; - - if (m_rendezvous_addr == LLDB_INVALID_ADDRESS) - cursor = info_addr = ResolveRendezvousAddress(m_process); - else - cursor = info_addr = m_rendezvous_addr; - - if (cursor == LLDB_INVALID_ADDRESS) - return false; - - if (!(cursor = ReadMemory(cursor, &info.version, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.brk, address_size))) - return false; - - if (!(cursor = ReadMemory(cursor, &info.state, word_size))) - return false; - - if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size))) - return false; - - // The rendezvous was successfully read. Update our internal state. - m_rendezvous_addr = info_addr; - m_previous = m_current; - m_current = info; - - return UpdateSOEntries(); -} - -bool -DYLDRendezvous::IsValid() -{ - return m_rendezvous_addr != LLDB_INVALID_ADDRESS; -} - -bool -DYLDRendezvous::UpdateSOEntries() -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - // When the previous and current states are consistent this is the first - // time we have been asked to update. Just take a snapshot of the currently - // loaded modules. - if (m_previous.state == eConsistent && m_current.state == eConsistent) - return TakeSnapshot(m_soentries); - - // If we are about to add or remove a shared object clear out the current - // state and take a snapshot of the currently loaded images. - if (m_current.state == eAdd || m_current.state == eDelete) - { - assert(m_previous.state == eConsistent); - m_soentries.clear(); - m_added_soentries.clear(); - m_removed_soentries.clear(); - return TakeSnapshot(m_soentries); - } - assert(m_current.state == eConsistent); - - // Otherwise check the previous state to determine what to expect and update - // accordingly. - if (m_previous.state == eAdd) - return UpdateSOEntriesForAddition(); - else if (m_previous.state == eDelete) - return UpdateSOEntriesForDeletion(); - - return false; -} - -bool -DYLDRendezvous::UpdateSOEntriesForAddition() -{ - SOEntry entry; - iterator pos; - - assert(m_previous.state == eAdd); - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - pos = std::find(m_soentries.begin(), m_soentries.end(), entry); - if (pos == m_soentries.end()) - { - m_soentries.push_back(entry); - m_added_soentries.push_back(entry); - } - } - - return true; -} - -bool -DYLDRendezvous::UpdateSOEntriesForDeletion() -{ - SOEntryList entry_list; - iterator pos; - - assert(m_previous.state == eDelete); - - if (!TakeSnapshot(entry_list)) - return false; - - for (iterator I = begin(); I != end(); ++I) - { - pos = std::find(entry_list.begin(), entry_list.end(), *I); - if (pos == entry_list.end()) - m_removed_soentries.push_back(*I); - } - - m_soentries = entry_list; - return true; -} - -bool -DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) -{ - SOEntry entry; - - if (m_current.map_addr == 0) - return false; - - for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next) - { - if (!ReadSOEntryFromMemory(cursor, entry)) - return false; - - if (entry.path.empty()) - continue; - - entry_list.push_back(entry); - } - - return true; -} - -addr_t -DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size) -{ - size_t bytes_read; - Error error; - - bytes_read = m_process->DoReadMemory(addr, dst, size, error); - if (bytes_read != size || error.Fail()) - return 0; - - return addr + bytes_read; -} - -std::string -DYLDRendezvous::ReadStringFromMemory(addr_t addr) -{ - std::string str; - Error error; - size_t size; - char c; - - if (addr == LLDB_INVALID_ADDRESS) - return std::string(); - - for (;;) { - size = m_process->DoReadMemory(addr, &c, 1, error); - if (size != 1 || error.Fail()) - return std::string(); - if (c == 0) - break; - else { - str.push_back(c); - addr++; - } - } - - return str; -} - -bool -DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) -{ - size_t address_size = m_process->GetAddressByteSize(); - - entry.clear(); - - if (!(addr = ReadMemory(addr, &entry.base_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.path_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.next, address_size))) - return false; - - if (!(addr = ReadMemory(addr, &entry.prev, address_size))) - return false; - - entry.path = ReadStringFromMemory(entry.path_addr); - - return true; -} - -void -DYLDRendezvous::DumpToLog(LogSP log) const -{ - int state = GetState(); - - if (!log) - return; - - log->PutCString("DYLDRendezvous:"); - log->Printf(" Address: %lx", GetRendezvousAddress()); - log->Printf(" Version: %d", GetVersion()); - log->Printf(" Link : %lx", GetLinkMapAddress()); - log->Printf(" Break : %lx", GetBreakAddress()); - log->Printf(" LDBase : %lx", GetLDBase()); - log->Printf(" State : %s", - (state == eConsistent) ? "consistent" : - (state == eAdd) ? "add" : - (state == eDelete) ? "delete" : "unknown"); - - iterator I = begin(); - iterator E = end(); - - if (I != E) - log->PutCString("DYLDRendezvous SOEntries:"); - - for (int i = 1; I != E; ++I, ++i) - { - log->Printf("\n SOEntry [%d] %s", i, I->path.c_str()); - log->Printf(" Base : %lx", I->base_addr); - log->Printf(" Path : %lx", I->path_addr); - log->Printf(" Dyn : %lx", I->dyn_addr); - log->Printf(" Next : %lx", I->next); - log->Printf(" Prev : %lx", I->prev); - } -} Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h Thu Jan 5 13:17:38 2012 @@ -1,227 +0,0 @@ -//===-- DYLDRendezvous.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_Rendezvous_H_ -#define liblldb_Rendezvous_H_ - -// C Includes -// C++ Includes -#include -#include - -// Other libraries and framework includes -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -namespace lldb_private { -class Process; -} - -/// @class DYLDRendezvous -/// @brief Interface to the runtime linker. -/// -/// A structure is present in a processes memory space which is updated by the -/// runtime liker each time a module is loaded or unloaded. This class provides -/// an interface to this structure and maintains a consistent snapshot of the -/// currently loaded modules. -class DYLDRendezvous { - - // This structure is used to hold the contents of the debug rendezvous - // information (struct r_debug) as found in the inferiors memory. Note that - // the layout of this struct is not binary compatible, it is simply large - // enough to hold the information on both 32 and 64 bit platforms. - struct Rendezvous { - uint64_t version; - lldb::addr_t map_addr; - lldb::addr_t brk; - uint64_t state; - lldb::addr_t ldbase; - - Rendezvous() - : version(0), map_addr(0), brk(0), state(0), ldbase(0) { } - }; - -public: - DYLDRendezvous(lldb_private::Process *process); - - /// Update the internal snapshot of runtime linker rendezvous and recompute - /// the currently loaded modules. - /// - /// This method should be called once one start up, then once each time the - /// runtime linker enters the function given by GetBreakAddress(). - /// - /// @returns true on success and false on failure. - /// - /// @see GetBreakAddress(). - bool - Resolve(); - - /// @returns true if this rendezvous has been located in the inferiors - /// address space and false otherwise. - bool - IsValid(); - - /// @returns the address of the rendezvous structure in the inferiors - /// address space. - lldb::addr_t - GetRendezvousAddress() const { return m_rendezvous_addr; } - - /// @returns the version of the rendezvous protocol being used. - int - GetVersion() const { return m_current.version; } - - /// @returns address in the inferiors address space containing the linked - /// list of shared object descriptors. - lldb::addr_t - GetLinkMapAddress() const { return m_current.map_addr; } - - /// A breakpoint should be set at this address and Resolve called on each - /// hit. - /// - /// @returns the address of a function called by the runtime linker each - /// time a module is loaded/unloaded, or about to be loaded/unloaded. - /// - /// @see Resolve() - lldb::addr_t - GetBreakAddress() const { return m_current.brk; } - - /// Returns the current state of the rendezvous structure. - int - GetState() const { return m_current.state; } - - /// @returns the base address of the runtime linker in the inferiors address - /// space. - lldb::addr_t - GetLDBase() const { return m_current.ldbase; } - - /// @returns true if modules have been loaded into the inferior since the - /// last call to Resolve(). - bool - ModulesDidLoad() const { return !m_added_soentries.empty(); } - - /// @returns true if modules have been unloaded from the inferior since the - /// last call to Resolve(). - bool - ModulesDidUnload() const { return !m_removed_soentries.empty(); } - - void - DumpToLog(lldb::LogSP log) const; - - /// @brief Constants describing the state of the rendezvous. - /// - /// @see GetState(). - enum RendezvousState { - eConsistent, - eAdd, - eDelete - }; - - /// @brief Structure representing the shared objects currently loaded into - /// the inferior process. - /// - /// This object is a rough analogue to the struct link_map object which - /// actually lives in the inferiors memory. - struct SOEntry { - lldb::addr_t base_addr; ///< Base address of the loaded object. - lldb::addr_t path_addr; ///< String naming the shared object. - lldb::addr_t dyn_addr; ///< Dynamic section of shared object. - lldb::addr_t next; ///< Address of next so_entry. - lldb::addr_t prev; ///< Address of previous so_entry. - std::string path; ///< File name of shared object. - - SOEntry() { clear(); } - - bool operator ==(const SOEntry &entry) { - return this->path == entry.path; - } - - void clear() { - base_addr = 0; - path_addr = 0; - dyn_addr = 0; - next = 0; - prev = 0; - path.clear(); - } - }; - -protected: - typedef std::list SOEntryList; - -public: - typedef SOEntryList::const_iterator iterator; - - /// Iterators over all currently loaded modules. - iterator begin() const { return m_soentries.begin(); } - iterator end() const { return m_soentries.end(); } - - /// Iterators over all modules loaded into the inferior since the last call - /// to Resolve(). - iterator loaded_begin() const { return m_added_soentries.begin(); } - iterator loaded_end() const { return m_added_soentries.end(); } - - /// Iterators over all modules unloaded from the inferior since the last - /// call to Resolve(). - iterator unloaded_begin() const { return m_removed_soentries.begin(); } - iterator unloaded_end() const { return m_removed_soentries.end(); } - -protected: - lldb_private::Process *m_process; - - /// Location of the r_debug structure in the inferiors address space. - lldb::addr_t m_rendezvous_addr; - - /// Current and previous snapshots of the rendezvous structure. - Rendezvous m_current; - Rendezvous m_previous; - - /// List of SOEntry objects corresponding to the current link map state. - SOEntryList m_soentries; - - /// List of SOEntry's added to the link map since the last call to Resolve(). - SOEntryList m_added_soentries; - - /// List of SOEntry's removed from the link map since the last call to - /// Resolve(). - SOEntryList m_removed_soentries; - - /// Reads @p size bytes from the inferiors address space starting at @p - /// addr. - /// - /// @returns addr + size if the read was successful and false otherwise. - lldb::addr_t - ReadMemory(lldb::addr_t addr, void *dst, size_t size); - - /// Reads a null-terminated C string from the memory location starting at @p - /// addr. - std::string - ReadStringFromMemory(lldb::addr_t addr); - - /// Reads an SOEntry starting at @p addr. - bool - ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry); - - /// Updates the current set of SOEntries, the set of added entries, and the - /// set of removed entries. - bool - UpdateSOEntries(); - - bool - UpdateSOEntriesForAddition(); - - bool - UpdateSOEntriesForDeletion(); - - /// Reads the current list of shared objects according to the link map - /// supplied by the runtime linker. - bool - TakeSnapshot(SOEntryList &entry_list); -}; - -#endif Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp Thu Jan 5 13:17:38 2012 @@ -1,423 +0,0 @@ -//===-- DynamicLoaderLinux.h ------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/Thread.h" -#include "lldb/Target/ThreadPlanRunToAddress.h" - -#include "AuxVector.h" -#include "DynamicLoaderLinuxDYLD.h" - -using namespace lldb; -using namespace lldb_private; - -void -DynamicLoaderLinuxDYLD::Initialize() -{ - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); -} - -void -DynamicLoaderLinuxDYLD::Terminate() -{ -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginName() -{ - return "DynamicLoaderLinuxDYLD"; -} - -const char * -DynamicLoaderLinuxDYLD::GetShortPluginName() -{ - return "linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginNameStatic() -{ - return "dynamic-loader.linux-dyld"; -} - -const char * -DynamicLoaderLinuxDYLD::GetPluginDescriptionStatic() -{ - return "Dynamic loader plug-in that watches for shared library " - "loads/unloads in Linux processes."; -} - -void -DynamicLoaderLinuxDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - -uint32_t -DynamicLoaderLinuxDYLD::GetPluginVersion() -{ - return 1; -} - -DynamicLoader * -DynamicLoaderLinuxDYLD::CreateInstance(Process *process, bool force) -{ - bool create = force; - if (!create) - { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Linux) - create = true; - } - - if (create) - return new DynamicLoaderLinuxDYLD (process); - return NULL; -} - -DynamicLoaderLinuxDYLD::DynamicLoaderLinuxDYLD(Process *process) - : DynamicLoader(process), - m_rendezvous(process), - m_load_offset(LLDB_INVALID_ADDRESS), - m_entry_point(LLDB_INVALID_ADDRESS), - m_auxv(NULL) -{ -} - -DynamicLoaderLinuxDYLD::~DynamicLoaderLinuxDYLD() -{ -} - -void -DynamicLoaderLinuxDYLD::DidAttach() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -void -DynamicLoaderLinuxDYLD::DidLaunch() -{ - ModuleSP executable; - addr_t load_offset; - - m_auxv.reset(new AuxVector(m_process)); - - executable = m_process->GetTarget().GetExecutableModule(); - load_offset = ComputeLoadOffset(); - - if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) - { - ModuleList module_list; - module_list.Append(executable); - UpdateLoadedSections(executable, load_offset); - ProbeEntry(); - m_process->GetTarget().ModulesDidLoad(module_list); - } -} - -Error -DynamicLoaderLinuxDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderLinuxDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - -Error -DynamicLoaderLinuxDYLD::CanLoadImage() -{ - return Error(); -} - -void -DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr) -{ - ObjectFile *obj_file = module->GetObjectFile(); - SectionList *sections = obj_file->GetSectionList(); - SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList(); - const size_t num_sections = sections->GetSize(); - - for (unsigned i = 0; i < num_sections; ++i) - { - Section *section = sections->GetSectionAtIndex(i).get(); - lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr; - lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section); - - // If the file address of the section is zero then this is not an - // allocatable/loadable section (property of ELF sh_addr). Skip it. - if (new_load_addr == base_addr) - continue; - - if (old_load_addr == LLDB_INVALID_ADDRESS || - old_load_addr != new_load_addr) - load_list.SetSectionLoadAddress(section, new_load_addr); - } -} - -void -DynamicLoaderLinuxDYLD::ProbeEntry() -{ - Breakpoint *entry_break; - addr_t entry; - - if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return; - - entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get(); - entry_break->SetCallback(EntryBreakpointHit, this, true); -} - -// The runtime linker has run and initialized the rendezvous structure once the -// process has hit its entry point. When we hit the corresponding breakpoint we -// interrogate the rendezvous structure to get the load addresses of all -// dependent modules for the process. Similarly, we can discover the runtime -// linker function and setup a breakpoint to notify us of any dynamically loaded -// modules (via dlopen). -bool -DynamicLoaderLinuxDYLD::EntryBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->LoadAllCurrentModules(); - dyld_instance->SetRendezvousBreakpoint(); - return false; // Continue running. -} - -void -DynamicLoaderLinuxDYLD::SetRendezvousBreakpoint() -{ - Breakpoint *dyld_break; - addr_t break_addr; - - break_addr = m_rendezvous.GetBreakAddress(); - dyld_break = m_process->GetTarget().CreateBreakpoint(break_addr, true).get(); - dyld_break->SetCallback(RendezvousBreakpointHit, this, true); -} - -bool -DynamicLoaderLinuxDYLD::RendezvousBreakpointHit(void *baton, - StoppointCallbackContext *context, - user_id_t break_id, - user_id_t break_loc_id) -{ - DynamicLoaderLinuxDYLD* dyld_instance; - - dyld_instance = static_cast(baton); - dyld_instance->RefreshModules(); - - // Return true to stop the target, false to just let the target run. - return dyld_instance->GetStopWhenImagesChange(); -} - -void -DynamicLoaderLinuxDYLD::RefreshModules() -{ - if (!m_rendezvous.Resolve()) - return; - - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); - - if (m_rendezvous.ModulesDidLoad()) - { - ModuleList new_modules; - - E = m_rendezvous.loaded_end(); - for (I = m_rendezvous.loaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - new_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidLoad(new_modules); - } - - if (m_rendezvous.ModulesDidUnload()) - { - ModuleList old_modules; - - E = m_rendezvous.unloaded_end(); - for (I = m_rendezvous.unloaded_begin(); I != E; ++I) - { - FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = - loaded_modules.FindFirstModuleForFileSpec(file, NULL, NULL); - if (module_sp.get()) - old_modules.Append(module_sp); - } - m_process->GetTarget().ModulesDidUnload(old_modules); - } -} - -ThreadPlanSP -DynamicLoaderLinuxDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop) -{ - LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); - ThreadPlanSP thread_plan_sp; - - StackFrame *frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *sym = context.symbol; - - if (sym == NULL || !sym->IsTrampoline()) - return thread_plan_sp; - - const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled); - if (!sym_name) - return thread_plan_sp; - - SymbolContextList target_symbols; - Target &target = thread.GetProcess().GetTarget(); - ModuleList &images = target.GetImages(); - - images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols); - size_t num_targets = target_symbols.GetSize(); - if (!num_targets) - return thread_plan_sp; - - typedef std::vector AddressVector; - AddressVector addrs; - for (size_t i = 0; i < num_targets; ++i) - { - SymbolContext context; - AddressRange range; - if (target_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange(eSymbolContextEverything, 0, false, range); - lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target); - if (addr != LLDB_INVALID_ADDRESS) - addrs.push_back(addr); - } - } - - if (addrs.size() > 0) - { - AddressVector::iterator start = addrs.begin(); - AddressVector::iterator end = addrs.end(); - - std::sort(start, end); - addrs.erase(std::unique(start, end), end); - thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop)); - } - - return thread_plan_sp; -} - -void -DynamicLoaderLinuxDYLD::LoadAllCurrentModules() -{ - DYLDRendezvous::iterator I; - DYLDRendezvous::iterator E; - ModuleList module_list; - - if (!m_rendezvous.Resolve()) - return; - - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) - { - FileSpec file(I->path.c_str(), false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr); - if (module_sp.get()) - module_list.Append(module_sp); - } - - m_process->GetTarget().ModulesDidLoad(module_list); -} - -ModuleSP -DynamicLoaderLinuxDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - if ((module_sp = modules.FindFirstModuleForFileSpec(file, NULL, NULL))) - { - UpdateLoadedSections(module_sp, base_addr); - } - else if ((module_sp = target.GetSharedModule(file, target.GetArchitecture()))) - { - UpdateLoadedSections(module_sp, base_addr); - modules.Append(module_sp); - } - - return module_sp; -} - -addr_t -DynamicLoaderLinuxDYLD::ComputeLoadOffset() -{ - addr_t virt_entry; - - if (m_load_offset != LLDB_INVALID_ADDRESS) - return m_load_offset; - - if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS) - return LLDB_INVALID_ADDRESS; - - ModuleSP module = m_process->GetTarget().GetExecutableModule(); - ObjectFile *exe = module->GetObjectFile(); - Address file_entry = exe->GetEntryPointAddress(); - - if (!file_entry.IsValid()) - return LLDB_INVALID_ADDRESS; - - m_load_offset = virt_entry - file_entry.GetFileAddress(); - return m_load_offset; -} - -addr_t -DynamicLoaderLinuxDYLD::GetEntryPoint() -{ - if (m_entry_point != LLDB_INVALID_ADDRESS) - return m_entry_point; - - if (m_auxv.get() == NULL) - return LLDB_INVALID_ADDRESS; - - AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY); - - if (I == m_auxv->end()) - return LLDB_INVALID_ADDRESS; - - m_entry_point = static_cast(I->value); - return m_entry_point; -} Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h Thu Jan 5 13:17:38 2012 @@ -1,165 +0,0 @@ -//===-- DynamicLoaderLinux.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_DynamicLoaderLinux_H_ -#define liblldb_DynamicLoaderLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Target/DynamicLoader.h" - -#include "DYLDRendezvous.h" - -class AuxVector; - -class DynamicLoaderLinuxDYLD : public lldb_private::DynamicLoader -{ -public: - - static void - Initialize(); - - static void - Terminate(); - - static const char * - GetPluginNameStatic(); - - static const char * - GetPluginDescriptionStatic(); - - static lldb_private::DynamicLoader * - CreateInstance(lldb_private::Process *process, bool force); - - DynamicLoaderLinuxDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderLinuxDYLD(); - - //------------------------------------------------------------------ - // DynamicLoader protocol - //------------------------------------------------------------------ - - virtual void - DidAttach(); - - virtual void - DidLaunch(); - - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); - - virtual lldb_private::Error - CanLoadImage(); - - //------------------------------------------------------------------ - // PluginInterface protocol - //------------------------------------------------------------------ - virtual const char * - GetPluginName(); - - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - -protected: - /// Runtime linker rendezvous structure. - DYLDRendezvous m_rendezvous; - - /// Virtual load address of the inferior process. - lldb::addr_t m_load_offset; - - /// Virtual entry address of the inferior process. - lldb::addr_t m_entry_point; - - /// Auxiliary vector of the inferior process. - std::auto_ptr m_auxv; - - /// Enables a breakpoint on a function called by the runtime - /// linker each time a module is loaded or unloaded. - void - SetRendezvousBreakpoint(); - - /// Callback routine which updates the current list of loaded modules based - /// on the information supplied by the runtime linker. - static bool - RendezvousBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper method for RendezvousBreakpointHit. Updates LLDB's current set - /// of loaded modules. - void - RefreshModules(); - - /// Updates the load address of every allocatable section in @p module. - /// - /// @param module The module to traverse. - /// - /// @param base_addr The virtual base address @p module is loaded at. - void - UpdateLoadedSections(lldb::ModuleSP module, - lldb::addr_t base_addr = 0); - - /// Locates or creates a module given by @p file and updates/loads the - /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr); - - /// Resolves the entry point for the current inferior process and sets a - /// breakpoint at that address. - void - ProbeEntry(); - - /// Callback routine invoked when we hit the breakpoint on process entry. - /// - /// This routine is responsible for resolving the load addresses of all - /// dependent modules required by the inferior and setting up the rendezvous - /// breakpoint. - static bool - EntryBreakpointHit(void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); - - /// Helper for the entry breakpoint callback. Resolves the load addresses - /// of all dependent modules. - void - LoadAllCurrentModules(); - - /// Computes a value for m_load_offset returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - ComputeLoadOffset(); - - /// Computes a value for m_entry_point returning the computed address on - /// success and LLDB_INVALID_ADDRESS on failure. - lldb::addr_t - GetEntryPoint(); - -private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderLinuxDYLD); -}; - -#endif // liblldb_DynamicLoaderLinuxDYLD_H_ Modified: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile (original) +++ lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile Thu Jan 5 13:17:38 2012 @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Linux-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderLinux -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile Modified: lldb/trunk/source/Plugins/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Makefile (original) +++ lldb/trunk/source/Plugins/Makefile Thu Jan 5 13:17:38 2012 @@ -30,7 +30,11 @@ endif ifeq ($(HOST_OS),Linux) -DIRS += Process/Linux DynamicLoader/Linux-DYLD +DIRS += Process/Linux Process/POSIX DynamicLoader/POSIX-DYLD +endif + +ifeq ($(HOST_OS),FreeBSD) +DIRS += Process/FreeBSD Process/POSIX DynamicLoader/POSIX-DYLD endif include $(LLDB_LEVEL)/Makefile Modified: lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (original) +++ lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp Thu Jan 5 13:17:38 2012 @@ -27,16 +27,13 @@ Platform * PlatformFreeBSD::CreateInstance () { - // The only time we create an instance is when we are creating a remote - // freebsd platform - const bool is_host = false; - return new PlatformFreeBSD (is_host); + return new PlatformFreeBSD (true); } const char * PlatformFreeBSD::GetPluginNameStatic() { - return "PlatformFreeBSD"; + return "plugin.platform.freebsd"; } const char * @@ -66,7 +63,7 @@ { #if defined (__FreeBSD__) PlatformSP default_platform_sp (CreateInstance()); - //default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); + default_platform_sp->SetSystemArchitecture (Host::GetArchitecture()); Platform::SetDefaultPlatform (default_platform_sp); #endif PluginManager::RegisterPlugin(PlatformFreeBSD::GetShortPluginNameStatic(false), @@ -79,7 +76,7 @@ void PlatformFreeBSD::Terminate () { - PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); + PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance); } //------------------------------------------------------------------ @@ -385,17 +382,16 @@ bool PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) { - bool sucess = false; + bool success = false; if (IsHost()) { - sucess = Platform::GetProcessInfo (pid, process_info); + success = Platform::GetProcessInfo (pid, process_info); } - else + else if (m_remote_platform_sp) { - if (m_remote_platform_sp) - sucess = m_remote_platform_sp->GetProcessInfo (pid, process_info); + success = m_remote_platform_sp->GetProcessInfo (pid, process_info); } - return sucess; + return success; } @@ -438,11 +434,11 @@ } lldb::ProcessSP -PlatformFreeBSD::Attach(lldb::pid_t pid, - Debugger &debugger, - Target *target, - Listener &listener, - Error &error) +PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info, + Debugger &debugger, + Target *target, + Listener &listener, + Error &error) { lldb::ProcessSP process_sp; if (IsHost()) @@ -457,6 +453,7 @@ emptyFileSpec, emptyArchSpec, false, + m_remote_platform_sp, new_target_sp); target = new_target_sp.get(); } @@ -472,13 +469,13 @@ process_sp = target->CreateProcess (listener, "gdb-remote"); if (process_sp) - error = process_sp->Attach (pid); + error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); else error.SetErrorString ("the platform is not currently connected"); } Modified: lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h (original) +++ lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h Thu Jan 5 13:17:38 2012 @@ -132,12 +132,16 @@ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); virtual lldb::ProcessSP - Attach(lldb::pid_t pid, + Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, lldb_private::Listener &listener, lldb_private::Error &error); + // FreeBSD processes can not be launched by spawning and attaching. + virtual bool + CanDebugProcess () { return false; } + // Only on PlatformMacOSX: virtual lldb_private::Error GetFile (const lldb_private::FileSpec &platform_file, Modified: lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h (original) +++ lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h Thu Jan 5 13:17:38 2012 @@ -104,6 +104,7 @@ Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Listener &listener, Error &error); + // Linux processes can not be launched by spawning and attaching. virtual bool CanDebugProcess () { Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp Thu Jan 5 13:17:38 2012 @@ -1,60 +0,0 @@ -//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "LinuxStopInfo.h" - -using namespace lldb; -using namespace lldb_private; - - -//===----------------------------------------------------------------------===// -// LinuxLimboStopInfo - -LinuxLimboStopInfo::~LinuxLimboStopInfo() { } - -lldb::StopReason -LinuxLimboStopInfo::GetStopReason() const -{ - return lldb::eStopReasonTrace; -} - -const char * -LinuxLimboStopInfo::GetDescription() -{ - return "thread exiting"; -} - -bool -LinuxLimboStopInfo::ShouldStop(Event *event_ptr) -{ - return true; -} - -bool -LinuxLimboStopInfo::ShouldNotify(Event *event_ptr) -{ - return true; -} - -//===----------------------------------------------------------------------===// -// LinuxCrashStopInfo - -LinuxCrashStopInfo::~LinuxCrashStopInfo() { } - -lldb::StopReason -LinuxCrashStopInfo::GetStopReason() const -{ - return lldb::eStopReasonException; -} - -const char * -LinuxCrashStopInfo::GetDescription() -{ - return ProcessMessage::GetCrashReasonString(m_crash_reason); -} Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h Thu Jan 5 13:17:38 2012 @@ -1,92 +0,0 @@ -//===-- LinuxStopInfo.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_LinuxStopInfo_H_ -#define liblldb_LinuxStopInfo_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/StopInfo.h" - -#include "LinuxThread.h" -#include "ProcessMessage.h" - -//===----------------------------------------------------------------------===// -/// @class LinuxStopInfo -/// @brief Simple base class for all Linux-specific StopInfo objects. -/// -class LinuxStopInfo - : public lldb_private::StopInfo -{ -public: - LinuxStopInfo(lldb_private::Thread &thread, uint32_t status) - : StopInfo(thread, status) - { } -}; - -//===----------------------------------------------------------------------===// -/// @class LinuxLimboStopInfo -/// @brief Represents the stop state of a process ready to exit. -/// -class LinuxLimboStopInfo - : public LinuxStopInfo -{ -public: - LinuxLimboStopInfo(LinuxThread &thread) - : LinuxStopInfo(thread, 0) - { } - - ~LinuxLimboStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - bool - ShouldStop(lldb_private::Event *event_ptr); - - bool - ShouldNotify(lldb_private::Event *event_ptr); -}; - - -//===----------------------------------------------------------------------===// -/// @class LinuxCrashStopInfo -/// @brief Represents the stop state of process that is ready to crash. -/// -class LinuxCrashStopInfo - : public LinuxStopInfo -{ -public: - LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, - ProcessMessage::CrashReason reason) - : LinuxStopInfo(thread, status), - m_crash_reason(reason) - { } - - ~LinuxCrashStopInfo(); - - lldb::StopReason - GetStopReason() const; - - const char * - GetDescription(); - - ProcessMessage::CrashReason - GetCrashReason() const; - -private: - ProcessMessage::CrashReason m_crash_reason; -}; - -#endif Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp Thu Jan 5 13:17:38 2012 @@ -1,350 +0,0 @@ -//===-- LinuxThread.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 - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Debugger.h" -#include "lldb/Host/Host.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "LinuxStopInfo.h" -#include "LinuxThread.h" -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" -#include "RegisterContextLinux_x86_64.h" -#include "UnwindLLDB.h" - -using namespace lldb_private; - - -LinuxThread::LinuxThread(Process &process, lldb::tid_t tid) - : Thread(process, tid), - m_frame_ap(0) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s (tid = %i)", __FUNCTION__, tid); -} - -LinuxThread::~LinuxThread() -{ - DestroyThread(); -} - -ProcessMonitor & -LinuxThread::GetMonitor() -{ - ProcessLinux &process = static_cast(GetProcess()); - return process.GetMonitor(); -} - -void -LinuxThread::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - // Let all threads recover from stopping and do any clean up based - // on the previous thread state (if any). - ProcessLinux &process = static_cast(GetProcess()); - process.GetThreadList().RefreshStateAfterStop(); -} - -const char * -LinuxThread::GetInfo() -{ - return NULL; -} - -lldb::RegisterContextSP -LinuxThread::GetRegisterContext() -{ - if (!m_reg_context_sp) - { - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - m_reg_context_sp.reset(new RegisterContextLinux_i386(*this, 0)); - break; - - case ArchSpec::eCore_x86_64_x86_64: - m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0)); - break; - } - } - return m_reg_context_sp; -} - -lldb::RegisterContextSP -LinuxThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame) -{ - lldb::RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) - reg_ctx_sp = GetRegisterContext(); - else - { - assert(GetUnwinder()); - reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_sp; -} - -lldb::StopInfoSP -LinuxThread::GetPrivateStopReason() -{ - return m_stop_info; -} - -Unwind * -LinuxThread::GetUnwinder() -{ - if (m_unwinder_ap.get() == NULL) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - - return m_unwinder_ap.get(); -} - -bool -LinuxThread::WillResume(lldb::StateType resume_state) -{ - SetResumeState(resume_state); - - ClearStackFrames(); - if (m_unwinder_ap.get()) - m_unwinder_ap->Clear(); - - return Thread::WillResume(resume_state); -} - -bool -LinuxThread::Resume() -{ - lldb::StateType resume_state = GetResumeState(); - ProcessMonitor &monitor = GetMonitor(); - bool status; - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("LinuxThread::%s ()", __FUNCTION__); - - switch (resume_state) - { - default: - assert(false && "Unexpected state for resume!"); - status = false; - break; - - case lldb::eStateRunning: - SetState(resume_state); - status = monitor.Resume(GetID(), GetResumeSignal()); - break; - - case lldb::eStateStepping: - SetState(resume_state); - status = monitor.SingleStep(GetID(), GetResumeSignal()); - break; - } - - return status; -} - -void -LinuxThread::Notify(const ProcessMessage &message) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () message kind = '%s'", __FUNCTION__, message.PrintKind()); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected message kind!"); - break; - - case ProcessMessage::eLimboMessage: - LimboNotify(message); - break; - - case ProcessMessage::eSignalMessage: - SignalNotify(message); - break; - - case ProcessMessage::eSignalDeliveredMessage: - SignalDeliveredNotify(message); - break; - - case ProcessMessage::eTraceMessage: - TraceNotify(message); - break; - - case ProcessMessage::eBreakpointMessage: - BreakNotify(message); - break; - - case ProcessMessage::eCrashMessage: - CrashNotify(message); - break; - } -} - -void -LinuxThread::BreakNotify(const ProcessMessage &message) -{ - bool status; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - - assert(GetRegisterContextLinux()); - status = GetRegisterContextLinux()->UpdateAfterBreakpoint(); - assert(status && "Breakpoint update failed!"); - - // With our register state restored, resolve the breakpoint object - // corresponding to our current PC. - assert(GetRegisterContext()); - lldb::addr_t pc = GetRegisterContext()->GetPC(); - if (log) - log->Printf ("LinuxThread::%s () PC=0x%8.8llx", __FUNCTION__, pc); - lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc)); - assert(bp_site); - lldb::break_id_t bp_id = bp_site->GetID(); - assert(bp_site && bp_site->ValidForThisThread(this)); - - - m_breakpoint = bp_site; - m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id); -} - -void -LinuxThread::TraceNotify(const ProcessMessage &message) -{ - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); -} - -void -LinuxThread::LimboNotify(const ProcessMessage &message) -{ - m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this)); -} - -void -LinuxThread::SignalNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo); - SetResumeSignal(signo); -} - -void -LinuxThread::SignalDeliveredNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - // Just treat debugger generated signal events like breakpoints for now. - m_stop_info = StopInfo::CreateStopReasonToTrace(*this); - SetResumeSignal(signo); -} - -void -LinuxThread::CrashNotify(const ProcessMessage &message) -{ - int signo = message.GetSignal(); - - assert(message.GetKind() == ProcessMessage::eCrashMessage); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log) - log->Printf ("LinuxThread::%s () signo = %i, reason = '%s'", __FUNCTION__, signo, message.PrintCrashReason()); - - m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo( - *this, signo, message.GetCrashReason())); - SetResumeSignal(signo); -} - -unsigned -LinuxThread::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - reg = RegisterContextLinux_i386::GetRegisterIndexFromOffset(offset); - break; - - case ArchSpec::eCore_x86_64_x86_64: - reg = RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(offset); - break; - } - return reg; -} - -const char * -LinuxThread::GetRegisterName(unsigned reg) -{ - const char * name; - ArchSpec arch = Host::GetArchitecture(); - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_32_i486: - case ArchSpec::eCore_x86_32_i486sx: - name = RegisterContextLinux_i386::GetRegisterName(reg); - break; - - case ArchSpec::eCore_x86_64_x86_64: - name = RegisterContextLinux_x86_64::GetRegisterName(reg); - break; - } - return name; -} - -const char * -LinuxThread::GetRegisterNameFromOffset(unsigned offset) -{ - return GetRegisterName(GetRegisterIndexFromOffset(offset)); -} - Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h Thu Jan 5 13:17:38 2012 @@ -1,102 +0,0 @@ -//===-- LinuxThread.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_LinuxThread_H_ -#define liblldb_LinuxThread_H_ - -// C Includes -// C++ Includes -#include - -// Other libraries and framework includes -#include "lldb/Target/Thread.h" - -class ProcessMessage; -class ProcessMonitor; -class RegisterContextLinux; - -//------------------------------------------------------------------------------ -// @class LinuxThread -// @brief Abstraction of a linux process (thread). -class LinuxThread - : public lldb_private::Thread -{ -public: - LinuxThread(lldb_private::Process &process, lldb::tid_t tid); - - virtual ~LinuxThread(); - - void - RefreshStateAfterStop(); - - bool - WillResume(lldb::StateType resume_state); - - const char * - GetInfo(); - - virtual lldb::RegisterContextSP - GetRegisterContext(); - - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame (lldb_private::StackFrame *frame); - - //-------------------------------------------------------------------------- - // These static functions provide a mapping from the register offset - // back to the register index or name for use in debugging or log - // output. - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - static const char * - GetRegisterNameFromOffset(unsigned offset); - - //-------------------------------------------------------------------------- - // These methods form a specialized interface to linux threads. - // - bool Resume(); - - void Notify(const ProcessMessage &message); - -private: - RegisterContextLinux * - GetRegisterContextLinux () - { - if (!m_reg_context_sp) - GetRegisterContext(); - return (RegisterContextLinux *)m_reg_context_sp.get(); - } - - std::auto_ptr m_frame_ap; - - lldb::BreakpointSiteSP m_breakpoint; - lldb::StopInfoSP m_stop_info; - - ProcessMonitor & - GetMonitor(); - - lldb::StopInfoSP - GetPrivateStopReason(); - - void BreakNotify(const ProcessMessage &message); - void TraceNotify(const ProcessMessage &message); - void LimboNotify(const ProcessMessage &message); - void SignalNotify(const ProcessMessage &message); - void SignalDeliveredNotify(const ProcessMessage &message); - void CrashNotify(const ProcessMessage &message); - - lldb_private::Unwind * - GetUnwinder(); -}; - -#endif // #ifndef liblldb_LinuxThread_H_ Modified: lldb/trunk/source/Plugins/Process/Linux/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/Makefile (original) +++ lldb/trunk/source/Plugins/Process/Linux/Makefile Thu Jan 5 13:17:38 2012 @@ -12,6 +12,6 @@ BUILD_ARCHIVE = 1 # Extend the include path so we may locate UnwindLLDB.h -CPPFLAGS += -I $(LLDB_LEVEL)/source/Plugins/Utility +CPPFLAGS += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility include $(LLDB_LEVEL)/Makefile Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Thu Jan 5 13:17:38 2012 @@ -20,10 +20,10 @@ #include "lldb/Target/Target.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "ProcessMonitor.h" -#include "LinuxThread.h" +#include "POSIXThread.h" using namespace lldb; using namespace lldb_private; @@ -50,42 +50,21 @@ CreateInstance); Log::Callbacks log_callbacks = { - ProcessLinuxLog::DisableLog, - ProcessLinuxLog::EnableLog, - ProcessLinuxLog::ListLogCategories + ProcessPOSIXLog::DisableLog, + ProcessPOSIXLog::EnableLog, + ProcessPOSIXLog::ListLogCategories }; Log::RegisterLogChannel (ProcessLinux::GetPluginNameStatic(), log_callbacks); + ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic()); } } -void -ProcessLinux::Terminate() -{ -} - -const char * -ProcessLinux::GetPluginNameStatic() -{ - return "plugin.process.linux"; -} - -const char * -ProcessLinux::GetPluginDescriptionStatic() -{ - return "Process plugin for Linux"; -} - - //------------------------------------------------------------------------------ // Constructors and destructors. ProcessLinux::ProcessLinux(Target& target, Listener &listener) - : Process(target, listener), - m_monitor(NULL), - m_module(NULL), - m_in_limbo(false), - m_exit_now(false) + : ProcessPOSIX(target, listener) { #if 0 // FIXME: Putting this code in the ctor and saving the byte order in a @@ -98,409 +77,28 @@ #endif } -ProcessLinux::~ProcessLinux() -{ - delete m_monitor; -} - -//------------------------------------------------------------------------------ -// Process protocol. - -bool -ProcessLinux::CanDebug(Target &target, bool plugin_specified_by_name) -{ - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target.GetExecutableModule()); - if (exe_module_sp.get()) - return exe_module_sp->GetFileSpec().Exists(); - return false; -} - -Error -ProcessLinux::DoAttachToProcessWithID(lldb::pid_t pid) -{ - Error error; - assert(m_monitor == NULL); - - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s(pid = %i)", __FUNCTION__, GetID()); - - m_monitor = new ProcessMonitor(this, pid, error); - - if (!error.Success()) - return error; - - SetID(pid); - return error; -} - -Error -ProcessLinux::WillLaunch(Module* module) -{ - Error error; - return error; -} - -Error -ProcessLinux::DoLaunch (Module *module, - const ProcessLaunchInfo &launch_info) -{ - Error error; - assert(m_monitor == NULL); - - SetPrivateState(eStateLaunching); - - const char *stdin_path = NULL; - const char *stdout_path = NULL; - const char *stderr_path = NULL; - const char *working_dir = launch_info.GetWorkingDirectory(); - - const ProcessLaunchInfo::FileAction *file_action; - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdin_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stdout_path = file_action->GetPath(); - } - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - if (file_action) - { - if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen) - stderr_path = file_action->GetPath(); - } - - m_monitor = new ProcessMonitor (this, - module, - launch_info.GetArguments().GetConstArgumentVector(), - launch_info.GetEnvironmentEntries().GetConstArgumentVector(), - stdin_path, - stdout_path, - stderr_path, - error); - - m_module = module; - - if (!error.Success()) - return error; - - SetID(m_monitor->GetPID()); - return error; -} - -void -ProcessLinux::DidLaunch() -{ -} - -Error -ProcessLinux::DoResume() -{ - StateType state = GetPrivateState(); - - assert(state == eStateStopped || state == eStateCrashed); - - // We are about to resume a thread that will cause the process to exit so - // set our exit status now. Do not change our state if the inferior - // crashed. - if (state == eStateStopped) - { - if (m_in_limbo) - SetExitStatus(m_exit_status, NULL); - else - SetPrivateState(eStateRunning); - } - - bool did_resume = false; - uint32_t thread_count = m_thread_list.GetSize(false); - for (uint32_t i = 0; i < thread_count; ++i) - { - LinuxThread *thread = static_cast( - m_thread_list.GetThreadAtIndex(i, false).get()); - did_resume = thread->Resume() || did_resume; - } - assert(did_resume && "Process resume failed!"); - - return Error(); -} - -addr_t -ProcessLinux::GetImageInfoAddress() -{ - Target *target = &GetTarget(); - ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(); - - if (addr.IsValid()) - return addr.GetLoadAddress(target); - else - return LLDB_INVALID_ADDRESS; -} - -Error -ProcessLinux::DoHalt(bool &caused_stop) -{ - Error error; - - if (IsStopped()) - { - caused_stop = false; - } - else if (kill(GetID(), SIGSTOP)) - { - caused_stop = false; - error.SetErrorToErrno(); - } - else - { - caused_stop = true; - } - - return error; -} - -Error -ProcessLinux::DoDetach() -{ - Error error; - - error = m_monitor->Detach(); - if (error.Success()) - SetPrivateState(eStateDetached); - - return error; -} - -Error -ProcessLinux::DoSignal(int signal) -{ - Error error; - - if (kill(GetID(), signal)) - error.SetErrorToErrno(); - - return error; -} - -Error -ProcessLinux::DoDestroy() -{ - Error error; - - if (!HasExited()) - { - // Drive the exit event to completion (do not keep the inferior in - // limbo). - m_exit_now = true; - - if (kill(m_monitor->GetPID(), SIGKILL) && error.Success()) - { - error.SetErrorToErrno(); - return error; - } - - SetPrivateState(eStateExited); - } - - return error; -} - void -ProcessLinux::SendMessage(const ProcessMessage &message) -{ - Mutex::Locker lock(m_message_mutex); - - switch (message.GetKind()) - { - default: - assert(false && "Unexpected process message!"); - break; - - case ProcessMessage::eInvalidMessage: - return; - - case ProcessMessage::eLimboMessage: - m_in_limbo = true; - m_exit_status = message.GetExitStatus(); - if (m_exit_now) - { - SetPrivateState(eStateExited); - m_monitor->Detach(); - } - else - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eExitMessage: - m_exit_status = message.GetExitStatus(); - SetExitStatus(m_exit_status, NULL); - break; - - case ProcessMessage::eTraceMessage: - case ProcessMessage::eBreakpointMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eSignalMessage: - case ProcessMessage::eSignalDeliveredMessage: - SetPrivateState(eStateStopped); - break; - - case ProcessMessage::eCrashMessage: - SetPrivateState(eStateCrashed); - break; - } - - m_message_queue.push(message); -} - -void -ProcessLinux::RefreshStateAfterStop() -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s()", __FUNCTION__); - - Mutex::Locker lock(m_message_mutex); - if (m_message_queue.empty()) - return; - - ProcessMessage &message = m_message_queue.front(); - - // Resolve the thread this message corresponds to and pass it along. - // FIXME: we're really dealing with the pid here. This should get - // fixed when this code is fixed to handle multiple threads. - lldb::tid_t tid = message.GetTID(); - if (log) - log->Printf ("ProcessLinux::%s() pid = %i", __FUNCTION__, tid); - LinuxThread *thread = static_cast( - GetThreadList().FindThreadByID(tid, false).get()); - - assert(thread); - thread->Notify(message); - - m_message_queue.pop(); -} - -bool -ProcessLinux::IsAlive() -{ - StateType state = GetPrivateState(); - return state != eStateDetached && state != eStateExited && state != eStateInvalid; -} - -size_t -ProcessLinux::DoReadMemory(addr_t vm_addr, - void *buf, size_t size, Error &error) -{ - assert(m_monitor); - return m_monitor->ReadMemory(vm_addr, buf, size, error); -} - -size_t -ProcessLinux::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size, - Error &error) -{ - assert(m_monitor); - return m_monitor->WriteMemory(vm_addr, buf, size, error); -} - -addr_t -ProcessLinux::DoAllocateMemory(size_t size, uint32_t permissions, - Error &error) -{ - addr_t allocated_addr = LLDB_INVALID_ADDRESS; - - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { - m_addr_to_mmap_size[allocated_addr] = size; - error.Clear(); - } else { - allocated_addr = LLDB_INVALID_ADDRESS; - error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions)); - } - - return allocated_addr; -} - -Error -ProcessLinux::DoDeallocateMemory(lldb::addr_t addr) +ProcessLinux::Terminate() { - Error error; - MMapMap::iterator pos = m_addr_to_mmap_size.find(addr); - if (pos != m_addr_to_mmap_size.end() && - InferiorCallMunmap(this, addr, pos->second)) - m_addr_to_mmap_size.erase (pos); - else - error.SetErrorStringWithFormat("unable to deallocate memory at 0x%llx", addr); - - return error; } - -size_t -ProcessLinux::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) -{ - static const uint8_t g_i386_opcode[] = { 0xCC }; - - ArchSpec arch = GetTarget().GetArchitecture(); - const uint8_t *opcode = NULL; - size_t opcode_size = 0; - - switch (arch.GetCore()) - { - default: - assert(false && "CPU type not supported!"); - break; - - case ArchSpec::eCore_x86_32_i386: - case ArchSpec::eCore_x86_64_x86_64: - opcode = g_i386_opcode; - opcode_size = sizeof(g_i386_opcode); - break; - } - - bp_site->SetTrapOpcode(opcode, opcode_size); - return opcode_size; -} - -Error -ProcessLinux::EnableBreakpoint(BreakpointSite *bp_site) +const char * +ProcessLinux::GetPluginNameStatic() { - return EnableSoftwareBreakpoint(bp_site); + return "linux"; } -Error -ProcessLinux::DisableBreakpoint(BreakpointSite *bp_site) +const char * +ProcessLinux::GetPluginDescriptionStatic() { - return DisableSoftwareBreakpoint(bp_site); + return "Process plugin for Linux"; } -uint32_t -ProcessLinux::UpdateThreadListIfNeeded() -{ - // Do not allow recursive updates. - return m_thread_list.GetSize(false); -} uint32_t ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_THREAD)); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() (pid = %i)", __FUNCTION__, GetID()); // Update the process thread list with this new thread. @@ -508,61 +106,15 @@ assert(m_monitor); ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false)); if (!thread_sp) - thread_sp.reset(new LinuxThread(*this, GetID())); + thread_sp.reset(new POSIXThread(*this, GetID())); - if (log && log->GetMask().Test(LINUX_LOG_VERBOSE)) + if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) log->Printf ("ProcessLinux::%s() updated pid = %i", __FUNCTION__, GetID()); new_thread_list.AddThread(thread_sp); return new_thread_list.GetSize(false); } -ByteOrder -ProcessLinux::GetByteOrder() const -{ - // FIXME: We should be able to extract this value directly. See comment in - // ProcessLinux(). - return m_byte_order; -} - -size_t -ProcessLinux::PutSTDIN(const char *buf, size_t len, Error &error) -{ - ssize_t status; - if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - error.SetErrorToErrno(); - return 0; - } - return status; -} - -size_t -ProcessLinux::GetSTDOUT(char *buf, size_t len, Error &error) -{ - ssize_t bytes_read; - - // The terminal file descriptor is always in non-block mode. - if ((bytes_read = read(m_monitor->GetTerminalFD(), buf, len)) < 0) - { - if (errno != EAGAIN) - error.SetErrorToErrno(); - return 0; - } - return bytes_read; -} - -size_t -ProcessLinux::GetSTDERR(char *buf, size_t len, Error &error) -{ - return GetSTDOUT(buf, len, error); -} - -UnixSignals & -ProcessLinux::GetUnixSignals() -{ - return m_linux_signals; -} //------------------------------------------------------------------------------ // ProcessInterface protocol. @@ -601,39 +153,3 @@ { return NULL; } - -//------------------------------------------------------------------------------ -// Utility functions. - -bool -ProcessLinux::HasExited() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateDetached: - case eStateExited: - return true; - } - - return false; -} - -bool -ProcessLinux::IsStopped() -{ - switch (GetPrivateState()) - { - default: - break; - - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - - return false; -} Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Thu Jan 5 13:17:38 2012 @@ -19,11 +19,12 @@ #include "lldb/Target/Process.h" #include "LinuxSignals.h" #include "ProcessMessage.h" +#include "ProcessPOSIX.h" class ProcessMonitor; class ProcessLinux : - public lldb_private::Process + public ProcessPOSIX { public: //------------------------------------------------------------------ @@ -51,97 +52,8 @@ ProcessLinux(lldb_private::Target& target, lldb_private::Listener &listener); - virtual - ~ProcessLinux(); - - //------------------------------------------------------------------ - // Process protocol. - //------------------------------------------------------------------ - virtual bool - CanDebug(lldb_private::Target &target, bool plugin_specified_by_name); - - virtual lldb_private::Error - WillLaunch(lldb_private::Module *module); - - virtual lldb_private::Error - DoAttachToProcessWithID(lldb::pid_t pid); - - virtual lldb_private::Error - DoLaunch (lldb_private::Module *exe_module, - const lldb_private::ProcessLaunchInfo &launch_info); - - virtual void - DidLaunch(); - - virtual lldb_private::Error - DoResume(); - - virtual lldb_private::Error - DoHalt(bool &caused_stop); - - virtual lldb_private::Error - DoDetach(); - - virtual lldb_private::Error - DoSignal(int signal); - - virtual lldb_private::Error - DoDestroy(); - - virtual void - RefreshStateAfterStop(); - - virtual bool - IsAlive(); - - virtual size_t - DoReadMemory(lldb::addr_t vm_addr, - void *buf, - size_t size, - lldb_private::Error &error); - - virtual size_t - DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, - lldb_private::Error &error); - - virtual lldb::addr_t - DoAllocateMemory(size_t size, uint32_t permissions, - lldb_private::Error &error); - - virtual lldb_private::Error - DoDeallocateMemory(lldb::addr_t ptr); - - virtual size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); - - virtual lldb_private::Error - EnableBreakpoint(lldb_private::BreakpointSite *bp_site); - - virtual lldb_private::Error - DisableBreakpoint(lldb_private::BreakpointSite *bp_site); - virtual uint32_t - UpdateThreadListIfNeeded(); - - uint32_t - UpdateThreadList(lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); - - virtual lldb::ByteOrder - GetByteOrder() const; - - virtual lldb::addr_t - GetImageInfoAddress(); - - virtual size_t - PutSTDIN(const char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDOUT(char *buf, size_t len, lldb_private::Error &error); - - virtual size_t - GetSTDERR(char *buf, size_t len, lldb_private::Error &error); - + UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -165,59 +77,11 @@ EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); - //-------------------------------------------------------------------------- - // ProcessLinux internal API. - - /// Registers the given message with this process. - void SendMessage(const ProcessMessage &message); - - ProcessMonitor & - GetMonitor() { assert(m_monitor); return *m_monitor; } - - lldb_private::UnixSignals & - GetUnixSignals(); - private: - /// Target byte order. - lldb::ByteOrder m_byte_order; - - /// Process monitor; - ProcessMonitor *m_monitor; - - /// The module we are executing. - lldb_private::Module *m_module; - - /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; - std::queue m_message_queue; - - /// True when the process has entered a state of "limbo". - /// - /// This flag qualifies eStateStopped. It lets us know that when we - /// continue from this state the process will exit. Also, when true, - /// Process::m_exit_status is set. - bool m_in_limbo; - - /// Drive any exit events to completion. - bool m_exit_now; /// Linux-specific signal set. LinuxSignals m_linux_signals; - /// Updates the loaded sections provided by the executable. - /// - /// FIXME: It would probably be better to delegate this task to the - /// DynamicLoader plugin, when we have one. - void UpdateLoadedSections(); - - /// Returns true if the process has exited. - bool HasExited(); - - /// Returns true if the process is stopped. - bool IsStopped(); - - typedef std::map MMapMap; - MMapMap m_addr_to_mmap_size; }; #endif // liblldb_MacOSXProcess_H_ Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp Thu Jan 5 13:17:38 2012 @@ -1,193 +0,0 @@ -//===-- ProcessLinuxLog.cpp ---------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessLinuxLog.h" - -#include "lldb/Interpreter/Args.h" -#include "lldb/Core/StreamFile.h" - -#include "ProcessLinux.h" - -using namespace lldb; -using namespace lldb_private; - - -// We want to avoid global constructors where code needs to be run so here we -// control access to our static g_log_sp by hiding it in a singleton function -// that will construct the static g_lob_sp the first time this function is -// called. -static LogSP & -GetLog () -{ - static LogSP g_log_sp; - return g_log_sp; -} - -LogSP -ProcessLinuxLog::GetLogIfAllCategoriesSet (uint32_t mask) -{ - LogSP log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return LogSP(); - } - return log; -} - -void -ProcessLinuxLog::DisableLog (Args &args, Stream *feedback_strm) -{ - LogSP log (GetLog ()); - if (log) - { - uint32_t flag_bits = 0; - - const size_t argc = args.GetArgumentCount (); - if (argc > 0) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; i < argc; ++i) - { - const char *arg = args.GetArgumentAtIndex (i); - - - if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~LINUX_LOG_ALL; - else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~LINUX_LOG_ASYNC; - else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~LINUX_LOG_BREAKPOINTS; - else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~LINUX_LOG_COMM; - else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~LINUX_LOG_DEFAULT; - else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~LINUX_LOG_PACKETS; - else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY; - else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_SHORT; - else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~LINUX_LOG_MEMORY_DATA_LONG; - else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~LINUX_LOG_PROCESS; - else if (::strcasecmp (arg, "ptrace") == 0 ) flag_bits &= ~LINUX_LOG_PTRACE; - else if (::strcasecmp (arg, "registers") == 0 ) flag_bits &= ~LINUX_LOG_REGISTERS; - else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~LINUX_LOG_STEP; - else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~LINUX_LOG_THREAD; - else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~LINUX_LOG_VERBOSE; - else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~LINUX_LOG_WATCHPOINTS; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - } - - } - } - - if (flag_bits == 0) - GetLog ().reset(); - else - log->GetMask().Reset (flag_bits); - } - - return; -} - -LogSP -ProcessLinuxLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits = 0; - LogSP log(GetLog ()); - if (log) - flag_bits = log->GetMask().Get(); - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - log = make_shared(log_stream_sp); - GetLog () = log; - } - - if (log) - { - bool got_unknown_category = false; - const size_t argc = args.GetArgumentCount(); - for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); - if (got_unknown_category == false) - { - got_unknown_category = true; - ListLogCategories (feedback_strm); - } - } - } - if (flag_bits == 0) - flag_bits = LINUX_LOG_DEFAULT; - log->GetMask().Reset(flag_bits); - log->GetOptions().Reset(log_options); - } - return log; -} - -void -ProcessLinuxLog::ListLogCategories (Stream *strm) -{ - strm->Printf ("Logging categories for '%s':\n" - " all - turn on all available logging categories\n" - " async - log asynchronous activity\n" - " break - log breakpoints\n" - " communication - log communication activity\n" - " default - enable the default set of logging categories for liblldb\n" - " packets - log gdb remote packets\n" - " memory - log memory reads and writes\n" - " data-short - log memory bytes for memory reads and writes for short transactions only\n" - " data-long - log memory bytes for memory reads and writes for all transactions\n" - " process - log process events and activities\n" -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION - " ptrace - log all calls to ptrace\n" -#endif - " registers - log register read/writes\n" - " thread - log thread events and activities\n" - " step - log step related activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n", ProcessLinux::GetPluginNameStatic()); -} - - -void -ProcessLinuxLog::LogIf (uint32_t mask, const char *format, ...) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } -} - -int ProcessLinuxLog::m_nestinglevel; Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h Thu Jan 5 13:17:38 2012 @@ -1,98 +0,0 @@ -//===-- ProcessLinuxLog.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_ProcessLinuxLog_h_ -#define liblldb_ProcessLinuxLog_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes - -// Project includes -#include "lldb/Core/Log.h" - -#define LINUX_LOG_VERBOSE (1u << 0) -#define LINUX_LOG_PROCESS (1u << 1) -#define LINUX_LOG_THREAD (1u << 2) -#define LINUX_LOG_PACKETS (1u << 3) -#define LINUX_LOG_MEMORY (1u << 4) // Log memory reads/writes calls -#define LINUX_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes -#define LINUX_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes -#define LINUX_LOG_BREAKPOINTS (1u << 7) -#define LINUX_LOG_WATCHPOINTS (1u << 8) -#define LINUX_LOG_STEP (1u << 9) -#define LINUX_LOG_COMM (1u << 10) -#define LINUX_LOG_ASYNC (1u << 11) -#define LINUX_LOG_PTRACE (1u << 12) -#define LINUX_LOG_REGISTERS (1u << 13) -#define LINUX_LOG_ALL (UINT32_MAX) -#define LINUX_LOG_DEFAULT LINUX_LOG_PACKETS - -// The size which determines "short memory reads/writes". -#define LINUX_LOG_MEMORY_SHORT_BYTES (4 * sizeof(ptrdiff_t)) - -class ProcessLinuxLog -{ - static int m_nestinglevel; - -public: - static lldb::LogSP - GetLogIfAllCategoriesSet(uint32_t mask = 0); - - static void - DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static lldb::LogSP - EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, - lldb_private::Args &args, lldb_private::Stream *feedback_strm); - - static void - ListLogCategories (lldb_private::Stream *strm); - - static void - LogIf (uint32_t mask, const char *format, ...); - - // The following functions can be used to enable the client to limit - // logging to only the top level function calls. This is useful for - // recursive functions. FIXME: not thread safe! - // Example: - // void NestingFunc() { - // LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet(LINUX_LOG_ALL)); - // if (log) - // { - // ProcessLinuxLog::IncNestLevel(); - // if (ProcessLinuxLog::AtTopNestLevel()) - // log->Print(msg); - // } - // NestingFunc(); - // if (log) - // ProcessLinuxLog::DecNestLevel(); - // } - - static bool - AtTopNestLevel() - { - return m_nestinglevel == 1; - } - - static void - IncNestLevel() - { - ++m_nestinglevel; - } - - static void - DecNestLevel() - { - --m_nestinglevel; - assert(m_nestinglevel >= 0); - } -}; - -#endif // liblldb_ProcessLinuxLog_h_ Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp Thu Jan 5 13:17:38 2012 @@ -1,245 +0,0 @@ -//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessMessage.h" - -using namespace lldb_private; - -const char * -ProcessMessage::GetCrashReasonString(CrashReason reason) -{ - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidAddress: - str = "invalid address"; - break; - case ePrivilegedAddress: - str = "address access protected"; - break; - case eIllegalOpcode: - str = "illegal instruction"; - break; - case eIllegalOperand: - str = "illegal instruction operand"; - break; - case eIllegalAddressingMode: - str = "illegal addressing mode"; - break; - case eIllegalTrap: - str = "illegal trap"; - break; - case ePrivilegedOpcode: - str = "privileged instruction"; - break; - case ePrivilegedRegister: - str = "privileged register"; - break; - case eCoprocessorError: - str = "coprocessor error"; - break; - case eInternalStackError: - str = "internal stack error"; - break; - case eIllegalAlignment: - str = "illegal alignment"; - break; - case eIllegalAddress: - str = "illegal address"; - break; - case eHardwareError: - str = "hardware error"; - break; - case eIntegerDivideByZero: - str = "integer divide by zero"; - break; - case eIntegerOverflow: - str = "integer overflow"; - break; - case eFloatDivideByZero: - str = "floating point divide by zero"; - break; - case eFloatOverflow: - str = "floating point overflow"; - break; - case eFloatUnderflow: - str = "floating point underflow"; - break; - case eFloatInexactResult: - str = "inexact floating point result"; - break; - case eFloatInvalidOperation: - str = "invalid floating point operation"; - break; - case eFloatSubscriptRange: - str = "invalid floating point subscript range"; - break; - } - - return str; -} - -const char * -ProcessMessage::PrintCrashReason(CrashReason reason) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (reason) - { - default: - assert(false && "invalid CrashReason"); - break; - - case eInvalidCrashReason: - str = "eInvalidCrashReason"; - break; - - // SIGSEGV crash rcase easons. - case eInvalidAddress: - str = "eInvalidAddress"; - break; - case ePrivilegedAddress: - str = "ePrivilegedAddress"; - break; - - // SIGILL crash rcase easons. - case eIllegalOpcode: - str = "eIllegalOpcode"; - break; - case eIllegalOperand: - str = "eIllegalOperand"; - break; - case eIllegalAddressingMode: - str = "eIllegalAddressingMode"; - break; - case eIllegalTrap: - str = "eIllegalTrap"; - break; - case ePrivilegedOpcode: - str = "ePrivilegedOpcode"; - break; - case ePrivilegedRegister: - str = "ePrivilegedRegister"; - break; - case eCoprocessorError: - str = "eCoprocessorError"; - break; - case eInternalStackError: - str = "eInternalStackError"; - break; - - // SIGBUS crash rcase easons: - case eIllegalAlignment: - str = "eIllegalAlignment"; - break; - case eIllegalAddress: - str = "eIllegalAddress"; - break; - case eHardwareError: - str = "eHardwareError"; - break; - - // SIGFPE crash rcase easons: - case eIntegerDivideByZero: - str = "eIntegerDivideByZero"; - break; - case eIntegerOverflow: - str = "eIntegerOverflow"; - break; - case eFloatDivideByZero: - str = "eFloatDivideByZero"; - break; - case eFloatOverflow: - str = "eFloatOverflow"; - break; - case eFloatUnderflow: - str = "eFloatUnderflow"; - break; - case eFloatInexactResult: - str = "eFloatInexactResult"; - break; - case eFloatInvalidOperation: - str = "eFloatInvalidOperation"; - break; - case eFloatSubscriptRange: - str = "eFloatSubscriptRange"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintCrashReason() const -{ - return PrintCrashReason(m_crash_reason); -} - -const char * -ProcessMessage::PrintKind(Kind kind) -{ -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Just return the code in asci for integration builds. - chcar str[8]; - sprintf(str, "%d", reason); -#else - const char *str = NULL; - - switch (kind) - { - default: - assert(false && "invalid Kind"); - break; - - case eInvalidMessage: - str = "eInvalidMessage"; - break; - case eExitMessage: - str = "eExitMessage"; - break; - case eLimboMessage: - str = "eLimboMessage"; - break; - case eSignalMessage: - str = "eSignalMessage"; - break; - case eSignalDeliveredMessage: - str = "eSignalDeliveredMessage"; - break; - case eTraceMessage: - str = "eTraceMessage"; - break; - case eBreakpointMessage: - str = "eBreakpointMessage"; - break; - case eCrashMessage: - str = "eCrashMessage"; - break; - } -#endif - - return str; -} - -const char * -ProcessMessage::PrintKind() const -{ - return PrintKind(m_kind); -} Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h Thu Jan 5 13:17:38 2012 @@ -1,171 +0,0 @@ -//===-- ProcessMessage.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_ProcessMessage_H_ -#define liblldb_ProcessMessage_H_ - -#include - -#include "lldb/lldb-defines.h" -#include "lldb/lldb-types.h" - -class ProcessMessage -{ -public: - - /// The type of signal this message can correspond to. - enum Kind - { - eInvalidMessage, - eExitMessage, - eLimboMessage, - eSignalMessage, - eSignalDeliveredMessage, - eTraceMessage, - eBreakpointMessage, - eCrashMessage - }; - - enum CrashReason - { - eInvalidCrashReason, - - // SIGSEGV crash reasons. - eInvalidAddress, - ePrivilegedAddress, - - // SIGILL crash reasons. - eIllegalOpcode, - eIllegalOperand, - eIllegalAddressingMode, - eIllegalTrap, - ePrivilegedOpcode, - ePrivilegedRegister, - eCoprocessorError, - eInternalStackError, - - // SIGBUS crash reasons, - eIllegalAlignment, - eIllegalAddress, - eHardwareError, - - // SIGFPE crash reasons, - eIntegerDivideByZero, - eIntegerOverflow, - eFloatDivideByZero, - eFloatOverflow, - eFloatUnderflow, - eFloatInexactResult, - eFloatInvalidOperation, - eFloatSubscriptRange - }; - - ProcessMessage() - : m_tid(LLDB_INVALID_PROCESS_ID), - m_kind(eInvalidMessage), - m_crash_reason(eInvalidCrashReason), - m_status(0), - m_addr(0) { } - - Kind GetKind() const { return m_kind; } - - lldb::tid_t GetTID() const { return m_tid; } - - /// Indicates that the thread @p tid is about to exit with status @p status. - static ProcessMessage Limbo(lldb::tid_t tid, int status) { - return ProcessMessage(tid, eLimboMessage, status); - } - - /// Indicates that the thread @p tid had the signal @p signum delivered. - static ProcessMessage Signal(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalMessage, signum); - } - - /// Indicates that a signal @p signum generated by the debugging process was - /// delivered to the thread @p tid. - static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) { - return ProcessMessage(tid, eSignalDeliveredMessage, signum); - } - - /// Indicates that the thread @p tid encountered a trace point. - static ProcessMessage Trace(lldb::tid_t tid) { - return ProcessMessage(tid, eTraceMessage); - } - - /// Indicates that the thread @p tid encountered a break point. - static ProcessMessage Break(lldb::tid_t tid) { - return ProcessMessage(tid, eBreakpointMessage); - } - - /// Indicates that the thread @p tid crashed. - static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason, - int signo, lldb::addr_t fault_addr) { - ProcessMessage message(pid, eCrashMessage, signo, fault_addr); - message.m_crash_reason = reason; - return message; - } - - int GetExitStatus() const { - assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); - return m_status; - } - - int GetSignal() const { - assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage || - GetKind() == eSignalDeliveredMessage); - return m_status; - } - - int GetStopStatus() const { - assert(GetKind() == eSignalMessage); - return m_status; - } - - CrashReason GetCrashReason() const { - assert(GetKind() == eCrashMessage); - return m_crash_reason; - } - - lldb::addr_t GetFaultAddress() const { - assert(GetKind() == eCrashMessage); - return m_addr; - } - - static const char * - GetCrashReasonString(CrashReason reason); - - const char * - PrintCrashReason() const; - - static const char * - PrintCrashReason(CrashReason reason); - - const char * - PrintKind() const; - - static const char * - PrintKind(Kind); - -private: - ProcessMessage(lldb::tid_t tid, Kind kind, - int status = 0, lldb::addr_t addr = 0) - : m_tid(tid), - m_kind(kind), - m_crash_reason(eInvalidCrashReason), - m_status(status), - m_addr(addr) { } - - lldb::tid_t m_tid; - Kind m_kind : 8; - CrashReason m_crash_reason : 8; - int m_status; - lldb::addr_t m_addr; -}; - -#endif // #ifndef liblldb_ProcessMessage_H_ Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Thu Jan 5 13:17:38 2012 @@ -28,9 +28,9 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/Utility/PseudoTerminal.h" -#include "LinuxThread.h" +#include "POSIXThread.h" #include "ProcessLinux.h" -#include "ProcessLinuxLog.h" +#include "ProcessPOSIXLog.h" #include "ProcessMonitor.h" @@ -63,8 +63,8 @@ static void PtraceDisplayBytes(__ptrace_request &req, void *data) { StreamString buf; - LogSP verbose_log (ProcessLinuxLog::GetLogIfAllCategoriesSet ( - LINUX_LOG_PTRACE | LINUX_LOG_VERBOSE)); + LogSP verbose_log (ProcessPOSIXLog::GetLogIfAllCategoriesSet ( + POSIX_LOG_PTRACE | POSIX_LOG_VERBOSE)); if (verbose_log) { @@ -120,7 +120,7 @@ { long int result; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PTRACE)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); if (log) log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d", @@ -170,10 +170,10 @@ size_t remainder; long data; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -187,7 +187,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -200,10 +200,10 @@ for (unsigned i = 0; i < remainder; ++i) dst[i] = ((data >> i*8) & 0xFF); - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)dst, (unsigned long)data); @@ -212,7 +212,7 @@ } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_read; } @@ -224,10 +224,10 @@ size_t bytes_written = 0; size_t remainder; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_ALL)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_ALL)); if (log) - ProcessLinuxLog::IncNestLevel(); - if (log && ProcessLinuxLog::AtTopNestLevel() && log->GetMask().Test(LINUX_LOG_MEMORY)) + ProcessPOSIXLog::IncNestLevel(); + if (log && ProcessPOSIXLog::AtTopNestLevel() && log->GetMask().Test(POSIX_LOG_MEMORY)) log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__, pid, word_size, (void*)vm_addr, buf, size); @@ -244,10 +244,10 @@ for (unsigned i = 0; i < word_size; ++i) data |= (unsigned long)src[i] << i*8; - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, data); @@ -255,7 +255,7 @@ { error.SetErrorToErrno(); if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } } @@ -266,7 +266,7 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -276,14 +276,14 @@ buff, word_size, error) != word_size) { if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } - if (log && ProcessLinuxLog::AtTopNestLevel() && - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_LONG) || - (log->GetMask().Test(LINUX_LOG_MEMORY_DATA_SHORT) && - size <= LINUX_LOG_MEMORY_SHORT_BYTES))) + if (log && ProcessPOSIXLog::AtTopNestLevel() && + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_LONG) || + (log->GetMask().Test(POSIX_LOG_MEMORY_DATA_SHORT) && + size <= POSIX_LOG_MEMORY_SHORT_BYTES))) log->Printf ("ProcessMonitor::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(unsigned long*)src, *(unsigned long*)buff); } @@ -292,7 +292,7 @@ src += word_size; } if (log) - ProcessLinuxLog::DecNestLevel(); + ProcessPOSIXLog::DecNestLevel(); return bytes_written; } @@ -420,7 +420,7 @@ ReadRegOperation::Execute(ProcessMonitor *monitor) { lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); // Set errno to zero so that we can detect a failed peek. errno = 0; @@ -434,7 +434,7 @@ } if (log) log->Printf ("ProcessMonitor::%s() reg %s: 0x%x", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), data); + POSIXThread::GetRegisterNameFromOffset(m_offset), data); } //------------------------------------------------------------------------------ @@ -460,7 +460,7 @@ { void* buf; lldb::pid_t pid = monitor->GetPID(); - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); if (sizeof(void*) == sizeof(uint64_t)) buf = (void*) m_value.GetAsUInt64(); @@ -472,7 +472,7 @@ if (log) log->Printf ("ProcessMonitor::%s() reg %s: %p", __FUNCTION__, - LinuxThread::GetRegisterNameFromOffset(m_offset), buf); + POSIXThread::GetRegisterNameFromOffset(m_offset), buf); if (PTRACE(PTRACE_POKEUSER, pid, (void*)m_offset, buf)) m_result = false; else @@ -794,7 +794,7 @@ /// launching or attaching to the inferior process, and then 2) servicing /// operations such as register reads/writes, stepping, etc. See the comments /// on the Operation class for more info as to why this is needed. -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, Module *module, const char *argv[], const char *envp[], @@ -802,7 +802,7 @@ const char *stdout_path, const char *stderr_path, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -858,10 +858,10 @@ } } -ProcessMonitor::ProcessMonitor(ProcessLinux *process, +ProcessMonitor::ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error) - : m_process(process), + : m_process(static_cast(process)), m_operation_thread(LLDB_INVALID_HOST_THREAD), m_pid(LLDB_INVALID_PROCESS_ID), m_terminal_fd(-1), @@ -978,7 +978,7 @@ lldb::pid_t pid; lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); // Propagate the environment if one is not supplied. if (envp == NULL || envp[0] == NULL) @@ -1101,11 +1101,10 @@ if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error)) goto FINISH; - // Update the process thread list with this new thread and mark it as - // current. + // Update the process thread list with this new thread. // FIXME: should we be letting UpdateThreadList handle this? // FIXME: by using pids instead of tids, we can only support one thread. - inferior.reset(new LinuxThread(process, pid)); + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding pid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); @@ -1167,9 +1166,8 @@ ProcessMonitor *monitor = args->m_monitor; ProcessLinux &process = monitor->GetProcess(); - lldb::ThreadSP inferior; - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_PROCESS)); + LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (pid <= 1) { @@ -1192,13 +1190,11 @@ goto FINISH; } - // Update the process thread list with the attached thread and - // mark it as current. - inferior.reset(new LinuxThread(process, pid)); + // Update the process thread list with the attached thread. + inferior.reset(new POSIXThread(process, pid)); if (log) log->Printf ("ProcessMonitor::%s() adding tid = %i", __FUNCTION__, pid); process.GetThreadList().AddThread(inferior); - process.GetThreadList().SetSelectedThreadByID(pid); // Let our process instance know the thread has stopped. process.SendMessage(ProcessMessage::Trace(pid)); @@ -1568,7 +1564,7 @@ } bool -ProcessMonitor::ReadRegisterValue(unsigned offset, RegisterValue &value) +ProcessMonitor::ReadRegisterValue(unsigned offset, unsigned size, RegisterValue &value) { bool result; ReadRegOperation op(offset, value, result); Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Thu Jan 5 13:17:38 2012 @@ -24,10 +24,12 @@ class Error; class Module; class Scalar; + } // End lldb_private namespace. class ProcessLinux; class Operation; +class ProcessPOSIX; /// @class ProcessMonitor /// @brief Manages communication with the inferior (debugee) process. @@ -47,7 +49,7 @@ /// Launches an inferior process ready for debugging. Forms the /// implementation of Process::DoLaunch. - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb_private::Module *module, char const *argv[], char const *envp[], @@ -56,7 +58,7 @@ const char *stderr_path, lldb_private::Error &error); - ProcessMonitor(ProcessLinux *process, + ProcessMonitor(ProcessPOSIX *process, lldb::pid_t pid, lldb_private::Error &error); @@ -104,7 +106,7 @@ /// /// This method is provided for use by RegisterContextLinux derivatives. bool - ReadRegisterValue(unsigned offset, lldb_private::RegisterValue &value); + ReadRegisterValue(unsigned offset, unsigned size, lldb_private::RegisterValue &value); /// Writes the given value to the register identified by the given /// (architecture dependent) offset. Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h Thu Jan 5 13:17:38 2012 @@ -1,40 +0,0 @@ -//===-- RegisterContext_x86_64.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_RegisterContextLinux_H_ -#define liblldb_RegisterContextLinux_H_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -#include "lldb/Target/RegisterContext.h" - -//------------------------------------------------------------------------------ -/// @class RegisterContextLinux -/// -/// @brief Extends RegisterClass with a few virtual operations useful on Linux. -class RegisterContextLinux - : public lldb_private::RegisterContext -{ -public: - RegisterContextLinux(lldb_private::Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContext(thread, concrete_frame_idx) { } - - /// Updates the register state of the associated thread after hitting a - /// breakpoint (if that make sense for the architecture). Default - /// implementation simply returns true for architectures which do not - /// require any update. - /// - /// @return - /// True if the operation succeeded and false otherwise. - virtual bool UpdateAfterBreakpoint() { return true; } -}; - -#endif // #ifndef liblldb_RegisterContextLinux_H_ Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp Thu Jan 5 13:17:38 2012 @@ -1,650 +0,0 @@ -//===-- RegisterContextLinux_i386.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/Core/DataExtractor.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessLinuxLog.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_i386.h" - -using namespace lldb_private; -using namespace lldb; - -enum -{ - k_first_gpr, - gpr_eax = k_first_gpr, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, - k_last_gpr = gpr_gs, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - k_last_fpr = fpu_xmm7, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum -{ - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags -}; - -enum -{ - dwarf_eax = 0, - dwarf_ecx, - dwarf_edx, - dwarf_ebx, - dwarf_esp, - dwarf_ebp, - dwarf_esi, - dwarf_edi, - dwarf_eip, - dwarf_eflags, - dwarf_stmm0 = 11, - dwarf_stmm1, - dwarf_stmm2, - dwarf_stmm3, - dwarf_stmm4, - dwarf_stmm5, - dwarf_stmm6, - dwarf_stmm7, - dwarf_xmm0 = 21, - dwarf_xmm1, - dwarf_xmm2, - dwarf_xmm3, - dwarf_xmm4, - dwarf_xmm5, - dwarf_xmm6, - dwarf_xmm7 -}; - -enum -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fcw = 24, - gdb_fsw = 25, - gdb_ftw = 26, - gdb_fpu_cs = 27, - gdb_ip = 28, - gdb_fpu_ds = 29, - gdb_dp = 30, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_eax, - gpr_ebx, - gpr_ecx, - gpr_edx, - gpr_edi, - gpr_esi, - gpr_ebp, - gpr_esp, - gpr_ss, - gpr_eflags, - gpr_eip, - gpr_cs, - gpr_ds, - gpr_es, - gpr_fs, - gpr_gs, -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_foo, - fpu_fos, - fpu_mxcsr, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, regs) + \ - offsetof(RegisterContextLinux_i386::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_i386::UserArea, i387) + \ - offsetof(RegisterContextLinux_i386::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_i386::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_i386::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_i386::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { dwarf_##reg##i, dwarf_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i } } - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(eax, NULL, gcc_eax, dwarf_eax, LLDB_INVALID_REGNUM, gdb_eax), - DEFINE_GPR(ebx, NULL, gcc_ebx, dwarf_ebx, LLDB_INVALID_REGNUM, gdb_ebx), - DEFINE_GPR(ecx, NULL, gcc_ecx, dwarf_ecx, LLDB_INVALID_REGNUM, gdb_ecx), - DEFINE_GPR(edx, NULL, gcc_edx, dwarf_edx, LLDB_INVALID_REGNUM, gdb_edx), - DEFINE_GPR(edi, NULL, gcc_edi, dwarf_edi, LLDB_INVALID_REGNUM, gdb_edi), - DEFINE_GPR(esi, NULL, gcc_esi, dwarf_esi, LLDB_INVALID_REGNUM, gdb_esi), - DEFINE_GPR(ebp, "fp", gcc_ebp, dwarf_ebp, LLDB_INVALID_REGNUM, gdb_ebp), - DEFINE_GPR(esp, "sp", gcc_esp, dwarf_esp, LLDB_INVALID_REGNUM, gdb_esp), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ss), - DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM, gdb_eflags), - DEFINE_GPR(eip, "pc", gcc_eip, dwarf_eip, LLDB_INVALID_REGNUM, gdb_eip), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_cs), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_es), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gs), - - // Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip), - DEFINE_FPR(cs, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(foo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp), - DEFINE_FPR(fos, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr), - - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - -}; - -#ifndef NDEBUG -static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo)); -#endif - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not in use. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - - -RegisterContextLinux_i386::RegisterContextLinux_i386(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_i386::~RegisterContextLinux_i386() -{ -} - -ProcessMonitor & -RegisterContextLinux_i386::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_i386::Invalidate() -{ -} - -void -RegisterContextLinux_i386::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_i386::GetRegisterCount() -{ - assert(k_num_register_infos == k_num_registers); - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_i386::GetRegisterInfoAtIndex(uint32_t reg) -{ - assert(k_num_register_infos == k_num_registers); - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_i386::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_i386::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_i386::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_i386::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_i386::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - return false; -} - -bool RegisterContextLinux_i386::WriteRegister(const RegisterInfo *reg_info, - const RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_i386::WriteAllRegisterValues(const DataBufferSP &data) -{ - return false; -} - -bool -RegisterContextLinux_i386::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_eip; - case LLDB_REGNUM_GENERIC_SP: return gpr_esp; - case LLDB_REGNUM_GENERIC_FP: return gpr_ebp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case dwarf_eax: return gpr_eax; - case dwarf_edx: return gpr_edx; - case dwarf_ecx: return gpr_ecx; - case dwarf_ebx: return gpr_ebx; - case dwarf_esi: return gpr_esi; - case dwarf_edi: return gpr_edi; - case dwarf_ebp: return gpr_ebp; - case dwarf_esp: return gpr_esp; - case dwarf_eip: return gpr_eip; - case dwarf_xmm0: return fpu_xmm0; - case dwarf_xmm1: return fpu_xmm1; - case dwarf_xmm2: return fpu_xmm2; - case dwarf_xmm3: return fpu_xmm3; - case dwarf_xmm4: return fpu_xmm4; - case dwarf_xmm5: return fpu_xmm5; - case dwarf_xmm6: return fpu_xmm6; - case dwarf_xmm7: return fpu_xmm7; - case dwarf_stmm0: return fpu_stmm0; - case dwarf_stmm1: return fpu_stmm1; - case dwarf_stmm2: return fpu_stmm2; - case dwarf_stmm3: return fpu_stmm3; - case dwarf_stmm4: return fpu_stmm4; - case dwarf_stmm5: return fpu_stmm5; - case dwarf_stmm6: return fpu_stmm6; - case dwarf_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_eax : return gpr_eax; - case gdb_ebx : return gpr_ebx; - case gdb_ecx : return gpr_ecx; - case gdb_edx : return gpr_edx; - case gdb_esi : return gpr_esi; - case gdb_edi : return gpr_edi; - case gdb_ebp : return gpr_ebp; - case gdb_esp : return gpr_esp; - case gdb_eip : return gpr_eip; - case gdb_eflags : return gpr_eflags; - case gdb_cs : return gpr_cs; - case gdb_ss : return gpr_ss; - case gdb_ds : return gpr_ds; - case gdb_es : return gpr_es; - case gdb_fs : return gpr_fs; - case gdb_gs : return gpr_gs; - case gdb_stmm0 : return fpu_stmm0; - case gdb_stmm1 : return fpu_stmm1; - case gdb_stmm2 : return fpu_stmm2; - case gdb_stmm3 : return fpu_stmm3; - case gdb_stmm4 : return fpu_stmm4; - case gdb_stmm5 : return fpu_stmm5; - case gdb_stmm6 : return fpu_stmm6; - case gdb_stmm7 : return fpu_stmm7; - case gdb_fcw : return fpu_fcw; - case gdb_fsw : return fpu_fsw; - case gdb_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_fos; - case gdb_dp : return fpu_foo; - case gdb_fop : return fpu_fop; - case gdb_xmm0 : return fpu_xmm0; - case gdb_xmm1 : return fpu_xmm1; - case gdb_xmm2 : return fpu_xmm2; - case gdb_xmm3 : return fpu_xmm3; - case gdb_xmm4 : return fpu_xmm4; - case gdb_xmm5 : return fpu_xmm5; - case gdb_xmm6 : return fpu_xmm6; - case gdb_xmm7 : return fpu_xmm7; - case gdb_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_i386::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t eflags; - - if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (eflags & TRACE_BIT) - return true; - - eflags |= TRACE_BIT; - } - else - { - if (!(eflags & TRACE_BIT)) - return false; - - eflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_eflags, eflags); -} - -void -RegisterContextLinux_i386::LogGPR(const char *title) -{ - LogSP log (ProcessLinuxLog::GetLogIfAllCategoriesSet (LINUX_LOG_REGISTERS)); - if (log) - { - if (title) - log->Printf ("%s", title); - for (uint32_t i=0; iPrintf("%12s = 0x%8.8x", g_register_infos[reg].name, (&user.regs)[reg]); - } - } -} - -bool -RegisterContextLinux_i386::ReadGPR() -{ - bool result; - - ProcessMonitor &monitor = GetMonitor(); - result = monitor.ReadGPR(&user.regs); - LogGPR("RegisterContextLinux_i386::ReadGPR()"); - return result; -} - -bool -RegisterContextLinux_i386::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h Thu Jan 5 13:17:38 2012 @@ -1,169 +0,0 @@ -//===-- RegisterContextLinux_i386.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_RegisterContextLinux_i386_h_ -#define liblldb_RegisterContextLinux_i386_h_ - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Log.h" -#include "RegisterContextLinux.h" - -class RegisterContextLinux_i386 : public RegisterContextLinux -{ -public: - RegisterContextLinux_i386(lldb_private::Thread &thread, - uint32_t concreate_frame_idx); - - ~RegisterContextLinux_i386(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - -#if 0 - bool - ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value); - - bool - ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data); -#endif - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - -#if 0 - bool - WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value); - - bool - WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data, - uint32_t data_offset = 0); -#endif - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR - { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t ds; - uint32_t es; - uint32_t fs; - uint32_t gs; - uint32_t orig_ax; - uint32_t eip; - uint32_t cs; - uint32_t eflags; - uint32_t esp; - uint32_t ss; - }; - - struct MMSReg - { - uint8_t bytes[8]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint32_t ip; - uint32_t cs; - uint32_t foo; - uint32_t fos; - uint32_t mxcsr; - uint32_t reserved; - MMSReg stmm[8]; - XMMReg xmm[8]; - uint32_t pad[56]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - FPU i387; // FPU registers. - uint32_t tsize; // Text segment size. - uint32_t dsize; // Data segment size. - uint32_t ssize; // Stack segment size. - uint32_t start_code; // VM address of text. - uint32_t start_stack; // VM address of stack bottom (top in rsp). - int32_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - uint32_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint32_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7). - }; -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - void LogGPR(const char *title); - - bool ReadGPR(); - bool ReadFPR(); -}; - -#endif // #ifndef liblldb_RegisterContextLinux_i386_h_ Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp (original) +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp Thu Jan 5 13:17:38 2012 @@ -1,759 +0,0 @@ -//===-- RegisterContextLinux_x86_64.cpp -------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include -#include -#include - -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Scalar.h" -#include "lldb/Target/Thread.h" -#include "lldb/Host/Endian.h" - -#include "ProcessLinux.h" -#include "ProcessMonitor.h" -#include "RegisterContextLinux_x86_64.h" - -using namespace lldb_private; -using namespace lldb; - -// Internal codes for all x86_64 registers. -enum -{ - k_first_gpr, - gpr_rax = k_first_gpr, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es, - k_last_gpr = gpr_es, - - k_first_fpr, - fpu_fcw = k_first_fpr, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15, - k_last_fpr = fpu_xmm15, - - k_num_registers, - k_num_gpr_registers = k_last_gpr - k_first_gpr + 1, - k_num_fpu_registers = k_last_fpr - k_first_fpr + 1 -}; - -// Number of register sets provided by this context. -enum -{ - k_num_register_sets = 2 -}; - -enum gcc_dwarf_regnums -{ - gcc_dwarf_gpr_rax = 0, - gcc_dwarf_gpr_rdx, - gcc_dwarf_gpr_rcx, - gcc_dwarf_gpr_rbx, - gcc_dwarf_gpr_rsi, - gcc_dwarf_gpr_rdi, - gcc_dwarf_gpr_rbp, - gcc_dwarf_gpr_rsp, - gcc_dwarf_gpr_r8, - gcc_dwarf_gpr_r9, - gcc_dwarf_gpr_r10, - gcc_dwarf_gpr_r11, - gcc_dwarf_gpr_r12, - gcc_dwarf_gpr_r13, - gcc_dwarf_gpr_r14, - gcc_dwarf_gpr_r15, - gcc_dwarf_gpr_rip, - gcc_dwarf_fpu_xmm0, - gcc_dwarf_fpu_xmm1, - gcc_dwarf_fpu_xmm2, - gcc_dwarf_fpu_xmm3, - gcc_dwarf_fpu_xmm4, - gcc_dwarf_fpu_xmm5, - gcc_dwarf_fpu_xmm6, - gcc_dwarf_fpu_xmm7, - gcc_dwarf_fpu_xmm8, - gcc_dwarf_fpu_xmm9, - gcc_dwarf_fpu_xmm10, - gcc_dwarf_fpu_xmm11, - gcc_dwarf_fpu_xmm12, - gcc_dwarf_fpu_xmm13, - gcc_dwarf_fpu_xmm14, - gcc_dwarf_fpu_xmm15, - gcc_dwarf_fpu_stmm0, - gcc_dwarf_fpu_stmm1, - gcc_dwarf_fpu_stmm2, - gcc_dwarf_fpu_stmm3, - gcc_dwarf_fpu_stmm4, - gcc_dwarf_fpu_stmm5, - gcc_dwarf_fpu_stmm6, - gcc_dwarf_fpu_stmm7 -}; - -enum gdb_regnums -{ - gdb_gpr_rax = 0, - gdb_gpr_rbx = 1, - gdb_gpr_rcx = 2, - gdb_gpr_rdx = 3, - gdb_gpr_rsi = 4, - gdb_gpr_rdi = 5, - gdb_gpr_rbp = 6, - gdb_gpr_rsp = 7, - gdb_gpr_r8 = 8, - gdb_gpr_r9 = 9, - gdb_gpr_r10 = 10, - gdb_gpr_r11 = 11, - gdb_gpr_r12 = 12, - gdb_gpr_r13 = 13, - gdb_gpr_r14 = 14, - gdb_gpr_r15 = 15, - gdb_gpr_rip = 16, - gdb_gpr_rflags = 17, - gdb_gpr_cs = 18, - gdb_gpr_ss = 19, - gdb_gpr_ds = 20, - gdb_gpr_es = 21, - gdb_gpr_fs = 22, - gdb_gpr_gs = 23, - gdb_fpu_stmm0 = 24, - gdb_fpu_stmm1 = 25, - gdb_fpu_stmm2 = 26, - gdb_fpu_stmm3 = 27, - gdb_fpu_stmm4 = 28, - gdb_fpu_stmm5 = 29, - gdb_fpu_stmm6 = 30, - gdb_fpu_stmm7 = 31, - gdb_fpu_fcw = 32, - gdb_fpu_fsw = 33, - gdb_fpu_ftw = 34, - gdb_fpu_cs = 35, - gdb_fpu_ip = 36, - gdb_fpu_ds = 37, - gdb_fpu_dp = 38, - gdb_fpu_fop = 39, - gdb_fpu_xmm0 = 40, - gdb_fpu_xmm1 = 41, - gdb_fpu_xmm2 = 42, - gdb_fpu_xmm3 = 43, - gdb_fpu_xmm4 = 44, - gdb_fpu_xmm5 = 45, - gdb_fpu_xmm6 = 46, - gdb_fpu_xmm7 = 47, - gdb_fpu_xmm8 = 48, - gdb_fpu_xmm9 = 49, - gdb_fpu_xmm10 = 50, - gdb_fpu_xmm11 = 51, - gdb_fpu_xmm12 = 52, - gdb_fpu_xmm13 = 53, - gdb_fpu_xmm14 = 54, - gdb_fpu_xmm15 = 55, - gdb_fpu_mxcsr = 56 -}; - -static const -uint32_t g_gpr_regnums[k_num_gpr_registers] = -{ - gpr_rax, - gpr_rbx, - gpr_rcx, - gpr_rdx, - gpr_rdi, - gpr_rsi, - gpr_rbp, - gpr_rsp, - gpr_r8, - gpr_r9, - gpr_r10, - gpr_r11, - gpr_r12, - gpr_r13, - gpr_r14, - gpr_r15, - gpr_rip, - gpr_rflags, - gpr_cs, - gpr_fs, - gpr_gs, - gpr_ss, - gpr_ds, - gpr_es -}; - -static const uint32_t -g_fpu_regnums[k_num_fpu_registers] = -{ - fpu_fcw, - fpu_fsw, - fpu_ftw, - fpu_fop, - fpu_ip, - fpu_cs, - fpu_dp, - fpu_ds, - fpu_mxcsr, - fpu_mxcsrmask, - fpu_stmm0, - fpu_stmm1, - fpu_stmm2, - fpu_stmm3, - fpu_stmm4, - fpu_stmm5, - fpu_stmm6, - fpu_stmm7, - fpu_xmm0, - fpu_xmm1, - fpu_xmm2, - fpu_xmm3, - fpu_xmm4, - fpu_xmm5, - fpu_xmm6, - fpu_xmm7, - fpu_xmm8, - fpu_xmm9, - fpu_xmm10, - fpu_xmm11, - fpu_xmm12, - fpu_xmm13, - fpu_xmm14, - fpu_xmm15 -}; - -static const RegisterSet -g_reg_sets[k_num_register_sets] = -{ - { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums }, - { "Floating Point Registers", "fpu", k_num_fpu_registers, g_fpu_regnums } -}; - -// Computes the offset of the given GPR in the user data area. -#define GPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, regs) + \ - offsetof(RegisterContextLinux_x86_64::GPR, regname)) - -// Computes the offset of the given FPR in the user data area. -#define FPR_OFFSET(regname) \ - (offsetof(RegisterContextLinux_x86_64::UserArea, i387) + \ - offsetof(RegisterContextLinux_x86_64::FPU, regname)) - -// Number of bytes needed to represent a GPR. -#define GPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::GPR*)NULL)->reg) - -// Number of bytes needed to represent a FPR. -#define FPR_SIZE(reg) sizeof(((RegisterContextLinux_x86_64::FPU*)NULL)->reg) - -// Number of bytes needed to represent the i'th FP register. -#define FP_SIZE sizeof(((RegisterContextLinux_x86_64::MMSReg*)NULL)->bytes) - -// Number of bytes needed to represent an XMM register. -#define XMM_SIZE sizeof(RegisterContextLinux_x86_64::XMMReg) - -#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } } - -#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \ - { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } } - -#define DEFINE_FP(reg, i) \ - { #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define DEFINE_XMM(reg, i) \ - { #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \ - eFormatVectorOfUInt8, \ - { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \ - LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } } - -#define REG_CONTEXT_SIZE (sizeof(RegisterContextLinux_x86_64::GPR) + sizeof(RegisterContextLinux_x86_64::FPU)) - -static RegisterInfo -g_register_infos[k_num_registers] = -{ - // General purpose registers. - DEFINE_GPR(rax, NULL, gcc_dwarf_gpr_rax, gcc_dwarf_gpr_rax, LLDB_INVALID_REGNUM, gdb_gpr_rax), - DEFINE_GPR(rbx, NULL, gcc_dwarf_gpr_rbx, gcc_dwarf_gpr_rbx, LLDB_INVALID_REGNUM, gdb_gpr_rbx), - DEFINE_GPR(rcx, NULL, gcc_dwarf_gpr_rcx, gcc_dwarf_gpr_rcx, LLDB_INVALID_REGNUM, gdb_gpr_rcx), - DEFINE_GPR(rdx, NULL, gcc_dwarf_gpr_rdx, gcc_dwarf_gpr_rdx, LLDB_INVALID_REGNUM, gdb_gpr_rdx), - DEFINE_GPR(rdi, NULL, gcc_dwarf_gpr_rdi, gcc_dwarf_gpr_rdi, LLDB_INVALID_REGNUM, gdb_gpr_rdi), - DEFINE_GPR(rsi, NULL, gcc_dwarf_gpr_rsi, gcc_dwarf_gpr_rsi, LLDB_INVALID_REGNUM, gdb_gpr_rsi), - DEFINE_GPR(rbp, "fp", gcc_dwarf_gpr_rbp, gcc_dwarf_gpr_rbp, LLDB_REGNUM_GENERIC_FP, gdb_gpr_rbp), - DEFINE_GPR(rsp, "sp", gcc_dwarf_gpr_rsp, gcc_dwarf_gpr_rsp, LLDB_REGNUM_GENERIC_SP, gdb_gpr_rsp), - DEFINE_GPR(r8, NULL, gcc_dwarf_gpr_r8, gcc_dwarf_gpr_r8, LLDB_INVALID_REGNUM, gdb_gpr_r8), - DEFINE_GPR(r9, NULL, gcc_dwarf_gpr_r9, gcc_dwarf_gpr_r9, LLDB_INVALID_REGNUM, gdb_gpr_r9), - DEFINE_GPR(r10, NULL, gcc_dwarf_gpr_r10, gcc_dwarf_gpr_r10, LLDB_INVALID_REGNUM, gdb_gpr_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_gpr_r11, gcc_dwarf_gpr_r11, LLDB_INVALID_REGNUM, gdb_gpr_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_gpr_r12, gcc_dwarf_gpr_r12, LLDB_INVALID_REGNUM, gdb_gpr_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_gpr_r13, gcc_dwarf_gpr_r13, LLDB_INVALID_REGNUM, gdb_gpr_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_gpr_r14, gcc_dwarf_gpr_r14, LLDB_INVALID_REGNUM, gdb_gpr_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_gpr_r15, gcc_dwarf_gpr_r15, LLDB_INVALID_REGNUM, gdb_gpr_r15), - DEFINE_GPR(rip, "pc", gcc_dwarf_gpr_rip, gcc_dwarf_gpr_rip, LLDB_REGNUM_GENERIC_PC, gdb_gpr_rip), - DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags), - DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_cs), - DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_fs), - DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_gs), - DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ss), - DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_ds), - DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_gpr_es), - - // i387 Floating point registers. - DEFINE_FPR(fcw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw), - DEFINE_FPR(fsw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw), - DEFINE_FPR(ftw, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw), - DEFINE_FPR(fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop), - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip), - // FIXME: Extract segment from ip. - DEFINE_FPR(ip, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs), - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp), - // FIXME: Extract segment from dp. - DEFINE_FPR(dp, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds), - DEFINE_FPR(mxcsr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr), - DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - - // FP registers. - DEFINE_FP(stmm, 0), - DEFINE_FP(stmm, 1), - DEFINE_FP(stmm, 2), - DEFINE_FP(stmm, 3), - DEFINE_FP(stmm, 4), - DEFINE_FP(stmm, 5), - DEFINE_FP(stmm, 6), - DEFINE_FP(stmm, 7), - - // XMM registers - DEFINE_XMM(xmm, 0), - DEFINE_XMM(xmm, 1), - DEFINE_XMM(xmm, 2), - DEFINE_XMM(xmm, 3), - DEFINE_XMM(xmm, 4), - DEFINE_XMM(xmm, 5), - DEFINE_XMM(xmm, 6), - DEFINE_XMM(xmm, 7), - DEFINE_XMM(xmm, 8), - DEFINE_XMM(xmm, 9), - DEFINE_XMM(xmm, 10), - DEFINE_XMM(xmm, 11), - DEFINE_XMM(xmm, 12), - DEFINE_XMM(xmm, 13), - DEFINE_XMM(xmm, 14), - DEFINE_XMM(xmm, 15) -}; - -static unsigned GetRegOffset(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_offset; -} - -#if 0 // These functions are currently not being used. -static unsigned GetRegSize(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register number."); - return g_register_infos[reg].byte_size; -} - -static bool IsGPR(unsigned reg) -{ - return reg <= k_last_gpr; // GPR's come first. -} - -static bool IsFPR(unsigned reg) -{ - return (k_first_fpr <= reg && reg <= k_last_fpr); -} -#endif - -RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, - uint32_t concrete_frame_idx) - : RegisterContextLinux(thread, concrete_frame_idx) -{ -} - -RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64() -{ -} - -ProcessMonitor & -RegisterContextLinux_x86_64::GetMonitor() -{ - ProcessLinux *process = static_cast(CalculateProcess()); - return process->GetMonitor(); -} - -void -RegisterContextLinux_x86_64::Invalidate() -{ -} - -void -RegisterContextLinux_x86_64::InvalidateAllRegisters() -{ -} - -size_t -RegisterContextLinux_x86_64::GetRegisterCount() -{ - return k_num_registers; -} - -const RegisterInfo * -RegisterContextLinux_x86_64::GetRegisterInfoAtIndex(uint32_t reg) -{ - if (reg < k_num_registers) - return &g_register_infos[reg]; - else - return NULL; -} - -size_t -RegisterContextLinux_x86_64::GetRegisterSetCount() -{ - return k_num_register_sets; -} - -const RegisterSet * -RegisterContextLinux_x86_64::GetRegisterSet(uint32_t set) -{ - if (set < k_num_register_sets) - return &g_reg_sets[set]; - else - return NULL; -} - -unsigned -RegisterContextLinux_x86_64::GetRegisterIndexFromOffset(unsigned offset) -{ - unsigned reg; - for (reg = 0; reg < k_num_registers; reg++) - { - if (g_register_infos[reg].byte_offset == offset) - break; - } - assert(reg < k_num_registers && "Invalid register offset."); - return reg; -} - -const char * -RegisterContextLinux_x86_64::GetRegisterName(unsigned reg) -{ - assert(reg < k_num_registers && "Invalid register offset."); - return g_register_infos[reg].name; -} - -bool -RegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, - RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp) -{ - data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0)); - if (data_sp && ReadGPR () && ReadFPR ()) - { - uint8_t *dst = data_sp->GetBytes(); - ::memcpy (dst, &user.regs, sizeof(user.regs)); - dst += sizeof(user.regs); - - ::memcpy (dst, &user.i387, sizeof(user.i387)); - return true; - } - return false; -} - -bool -RegisterContextLinux_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value) -{ - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteRegisterValue(GetRegOffset(reg), value); -} - -bool -RegisterContextLinux_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp) -{ - if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) - { - const uint8_t *src = data_sp->GetBytes(); - ::memcpy (&user.regs, src, sizeof(user.regs)); - src += sizeof(user.regs); - - ::memcpy (&user.i387, src, sizeof(user.i387)); - return WriteGPR() & WriteFPR(); - } - return false; -} - -bool -RegisterContextLinux_x86_64::UpdateAfterBreakpoint() -{ - // PC points one byte past the int3 responsible for the breakpoint. - lldb::addr_t pc; - - if ((pc = GetPC()) == LLDB_INVALID_ADDRESS) - return false; - - SetPC(pc - 1); - return true; -} - -uint32_t -RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind, - uint32_t num) -{ - if (kind == eRegisterKindGeneric) - { - switch (num) - { - case LLDB_REGNUM_GENERIC_PC: return gpr_rip; - case LLDB_REGNUM_GENERIC_SP: return gpr_rsp; - case LLDB_REGNUM_GENERIC_FP: return gpr_rbp; - case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags; - case LLDB_REGNUM_GENERIC_RA: - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF) - { - switch (num) - { - case gcc_dwarf_gpr_rax: return gpr_rax; - case gcc_dwarf_gpr_rdx: return gpr_rdx; - case gcc_dwarf_gpr_rcx: return gpr_rcx; - case gcc_dwarf_gpr_rbx: return gpr_rbx; - case gcc_dwarf_gpr_rsi: return gpr_rsi; - case gcc_dwarf_gpr_rdi: return gpr_rdi; - case gcc_dwarf_gpr_rbp: return gpr_rbp; - case gcc_dwarf_gpr_rsp: return gpr_rsp; - case gcc_dwarf_gpr_r8: return gpr_r8; - case gcc_dwarf_gpr_r9: return gpr_r9; - case gcc_dwarf_gpr_r10: return gpr_r10; - case gcc_dwarf_gpr_r11: return gpr_r11; - case gcc_dwarf_gpr_r12: return gpr_r12; - case gcc_dwarf_gpr_r13: return gpr_r13; - case gcc_dwarf_gpr_r14: return gpr_r14; - case gcc_dwarf_gpr_r15: return gpr_r15; - case gcc_dwarf_gpr_rip: return gpr_rip; - case gcc_dwarf_fpu_xmm0: return fpu_xmm0; - case gcc_dwarf_fpu_xmm1: return fpu_xmm1; - case gcc_dwarf_fpu_xmm2: return fpu_xmm2; - case gcc_dwarf_fpu_xmm3: return fpu_xmm3; - case gcc_dwarf_fpu_xmm4: return fpu_xmm4; - case gcc_dwarf_fpu_xmm5: return fpu_xmm5; - case gcc_dwarf_fpu_xmm6: return fpu_xmm6; - case gcc_dwarf_fpu_xmm7: return fpu_xmm7; - case gcc_dwarf_fpu_xmm8: return fpu_xmm8; - case gcc_dwarf_fpu_xmm9: return fpu_xmm9; - case gcc_dwarf_fpu_xmm10: return fpu_xmm10; - case gcc_dwarf_fpu_xmm11: return fpu_xmm11; - case gcc_dwarf_fpu_xmm12: return fpu_xmm12; - case gcc_dwarf_fpu_xmm13: return fpu_xmm13; - case gcc_dwarf_fpu_xmm14: return fpu_xmm14; - case gcc_dwarf_fpu_xmm15: return fpu_xmm15; - case gcc_dwarf_fpu_stmm0: return fpu_stmm0; - case gcc_dwarf_fpu_stmm1: return fpu_stmm1; - case gcc_dwarf_fpu_stmm2: return fpu_stmm2; - case gcc_dwarf_fpu_stmm3: return fpu_stmm3; - case gcc_dwarf_fpu_stmm4: return fpu_stmm4; - case gcc_dwarf_fpu_stmm5: return fpu_stmm5; - case gcc_dwarf_fpu_stmm6: return fpu_stmm6; - case gcc_dwarf_fpu_stmm7: return fpu_stmm7; - default: - return LLDB_INVALID_REGNUM; - } - } - - if (kind == eRegisterKindGDB) - { - switch (num) - { - case gdb_gpr_rax : return gpr_rax; - case gdb_gpr_rbx : return gpr_rbx; - case gdb_gpr_rcx : return gpr_rcx; - case gdb_gpr_rdx : return gpr_rdx; - case gdb_gpr_rsi : return gpr_rsi; - case gdb_gpr_rdi : return gpr_rdi; - case gdb_gpr_rbp : return gpr_rbp; - case gdb_gpr_rsp : return gpr_rsp; - case gdb_gpr_r8 : return gpr_r8; - case gdb_gpr_r9 : return gpr_r9; - case gdb_gpr_r10 : return gpr_r10; - case gdb_gpr_r11 : return gpr_r11; - case gdb_gpr_r12 : return gpr_r12; - case gdb_gpr_r13 : return gpr_r13; - case gdb_gpr_r14 : return gpr_r14; - case gdb_gpr_r15 : return gpr_r15; - case gdb_gpr_rip : return gpr_rip; - case gdb_gpr_rflags : return gpr_rflags; - case gdb_gpr_cs : return gpr_cs; - case gdb_gpr_ss : return gpr_ss; - case gdb_gpr_ds : return gpr_ds; - case gdb_gpr_es : return gpr_es; - case gdb_gpr_fs : return gpr_fs; - case gdb_gpr_gs : return gpr_gs; - case gdb_fpu_stmm0 : return fpu_stmm0; - case gdb_fpu_stmm1 : return fpu_stmm1; - case gdb_fpu_stmm2 : return fpu_stmm2; - case gdb_fpu_stmm3 : return fpu_stmm3; - case gdb_fpu_stmm4 : return fpu_stmm4; - case gdb_fpu_stmm5 : return fpu_stmm5; - case gdb_fpu_stmm6 : return fpu_stmm6; - case gdb_fpu_stmm7 : return fpu_stmm7; - case gdb_fpu_fcw : return fpu_fcw; - case gdb_fpu_fsw : return fpu_fsw; - case gdb_fpu_ftw : return fpu_ftw; - case gdb_fpu_cs : return fpu_cs; - case gdb_fpu_ip : return fpu_ip; - case gdb_fpu_ds : return fpu_ds; - case gdb_fpu_dp : return fpu_dp; - case gdb_fpu_fop : return fpu_fop; - case gdb_fpu_xmm0 : return fpu_xmm0; - case gdb_fpu_xmm1 : return fpu_xmm1; - case gdb_fpu_xmm2 : return fpu_xmm2; - case gdb_fpu_xmm3 : return fpu_xmm3; - case gdb_fpu_xmm4 : return fpu_xmm4; - case gdb_fpu_xmm5 : return fpu_xmm5; - case gdb_fpu_xmm6 : return fpu_xmm6; - case gdb_fpu_xmm7 : return fpu_xmm7; - case gdb_fpu_xmm8 : return fpu_xmm8; - case gdb_fpu_xmm9 : return fpu_xmm9; - case gdb_fpu_xmm10 : return fpu_xmm10; - case gdb_fpu_xmm11 : return fpu_xmm11; - case gdb_fpu_xmm12 : return fpu_xmm12; - case gdb_fpu_xmm13 : return fpu_xmm13; - case gdb_fpu_xmm14 : return fpu_xmm14; - case gdb_fpu_xmm15 : return fpu_xmm15; - case gdb_fpu_mxcsr : return fpu_mxcsr; - default: - return LLDB_INVALID_REGNUM; - } - } - else if (kind == eRegisterKindLLDB) - { - return num; - } - - return LLDB_INVALID_REGNUM; -} - -bool -RegisterContextLinux_x86_64::HardwareSingleStep(bool enable) -{ - enum { TRACE_BIT = 0x100 }; - uint64_t rflags; - - if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL) - return false; - - if (enable) - { - if (rflags & TRACE_BIT) - return true; - - rflags |= TRACE_BIT; - } - else - { - if (!(rflags & TRACE_BIT)) - return false; - - rflags &= ~TRACE_BIT; - } - - return WriteRegisterFromUnsigned(gpr_rflags, rflags); -} - -bool -RegisterContextLinux_x86_64::ReadGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::ReadFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.ReadFPR(&user.i387); -} - -bool -RegisterContextLinux_x86_64::WriteGPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteGPR(&user.regs); -} - -bool -RegisterContextLinux_x86_64::WriteFPR() -{ - ProcessMonitor &monitor = GetMonitor(); - return monitor.WriteFPR(&user.i387); -} Modified: lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h (original) +++ lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h Thu Jan 5 13:17:38 2012 @@ -10,67 +10,7 @@ #ifndef liblldb_RegisterContextLinux_x86_64_H_ #define liblldb_RegisterContextLinux_x86_64_H_ -#include "RegisterContextLinux.h" - -class ProcessMonitor; - -class RegisterContextLinux_x86_64 - : public RegisterContextLinux -{ -public: - RegisterContextLinux_x86_64 (lldb_private::Thread &thread, - uint32_t concrete_frame_idx); - - ~RegisterContextLinux_x86_64(); - - void - Invalidate(); - - void - InvalidateAllRegisters(); - - size_t - GetRegisterCount(); - - const lldb_private::RegisterInfo * - GetRegisterInfoAtIndex(uint32_t reg); - - size_t - GetRegisterSetCount(); - - const lldb_private::RegisterSet * - GetRegisterSet(uint32_t set); - - static unsigned - GetRegisterIndexFromOffset(unsigned offset); - - static const char * - GetRegisterName(unsigned reg); - - virtual bool - ReadRegister(const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value); - - bool - ReadAllRegisterValues(lldb::DataBufferSP &data_sp); - - virtual bool - WriteRegister(const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue &value); - - bool - WriteAllRegisterValues(const lldb::DataBufferSP &data_sp); - - uint32_t - ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num); - - bool - HardwareSingleStep(bool enable); - - bool - UpdateAfterBreakpoint(); - - struct GPR + typedef struct _GPR { uint64_t r15; uint64_t r14; @@ -99,67 +39,6 @@ uint64_t es; uint64_t fs; uint64_t gs; - }; - - struct MMSReg - { - uint8_t bytes[10]; - uint8_t pad[6]; - }; - - struct XMMReg - { - uint8_t bytes[16]; - }; - - struct FPU - { - uint16_t fcw; - uint16_t fsw; - uint16_t ftw; - uint16_t fop; - uint64_t ip; - uint64_t dp; - uint32_t mxcsr; - uint32_t mxcsrmask; - MMSReg stmm[8]; - XMMReg xmm[16]; - uint32_t padding[24]; - }; - - struct UserArea - { - GPR regs; // General purpose registers. - int32_t fpvalid; // True if FPU is being used. - int32_t pad0; - FPU i387; // FPU registers. - uint64_t tsize; // Text segment size. - uint64_t dsize; // Data segment size. - uint64_t ssize; // Stack segment size. - uint64_t start_code; // VM address of text. - uint64_t start_stack; // VM address of stack bottom (top in rsp). - int64_t signal; // Signal causing core dump. - int32_t reserved; // Unused. - int32_t pad1; - uint64_t ar0; // Location of GPR's. - FPU* fpstate; // Location of FPR's. - uint64_t magic; // Identifier for core dumps. - char u_comm[32]; // Command causing core dump. - uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7). - uint64_t error_code; // CPU error code. - uint64_t fault_address; // Control register CR3. - }; - -private: - UserArea user; - - ProcessMonitor &GetMonitor(); - - bool ReadGPR(); - bool ReadFPR(); - - bool WriteGPR(); - bool WriteFPR(); -}; + } GPR; -#endif // #ifndef liblldb_RegisterContextLinux_x86_64_H_ +#endif Modified: lldb/trunk/source/lldb.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/source/lldb.cpp (original) +++ lldb/trunk/source/lldb.cpp Thu Jan 5 13:17:38 2012 @@ -52,13 +52,16 @@ #endif #if defined (__linux__) -#include "Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h" +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/Linux/PlatformLinux.h" #include "Plugins/Process/Linux/ProcessLinux.h" #endif #if defined (__FreeBSD__) +#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h" #include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h" +#include "Plugins/Process/POSIX/ProcessPOSIX.h" +#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h" #endif #include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" @@ -120,10 +123,12 @@ //---------------------------------------------------------------------- PlatformLinux::Initialize(); ProcessLinux::Initialize(); - DynamicLoaderLinuxDYLD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Initialize(); + PlatformFreeBSD::Initialize(); + ProcessFreeBSD::Initialize(); + DynamicLoaderPOSIXDYLD::Initialize(); #endif //---------------------------------------------------------------------- // Platform agnostic plugins @@ -190,11 +195,13 @@ #if defined (__linux__) PlatformLinux::Terminate(); ProcessLinux::Terminate(); - DynamicLoaderLinuxDYLD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif #if defined (__FreeBSD__) - PlatformFreeBSD::Terminate(); + PlatformFreeBSD::Terminate(); + ProcessFreeBSD::Terminate(); + DynamicLoaderPOSIXDYLD::Terminate(); #endif DynamicLoaderStatic::Terminate(); Modified: lldb/trunk/tools/driver/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/Makefile?rev=147609&r1=147608&r2=147609&view=diff ============================================================================== --- lldb/trunk/tools/driver/Makefile (original) +++ lldb/trunk/tools/driver/Makefile Thu Jan 5 13:17:38 2012 @@ -25,7 +25,6 @@ ifeq ($(HOST_OS),FreeBSD) CPP.Flags += -I/usr/include/edit #-v - LD.Flags += -lEnhancedDisassembly LD.Flags += -Wl,-rpath,$(LibDir) endif From cdavis at mymail.mines.edu Thu Jan 5 15:07:57 2012 From: cdavis at mymail.mines.edu (Charles Davis) Date: Thu, 5 Jan 2012 14:07:57 -0700 Subject: [Lldb-commits] [lldb] r147609 - in /lldb/trunk: ./ include/lldb/Host/ lib/ source/ source/Host/freebsd/ source/Host/linux/ source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/ source/Plugins/Platform/FreeBSD/ source/Plugins/Platform/Linux/ source/Plugins/Process/Linux/ tools/driver/ In-Reply-To: <20120105191739.DCD8D1BE003@llvm.org> References: <20120105191739.DCD8D1BE003@llvm.org> Message-ID: <0201DFDD-8B33-4B9D-8813-8CDFB39A5585@mymail.mines.edu> On Jan 5, 2012, at 12:17 PM, Johnny Chen wrote: > Modified: > lldb/trunk/Makefile > lldb/trunk/include/lldb/Host/Host.h > lldb/trunk/lib/Makefile > lldb/trunk/source/Host/freebsd/Host.cpp > lldb/trunk/source/Host/linux/Host.cpp > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h > lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile > lldb/trunk/source/Plugins/Makefile > lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp > lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h > lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h > lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp > lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h > lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp > lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h > lldb/trunk/source/Plugins/Process/Linux/Makefile > lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp > lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h > lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp > lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h > lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp > lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h > lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp > lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h > lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h > lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp > lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h > lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp > lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h > lldb/trunk/source/lldb.cpp > lldb/trunk/tools/driver/Makefile > > Modified: lldb/trunk/Makefile > URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/Makefile?rev=147609&r1=147608&r2=147609&view=diff > ============================================================================== > --- lldb/trunk/Makefile (original) > +++ lldb/trunk/Makefile Thu Jan 5 13:17:38 2012 > @@ -39,6 +39,7 @@ > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility > CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility > +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX Did you forget to 'svn add' something? Chip From mark at peek.org Thu Jan 5 15:27:20 2012 From: mark at peek.org (Mark Peek) Date: Thu, 05 Jan 2012 13:27:20 -0800 Subject: [Lldb-commits] [lldb] r147609 - in /lldb/trunk: ./ include/lldb/Host/ lib/ source/ source/Host/freebsd/ source/Host/linux/ source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/ source/Plugins/Platform/FreeBSD/ source/Plugins/Platform/Linux/ source/Plugins/Process/Linux/ tools/driver/ In-Reply-To: <0201DFDD-8B33-4B9D-8813-8CDFB39A5585@mymail.mines.edu> References: <20120105191739.DCD8D1BE003@llvm.org> <0201DFDD-8B33-4B9D-8813-8CDFB39A5585@mymail.mines.edu> Message-ID: <4F0615B8.9060501@peek.org> On 1/5/12 1:07 PM, Charles Davis wrote: > > On Jan 5, 2012, at 12:17 PM, Johnny Chen wrote: >> Modified: >> lldb/trunk/Makefile >> lldb/trunk/include/lldb/Host/Host.h >> lldb/trunk/lib/Makefile >> lldb/trunk/source/Host/freebsd/Host.cpp >> lldb/trunk/source/Host/linux/Host.cpp >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h >> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile >> lldb/trunk/source/Plugins/Makefile >> lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp >> lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h >> lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h >> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp >> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h >> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp >> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h >> lldb/trunk/source/Plugins/Process/Linux/Makefile >> lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp >> lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h >> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp >> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h >> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp >> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h >> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp >> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h >> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h >> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp >> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h >> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp >> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h >> lldb/trunk/source/lldb.cpp >> lldb/trunk/tools/driver/Makefile >> >> Modified: lldb/trunk/Makefile >> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/Makefile?rev=147609&r1=147608&r2=147609&view=diff >> ============================================================================== >> --- lldb/trunk/Makefile (original) >> +++ lldb/trunk/Makefile Thu Jan 5 13:17:38 2012 >> @@ -39,6 +39,7 @@ >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility >> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility >> +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX > Did you forget to 'svn add' something? > > Chip At first glance it would appear that these changes are needed: - Remove lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD and contents (currently 0 size) - Remove 0 size files inside of lldb/trunk/source/Plugins/Process/ - Add lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD and contents - Add lldb/trunk/source/Plugins/Process/POSIX and contents - Add lldb/trunk/source/Plugins/Process/FreeBSD and contents I think that will fix it but I'd have to do a more exhaustive check. Thanks, Mark From johnny.chen at apple.com Thu Jan 5 15:33:08 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 05 Jan 2012 13:33:08 -0800 Subject: [Lldb-commits] [lldb] r147609 - in /lldb/trunk: ./ include/lldb/Host/ lib/ source/ source/Host/freebsd/ source/Host/linux/ source/Plugins/ source/Plugins/DynamicLoader/Linux-DYLD/ source/Plugins/Platform/FreeBSD/ source/Plugins/Platform/Linux/ source/Plugins/Process/Linux/ tools/driver/ In-Reply-To: <4F0615B8.9060501@peek.org> References: <20120105191739.DCD8D1BE003@llvm.org> <0201DFDD-8B33-4B9D-8813-8CDFB39A5585@mymail.mines.edu> <4F0615B8.9060501@peek.org> Message-ID: Looking into it.... On Jan 5, 2012, at 1:27 PM, Mark Peek wrote: > On 1/5/12 1:07 PM, Charles Davis wrote: >> >> On Jan 5, 2012, at 12:17 PM, Johnny Chen wrote: >>> Modified: >>> lldb/trunk/Makefile >>> lldb/trunk/include/lldb/Host/Host.h >>> lldb/trunk/lib/Makefile >>> lldb/trunk/source/Host/freebsd/Host.cpp >>> lldb/trunk/source/Host/linux/Host.cpp >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.cpp >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/AuxVector.h >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.cpp >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DYLDRendezvous.h >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.cpp >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/DynamicLoaderLinuxDYLD.h >>> lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/Makefile >>> lldb/trunk/source/Plugins/Makefile >>> lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp >>> lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h >>> lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.h >>> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp >>> lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h >>> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp >>> lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h >>> lldb/trunk/source/Plugins/Process/Linux/Makefile >>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp >>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h >>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp >>> lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h >>> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp >>> lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h >>> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp >>> lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h >>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h >>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp >>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h >>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp >>> lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h >>> lldb/trunk/source/lldb.cpp >>> lldb/trunk/tools/driver/Makefile >>> >>> Modified: lldb/trunk/Makefile >>> URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/Makefile?rev=147609&r1=147608&r2=147609&view=diff >>> ============================================================================== >>> --- lldb/trunk/Makefile (original) >>> +++ lldb/trunk/Makefile Thu Jan 5 13:17:38 2012 >>> @@ -39,6 +39,7 @@ >>> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source >>> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Utility >>> CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Utility >>> +CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/POSIX >> Did you forget to 'svn add' something? >> >> Chip > > At first glance it would appear that these changes are needed: > > - Remove lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD and contents (currently 0 size) > - Remove 0 size files inside of lldb/trunk/source/Plugins/Process/ > - Add lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD and contents > - Add lldb/trunk/source/Plugins/Process/POSIX and contents > - Add lldb/trunk/source/Plugins/Process/FreeBSD and contents > > I think that will fix it but I'd have to do a more exhaustive check. > > Thanks, > Mark > > From johnny.chen at apple.com Thu Jan 5 15:48:16 2012 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 05 Jan 2012 21:48:16 -0000 Subject: [Lldb-commits] [lldb] r147613 - in /lldb/trunk/source/Plugins: DynamicLoader/Linux-DYLD/ DynamicLoader/POSIX-DYLD/ Process/FreeBSD/ Process/Linux/ Process/POSIX/ Message-ID: <20120105214817.273981BE003@llvm.org> Author: johnny Date: Thu Jan 5 15:48:15 2012 New Revision: 147613 URL: http://llvm.org/viewvc/llvm-project?rev=147613&view=rev Log: Fix incomplete commit of http://llvm.org/viewvc/llvm-project?rev=147609&view=rev: This patch combines common code from Linux and FreeBSD into a new POSIX platform. It also contains fixes for 64bit FreeBSD. The patch is based on changes by Mark Peek and "K. Macy" in their github repo located at https://github.com/fbsd/lldb. Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile lldb/trunk/source/Plugins/Process/FreeBSD/ lldb/trunk/source/Plugins/Process/FreeBSD/Makefile lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp lldb/trunk/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.h lldb/trunk/source/Plugins/Process/FreeBSD/RegisterContextFreeBSD_x86_64.h lldb/trunk/source/Plugins/Process/POSIX/ lldb/trunk/source/Plugins/Process/POSIX/Makefile lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.cpp lldb/trunk/source/Plugins/Process/POSIX/POSIXStopInfo.h lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.h lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.cpp lldb/trunk/source/Plugins/Process/POSIX/ProcessMessage.h lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.cpp lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIX.h lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp lldb/trunk/source/Plugins/Process/POSIX/ProcessPOSIXLog.h lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIX.h lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.cpp lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_i386.h lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp lldb/trunk/source/Plugins/Process/POSIX/RegisterContext_x86_64.h Removed: lldb/trunk/source/Plugins/DynamicLoader/Linux-DYLD/ lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessLinuxLog.h lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.cpp lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_i386.h lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.cpp lldb/trunk/source/Plugins/Process/Linux/RegisterContextLinux_x86_64.h Added: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp?rev=147613&view=auto ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp (added) +++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp Thu Jan 5 15:48:15 2012 @@ -0,0 +1,153 @@ +//===-- AuxVector.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 +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/Process.h" + +#include "AuxVector.h" + +using namespace lldb; +using namespace lldb_private; + +