diff options
author | Greg Clayton <gclayton@apple.com> | 2012-01-04 22:56:43 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2012-01-04 22:56:43 +0000 |
commit | 96c09687bce5e2dfb6f81eca705515a106d1c1a3 (patch) | |
tree | eef2f707fe4a5284c16a7ea6d1c66dcaa413cd84 | |
parent | 3ad904245686d7aeef7d2770e938146d2d97255a (diff) | |
download | bcm5719-llvm-96c09687bce5e2dfb6f81eca705515a106d1c1a3.tar.gz bcm5719-llvm-96c09687bce5e2dfb6f81eca705515a106d1c1a3.zip |
<rdar://problem/10507811>
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.
llvm-svn: 147559
-rw-r--r-- | lldb/include/lldb/API/SBFrame.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/DWARFExpression.h | 6 | ||||
-rw-r--r-- | lldb/include/lldb/Host/File.h | 35 | ||||
-rwxr-xr-x | lldb/scripts/build-lldb-llvm-clang | 9 | ||||
-rw-r--r-- | lldb/source/Core/ConnectionFileDescriptor.cpp | 47 | ||||
-rw-r--r-- | lldb/source/Expression/DWARFExpression.cpp | 12 | ||||
-rw-r--r-- | lldb/source/Host/common/File.cpp | 182 | ||||
-rw-r--r-- | lldb/source/Host/common/FileSpec.cpp | 77 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 60 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h | 4 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 13 |
11 files changed, 292 insertions, 155 deletions
diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h index d351fd21376..bd4636c0df1 100644 --- a/lldb/include/lldb/API/SBFrame.h +++ b/lldb/include/lldb/API/SBFrame.h @@ -16,8 +16,6 @@ namespace lldb { -class SBValue; - class SBFrame { public: diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 3db1a645acc..68317083363 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -142,6 +142,10 @@ public: /// @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 @@ public: /// 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); diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h index 160f2e7e8ee..69e8cc6f131 100644 --- a/lldb/include/lldb/Host/File.h +++ b/lldb/include/lldb/Host/File.h @@ -35,9 +35,10 @@ public: 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 @@ public: 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 diff --git a/lldb/scripts/build-lldb-llvm-clang b/lldb/scripts/build-lldb-llvm-clang index 17c7e5475bc..822e9944bf6 100755 --- a/lldb/scripts/build-lldb-llvm-clang +++ b/lldb/scripts/build-lldb-llvm-clang @@ -22,13 +22,11 @@ svn co -q -r $LLVM_REVISION http://llvm.org/svn/llvm-project/llvm/trunk llvm # 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 @@ elif [ "$LLVM_CONFIGURATION" = "Release" ]; then 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 diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index 5c0e97d71e2..f83d9994c35 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -188,7 +188,10 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) { // 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 @@ ConnectionFileDescriptor::Read (void *dst, 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 @@ ConnectionFileDescriptor::Read (void *dst, 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 @@ ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStat 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; } diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 6ce82015ce9..3555c41fd58 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -992,18 +992,15 @@ GetOpcodeDataSize (const DataExtractor &data, const uint32_t data_offset, const } 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 @@ DWARFExpression::LocationContains_DW_OP_addr (lldb::addr_t file_addr) const { const uint32_t op_arg_size = GetOpcodeDataSize (m_data, offset, op); if (op_arg_size == UINT32_MAX) + { + error = true; break; + } offset += op_arg_size; } } diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index a12cd3aeeac..a84266f7110 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -10,11 +10,13 @@ #include "lldb/Host/File.h" +#include <errno.h> #include <fcntl.h> #include <limits.h> #include <stdarg.h> #include <sys/stat.h> +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Host/Config.h" #include "lldb/Host/FileSpec.h" @@ -135,7 +137,12 @@ File::GetStream () { 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 @@ File::Open (const char *path, uint32_t options, uint32_t permissions) 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; - - m_descriptor = ::open(path, oflag, mode); + 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); + if (!DescriptorIsValid()) error.SetErrorToErrno(); else @@ -357,7 +378,13 @@ File::Flush () 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 @@ File::Sync () 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 @@ Error 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 @@ File::Read (void *buf, size_t &num_bytes) } 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 @@ Error 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 @@ File::Write (const void *buf, size_t &num_bytes) } 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 @@ File::Read (void *buf, size_t &num_bytes, off_t &offset) 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 @@ File::Read (void *buf, size_t &num_bytes, off_t &offset) } 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<DataBufferHeap> 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; diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index b6e6e94d846..1f0942d5bb5 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -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 @@ FileSpec::ReadFileContents (off_t file_offset, void *dst, size_t dst_len) const char resolved_path[PATH_MAX]; if (GetPath(resolved_path, sizeof(resolved_path))) { - int fd = ::open (resolved_path, O_RDONLY, 0); - if (fd != -1) + Error error; + File file; + error = file.Open(resolved_path, File::eOpenOptionRead); + if (error.Success()) { - 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; - } - } - } + 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 @@ FileSpec::ReadFileContents (off_t file_offset, size_t file_size) const 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<DataBufferHeap> 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; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 26961f497cb..48506def369 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -720,19 +720,16 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges std::vector<dw_offset_t> 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 @@ DWARFDebugInfoEntry::Dump 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 @@ DWARFDebugInfoEntry::GetAttributes 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 @@ DWARFDebugInfoEntry::GetAttributeValue 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 @@ DWARFDebugInfoEntry::GetAttributeValue 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 (idx<attr_idx) DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu); @@ -1583,7 +1578,7 @@ DWARFDebugInfoEntry::AppendTypeName 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 @@ DWARFDebugInfoEntry::LookupAddress } 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; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 350e4de9f9c..9c2914f5840 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -300,7 +300,9 @@ public: 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 diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 6b16f0f6276..3d196040ca6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -5553,10 +5553,19 @@ SymbolFileDWARF::ParseVariableDIE 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 @@ SymbolFileDWARF::ParseVariableDIE // 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 |